一、@RequestMapping
通過 RequestMapping 注解可以定義不同的處理器映射規(guī)則。
二、 url 映射
定義 controller 方法對應(yīng)的 url,進行處理器映射使用。
@RequestMapping(value="/user")或@RequestMapping("/user)
value 的值是數(shù)組,可以將多個 url 映射到同一個方法
- 窄化請求映射
在 class 上添加@RequestMapping(url)指定通用請求前綴,限制此類下的所有方法請求 url 必
須以請求前綴開頭,通過此方法對 url 進行分類管理。
如下:
// 放在類名上邊,設(shè)置請求前綴
@RequestMapping
@Controller
@RequestMapping("/user")
方法名上邊設(shè)置請求映射 url:
@RequestMapping 放在方法名上邊,如下:
@RequestMapping("/list")
訪問地址為:/user/list
- 請求方法限定
◆ 限定 GET 方法
@RequestMapping(method = RequestMethod.GET)
如果通過 Post 訪問則報錯:
HTTP Status 405 - Request method 'POST' not supported
例如:
@RequestMapping(value="/user",method=RequestMethod.GET)
◆ 限定 POST 方法
@RequestMapping(method = RequestMethod.POST)
如果通過 GET 訪問則報錯:
HTTP Status 405 - Request method 'GET' not supported
◆ GET 和 POST 都可以
@RequestMapping(method={RequestMethod.GET,RequestMethod.POST})
三、 controller 方法的返回值
- 返回 ModelAndView
controller 方法中定義 ModelAndView 對象并返回,對象中可添加 model 數(shù)據(jù)、指定view。 - 返回 void
在 controller 方法形參上可以定義 request 和 response,使用 request 或 response 指定響應(yīng)結(jié)果:
A. 使用 request 轉(zhuǎn)向頁面,如下:
request.getRequestDispatcher("頁面路徑").forward(request, response);
B. 也可以通過 response 頁面重定向:
response.sendRedirect("url")
C. 也可以通過 response 指定響應(yīng)結(jié)果,例如響應(yīng) json 數(shù)據(jù)如下:
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("json 串");
- 返回字符串
A. 邏輯視圖名
controller 方法返回字符串可以指定邏輯視圖名,通過視圖解析器解析為物理視圖地址。
//指定邏輯視圖名,經(jīng)過視圖解析器解析為jsp物理路徑:
/WEBINF/views/user/list.jsp
return "user/list";
B. Redirect 重定向
Contrller 方法返回結(jié)果重定向到一個 url 地址,如下商品修改提交后重定向到商品查詢方法,參數(shù)無法帶到商品查詢方法中。
// 重定向到 list 地址,request 無法帶過去
return "redirect:list";
redirect 方式相當(dāng)于“response.sendRedirect()”,轉(zhuǎn)發(fā)后瀏覽器的地址欄變?yōu)檗D(zhuǎn)發(fā)后的地址,因為轉(zhuǎn)發(fā)即執(zhí)行了一個新的 request 和 response。
由于新發(fā)起一個 request 原來的參數(shù)在轉(zhuǎn)發(fā)時就不能傳遞到下一個 url,如果要傳參數(shù)可以/user/list 后邊加參數(shù),如下:
/user/list?...&…..
C. forward 轉(zhuǎn)發(fā)
controller 方法執(zhí)行后繼續(xù)執(zhí)行另一個 controller 方法。
// 結(jié)果轉(zhuǎn)發(fā)到 list,request 可以帶過去
return "forward:list";
forward 方式相當(dāng)于
“request.getRequestDispatcher().forward(request,response)”
轉(zhuǎn)發(fā)后瀏覽器地址欄還是原來的地址。轉(zhuǎn)發(fā)并沒有執(zhí)行新的 request 和 response,而是和轉(zhuǎn)發(fā)前的請求共用一個 request 和 response。所以轉(zhuǎn)發(fā)前請求的參數(shù)在轉(zhuǎn)發(fā)后仍然可以讀取到。
四、參數(shù)綁定
處理器適配器在執(zhí)行 Handler 之前需要把 http 請求的 key/value 數(shù)據(jù)綁定到 Handler 方法形參數(shù)上。
spring 參數(shù)綁定過程
- 默認支持的類型
直接在 controller 方法形參上定義下邊類型的對象,就可以使用這些對象。在參數(shù)綁定過程中,如果遇到下邊類型直接進行綁定。
A. HttpServletRequest
通過 request 對象獲取請求信息
B. HttpServletResponse
通過 response 處理響應(yīng)信息
C. HttpSession
通過 session 對象得到 session 中存放的對象
D. Model/ModelMap
? 控制器類:
@RequestMapping("/testUser")
public String testUser(Model model,ModelMap map){
model.addAttribute("user", "張三");
map.addAttribute("date", new Date());
return "userShow";
}
? 頁面顯示:
<body>
${user }
${date }
</body>
ModelMap 是 Model 接口的實現(xiàn)類,通過 Model 或 ModelMap 向頁面?zhèn)鬟f數(shù)據(jù),如下:
//調(diào)用 service 查詢商品信息
Items item = itemService.findItemById(id);
model.addAttribute("item", item);
頁面通過${item.XXXX}獲取 item 對象的屬性值。
使用 Model 和 ModelMap 的效果一樣,如果直接使用 Model,springmvc 會實例化ModelMap。
注解適配器對 RequestMapping 標(biāo)記的方法進行適配,對方法中的形參會進行參數(shù)綁定,早期 springmvc 采用 PropertyEditor(屬性編輯器)進行參數(shù)綁定將 request 請求的參數(shù)綁定到方法形參上,3.X 之后 springmvc 就開始使用 Converter 進行參數(shù)綁定。
- 簡單類型
當(dāng)請求的參數(shù)名稱和處理器形參名稱一致時會將請求參數(shù)與形參進行綁定。
A. 整型
public String editItem(Model model,Integer id) throws Exception{
}
B. 字符串
public String editItem(Model model,String id) throws Exception{
}
C. 單精度/雙精度
public String editItem(Model model,Float id) throws Exception{
}
D. 布爾型
public String editItem(Model model,Boolean id) throws Exception{
}
處理器方法:
public String editItem(Model model,Integer id,Boolean status) throws Exception
請求 url:
http://localhost:8080/springmvc_mybatis/item/editItem.action?id=2&status=false
說明:對于布爾類型的參數(shù),請求的參數(shù)值為 true 或 false。
E. 使用@RequestParam 常用于處理簡單類型的綁定。
value:參數(shù)名字,即入?yún)⒌恼埱髤?shù)名字,如 value=“itemid”表示請求的參數(shù)區(qū)中的名字為 itemid 的參數(shù)的值將傳入;
required:是否必須,默認是 true,表示請求中一定要有相應(yīng)的參數(shù),否則將報;
TTP Status 400 - Required Integer parameter 'XXXX' is not present
defaultValue:默認值,表示如果請求中沒有同名參數(shù)時的默認值
定義如下:
public String editItem(@RequestParam(value="item_id",required=true) String id) {
}
形參名稱為 id,但是這里使用 value=" itemid"限定請求的參數(shù)名為 itemid,所以頁面?zhèn)鬟f參數(shù)的名必須為 itemid。
注意:如果請求參數(shù)中沒有 item_id 將跑出異常:
HTTP Status 500 - Required Integer parameter 'itemid' is not present
這里通過 required=true 限定 itemid 參數(shù)為必需傳遞,如果不傳遞則報 400 錯誤,可以使用 defaultvalue 設(shè)置默認值,即使 required=true 也可以不傳 itemid 參數(shù)值。
- pojo綁定
將pojo對象中的屬性名于傳遞進來的屬性名對應(yīng),如果傳進來的參數(shù)名稱和對象中的屬性名稱一致則將參數(shù)值設(shè)置在pojo對象中
A. 頁面定義如下;
<input type="text" name="name"/>
<input type="text" name="price"/>
B. Contrller方法定義如下:
@RequestMapping("/editItemSubmit")
public String editItemSubmit(Items items)throws Exception{
System.out.println(items);
}
請求的參數(shù)名稱和pojo的屬性名稱一致,會自動將請求參數(shù)賦值給pojo的屬性。
- 包裝pojo
如果采用類似struts中對象.屬性的方式命名,需要將pojo對象作為一個包裝對象的屬性,action中以該包裝對象作為形參。
A. 包裝對象定義如下:
Public class QueryVo {
private Items items;
}
B. 頁面定義:
<input type="text" name="items.name" />
<input type="text" name="items.price" />
C. Controller方法定義如下:
public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{
System.out.println(queryVo.getItems());
}
- 自定義參數(shù)綁定
根據(jù)業(yè)務(wù)需求自定義日期格式進行參數(shù)綁定。
A. 自定義Converter
public class CustomDateConverter implements Converter<String, Date> {
@Override
public Date convert(String source) {
try {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return simpleDateFormat.parse(source);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
B. 配置方式1
<mvc:annotation-driven conversion-service="conversionService">
</mvc:annotation-driven>
<!-- conversionService -->
<bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<!-- 轉(zhuǎn)換器 -->
<property name="converters">
<list>
<bean class="com.neuedu.converter.CustomDateConverter" />
</list>
</property>
</bean>
C. 配置方式2
<!-- 注解映射器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<!--注解適配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="webBindingInitializer" ref="customBinder"></property>
</bean>
<!-- 自定義webBinder -->
<bean id="customBinder"
class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
<property name="conversionService" ref="conversionService"/>
</bean>
<!--注解適配器 -->
<bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<!-- 轉(zhuǎn)換器 -->
<property name="converters">
<list>
<bean class="com.neuedu.converter.CustomDateConverter"/>
</list>
</property>
</bean>
說明:
與配置方式1相同,只不過是手動加載映射器與適配器。
D. 實體類中加日期格式化注解
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date receiveAppTime;
使用注解,一定要去掉原有添加的自定義時間轉(zhuǎn)換器,否則兩個沖突。
E、頁面把日期類型轉(zhuǎn)換成字符串JSP:
如果是JSON格式,一定要加以下注解。
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
或
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<fmt:formatDate value="${job.jobtime }" pattern="yyyy-MM-dd HH:mm:ss"/>
雖然時間格式正確了,但早了8小時,因為,jackson在序列化時間時是按照國際標(biāo)準(zhǔn)時間GMT進行格式化的,而在國內(nèi)默認時區(qū)使用的是CST時區(qū),兩者相差8小時。
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
因為 @JsonFormat 注解不是 Spring 自帶的注解,所以使用該注解前需要添加 jackson 相關(guān)的依賴包。當(dāng)然,如果是 SpringBoot 項目就不需要自己手動添加依賴了,因為在 spring-boot-start-web 下已經(jīng)包含了 jackson 相關(guān)依賴。
<!--spring mvc-json依賴-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.9</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.9</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.9</version>
</dependency>
總結(jié):
注解@JsonFormat主要是后臺到前臺的時間格式的轉(zhuǎn)換
注解@DataFormAT主要是前后到后臺的時間格式的轉(zhuǎn)換
- 集合類
A. 字符串?dāng)?shù)組
頁面定義如下:
頁面選中多個checkbox向controller方法傳遞
<input type="checkbox" name="itemid" value="001"/>
<input type="checkbox" name=" itemid" value="002"/>
<input type="checkbox" name="itemid" value="002"/>
傳遞到controller方法中的格式是:001,002,003
Controller方法中可以用String[]接收,定義如下:
public String deleteitem(String[] itemid)throws Exception{
System.out.println(itemid);
}
B. List
List中存放對象,并將定義的List放在包裝類中,action使用包裝對象接收。
List中對象:
Public class QueryVo {
Private List<Items> itemList; // 商品列表
//get/set方法..
}
包裝類中定義List對象,并添加get/set方法如下:
頁面定義如下:
<tr>
<td><input type="text" name=" itemsList[0].id" value="${item.id}" />
</td>
<td><input type="text" name=" itemsList[0].name"
value="${item.name }" /></td>
<td><input type="text" name=" itemsList[0].price"
value="${item.price}" /></td>
</tr>
<tr>
<td><input type="text" name=" itemsList[1].id" value="${item.id}" />
</td>
<td><input type="text" name=" itemsList[1].name"
value="${item.name }" /></td>
<td><input type="text" name=" itemsList[1].price"
value="${item.price}" /></td>
</tr>
上邊的靜態(tài)代碼改為動態(tài)jsp代碼如下:
<c:forEach items="${itemsList }" var="item" varStatus="s">
<tr>
<td><input type="text" name="itemsList[${s.index }].name" value="${item.name }"/></td>
<td><input type="text" name="itemsList[${s.index }].price" value="${item.price }"/></td>
.....
.....
</tr>
</c:forEach>
Contrller方法定義如下:
public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{
System.out.println(queryVo.getItemList());
}
C. Map
在包裝類中定義Map對象,并添加get/set方法,action使用包裝對象接收。
包裝類中定義Map對象如下:
Public class QueryVo {
private Map<String, Object> itemInfo = new HashMap<String, Object>();
//get/set方法..
}
頁面定義如下:
<tr>
<td>學(xué)生信息:</td>
<td>
姓名:<inputtype="text" name="itemInfo['name']"/>
年齡:<inputtype="text" name="itemInfo['price']"/>
</td>
</tr>
Contrller方法定義如下:
public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{
System.out.println(queryVo.getStudentinfo());
}
五、JSON數(shù)據(jù)
1. 請求參數(shù)添加注解:@RequestBody
public RequestUser userJson(@RequestBody RequestUser requestUser) {}
2. 如果獲取響應(yīng)數(shù)據(jù)添加注解: @ResponseBody
@ResponseBody
public RequestUser userJson(@RequestBody RequestUser requestUser) {}
或:
public @ResponseBody RequestUser userJson(@RequestBody RequestUser requestUser) {
六、常用注解
| 注解 | 說明 |
|---|---|
| @Controller | 用于標(biāo)識是處理器類; |
| @RequestMapping | 請求到處理器功能方法的映射規(guī)則; |
| @RequestParam | 請求參數(shù)到處理器功能處理方法的方法參數(shù)上的綁定; |
| @ModelAttribute | 請求參數(shù)到命令對象的綁定; |
| @SessionAttributes | 用于聲明 session 級別存儲的屬性,放置在處理器類上,通常列出模型屬性(如@ModelAttribute)對應(yīng)的名稱,則這些屬性會透明的保存到 session 中; |
| @InitBinder | 自定義數(shù)據(jù)綁定注冊支持,用于將請求參數(shù)轉(zhuǎn)換到命令對象屬性的對應(yīng)類型; |
| @CookieValue | cookie 數(shù)據(jù)到處理器功能處理方法的方法參數(shù)上的綁定; |
| @RequestHeader | 請求頭(header)數(shù)據(jù)到處理器功能處理方法的方法參數(shù)上的綁定; |
| @RequestBody | 請求的 body 體的綁定(通過 httpMessageConverter 進行類型轉(zhuǎn)換); |
| @ResponseBody | 處理器功能處理方法的返回值作為響應(yīng)體(通過 |
HttpMessageConverter 進行類型轉(zhuǎn)換);
@ResponseStatus |定義處理器功能處理方法/異常處理器返回的狀態(tài)碼和原因;
@ExceptionHandler |注解式聲明異常處理器;
@PathVariable | 請求 URI 中的模板變量部分到處理器功能處理方法的方法參數(shù)上的綁定,從而支持 RESTful 架構(gòu)風(fēng)格
六、常見錯誤:
-
嚴重: Unable to process Jar entry [module-info.class] from Jar [jar:file:/d:/.m2/org/ow2/asm/asm/7.1/asm-7.1.jar!/] for annotations
解決:
無法從Jar包[****]中處理Jar條目[module-info.class],而module-info.class用記事本打開后可以看到其內(nèi)容,而且在實際項目中,module-info.java經(jīng)常用來處理模塊之間的依賴關(guān)系等,可選擇直接刪除。
刪除module-info.class
