天天看點

SpringMVC學習筆記SpringMVC學習筆記SpringMVC概述SpringMVC 注解式開發SSM 整合開發SpringMVC 核心技術

SpringMVC學習筆記

文章目錄

  • SpringMVC學習筆記
  • SpringMVC概述
    • SpringMVC 基本說明
    • SpringMVC中的核心Servlet---DispatcherServlet
    • springmvc請求的處理過程
    • web開發中配置檔案說明
    • SpringMVC内部執行流程
  • SpringMVC 注解式開發
    • @RequestMapping注解的使用。
    • 接受請求中的參數
      • 逐個接收
      • 請求中參數名和形參名不一樣,使用@RequestParam
      • 對象接收參數
    • 控制器方法的傳回值
      • 傳回資料和視圖
      • 傳回String 視圖
      • 傳回值void 沒有資料和視圖
      • 傳回值是Object對象
        • HttpMessageConverter 消息轉換器
        • @ResponseBody
        • 控制器方法傳回對象轉為json的步驟
    • 靜态資源處理
      • tomcat的default servlet
      • 央排程器設定 "/"
      • 第一種方式處理靜态資源
      • 第二種靜态資源的處理方式
  • SSM 整合開發
    • SSM 整合思路
    • 容器的建立
    • SSM整合開發步驟
    • 相對路徑
  • SpringMVC 核心技術
    • 轉發和重定向
    • 異常處理
    • 攔截器
      • 第一個攔截器
      • 多個攔截器
      • 攔截器和過濾器的對比

SpringMVC概述

SpringMVC 基本說明

SpringMVC是基于spring的, 是spring中的一個子產品,做web開發使用的。

  1. 說明他是spring的核心技術, 做web開發,springmvc内部是使用mvc架構模式。
  2. SpringMVC 是一個容器, 管理對象的,使用IoC核心技術。 springmvc管理界面層中的控制器對象。
  3. SpringMVC底層也是Servlet。 以Servlet為核心, 接收請求,處理請求。 顯示處理結果給使用者。

處理使用者請求的步驟:

使用者發起請求----SpringMVC—Spring—MyBatis–mysql資料庫

SpringMVC中的核心Servlet—DispatcherServlet

1.DispatcherServlet 是架構一個Servlet對象。 負責接收請求, 響應處理結果。

2.DispatcherServlet 他的父類是HttpServlet

3.DispatcherServlet 也叫做前端控制器( front controller)。

4.SpringMVC是管理控制器對象, 原來沒有SpringMVC之前使用 Servlet作為控制器對象使用。現在通過SpringMVC容器建立一種叫做控制器的對象,代替Servlet行駛控制器的角色。功能。

5.SpringMVC 主要使用注解的方式, 建立控制器對象, 處理請求。

springmvc請求的處理過程

簡單的處理過程:

使用者發起請求some.do—>Tomcat接收了請求—DispatcherServlet–配置設定MyController(doSome()傳回mv對象)–mv顯示給使用者了。

SpringMVC學習筆記SpringMVC學習筆記SpringMVC概述SpringMVC 注解式開發SSM 整合開發SpringMVC 核心技術

web開發中配置檔案說明

1.web.xml 部署描述符檔案 , 給伺服器(tomcat)。

作用:伺服器在啟動的時候,讀取web.xml ,根據檔案中的聲明建立各種對象,根據檔案中的聲明 知道 請求和servlet等對象的關系。

