Spring MVC要點1

Spring MVC要點 1

Spring MVC執行過程 及原理分析

在這裏插入圖片描述
1、服務器啓動,應用被加載。讀取到 web.xml 中的配置創建 spring 容器並且初始化容器中的對象。
從入門案例中可以看到的是:HelloController 和 InternalResourceViewResolver,但是遠不止這些。
2、瀏覽器發送請求,被 DispatherServlet 捕獲,該 Servlet 並不處理請求,而是把請求轉發出去。轉發
的路徑是根據請求 URL,匹配@RequestMapping 中的內容。
3、匹配到了後,執行對應方法。該方法有一個返回值。
4、根據方法的返回值,藉助 InternalResourceViewResolver 找到對應的結果視圖。
5、渲染結果視圖,響應瀏覽器。

SpringMVC 的 的 請求響應流程

在這裏插入圖片描述
DispatcherServlet :前端控制器
用戶請求到達前端控制器,它就相當於 mvc 模式中的 c,dispatcherServlet 是整個流程控制的中心,由
它調用其它組件處理用戶的請求,dispatcherServlet 的存在降低了組件之間的耦合性。

HandlerMapping :處理器映射器
HandlerMapping 負責根據用戶請求找到 Handler 即處理器,SpringMVC 提供了不同的映射器實現不同的
映射方式,例如:配置文件方式,實現接口方式,註解方式等。

Handler :處理器
它就是我們開發中要編寫的具體業務控制器。由 DispatcherServlet 把用戶請求轉發到 Handler。由
Handler 對具體的用戶請求進行處理。

HandlAdapter: 處理器適配器
通過 HandlerAdapter 對處理器進行執行,這是適配器模式的應用,通過擴展適配器可以對更多類型的處理
器進行執行。
在這裏插入圖片描述
View Resolver :視圖解析器
View Resolver 負責將處理結果生成 View 視圖,View Resolver 首先根據邏輯視圖名解析成物理視圖名
即具體的頁面地址,再生成 View 視圖對象,最後對 View 進行渲染將處理結果通過頁面展示給用戶。

View :視圖
SpringMVC 框架提供了很多的 View 視圖類型的支持,包括:jstlView、freemarkerView、pdfView
等。我們最常用的視圖就是 jsp。
一般情況下需要通過頁面標籤或頁面模版技術將模型數據通過頁面展示給用戶,需要由程序員根據業務需求開發具體的頁面。

< mvc:annotation-driven> 說明
在 SpringMVC 的各個組件中,處理器映射器、處理器適配器、視圖解析器稱爲 SpringMVC 的三大組件。
使 用 < mvc:annotation-driven> 自 動加載 RequestMappingHandlerMapping (處理映射器) 和
RequestMappingHandlerAdapter ( 處 理 適 配 器 ) , 可 用 在 SpringMVC.xml 配 置 文 件 中 使 用
< mvc:annotation-driven>替代註解處理器和適配器的配置。
它就相當於在 xml 中配置了:

<!-- 上面的標籤相當於 如下配置-->
<!-- Begin -->
<!-- HandlerMapping -->
<bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerM
apping"></bean>
<bean
class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
<!-- HandlerAdapter -->
<bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerA
dapter"></bean>
<bean
class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"></bean>
<bean
class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
<!-- HadnlerExceptionResolvers -->
<bean
class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExcept
ionResolver"></bean>
<bean
class="org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolv
er"></bean>
<bean
class="org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver"
></bean>
<!-- End -->
注意:
一般開發中,我們都需要寫上此標籤(雖然從入門案例中看,我們不寫也行,隨着課程的深入,該標籤還
有具體的使用場景)。
明確:
我們只需要編寫處理具體業務的控制器以及視圖。

RequestMapping 註解

