SpringMVC:注解开发
@RequestMapping 使用
在SpringMVC中,RequestDispatcher(在Front Controller之下)这个servlet负责将进入的HTTP请求路由到控制器的处理方法,并通过RequestMapping注解指定请求与处理方法之间的映射关系。
@RequestMapping注解可以在Controller类及类中方法的级别上使用。
URL路径映射
@RequestMapping(value="/item")
或@RequestMapping("/item")
value的值是数组,可以将多个url映射到同一个方法,如:
@RestController
@RequestMapping("/home ")
public class IndexController {
@RequestMapping(value = {
" ",
"/page ",
"page* ",
"view/*,**/msg "
})
String indexMultipleMapping() {
return "Hello from index multiple mapping. ";
}
}
如下的这些 URL 都会由 indexMultipleMapping() 来处理:
- localhost:8080/home
- localhost:8080/home/
- localhost:8080/home/page
- localhost:8080/home/pageabc
- localhost:8080/home/view/
- localhost:8080/home/view/view
窄化请求映射
在class上添加@RequestMapping(url)指定通用请求前缀, 限制此类下的所有方法请求url必须以请求前缀开头,通过此方法对url进行分类管理。
@Controller
@RequestMapping("/items")
public class ItemsController {
@Autowired
private ItemsService itemsService;
// 商品查询
@RequestMapping("/queryItems")
public ModelAndView queryItems(HttpServletRequest request) throws Exception {
List<ItemsCustom> itemsList = itemsService.findItemsList(null);
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("itemsList", itemsList);
modelAndView.setViewName("items/itemsList");
return modelAndView;
}
...
}
商品列表请求路径为:“/items/queryItems.action”。
限定请求方法
出于安全性考虑,对http的链接进行方法限制。
- HTTP 请求的方法:
RequestMethod.GET
、RequestMethod.POST
、RequestMethod.DELETE
、RequestMethod.PUT
、RequestMethod.PATCH
//商品信息修改页面显示
@RequestMapping(value="/editItems",method={RequestMethod.POST,RequestMethod.GET})
public ModelAndView editItems()throws Exception {
ItemsCustom itemsCustom = itemsService.findItemsById(1);
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("itemsCustom", itemsCustom);
modelAndView.setViewName("items/editItems");
return modelAndView;
}
如果限制请求为post方法(method={RequestMethod.GET}),进行get请求,报错:
带有@RequestParam的RequestMapping
@RequestParam注解配合@RequestMapping一起使用,可以将请求的参数同处理方法的参数绑定在一起。
@RequestParam 的使用:
- 通过在@RequestParam里边指定request传入参数名称和形参进行绑定;
@RequestParam Integer items_id
:传入参数、形参均为items_id;@RequestParam(value="id") Integer items_id
:传入参数为id,形参为items_id;
- 通过required属性指定参数是否必须要传入;
@RequestParam(value="id",required=true) Integer items_id
- 通过defaultValue可以设置默认值,如果形参没有传入,将默认值和形参绑定;
@RequestParam(value="id",required=true,defaultValue="10001") Integer items_id
//商品信息修改页面显示
@RequestMapping(value="/editItems",method={RequestMethod.POST,RequestMethod.GET})
public String editItems(Model model,@RequestParam(value="id",required=true) Integer items_id)throws Exception {
ItemsCustom itemsCustom = itemsService.findItemsById(items_id);
//通过形参中的model将model数据传到页面
//相当于modelAndView.addObject方法
model.addAttribute("itemsCustom", itemsCustom);
return "items/editItems";
}
处理生产和消费对象
可以使用@RequestMapping注解的produces
和consumes
这两个元素来缩小请求映射类型的范围。
- 用@RequestMapping的
produces
元素结合@ResponseBody
注解,来用请求的媒体类型产生对象; - 用@RequestMapping的
comsumes
元素结合@RequestBody
注解,来用请求的媒体类型消费对象;
如:
@RestController
@RequestMapping("/home ")
public class IndexController {
@RequestMapping(value = "/prod ", produces = {"application/JSON "})
@ResponseBody
String getProduces() {
return "Produces attribute ";
}
@RequestMapping(value = "/cons ", consumes = {"application/JSON ","application/XML "})
@RequestBody
String getConsumes() {
return "Consumes attribute ";
}
}
在这段代码中,getProduces()处理方法会产生一个JSON响应,getConsumes()处理方法可以同时处理请求中的JSON和XML内容。
处理消息头
@RequestMapping注解提供了header
元素来根据请求中的消息头内容缩小请求映射的范围。
指定消息头,如:
@RestController
@RequestMapping("/home ")
public class IndexController {
@RequestMapping(value = "/head ", headers = {"content-type=text/plain"})
String post() {
return "Mapping applied along with headers ";
}
}
如上代码段, @RequestMapping注解的headers属性将映射范围缩小到了post()方法,使post()只会处理url为“/home/head”并且content-type为“text/plain”的请求。
指定多个消息头,如:
@RestController
@RequestMapping("/home ")
public class IndexController {
@RequestMapping(value = "/head ", headers = {
"content-type=text/plain ",
"content-type=text/html "
}) String post() {
return "Mapping applied along with headers ";
}
}
如上代码段, post()会处理url为“/home/head”,并且content-type为“text/plain”和“text/html”的请求。
处理请求参数
@RequestMapping 直接的params
元素可以进一步帮助我们缩小请求映射的定位范围。使用params
元素,可以让多个处理方法处理params不一样的同一个URL请求。
如:
@RestController
@RequestMapping("/home ")
public class IndexController {
@RequestMapping(value = "/fetch", params = {"id=10"})
String getParams(@RequestParam("personId") String id) {
return "Fetched parameter using params attribute = " + id;
}
@RequestMapping(value = "/fetch", params = {"personId=20"})
String getParamsDiff(@RequestParam("personId") String id) {
return "Fetched parameter using params attribute = " + id;
}
@RequestMapping(value = "/fetch", params = {"username","age!=10"})
public String getParamsDifferent() {
System.out.println("testParamsAndHeaders");
return SUCCESS;
}
}
如上代码段,getParams() 和 getParamsDifferent() 两个方法都能处理相同的一个 URL (“/home/fetch”) ,但是会根据 params 元素的配置不同而决定具体来执行哪一个方法:
- URL 为“/home/fetch?id=10”时,getParams() 会执行;
- URL 为“/home/fetch?personId=20”时,getParamsDiff() 会执行;
- URL 包含时“username”和“age”,且“age”不等于“10”时(如“/home/fetch?username=ejiux&age=26”),getParamsDifferent() 会执行;
处理动态URI
@RequestMapping 注解可以同@PathVaraible
注解一起使用,用来处理动态的 URI,URI 的值可以作为控制器中处理方法的参数。
- 可以使用正则表达式,以只处理匹配到的动态URI。
- @PathVariable 同 @RequestParam的运行方式不同。使用 @PathVariable 是为了从 URI 里取到查询参数值,而使用 @RequestParam 是为了从 URI 模板中获取参数值。
@RestController
@RequestMapping("/home ")
public class IndexController {
@RequestMapping(value = "/fetch/{id} ", method = RequestMethod.GET)
String getDynamicUriValue(@PathVariable String id) {
System.out.println("ID is " + id);
return "Dynamic URI parameter fetched ";
}
@RequestMapping(value = "/fetch/{id:[a-z]+}/{name} ", method = RequestMethod.GET)
String getDynamicUriValueRegex(@PathVariable("name") String name) {
System.out.println("Name is " + name);
return "Dynamic URI parameter fetched using regex ";
}
}
如上代码段:
- 方法 getDynamicUriValue() 会在“localhost:8080/home/fetch/10”的请求时执行;
- 方法 getDynamicUriValueRegex() 会在“localhost:8080/home/fetch/category/shirt”的请求时执行;
- 如果请求是“/home/fetch/10/shirt”,则会抛出异常,因为这个URI并不能匹配正则表达式;
默认的处理方法
在Controller中可以有一个默认的处理方法,它在发起请求默认 URI 时被执行。
如:
@RestController
@RequestMapping("/home")
public class IndexController {
@RequestMapping()
String
default () {
return "This is a default method for the class ";
}
}
如上代码段,发起请求“/home”将会由 default() 来处理,因为方法的 @RequestMapping 注解并没有指定任何值。
快捷方式(组合注解)
Spring 4.3 引入了方法级注解的变体,也被叫做 @RequestMapping 的组合注解,组合注解可以更好的表达被注解方法的语义。它们所扮演的角色就是针对 @RequestMapping 的封装,而且成了定义端点的标准方法。
方法级别的注解变体,如:
- GetMapping :相当于 @RequestMapping(method =RequestMethod.GET) 的一个快捷方式;
- PostMapping :...;
- PutMapping :...;
- DeleteMapping :...;
- PatchMapping :...;
- 每个变体都可以使用带有方法属性的 @RequestMapping 注解来互换实现。
组合注解的使用如下:
@RestController
@RequestMapping("/home")
public class IndexController {
@GetMapping("/person")
public @ResponseBody ResponseEntity < String > getPerson() {
return new ResponseEntity < String > ("Response from GET", HttpStatus.OK);
}
@GetMapping("/person/{id}")
public @ResponseBody ResponseEntity < String > getPersonById(@PathVariable String id) {
return new ResponseEntity < String > ("Response from GET with id " + id, HttpStatus.OK);
}
@PostMapping("/person")
public @ResponseBody ResponseEntity < String > postPerson() {
return new ResponseEntity < String > ("Response from POST method", HttpStatus.OK);
}
@PutMapping("/person")
public @ResponseBody ResponseEntity < String > putPerson() {
return new ResponseEntity < String > ("Response from PUT method", HttpStatus.OK);
}
@DeleteMapping("/person")
public @ResponseBody ResponseEntity < String > deletePerson() {
return new ResponseEntity < String > ("Response from DELETE method", HttpStatus.OK);
}
@PatchMapping("/person")
public @ResponseBody ResponseEntity < String > patchPerson() {
return new ResponseEntity < String > ("Response from PATCH method", HttpStatus.OK);
}
}
Handler方法返回值
ModelAndView
controller方法中定义ModelAndView
对象并返回,对象中可添加model数据、指定view。
@RequestMapping("/queryItems")
public ModelAndView queryItems(HttpServletRequest request) throws Exception {
List<ItemsCustom> itemsList = itemsService.findItemsList(null);
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("itemsList", itemsList);
modelAndView.setViewName("items/itemsList");
return modelAndView;
}
itemsList页面代码如:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>查询商品列表</title>
</head>
<body>
<form
action="${pageContext.request.contextPath }/items/queryItems.action"
method="post">
查询条件:
<table width="100%" border=1>
<tr>
<td><input type="submit" value="查询" /></td>
</tr>
</table>
商品列表:
<table width="100%" border=1>
<tr>
<td>商品名称</td>
<td>商品价格</td>
<td>生产日期</td>
<td>商品描述</td>
<td>操作</td>
</tr>
<c:forEach items="${itemsList }" var="item">
<tr>
<td>${item.name }</td>
<td>${item.price }</td>
<td><fmt:formatDate value="${item.createtime}"
pattern="yyyy-MM-dd HH:mm:ss" /></td>
<td>${item.detail }</td>
<td><a href="${pageContext.request.contextPath }/items/editItems.action?id=${item.id}">修改</a></td>
</tr>
</c:forEach>
</table>
</form>
</body>
</html>
void
在controller方法形参上可以定义request
和response
,使用request或response指定响应结果:
- 使用request转向页面,如:
request.getRequestDispatcher("页面路径").forward(request, response);
- 通过response页面重定向:
response.sendRedirect("url")
- 通过response指定响应结果,例如响应json数据如下:
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("json串");