web.xml檔案配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    
    
    <!--聲明springmvc的核心對象

        通路mymvc位址後, 報錯 檔案沒有找到。找的檔案 /WEB-INF/springmvc-servlet.xml
                                                  /WEB-INF/myweb-servlet.xml
        錯誤原因:
           在Servlet的init()方法中,建立springmvc使用的容器對象WebApplicationContext.
           WebApplicationContext ctx = new ClassPathXmlApplicationContext(配置檔案)。
           配置檔案的預設路徑: /WEB-INF/<servlet-name>-servlet.xml
    -->

    <servlet>
        <servlet-name>myweb</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--自定義配置檔案的位置-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <!--
           表示伺服器tomcat建立對象的順序, 是個整數值, 大于等于0.
           數值越小,建立對象的時間越早。
        -->
        <load-on-startup>1</load-on-startup>
    </servlet>


    <servlet-mapping>
        <servlet-name>myweb</servlet-name>
        <!--
           url-pattern 作用: 把一些請求交給指定的servlet處理
           使用中央排程器(DispatcherServlet)
           1. 使用擴充名方式, 格式 *.xxx ,  xxx是自定義的擴充名。
              例如  *.do , *.action, *.mvc 等等. 不能使用*.jsp
              http://localhost:8080/myweb/some.do
              http://localhost:8080/myweb/user/list/queryUser.do
              http://localhost:8080/myweb/user/list/list.do

           2. 使用斜杠 "/"
        -->
        <url-pattern>*.do</url-pattern>

    </servlet-mapping>


</web-app>
           

2.架構的配置檔案, springmvc的配置檔案

作用:聲明架構建立的項目中的各種對象, 主要是建立Controller對象的

配置檔案的加載順序和功能

3.tomcat伺服器啟動, 讀取web.xml. 根據web.xml檔案中的說明,建立對象。建立DispatcherServlet他的對象, 會執行init()方法。 在init()方法中會執行 springmvc容器對象建立WebApplicationContext ctx = new ClassPathXmlApplicationContext(“classpath:springmvc.xml”)

4.springmvc架構, new ClassPathXmlApplicationContext()讀取springmvc的配置檔案。

//聲明元件掃描器,掃描控制器處理方法所在的包
<context:component-scan base-package="com.bjpowernode.controller" />
           

使用元件掃描器base-package=“com.bjpowernode.controller” ,周遊controller包中的所有類,MyController類, 找到這個類中的@Controller, @RequestMapping注解, 就能建立MyContoller對象。知道some.do的請求是執行doSome()方法以上 1, 2. 都是項目啟動的過程, 沒有執行任何的使用者請求。使用者發起請求some.do----DispatcherServlet DispatcherServlet裡面有 WebApplicationContext 。WebApplicationContext 裡面有MyController對象。請求some.do ,DispatcherServlet 就知道是 MyController處理的。

SpringMVC内部執行流程

springmvc内部請求的處理過程:

1.使用者發起請求給DispatcherServlet

2.DispatcherServlet把請求(request)交給了 處理器映射器。

3.處理器映射器: springmvc架構中的對象, 需要實作HandlerMapping接口。

4.映射器作用: 從springmvc容器中,擷取控制器對象(MyController),把找到的控制器和攔截器對象都放到處理器執行鍊對象中,儲存,并傳回給中央排程器。(MyController controller = ApplicationContext.getBean())

5.DispatcherServlet把擷取到的處理器執行鍊中的控制器對象,交給了處理器擴充卡

處理器擴充卡:是springmvc架構中的對象, 實作HandlerAdapter接口。

擴充卡作用: 執行控制器的方法, 也就是執行MyController.doSome()方法。得到結果ModelAndView

6.DispatcherServlet把控制器執行結果mv交給了 視圖解析器

視圖解析器: springmvc中的對象,需要實作ViewResolver接口。

視圖解析器作用: 處理視圖的, 組成視圖的完整路徑。 能建立View類型的對象

7.DispatcherServlet調用View類的方法, 把Model中的資料放入到request作用域。 執行request.setAttribute(), 對視圖執行forward()轉發行為, request.getRequestDispather("/show.jsp").forward(request,response)

SpringMVC 注解式開發

@RequestMapping注解的使用。

1.屬性:

value 請求的uri位址。

2.位置:

  1. 在方法的上面, 必須的。
  2. 在類的上面作為子產品名稱
@RequestMapping(value ="/some.do") 
public ModelAndView doSome(){
	...
}


//屬性 method 請求的方式, 使用RequestMehtod類的枚舉,表示請求方式
@RequestMapping(value ="/other.do",method = RequestMethod.POST) public ModelAndView doOther(){
	...
}
           

接受請求中的參數