源碼:
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
}
作用:
用於建立請求 URL 和處理請求方法之間的對應關係。
出現 位置:
類上:
請求 URL 的第一級訪問目錄。此處不寫的話,就相當於應用的根目錄。寫的話需要以/開頭。
它出現的目的是爲了使我們的 URL 可以按照模塊化管理:
例如:
賬戶模塊:
/account/add
/account/update
/account/delete
...
訂單模塊:
/order/add
/order/update
/order/delete
紅色的部分就是把 RequsetMappding 寫在類上,使我們的 URL 更加精細。
方法上:
請求 URL 的第二級訪問目錄。
屬性:
value:用於指定請求的 URL。它和 path 屬性的作用是一樣的。
method:用於指定請求的方式。
params:用於指定限制請求參數的條件。它支持簡單的表達式。要求請求參數的 key 和 value 必須和
配置的一模一樣。
例如:
params = {"accountName"},表示請求參數必須有 accountName
params = {"moeny!100"},表示請求參數中 money 不能是 100。
headers:用於指定限制請求消息頭的條件。
注意:
以上四個屬性只要出現 2 個或以上時,他們的關係是與的關係。

出現位置的示例:

@Controller("accountController")
@RequestMapping("/account")
public class AccountController {
@RequestMapping("/findAccount")
public String findAccount() {
System.out.println("查詢了賬戶。。。。");
return "success";
}
}
<!-- 第一種訪問方式 -->
<a href="${pageContext.request.contextPath}/account/findAccount">

method 屬性的示例:

@RequestMapping(value="/saveAccount",method=RequestMethod.POST)
public String saveAccount() {
System.out.println("保存了賬戶");
return "success";
}

params 屬性的示例:

@RequestMapping(value="/removeAccount",params= {"accountName","money>100"})
public String removeAccount() {
System.out.println("刪除了賬戶");
return "success";
}
jsp 中的代碼:
<!-- 請求參數的示例 -->
<a href="account/removeAccount?accountName=aaa&money>100">刪除賬戶,金額 100</a>
<br/>
<a href="account/removeAccount?accountName=aaa&money>150">刪除賬戶,金額 150</a>
注意:
當我們點擊第一個超鏈接時,可以訪問成功。
當我們點擊第二個超鏈接時,無法訪問。

請求參數的

支持的數據類型:
基本類型參數 :
包括基本類型和 String 類型
POJO 類型參數 :
包括實體類,以及關聯的實體類
數組和集合類型參數 :
包括 List 結構和 Map 結構的集合(包括數組)
SpringMVC 綁定請求參數是自動實現的,但是要想使用,必須遵循使用要求。

使用要 求:

如果是基本類型或者 String 類型:
要求我們的參數名稱必須和控制器中方法的形參名稱保持一致。(嚴格區分大小寫)
是 如果是 POJO 類型 ,或者 它的關聯對象 :
要求表單中參數名稱和 POJO 類的屬性名稱保持一致。並且控制器方法的參數類型是 POJO 類型。
如果是集合類型, 有兩種方式 :
第一種:
要求集合類型的請求參數必須在 POJO 中。在表單中請求參數名稱要和 POJO 中集合屬性名稱相同。
給 List 集合中的元素賦值,使用下標。
給 Map 集合中的元素賦值,使用鍵值對。
第二種:
接收的請求參數是 json 格式數據。需要藉助一個註解實現。
注意:
它還可以實現一些數據類型自動轉換。內置轉換器全都在:
org.springframework.core.convert.support 包下。

POST請求參數亂碼問題

post 請求方式:

在 web.xml 中配置一個過濾器
<!-- 配置 springMVC 編碼過濾器 -->
<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>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<!-- 過濾所有請求 -->
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

在 springmvc 的配置文件中可以配置,靜態資源不過濾:

<!-- location 表示路徑,mapping 表示文件,**表示該目錄下的文件以及子目錄的文件 -->
<mvc:resources location="/css/" mapping="/css/**"/>
<mvc:resources location="/images/" mapping="/images/**"/>
<mvc:resources location="/scripts/" mapping="/javascript/**"/>

get 請求方式:

tomacat 對 GETPOST 請求處理方式是不同的,GET請求的編碼問題,要改 tomcat 的 server.xml
配置文件,如下:
<Connector connectionTimeout="20000" port="8080"
protocol="HTTP/1.1" redirectPort="8443"/>
改爲:
<Connector connectionTimeout="20000" port="8080"
protocol="HTTP/1.1" redirectPort="8443"
useBodyEncodingForURI="true"/>
如果遇到 ajax 請求仍然亂碼,請把:
useBodyEncodingForURI="true"改爲 URIEncoding="UTF-8"
即可。

自定義類型轉換器

@RequestMapping("/deleteAccount")
public String deleteAccount(String date) {
System.out.println("刪除了賬戶。。。。"+date);
return "success";
}

使用步驟
第一步:定義一個類,實現 Converter 接口,該接口有兩個泛型。

public interface Converter<S, T> {//S:表示接受的類型,T:表示目標類型
/**
* 實現類型轉換的方法
*/
@Nullable
T convert(S source);
}
public class StringToDateConverter implements Converter<String, Date> {
/**
* 用於把 String 類型轉成日期類型
*/
@Override
public Date convert(String source) {
DateFormat format = null;
try {
if(StringUtils.isEmpty(source)) {
throw new NullPointerException("請輸入要轉換的日期");
}
format = new SimpleDateFormat("yyyy-MM-dd");
Date date = format.parse(source);
return date;
} catch (Exception e) {
throw new RuntimeException("輸入日期有誤");
}
}
}

第二步:在 spring 配置文件中配置類型轉換器。
spring 配置類型轉換器的機制是,將自定義的轉換器註冊到類型轉換服務中去。

<!-- 配置類型轉換器工廠 -->
<bean id="converterService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<!-- 給工廠注入一個新的類型轉換器 -->
<property name="converters">
<array>
<!-- 配置自定義類型轉換器 -->
<bean class="com.itheima.web.converter.StringToDateConverter"></bean>
</array>
</property>
</bean>

第三步:在 annotation-driven 標籤中引用配置的類型轉換服務

<!-- 引用自定義類型轉換器 -->
<mvc:annotation-driven
conversion-service="converterService"></mvc:annotation-driven>

使用 ServletAPI 對象作爲方法參數

@RequestMapping("/testServletAPI")
public String testServletAPI(HttpServletRequest request,
HttpServletResponse response,
HttpSession session) {
System.out.println(request);
System.out.println(response);
System.out.println(session);
return "success";
}

常用註解

RequestParam
作用:
把請求中指定名稱的參數給控制器中的形參賦值。
屬性:
value:請求參數中的名稱。
required:請求參數中是否必須提供此參數。默認值:true。表示必須提供,如果不提供將報錯。
jsp 中的代碼:

<!-- requestParams 註解的使用 -->
<a href="springmvc/useRequestParam?name=test">requestParam 註解</a>

控制器中的代碼:

@RequestMapping("/useRequestParam")
public String useRequestParam(@RequestParam("name")String username,
@RequestParam(value="age",required=false)Integer age){
System.out.println(username+","+age);
return "success";
}

在這裏插入圖片描述
RequestBody
作用:
用於獲取請求體內容。直接使用得到是 key=value&key=value…結構的數據。
get 請求方式不適用。
屬性:
required:是否必須有請求體。默認值是:true。當取值爲 true 時,get 請求方式會報錯。如果取值
爲 false,get 請求得到是 null。
post 請求 jsp 代碼:

<form action="springmvc/useRequestBody" method="post">
用戶名稱:<input type="text" name="username" ><br/>
用戶密碼:<input type="password" name="password" ><br/>
用戶年齡:<input type="text" name="age" ><br/>
<input type="submit" value=" 保存 ">
</form>

get 請求 jsp 代碼:

<a href="springmvc/useRequestBody?body=test">requestBody 註解 get 請求</a>

控制器代碼:

@RequestMapping("/useRequestBody")
public String useRequestBody(@RequestBody(required=false) String body){
System.out.println(body);
return "success";
}

