1 入門程序
2 SpringMVC運行流程
3 注解
4 請求參數綁定
5 請求參數中文亂碼的解決
6 自定義類型轉換器
SpringMVC
WEB層框架,MVC框架
表現層:WEB層,用來和客戶端進行交互的。表現層一般會采用MVC的設計模型
基于 HTTP請求響應的方式。
在 SpringMVC 的各個組件中,處理器映射器、處理器適配器、視圖解析器稱為 SpringMVC 的三大組件。
2、運行流程
? 入門程序,環境搭建
? 1、新建 maven 工程,打包方式 war
? 2、pom.xml 導入依賴坐標
<!-- 版本鎖定 -->
<properties>
<spring.version>5.0.2.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
3、webapp---WEB-INF--web.xml 中配置前端控制器 DispatcherServlet
<servlet>
<servlet-name>自己命名(springmvc)</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<!--springmvc 配置文件所在的路徑-->
<param-value>classpath*:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>自己命名(springmvc)</servlet-name>
<url-parttern>/</url-parttern>
</servlet-mapping>
3、在resources里編寫 springmvc 的核心配置文件: springmvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 配置spring創建容器時要掃描的包 -->
<context:component-scan base-package="com.itheima"></context:component-scan>
<!-- 配置視圖解析器 -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 視圖所在的目錄 -->
<property name="prefix" value="/WEB-INF/pages/"></property>
<!-- 文件的后綴名是什么 -->
<property name="suffix" value=".jsp"></property>
</bean>
<!-- 配置spring開啟注解mvc的支持-->
<mvc:annotation-driven/>
</beans>
配置包掃描器、視圖解析器、<mvc:annotation-driven/>
配置了這句話就相當于 自動加載 RequestMappingHandlerMapping
(處理映射器)和RequestMappingHandlerAdapter
(處理適配器 )
<!-- 配置spring開啟注解mvc的支持-->
<mvc:annotation-driven/>
4、編寫 Controller (在類上 加 @Controller)
編寫 Handler 接收請求,給出響應
@Controller 類上
@RequestMapping 方法上,也可以在類上
@RequestMapping(value="請求的url",method=RequestMethod.請求方式)
public String sayHello(){
return "success";//邏輯視圖名
}
5、編寫JSP頁面
6、測試 tomcat 部署項目
SpringMVC運行流程
springMVC執行流程:
首先瀏覽器端發送一個request請求發送到前端控制器DispatcherServlet
,前端控制器了解這個請求應該由誰來處理,通過處理器映射器HandlerMapping
最終找到Controller,Controller了解這個業務的細節邏輯,就會調用業務邏輯產生業務數據,并將這個業務數據返回給前端控制器,此時前端控制將這些業務數據通過處理器適配器HandlerAdapter
返還給業務視圖,由業務視圖呈現頁面,再將這些頁面返還給前端控制器,前端控制器再把這些頁面通過視圖解析器ViewResolver
返回給瀏覽器端。
DispatcherServlet
:前端控制器
用戶請求第一步到達前端控制器,相當于mvc模式中的c,它是整個流程控制的中心,由它調用其他組件完成用戶的請求,它的存在降低了程序之間的耦合。
HandlerMapping
:處理器映射器
HandlerMapping負責根據用戶的請求找到處理器Handler
(就是編寫的具體業務處理請求的方法) ,springmvc提供了不同的映射方式 比如配置文件方式、實現接口方式、注解方式等。它返回的是一個執行鏈。
HandlerAdapter
:處理器適配器
適配能夠處理請求的 適配器(現在用的是注解,所以使用 RequestMappingHandlerAdapter)去執行 Handler。
ModelAndView
:視圖解析器
這個對象是 springmvc 提供的,負責將處理結果生成View視圖,View Resolver 首先根據邏輯視圖名解析成物理視圖名 即具體的頁面地址,再生成 View 視圖對象,最后對 View 進行渲染將處理結果通過頁面展示給用戶。
**View
:視圖 **
無論返回是 String、還是 void、還是 ModelAndView ,Springmvc 最終都會把它封裝成一個ModelAndView 對象。
InternalResourceViewResolver:視圖解析器可以把 邏輯視圖(字符串)變成物理視圖(JSP)。可以對邏輯視圖進行路徑拼接 因為視圖有很多種:JSP、HTML、PDF、World、Excel
注解
@RequestMapping
RequestMapping 用于簡歷請求URL和處理請求方法之間的對應關系。 可以標記在類和方法上,如果類和方法上都標記有該注解,則訪問時需要 /類注解url/方法注解url。
注意:該注解必不可少,其 value 值不能重復
舉例:
@Controller
@RequestMapping("/user")
public class UserController{
@RequestMapping("/save")
public String save(){
return null;
}
}
如上:映射請求的 URL 為 /user/save
屬性:
value:用于指定請求的 URL。它和 path 屬性的作用是一樣的。
method:用于指定請求的方式。
params:底層字符串,用于指定限制請求參數的條件。它支持簡單的表達式。要求請求參數的條件必須滿足在params上字符串的條件。
headers 發送的請求中必須包含的請求頭。
@RequestParam
說人話:修飾當前方法的參數
把請求中指定的名稱參數給控制器中的形參賦值。
屬性:
value:參數名稱
requried:指定該參數是否必須
defaultValue:指定默認值
代碼:
jsp 中的代碼:
<!-- requestParams 注解的使用 -->
<a href="springmvc/useRequestParam?name=test">requestParam 注解</a>
控制器中的代碼:
/**
* requestParams 注解的使用
*/
@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代碼:
<!-- request body 注解 -->
<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>
控制器代碼:
//RequestBody 注解
@RequestMapping("/useRequestBody")
public String useRequestBody(@RequestBody(required=false) String body){
System.out.println(body);
return "success";
}
?
PathVariable
作用: 用于綁定 url 中的占位符。例如:請求 url 中 /delete/{id},這個{id}就是 url 占位符。 url 支持占位符是 spring3.0 之后加入的。是 springmvc 支持 rest 風格 URL 的一個重要標志。它就是可以取到id里的值。
屬性: value:用于指定 url 中占位符名稱。 required:是否必須提供占位符。
代碼:
jsp 代碼:
<!-- PathVariable 注解 -->
<a href="springmvc/usePathVariable/100">pathVariable 注解</a>
控制器代碼: /**
* PathVariable 注解
*/
@RequestMapping("/usePathVariable/{id}")
public String usePathVariable(@PathVariable("id") Integer id){
System.out.println(id);
return "success";
}
restFule風格:例如同一個類當中會有增刪改查的方法,傳統的方式路徑會是:localhost:8080/路徑/所執行方法。而restfule風格則是:localhost:8080/路徑。至于執行哪個方法則是又方法訪問方式所決定 比如查詢用get、新增用post、更新用put等,到時候用的時候通過獲取請求方式來判斷到底執行路徑下的哪個方法。
查詢的方式有根據ID查詢和查詢全部,如果是這樣,單獨通過請求方式就無法判斷執行的是哪個方法了,所以這時候會在根據id查詢的方法路徑后面放一個{id},這樣就能區分了。
HiddenHttpMethodFilter(不重要)
作用:由于瀏覽器的form表單只支持GET和post請求,而DELETE/PUT等method不支持, 所以spring3.0添加了過濾器HiddenHttpMethodFilter
,它可以將瀏覽器請求改為指定的請求方式。
修改方法:
1 在web.xml 中配置 過濾器 HiddenHttpMethodFilter。
2 請求發過貨四必須用psot請求。
3 按照提供的method請求參數,該參數的值就是我們需要請求的方式。
tomcat8 不兼容 put 跟 delete 請求,需要更換成 tomcat7
在 restful 中,請求與方式相對應
GET:查詢
POST:新增
PUT:更新
DELETE:刪除
jsp 中示例代碼:
<!-- 保存 -->
<form action="springmvc/testRestPOST" method="post">
用戶名稱:<input type="text" name="username"><br/>
<!-- <input type="hidden" name="_method" value="POST"> -->
<input type="submit" value=" 保存 ">
</form>
<hr/>
<!-- 更新 -->
<form action="springmvc/testRestPUT/1" method="post">
用戶名稱:<input type="text" name="username"><br/>
<input type="hidden" name="_method" value="PUT">
<input type="submit" value=" 更新 ">
</form>
<hr/>
<!-- 刪除 -->
<form action="springmvc/testRestDELETE/1" method="post">
<input type="hidden" name="_method" value="DELETE">
<input type="submit" value=" 刪除 ">
</form>
<hr/>
<!-- 查詢一個 -->
<form action="springmvc/testRestGET/1" method="post">
<input type="hidden" name="_method" value="GET">
<input type="submit" value=" 查詢 ">
</form>
控制器中示例代碼:
/**
* post 請求:保存 .
*/
@RequestMapping(value="/testRestPOST",method=RequestMethod.POST)
public String testRestfulURLPOST(User user){
System.out.println("rest post"+user);
return "success";
}
/**
* put 請求:更新
*/
@RequestMapping(value="/testRestPUT/{id}",method=RequestMethod.PUT)
public String testRestfulURLPUT(@PathVariable("id")Integer id,User user){
System.out.println("rest put "+id+","+user);
return "success";
}
/**
* post 請求:刪除
*/ @RequestMapping(value="/testRestDELETE/{id}",method=RequestMethod.DELETE)
public String testRestfulURLDELETE(@PathVariable("id")Integer id){
System.out.println("rest delete "+id);
return "success";
}
/**
* post 請求:查詢
*/
@RequestMapping(value="/testRestGET/{id}",method=RequestMethod.GET)
public String testRestfulURLGET(@PathVariable("id")Integer id){
System.out.println("rest get "+id);
return "success";
}
RequestHeader
作用: 用于獲取請求消息頭。
屬性: value:提供消息頭名稱
required:是否必須有此消息頭
注: 在實際開發中一般不怎么用。
CookieValue
作用: 用于把指定 cookie 名稱的值傳入控制器方法參數。
屬性: value:指定 cookie 的名稱。
required:是否必須有此 cookie。
注: 在實際開發中一般不怎么用。
ModelAttribute
作用:出現在方法上,表示當前方法會在控制器的方法執行之前,先執行。它可以修飾沒有返回值的方法,也可 以修飾有具體返回值的方法。 出現在參數上,獲取指定的數據給參數賦值。
屬性: value:用于獲取數據的 key。key 可以是 POJO 的屬性名稱,也可以是 map 結構的 key。
應用場景: 當表單提交數據不是完整的實體類數據時,保證沒有提交數據的字段使用數據庫對象原來的數據。
我們在編輯一個用戶時,用戶有一個創建信息字段,該字段的值是不允許被修改的。在提交表單數據是肯定沒有此字段的內容,一旦更新會把該字段內容置為 null,此時就可以使用此注解解決問題。
基于 POJO 屬性的基本使用:
jps 代碼:
<!-- ModelAttribute 注解的基本使用 -->
<a href="springmvc/testModelAttribute?username=test">測試 modelattribute</a>
控制器代碼:
/**
* 被 ModelAttribute 修飾的方法
*/
@ModelAttribute
public void showModel(User user) {
System.out.println("執行了 showModel 方法"+user.getUsername());
}
/**
* 接收請求的方法
*/
@RequestMapping("/testModelAttribute")
public String testModelAttribute(User user) {
System.out.println("執行了控制器的方法"+user.getUsername());
return "success";
}
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>
控制器中的代碼:
/**
* SessionAttribute 注解的使用
*/
@Controller("sessionAttributeController")
@RequestMapping("/springmvc")
@SessionAttributes(value ={"username","password"},types={Integer.class})
public class SessionAttributeController {
/**
* 把數據存入 SessionAttribute
* 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 綁定機制:表單提交的數據都是k=v格式的 username=haha&password=123
2 SpringMVC的參數綁定過程是把表單提交的請求參數,作為控制器中方法的參數進行綁定的。
3 要求:提交表單的name和參數的名稱是相同的 。
支持的數據類型:
1 基本數據類型和字符串類型
2 實體類型(JavaBean)
3 集合數據類型(List、map集合等)
基本數據類型和字符串類型
1 提交表單的name和參數的名稱是相同的
2 區分大小寫
實體類型(JavaBean)
1 提交表單的name和JavaBean中的屬性名稱需要一致
2 如果一個JavaBean類中包含其他的引用類型,那么表單的name屬性需要編寫成:對象.屬性 例如: address.name
給集合屬性數據封裝
JSP頁面編寫方式:list[0].屬性 。
支持的數據類型:
基本類型參數: 包括基本類型和 String 類型
POJO 類型參數: 包括實體類,以及關聯的實體類
數組和集合類型參數: 包括 List 結構和 Map 結構的集合(包括數組)
SpringMVC 綁定請求參數是自動實現的,但是要想使用,必須遵循使用要求。
基本類型和 String 類型作為參數 :
jsp 代碼:
<!-- 基本類型示例 -->
<a href="account/findAccount?accountId=10&accountName=zhangsan">查詢賬戶</a>
控制器代碼:
/**
* 查詢賬戶
* @return
*/
@RequestMapping("/findAccount")
public String findAccount(Integer accountId,String accountName) {
System.out.println("查詢了賬戶。。。。"+accountId+","+accountName);
return "success";
}
POJO 類型作為參數
實體類代碼:
/**
* 賬戶信息
*/
public class Account implements Serializable {
private Integer id;
private String name;
private Float money;
private Address address;
//此處省略getters and setters
}
/**
* 地址的實體類
*/
public class Address implements Serializable {
private String provinceName;
private String cityName;
//此處省略getters and setters
}
jsp 代碼:
<!-- pojo 類型演示 -->
<form action="account/saveAccount" method="post">
賬戶名稱:<input type="text" name="name" ><br/>
賬戶金額:<input type="text" name="money" ><br/>
賬戶省份:<input type="text" name="address.provinceName" ><br/>
賬戶城市:<input type="text" name="address.cityName" ><br/>
<input type="submit" value=" 保存 "> </form>
控制器代碼:
/**
* 保存賬戶
*/
@RequestMapping("/saveAccount")
public String saveAccount(Account account) {
System.out.println("保存了賬戶。。。。"+account);
return "success";
}
POJO 類中包含集合類型參數
實體類代碼:
/**
* 用戶實體類
*/
public class User implements Serializable {
private String username;
private String password;
private Integer age;
private List<Account> accounts;
private Map<String,Account> accountMap;
//此處省略getters and setters
@Override
public String toString() {
return "User [username=" + username + ", password=" + password + ", age=" + age + ",\n accounts=" + accounts
+ ",\n accountMap=" + accountMap + "]";
}
}
jsp 代碼:
<!-- POJO 類包含集合類型演示 -->
<form action="account/updateAccount" method="post">
用戶名稱:<input type="text" name="username" ><br/>
用戶密碼:<input type="password" name="password" ><br/>
用戶年齡:<input type="text" name="age" ><br/>
賬戶 1 名稱:<input type="text" name="accounts[0].name" ><br/>
賬戶 1 金額:<input type="text" name="accounts[0].money" ><br/>
賬戶 2 名稱:<input type="text" name="accounts[1].name" ><br/>
賬戶 2 金額:<input type="text" name="accounts[1].money" ><br/>
賬戶 3 名稱:<input type="text" name="accountMap['one'].name" ><br/>
賬戶 3 金額:<input type="text" name="accountMap['one'].money" ><br/>
賬戶 4 名稱:<input type="text" name="accountMap['two'].name" ><br/>
賬戶 4 金額:<input type="text" name="accountMap['two'].money" ><br/>
<input type="submit" value=" 保存 "> </form>
控制器代碼:
/**
* 更新賬戶
*/
@RequestMapping("/updateAccount")
public String updateAccount(User user) {
System.out.println("更新了賬戶。。。。"+user);
return "success";
}
請求參數中文亂碼的解決
- 在web.xml中配置Spring提供的過濾器類
<!-- 配置過濾器,解決中文亂碼的問題 -->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filterclass>
<!-- 指定字符集 -->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
自定義類型轉換器
表單提交的任何數據類型全部都是字符串類型,但是后臺定義Integer類型,數據也可以封裝上,說明 Spring框架內部會默認進行數據類型轉換。
如果想自定義數據類型轉換,可以實現Converter的接口。
自定義類型轉換器
package cn.itcast.utils;
import java.text.DateFormat; import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.core.convert.converter.Converter;
/**
* 把字符串轉換成日期的轉換器
*/
public class StringToDateConverter implements Converter<String, Date>{
/**
* 進行類型轉換的方法
* String:傳進來的字符串
*/
public Date convert(String source) {
// 判斷
if(source == null) {
//運行時異常
throw new RuntimeException("參數不能為空");
}
try {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
// 解析字符串
Date date = df.parse(source);
return date;
} catch (Exception e) {
throw new RuntimeException("類型轉換錯誤");
}
}
}
注冊自定義類型轉換器,在springmvc.xml配置文件中編寫配置
<!-- 注冊自定義類型轉換器 -->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="cn.itcast.utils.StringToDateConverter"/>
</set>
</property>
</bean>
<!-- 開啟Spring對MVC注解的支持 -->
<mvc:annotation-driven conversion-service="conversionService"/>
在控制器中使用原生的ServletAPI對象
只需要在控制器的方法參數定義HttpServletRequest和HttpServletResponse對象