對應HttpServletRequest, HttpServletResponse, HttpSession 隻需要在控制器方法的形參清單中,定義就可以了。架構會給參數指派, 在控制器方法内部可以直接使用 request,response,session參數。

400 : http status , 表示用戶端異常。 主要是發生在使用者送出參數過程中。

接收請求中的參數方式有: 逐個接收, 對象接收

逐個接收

逐個接收: 請求中的參數名和控制器方法的形參名一樣。按照名稱對象接收參數

Controller接收參數

@RequestMapping(value ="/receive-property.do") 
public ModelAndView doPropertyParam(String name, Integer age) {
	...
}
           

接收參數的問題:

1.參數最好使用包裝類型。 例如Integer ,能接收空值情況, 接收的是null

2.架構可以使用String到int ,long, float, double等類型轉換。

3.post請求中有亂碼的問題, 使用字元集過濾器。

字元集過濾器的聲明: 使用

CharacterEncodingFilter

在web.xml 聲明過濾器 
<filter> 
<filter-name>characterEncodingFilter</filter-name> 
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
 	<!--給過濾器屬性指派--> 
 	<init-param> 
 	<!--項目使用的字元編碼--> 
 	<param-name>encoding</param-name>
  	<param-value>utf-8</param-value>
   	</init-param>
   	
  	<init-param> 
  	<!--強制請求(request)對象使用encoding的編碼方式--> 
  	<param-name>forceRequestEncoding</param-name> 
  	<param-value>true</param-value> 
	</init-param> 
	
  	<init-param> 
  	<!--強制應答(response)對象使用encoding的編碼方式--> 
  	<param-name>forceResponseEncoding</param-name> 
  	<param-value>true</param-value> 
  	</init-param> 
</filter> 
  	
  	<filter-mapping> 
  	<filter-name>characterEncodingFilter</filter-name> 
  	<!--強制所有請求,先經過過濾器處理--> 
  	<url-pattern>/*</url-pattern> </filter-mapping>
           

請求中參數名和形參名不一樣,使用@RequestParam

/**
* 逐個接收請求參數, 請求中參數名和形參名不一樣 
* @RequestParam : 解決名稱不一樣的問題 
* 屬性: value 請求中的參數名稱 
* required : boolean類型的,預設是true
* true:請求中必須有此參數,沒有報錯。
* false:請求中可以沒有此參數。 
* 位置: 在形參定義的前面 
* */
@RequestMapping(value ="/receive-param.do") 
public ModelAndView doReceiveParam( 
@RequestParam(value = "rname",required = false) String name, 
@RequestParam(value = "rage",required = false) Integer age) { 
	...
}
           

對象接收參數

對象接收: 在控制器方法的形參是java對象, 使用java對象的屬性接收請求中參數值。

要求: java對象的屬性名和請求中參數名一樣。

@RequestMapping("/receive-object.do") 
public ModelAndView doReceiveObject(Student student){ 
	System.out.println("MyController的方法doReceiveObject="+student); 
	ModelAndView mv = new ModelAndView(); 
	mv.addObject("myname", student.getName()); 
	mv.addObject("myage", student.getAge()); 
	mv.setViewName("show"); return mv; 
}
           

控制器方法的傳回值

控制器方法的傳回值表示本次請求的處理結果,傳回值有ModelAndView, String, void , Object,請求的處理結果包含: 資料和視圖。

傳回資料和視圖

當請求的結果有資料和視圖,使用ModelAndView最友善

資料:存放request作用域。

視圖:執行forward轉發操作

傳回String 視圖

架構對傳回值是String,執行的是forward轉發操作。

視圖可以表示為完整視圖路徑, 或者視圖的邏輯名稱

@RequestMapping(value ="/return-string-view.do") 
public String doReturnStringView1(HttpServletRequest request,String name, Integer age) { 
	System.out.println("執行了MyController的doReturnStringView1方法name=");
    //傳回結果,forward,轉發到show.jsp
    //邏輯名稱, 需要配置視圖解析器
    return "show";
}