在這裏插入圖片描述
PathVaribale
作用:
用於綁定 url 中的佔位符。例如:請求 url 中 /delete/{id},這個{id}就是 url 佔位符。
url 支持佔位符是 spring3.0 之後加入的。是 springmvc 支持 rest 風格 URL 的一個重要標誌。
屬性:
value:用於指定 url 中佔位符名稱。
required:是否必須提供佔位符。
jsp 代碼:

<!-- PathVariable 註解 -->
<a href="springmvc/usePathVariable/100">pathVariable 註解</a>

控制器代碼:

/**
* PathVariable 註解
* @param user
* @return
*/
@RequestMapping("/usePathVariable/{id}")
public String usePathVariable(@PathVariable("id") Integer id){
System.out.println(id);
return "success";
}

在這裏插入圖片描述
RequestHeader
作用:
用於獲取請求消息頭。
屬性:
value:提供消息頭名稱
required:是否必須有此消息頭
注:
在實際開發中一般不怎麼用。
jsp 中代碼:

<a href="springmvc/useRequestHeader">獲取請求消息頭</a>

控制器中代 碼:

/**
* RequestHeader 註解
* @param user
* @return
*/
@RequestMapping("/useRequestHeader")
public String useRequestHeader(@RequestHeader(value="Accept-Language",
required=false)String requestHeader){
System.out.println(requestHeader);
return "success";
}

在這裏插入圖片描述
CookieValue
作用:
用於把指定 cookie 名稱的值傳入控制器方法參數。
屬性:
value:指定 cookie 的名稱。
required:是否必須有此 cookie。
jsp 中的代碼:

<a href="springmvc/useCookieValue">綁定 cookie 的值</a>

控制器中的代碼:

/**
* Cookie 註解註解
* @param user
* @return
*/
@RequestMapping("/useCookieValue")
public String useCookieValue(@CookieValue(value="JSESSIONID",required=false)
String cookieValue){
System.out.println(cookieValue);
return "success";
}

在這裏插入圖片描述
ModelAttribute
作用:
該註解是 SpringMVC4.3 版本以後新加入的。它可以用於修飾方法和參數。
出現在方法上,表示當前方法會在控制器的方法執行之前,先執行。它可以修飾沒有返回值的方法,也可
以修飾有具體返回值的方法。
出現在參數上,獲取指定的數據給參數賦值。
屬性:
value:用於獲取數據的 key。key 可以是 POJO 的屬性名稱,也可以是 map 結構的 key。
應用場景:
當表單提交數據不是完整的實體類數據時,保證沒有提交數據的字段使用數據庫對象原來的數據。
例如:
我們在編輯一個用戶時,用戶有一個創建信息字段,該字段的值是不允許被修改的。在提交表單數
據是肯定沒有此字段的內容,一旦更新會把該字段內容置爲 null,此時就可以使用此註解解決問題。

基於 POJO 屬性的基本使用
jps 代碼:

<a href="springmvc/testModelAttribute?username=test">測試 modelattribute</a>

控制器代碼:

/**
* 被 ModelAttribute 修飾的方法
* @param user
*/
@ModelAttribute
public void showModel(User user) {
System.out.println("執行了 showModel 方法"+user.getUsername());
}
/**
* 接收請求的方法
* @param user
* @return
*/
@RequestMapping("/testModelAttribute")
public String testModelAttribute(User user) {
System.out.println("執行了控制器的方法"+user.getUsername());
return "success";
}

在這裏插入圖片描述
基於 Map 的應用場景示例 1 :ModelAttribute 修飾方法帶返回值
需求:
修改用戶信息,要求用戶的密碼不能修改
jsp 的代碼:

<!-- 修改用戶信息 -->
<form action="springmvc/updateUser" method="post">
用戶名稱:<input type="text" name="username" ><br/>
用戶年齡:<input type="text" name="age" ><br/>
<input type="submit" value=" 保存 ">
</form>

控制的代碼:

/**
* 查詢數據庫中用戶信息
* @param user
*/
@ModelAttribute
public User showModel(String username) {
//模擬去數據庫查詢
User abc = findUserByName(username);
System.out.println("執行了 showModel 方法"+abc);
return abc;
}
/**
* 模擬修改用戶方法
* @param user
* @return
*/
@RequestMapping("/updateUser")
public String testModelAttribute(User user) {
System.out.println("控制器中處理請求的方法:修改用戶:"+user);
return "success";
}
/**
* 模擬去數據庫查詢
* @param username
* @return
*/
private User findUserByName(String username) {
User user = new User();
user.setUsername(username);
user.setAge(19);
user.setPassword("123456");
return user;
}

在這裏插入圖片描述
基於 Map 的應用場景示例 1 :ModelAttribute 修飾方法 不 帶返回值
需求:
修改用戶信息,要求用戶的密碼不能修改
jsp 中的代碼:

<!-- 修改用戶信息 -->
<form action="springmvc/updateUser" method="post">
用戶名稱:<input type="text" name="username" ><br/>
用戶年齡:<input type="text" name="age" ><br/>
<input type="submit" value=" 保存 ">
</form>

控制器中的代碼:

/**
* 查詢數據庫中用戶信息
* @param user
*/
@ModelAttribute
public void showModel(String username,Map<String,User> map) {
//模擬去數據庫查詢
User user = findUserByName(username);
System.out.println("執行了 showModel 方法"+user);
map.put("abc",user);
}
/**
* 模擬修改用戶方法
* @param user
* @return
*/
@RequestMapping("/updateUser")
public String testModelAttribute(@ModelAttribute("abc")User user) {
System.out.println("控制器中處理請求的方法:修改用戶:"+user);
return "success";
}
/**
* 模擬去數據庫查詢
* @param username
* @return
*/
private User findUserByName(String username) {
User user = new User();
user.setUsername(username);
user.setAge(19);
user.setPassword("123456");
return user;
}

在這裏插入圖片描述
SessionAttribute
作用:
用於多次執行控制器方法間的參數共享。
屬性:
value:用於指定存入的屬性名稱
type:用於指定存入的數據類型。
jsp 中的代碼 :

<!-- SessionAttribute 註解的使用 -->
<a href="springmvc/testPut">存入 SessionAttribute</a>
<hr/>
<a href="springmvc/testGet">取出 SessionAttribute</a>
<hr/>
<a href="springmvc/testClean">清除 SessionAttribute</a>

控制器中的代碼 :

@Controller("sessionAttributeController")
@RequestMapping("/springmvc")
@SessionAttributes(value ={"username","password"},types={Integer.class})
public class SessionAttributeController {
/**
* 把數據存入 SessionAttribute
* @param model
* @return
* Model 是 spring 提供的一個接口,該接口有一個實現類 ExtendedModelMap
* 該類繼承了 ModelMap,而 ModelMap 就是 LinkedHashMap 子類
*/
@RequestMapping("/testPut")
public String testPut(Model model){
model.addAttribute("username", "泰斯特");
model.addAttribute("password","123456");
model.addAttribute("age", 31);
//跳轉之前將數據保存到 username、password 和 age 中,因爲註解@SessionAttribute 中有
這幾個參數
return "success";
}
@RequestMapping("/testGet")
public String testGet(ModelMap model){
System.out.println(model.get("username")+";"+model.get("password")+";"+model.get("a
ge"));
return "success";
}
@RequestMapping("/testClean")
public String complete(SessionStatus sessionStatus){
sessionStatus.setComplete();
return "success";
}
}

在這裏插入圖片描述

響應數據和 結果視圖

1 字符串
2 void
3 ModelAndView

轉發和重定向

forward 轉發

return "forward:/WEB-INF/pages/success.jsp";

Redirect 重定向

return "redirect:testReturnModelAndView";

ResponseBody 響應 json 數據
該註解用於將 Controller 的方法返回的對象,通過 HttpMessageConverter 接口轉換爲指定格式的
數據如:json,xml 等,通過 Response 響應給客戶端

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章