@RequestMapping(value ="/return-string-view2.do") 
public String doReturnStringView2(HttpServletRequest request,String name, Integer age) { 
	System.out.println("執行了MyController的doReturnStringView2方法name="); 
	//完整視圖路徑,不能使用視圖解析器 return "/WEB-INF/view/show.jsp";
} 
           

傳回值void 沒有資料和視圖

void: 沒有資料和視圖, 可以使用HttpServletResponse對象輸出資料,響應ajax請求。

@RequestMapping("/return-void-ajax.do")
    public void returnVoidAjax(HttpServletResponse response,String name,Integer age) throws IOException {
        System.out.println("處理void傳回類型, name="+name+",age="+age);
        //調用service得到結果對象
        Student  student = new Student();
        student.setName(name+"同學");
        student.setAge(age);

        //把對象轉為json
        ObjectMapper om  = new ObjectMapper();
        String json  = om.writeValueAsString(student);
        System.out.println("伺服器端對象轉為的json==="+json);

        //輸出json,響應ajax
        response.setContentType("application/json;charset=utf-8");
        PrintWriter pw  = response.getWriter();
        pw.println(json);
        pw.flush();
        pw.close();
    }
           

傳回值是Object對象

傳回Student 表示資料,還是視圖。 是以控制器方法傳回對象Object, 用來響應ajax請求。

傳回對象Object ,可以是List, Student , Map ,String ,Integer… 這些都是資料, 而ajax請求需要的是資料。 在ajax請求中,一般需要從伺服器傳回的是json格式的資料, 經常要處理java對象到json的轉換。而且還需要輸出資料響應ajax請求。 架構提供了處理 java對象到json轉換, 還是資料輸出工作。

HttpMessageConverter 消息轉換器

HttpMessageConverter 接口,作用是

1.實作請求的資料轉為java對象,

2.把控制器方法傳回的對象轉為json,xml,text,二進制等不同格式的資料。

public interface HttpMessageConverter {
作用: 檢查clazz這個類型的對象,能否轉為 mediaType表示的資料格式 如果能轉為mediaType表示的類型, 傳回true, 傳回true調用read() / boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);
作用: 接收請求中的資料,把資料轉為 clazz表示的對象  
T read(Class<? extends T> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException;
作用:檢查clazz這種資料類型,能否轉為mediaType表示的資料格式 
boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);
作用: 把t對象,按照contentType說明的格式,把對象轉為json或者xml 
void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException;
}
           

MediaType:媒體類型,表示網際網路中資料的格式。例如application/json, text/html, image/gif

HttpMessageConverter 接口的實作類:
MappingJackson2HttpMessageConverter : 用jackson工具庫的ObjectMapper把java對象轉為json資料格式 
StringHttpMessageConverter : 把字元串類型的資料,進行格式轉換和編碼
           

怎麼使用實作類:

架構根據控制器方法的傳回類型, 自動查找使用的實作類。

@RequestMapping("/receive-object.do") 
public Student doReceiveObject(String name,Integer age){ 
   System.out.println("MyController的方法doReceiveObject="); 
   Student student = new Student(); student.setName("lisi");
   student.setAge(20); 
   return student; 
}
           

預設情況下: springmvc使用了HttpMessageConveter接口的4個實作類。包括了StringHttpMessageConverter.

需要在springmvc的配置檔案,加入注解驅動的标簽 mvc:annotation-driven. 加入這個标簽後, springmvc項目啟動後,會建立HttpMessageConveter接口的7個實作類對象,包括StringHttpMessageConverter 和 MappingJackson2HttpMessageConverter。

@ResponseBody

@ResponseBody注解的作用,就是把student轉換後的json通過HttpServletResponse對象輸出給浏覽器。

//輸出json,響應ajax 
response.setContentType("application/json;charset=utf-8"); 
PrintWriter pw = response.getWriter(); 
pw.println(json); 
pw.flush(); 
pw.close();

@ResponseBody注解作用就上面的代碼的實作
           

控制器方法傳回對象轉為json的步驟

  1. pom.xml加入jackson依賴,springmvc架構,預設處理json就是使用jackson
  2. 在springmvc的配置檔案中,加入注解驅動的标簽mvc:annotation-dirven
  3. 在控制器方法的上面加入@ResponseBody注解,表示傳回值資料,輸出到浏覽器。

靜态資源處理

tomcat的default servlet

tomcat安裝目錄/conf/web.xml

<servlet-name>default</servlet-name> 
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class> 
<init-param> 
	<param-name>debug</param-name> 
	<param-value>0</param-value> 
</init-param> 
<init-param> 
	<param-name>listings</param-name> 
	<param-value>false</param-value> 
</init-param> 
<load-on-startup>1</load-on-startup> 
<servlet-mapping> 
	<servlet-name>default</servlet-name> 
	<url-pattern>/</url-pattern> 
</servlet-mapping>
           

default 叫做預設servlet ,作用:

1.它提供靜态資源的處理

2.它處理所有未映射到其他請求的請求處理

央排程器設定 “/”

使用斜杠 "/" . 導緻中央排程器稱為了預設的default servlet。 
需要處理靜态資源和其他的未映射的請求。 
預設中央排程器沒有處理靜态資源的控制器對象, 是以靜态資源都是 404 。 some.do這個請求有MyController對象, 是以能通路。
如果項目中 , 中央排程器設定了“/” , 動态資源能通路,靜态資源不能通路。
需要處理靜态資源的通路工作。
           

第一種方式處理靜态資源

在springmvc的配置檔案加入 mvc:default-servlet-handler标簽,springmvc架構會在項目運作時,加入DefaultServletHttpRequestHandler對象,讓這個對象處理靜态資源的通路。

<mvc:annotation-driven />
<mvc:default-servlet-handler />
           

第二種靜态資源的處理方式

在springmvc配置檔案中加入一個 mvc:resources标簽, 架構會建立ResourceHttpRequestHandler控制器對象, 使用這個對象處理靜态資源的通路。 不依賴tomcat伺服器。 推薦使用的。

<mvc:annotation-driven />

<!--聲明靜态資源的第二種處理方式
    mapping: 通路靜态資源的uri位址, 可以使用通配符(**)。
              ** : 表示任意的目錄和目錄和資源名稱
    location: 靜态資源在項目中的位置, 不要使用/WEB-INF目錄

-->
<mvc:resources mapping="/images/**" location="/images/" />
<mvc:resources mapping="/html/**" location="/html/" />
<mvc:resources mapping="/js/**" location="/js/" />

<!--一句話設定靜态資源-->
<!--<mvc:resources mapping="/static/**" location="/static/" />-->
           

SSM 整合開發

SSM 整合思路

SSM思路: SpringMVC+ Spring + MyBatis(IBatis), 是以有人叫做SSI整合。 SSM整合是使用三個架構的優勢功能。三個架構對應的三層架構的三層。 SpringMVC是視圖層, Spring是業務層, MyBatis持久層。

SSM 整合,需要把對象交給容器管理, 讓容器去建立項目中要使用的java對象。 現在有兩個容器。

第一個是Spring容器: Spring容器是管理service 和 dao等對象的。 是業務層對象的容器。

第二個是SpringMVC容器:管理控制器對象的。 是視圖層對象。

SSM整合就是把對象交給容器管理。 兩個容器共存。 各自負責管理不同的對象。 把對象聲明到配置檔案中,讓兩個容器建立對象。 spring建立service,dao; springmvc建立controller。

容器的建立

Spring容器建立: 在web.xml聲明了監聽器ContextLoaderListener , 這個功能架構寫好了。功能是建立spring的容器對象 WebApplicationContext. 在建立WebApplicationContext對象時,讀取spring的配置檔案, 讀取檔案的時候,遇到bean标簽或者注解,就能建立service ,dao等對象, 放到容器中。

在Spring的配置檔案中,配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:context="http://www.springframework.org/schema/context"
      xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

   <!--spring配置檔案:聲明service,dao,工具類等-->
   <context:property-placeholder location="classpath:conf/jdbc.properties"/>
   <!--聲明資料源,作用是連接配接資料庫-->
   <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
         init-method="init" destroy-method="close">
       <!--set注入給DruidDataSource提供資料庫資訊-->
       <property name="url" value="${jdbc.url}"/>
       <property name="password" value="${jdbc.password}"/>
       <property name="username" value="${jdbc.username}"/>
   </bean>


   <!--SqlSessionFactoryBean建立SqlSessionFactory-->
   <!-- 聲明的是mybatis中提供的SqlSessionFactoryBean類,這個類内部建立SqlSessionFactory類 -->
   <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
       <!-- set注入,把資料庫連接配接池賦給了dataSource屬性 -->
       <property name="dataSource" ref="dataSource"/>
       <!--
       mybatis主配置檔案名的位置
           configLocation屬性是Resource類型,讀取配置檔案
           他的指派:使用value,指定檔案的路徑,使用classpath:表示檔案的位置
        -->
       <property name="configLocation" value="classpath:conf/mybatis.xml"/>
   </bean>

   <!--
   聲明mybatis的掃描器,建立dao對象
   使用SqlSession的getMapper(StudentDao.class)
   MapperScannerConfigurer:在内部調用getMapper()生成每個dao接口的代理對象
   -->
   <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
       <!-- 指定SqlSession對象的id -->
       <property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean"/>
       <!--
       指定包名,包名是dao接口所在的包
       MapperScannerConfigurer會掃描這個包中的所有接口,把每個接口都執行一次getMapper()方法,
       得到每個接口的dao對象。
       建立好的dao對象放入到spring的容器中
        -->
       <property name="basePackage" value="com.zhang.dao"/>
   </bean>

   <!--聲明service的注解@service所在包的位置-->
<context:component-scan base-package="com.zhang.service"/>
       </beans>
           

SpringMVC容器: 在web.xml聲明了中央排程器DispatcherServlet。 在這個servlet的init()方法中, 建立了容器對象 WebApplicationContext, 在建立WebApplicationContext對象,讀取springmvc的配置檔案, 讀取檔案的時候,遇到@Controller注解,建立控制器controller對象,放到容器中。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
">

    <!--springmvc的配置檔案,聲明controller-->
    <!--springmvc的配置-->
    <!--掃描所有元件-->
    <context:component-scan base-package="com.zhang.controller"/>

    <!--聲明視圖解析器:幫助處理視圖-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--字首:指定視圖檔案的路徑-->
        <property name="prefix" value="/WEB-INF/view/"/>
        <!--字尾:視圖檔案的擴充名-->
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--注解驅動
        1.相應ajax請求
        2.解決靜态資源通路問題
    -->
    <mvc:annotation-driven/>

</beans>
           

記憶體中, 建立對象

WebApplicationContext spring = new WebApplicationContext();

//spring–map(service, dao)

WebApplicationContext springmvc = new WebApplicationContext(); //springmvc–map(controller)

SpringMVC容器和Spring容器的關系: 設計上SpringMVC容器對象是 Spring容器的子容器。

Spring是父容器。 SpringMVC子容器。 相當于java中的繼承關系。

SpringMVC學習筆記SpringMVC學習筆記SpringMVC概述SpringMVC 注解式開發SSM 整合開發SpringMVC 核心技術

SSM整合開發步驟

1.使用的student表(id,name,age)

2.建立maven web項目

3.修改pom.xml加入依賴: spring ,springmvc,mybatis, mybatis-spring, mysql驅動,druid, jackson

4.寫web.xml : 聲明容器對象

  1. 聲明spring的監聽器ContextLoaderListener: 建立spring的容器對象, 建立service ,dao對象
  2. 聲明springmvc的中央排程器DispatherServlet : 建立springmvc容器對象, 建立controller對象
  3. 聲明字元集的過濾器 CharacterEncodingFilter , 解決post請求亂碼的問題

5.建立程式中的包, dao ,service, controller, entity

6.寫spring,springmvc, mybatis配置檔案

7.寫java代碼, 實體類, dao接口和mapper檔案, service類,controller類。 使用注解聲明對象和指派

8.建立視圖檔案, 各種jsp

相對路徑

在頁面中,有路徑的問題, 通路路徑有 "/"開頭的, 還有沒有 “/”。

位址的差別,現在看的都是在頁面中的位址。

  1. 有協定開頭的例如http://www.baidu.com , 稱為絕對位址。 位址是唯一的,你能夠直接通路
  2. 沒有協定開頭的,例如 test/some.do , /test/some.do 稱為相對位址。 相對位址單獨使用不能表示某個資源,不能通路。 相對位址必須有參考位址在一起,才能表示一個資源的完整位址,才能通路。

參考位址: 有“ /" 和沒有”/“ 參考位址不同的。

1)沒有斜杠開頭的位址, 參考位址:目前資源的通路路徑

​ 目前通路的位址: http://localhost:8080/ch07_path/index.jsp

​ 資源名稱: index.jsp

​ 資源路徑: http://localhost:8080/ch07_path

​ 在index.jsp 有 通路位址 a href=“test/some.do”

​ 點選some.do後, 位址變成 http://localhost:8080/ch07_path/test/some.do

此時:http://localhost:8080/ch07path/test/some.do 
資源名稱:some.do 
資源路徑:http://localhost:8080/ch07path/test/
點選 test/some.do 位址:
//出現問題了
http://localhost:8080/ch07_path/test/test/some.do
           

解決方式:

1)使用${pageContext.request.contextPath}。 
表示通路項目的路徑(上下檔案 context path) 
發起請求test/some.do
優點:好了解 缺點:每個連結位址,都需要加el表達式
2)固定目前頁面中的 沒有“/”開頭位址的 
參考位址 
使用html中base标簽 
	<% String basePath = request.getScheme() + 
	"://" + request.getServerName()+
	":"+request.getServerPort()+
	request.getContextPath()+"/"; %>

           

2)有斜杠開頭的位址

a href="/test/some.do" target="_blank" rel="external nofollow"

現在通路的的 http://localhost:8080/ch07_path/index.jsp 
在index.jsp中有 /test/some.do. 點選/test/some.do,
位址變成 http://localhost:8080/test/some.do
有斜杠開頭的位址,
參考位址是伺服器位址, 也就是從協定開始到端口号的位置 http://localhost:8080
位址組成:http://localhost:8080/test/some.do
位址缺少項目通路路徑, ch07_path.
           

解決問題的方式:在你的路徑前面加入 el表達式 ${pageContext.request.contextPath}

有/開頭的位址
/test/some.do
           

SpringMVC 核心技術

轉發和重定向

forward:視圖完整路徑

redirect:視圖完整路徑

轉發和重定向不使用視圖解析器。

重定向不可以通路WEB-INF下的資源檔案。

mv.setViewName("forward:/hello.jsp"); 
mv.setViewName("redirect:/other.jsp");
           

異常處理

架構使用的是集中的異常處理。 把各個Controller中抛出的異常集中到一個地方處理。 處理異常的叫做異常處理器。

架構中使用兩個注解完成異常的集中處理。 這樣每個controller不用單獨處理異常了。注解是:

1)@ExceptionHandler : 放在方法的上面,表示此方法可以處理某個類型的異常。 當異常發生時,執行這個方法。

2) @ControllerAdvice: 放在類的上面, 表示這個類中有異常的處理方法。 相當于aop中的@Aspect.

​ @ControllerAdvice看做是 控制器增強, 就是給Controller類增加異常(切面)的處理功能.

攔截器

攔截器:是springmvc架構中的一種對象, 需要實作接口HandlerInterceptor. 攔截使用者的請求。 攔截到controller的請求。

作用:攔截使用者的請求, 可以預先對請求做處理。 根據處理結果, 決定是否執行controller 。 也可以把多個controller中共用的功能定義到攔截器。

特點:

攔截器可以分為系統攔截器和自定義攔截器。

一個項目可以多個攔截器。0,或多個自定義攔截器。

攔截器側重攔截使用者的請求。

攔截器是在請求處理之前先執行的。

攔截器的定義:

1)建立類實作攔截器接口HandlerInterceptor,實作接口中的方法(3個)

2)在springmvc配置檔案中,聲明攔截器對象,并指定攔截的uri位址

第一個攔截器

public class MyInterceptor implements HandlerInterceptor { 
/** 
* preHandle: 預先處理請求的方法。 
* 參數: 
*  Object handler : 被攔截的控制器對象(MyController) 
*  傳回值: boolean 
* true: 請求是正确的,可以被controller處理的。 
*  =====MyInterceptor攔截器的preHandle====
*  執行了MyController的doSome方法 
* =====MyInterceptor攔截器的postHandle====
*  =====MyInterceptor攔截器的afterCompletion==== 
*  false: 請求不能被處理, 控制器方法不會執行。 請求到此截止。
*  =====MyInterceptor攔截器的preHandle==== 
*  特點: 
* 1. 預處理方法他的執行時間: 在控制器方法之前先執行的。 
* 2. 可以對請求做處理, 可以做登入的檢查, 權限的判斷, 統計資料等等。
* 3. 決定請求是否執行。 
* */ 
@Override 
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
	System.out.println("=====MyInterceptor攔截器的preHandle====");
 	return true; 
 }
/**
 * postHandle: 後處理方法
 * 參數:
 *  Object handler : 被攔截的控制器對象(MyController)
 *  ModelAndView mv: 控制器方法的傳回值(請求的執行結果)
 *
 * 特點:
 *  1. 在控制器方法之後執行的。
 *  2. 能擷取到控制器方法的執行結果。 可以修改原來的執行結果。
 *     可以修改資料, 也可以修改視圖
 *  3. 可以做對請求的二次處理。
 */
@Override
public void postHandle(HttpServletRequest request,
                       HttpServletResponse response,
                       Object handler,
                       ModelAndView mv) throws Exception {
    System.out.println("=====MyInterceptor攔截器的postHandle====");
}




/**
 * afterCompletion: 最後執行的方法
 * 參數:
 *   Object handler : 被攔截的控制器對象(MyController)
 *   Exception ex: 異常對象
 *
 * 特點:
 *  1. 在請求處理完成後執行的,
 *     請求處理完成的标志是 視圖處理完成,對視圖執行forward操作後。
 *
 *  2. 可以做程式最後要做的工作, 釋放記憶體, 清理臨時變量。
 *
 *  3. 方法的執行條件:
 *     1)目前的攔截器他的preHandle()方法必須執行。
 *     2)preHandle()必須傳回true。
 */
@Override
public void afterCompletion(HttpServletRequest request,
                            HttpServletResponse response,
                            Object handler,
                            Exception ex) throws Exception {
    System.out.println("=====MyInterceptor攔截器的afterCompletion====");
}
           

配置檔案

<mvc:interceptors>
 	<mvc:interceptor> 
		<mvc:mapping path="/**"/> 
	</mvc:interceptor>
</mvc:interceptors>
           

多個攔截器

為什麼要使用多個攔截器 ?

把驗證功能分散到獨立的攔截器。 每個攔截器做單一的驗證處理。

組合多個攔截器。

總結:

多個攔截器, 串在一個鍊條上的。 多個攔截器和一個控制器對象在一個鍊條上 ,架構中使用HandlerExecutionChain(處理器執行鍊),表示這個執行鍊條

攔截器和過濾器的對比

1)攔截器是springmvc架構中的對象。 過濾器是servlet中的對象。

2)攔截器對象是架構容器建立的, 過濾器對象是tomcat建立的對象。

3) 攔截器是側重對請求做判斷的,處理的, 可以截斷請求。 過濾器是側重對request,response對象的屬性,參數設定值的。 例如request.setCharacterEncoding(“utf-8”)

4) 攔截器的他執行時間有三個, 控制器方法之前, 之後, 請求完成後。 過濾器是在請求之前。

5)攔截器是攔截對controller,動态資源請求的 。 過濾器可以過濾所有請求動态的和靜态的。

6)攔截器和過濾器一起執行的, 先執行的過濾器,後面是 中央排程器 , 後面才是攔截器, 再後面是控制器方法