(六)Spring MVC常用注解(下)
6.2 参数绑定注解
6.2.1 @RequstParam注解
@RequstParam注解用于将制定的请求参数赋值给方法中的形参。@RequstParam注解可以使用的属性如表6-5所示。
表6-5 @RequstParam常用属性
属性名称 |
类 型 |
是否必填 |
描 述 |
name |
String |
否 |
指定请求头绑定的名称 |
value |
String |
否 |
name属性的别名 |
required |
Boolean |
否 |
指定参数是否必须绑定 |
defaultValue |
String |
否 |
请求没有传递参数而使用的默认值 |
@RequstParam注解的使用实例如下:
public class AyUserController {
public String findById( String id){
AyUser ayUser = ayUserService.findById(id);
return "success";
}
}
public class AyUserController {
public String findByNameAndPassword(
String name,
defaultValue = String password){ )
System.out.println("name=" + name);
System.out.println("password" + password);
return "success";
}
}
当浏览器中输入URL请求:http://localhost:8080/user/findByNameAndPassword?name=ay时,name参数被赋值为ay,由于password没传任何值,故默认值为123。
6.2.2 @PathVariable注解
public class AyUserController {
public String findPet( Long ownerId, Long petId) {
// ...
return "";
}
}
public class AyUserController {
public String findPet( Long ownerId, Long petId) {
// ...
return "";
}
}
6.2.3 @RequestHeader注解
表6-6 @RequestHeader常用属性
属性名称 |
类 型 |
是否必填 |
描 述 |
name |
String |
否 |
指定请求头绑定的名称 |
value |
String |
否 |
name属性的别名 |
required |
Boolean |
否 |
指定参数是否必须绑定 |
defaultValue |
String |
否 |
请求没有传递参数而使用的默认值 |
一般请求头信息如下所示:
Host localhost:8080
Accepttext/html,application/xhtml+xml,application/xml;q=0.9
Accept-Languagefr,en-gb;q=0.7,en;q=0.3
Accept-Encodinggzip,deflate
Accept-CharsetISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive300
下面通过@RequestHeader注解获取Accept-Encoding和Keep-Alive信息,具体示例如下所示:
public class AyUserController {
public String handle(
String[] encoding,
String[] accept) {
//...
return "";
}
}
6.2.4 @CookieValue注解
表6-7 @CookieValue 常用属性
属性名称 |
类 型 |
是否必填 |
描 述 |
name |
String |
否 |
指定请求头绑定的名称 |
value |
String |
否 |
name属性的别名 |
required |
Boolean |
否 |
指定参数是否必须绑定 |
defaultValue |
String |
否 |
请求没有传递参数而使用的默认值 |
public class AyUserController {
public String handle( String cookie) {
//...
return "";
}
}
6.2.5 @ModelAttribute注解
public class AyUserController {
public void init(){
System.out.println("init ...");
}
public void init02(){
System.out.println("init 02 ...");
}
public String findById( String id) {
// ...
return "";
}
public void init03(){
System.out.println("init 03 ...");
}
}
init ...
init 02 ...
init 03 ...
@ModelAttribute注解有很多的额外使用方式,下面逐一进行介绍。
1. @ModelAtterbute方法无返回值的情况
"/user") (value =
public class AyUserController {
public void init(Model model){
AyUser ayUser = new AyUser();
ayUser.setId(1);
ayUser.setName("ay");
model.addAttribute("user", ayUser);
}
"/hello") (
public String hello(){
return "hello";
}
}
<%@page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false"%>
<html>
<head>
<title>Getting Started: Serving Web Content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
hello, ${user.name}
</body>
</html>
2. @ModelAttribute标记方法有返回值
public class AyUserController {
public String init( String name){
return name;
}
public String hello(){
return "hello";
}
}
model.addAttribute("name",name);
对应前端src\main\webapp\WEB-INF\views\hello.jsp页面代码如下所示:
<%@page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false"%>
<html>
<head>
<title>Getting Started: Serving Web Content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
hello, ${name}
</body>
</html>
3. @ModelAttribute注解和@RequestMapping注解
@ModelAttribute注解和@RequestMapping注解同时标记在一个方法上。
public class AyUserController {
public String hello(){
return "ay";
}
}
<%@page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false"%>
<html>
<head>
<title>Getting Started: Serving Web Content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
hello, ${name}
</body>
</html>
4. 使用@ModelAttribute注解方法的参数。
public class AyUserController {
public AyUser init( Integer id,
String name){
AyUser ayUser = new AyUser();
ayUser.setId(id);
ayUser.setName(name);
return ayUser;
}
public String hello( AyUser ayUser){
return "hello";
}
<%@page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false"%>
<html>
<head>
<title>Getting Started: Serving Web Content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
hello, ${ayUser.name}
</body>
</html>
6.2.6 @SessionAttribute和@SessionAttributes注解
表6-8 @RequestHeader常用属性
属性名称 |
类 型 |
是否必填 |
描 述 |
names |
String[] |
否 |
需要存储到session中数据的名称 |
value |
String |
否 |
name属性的别名 |
types |
Class<?>[] |
否 |
根据指定参数的类型,将模型中对应类型的参数存储到session中 |
下面看具体实例,具体代码如下:
public class AyUserController {
public String redirectTest(Model model){
AyUser ayUser = new AyUser();
ayUser.setName("ay");
model.addAttribute("ayUser",ayUser);
return "redirect:hello";
}
public String hello(ModelMap modelMap){
AyUser ayUser = (AyUser) modelMap.get("ayUser");
System.out.println(ayUser.getName());
return "hello";
}
}
public class AyUserController {
public String redirectTest(Model model){
AyUser ayUser = new AyUser();
ayUser.setName("ay");
model.addAttribute("ayUser",ayUser);
return "redirect:hello";
}
public String hello( AyUser ayUser){
System.out.println(ayUser.getName());
return "hello";
}
}
"redirect") (
public String redirectTest(Model model,SessionStatus sessionStatus){
AyUser ayUser = new AyUser();
ayUser.setName("ay");
model.addAttribute("ayUser",ayUser);
//删除HttpSession中的属性
sessionStatus.setComplete();
return "redirect:hello";
}
@SessionAttributes(types = {AyUser.class, AyRole.class},value = {"ayUser", "ayRole"})
type属性用来指定放入HttpSession当中的对象类型。
6.2.7 @ResponseBody和@RequestBody注解
1. @ResponseBody注解
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
(1)返回普通的字符串
public class AyUserController {
public String hello(){
return "I am not view";
}
}
(2)返回集合对象
"/user") (
public class AyUserController {
"/hello") (
public List<String> hello(){
List<String> list = new ArrayList<String>();
list.add("ay");
list.add("al");
return list;
}
}
public class AyUserController {
public void hello( AyUser ayUser){
System.out.println("name" + ayUser.getName());
System.out.println("password" + ayUser.getPassword());
}
}
6.3 信息转换详解
6.3.1 HttpMessageConverter<T>
public interface HttpMessageConverter<T> {
boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);
boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);
List<MediaType> getSupportedMediaTypes();
T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException;
void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException;
}
表6-9 HttpMessageConverter接口实现类
属性名称 |
描 述 |
StringHttpMessageConverter |
将请求信息转换为字符串,泛型T为String,可读取所有媒体类型(*/*),可通过supportedMediaTypes属性指定媒体类型。响应信息的媒体类型为text/plain(即Content-Type的值) |
(续表)
属性名称 |
描 述 |
ByteArrayHttpMessageConverter |
读写二进制数据,泛型T为byte[]类型,可读取*/*,可通过supportedMediaTypes属性指定媒体类型,响应信息媒体类型为application/octer-stream |
MarshallingHttpMessageConverter |
泛型T为Object,可读取text/xml和application/xml媒体类型请求,响应信息的媒体类型为text/xml或application/xml |
Jaxb2RootElementHttpMessageConverter |
通过JAXB2读写XML信息,将请求消息转换到标注XmlRootElement和XmlType注解的类中,泛型T为Object,可读取text/xml和application/xml媒体类型请求,响应信息的媒体类型为text/xml或application/xml |
MappingJacksonHttpMessageConverter |
利用jackson的ObjectMapper读写JSON数据,泛型T为Object,可读取application/json,响应媒体类型为application/json |
FormHttpMessageConverter |
表单与 MultiValueMap的相互转换。读支持响应MediaType为application/x-www-form-urlencoded,写支持的响应类型为application/x-www-form-urlencoded和multipart/form-data |
SourceHttpMessageConverter |
数据与javax.xml.transform.Source的相互转换。读支持响应MediaType为text/xml 和 application/xml,写支持的响应类型为text/xml 和 application/xml |
BufferedImageHttpMessageConverter |
数据与java.awt.image.BufferedImage的相互转换。读支持 MediaType为Java I/O API的所有类型,写支持的响应类型为Java I/O API的所有类型。 |
6.3.2 RequestMappingHandlerAdapter
RequestMappingHandlerMapping
RequestMappingHandlerAdapter
DefaultHandlerExceptionResolver
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
implements BeanFactoryAware, InitializingBean {
//省略大量代码
private List<HttpMessageConverter<?>> messageConverters;
public RequestMappingHandlerAdapter() {
StringHttpMessageConverter stringHttpMessageConverter
= new StringHttpMessageConverter();
stringHttpMessageConverter.setWriteAcceptCharset(false); // see SPR-7316
this.messageConverters = new ArrayList<>(4);
this.messageConverters.add(new ByteArrayHttpMessageConverter());
this.messageConverters.add(stringHttpMessageConverter);
this.messageConverters.add(new SourceHttpMessageConverter<>());
this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
}
}
l ByteArrayHttpMessageConverter
l StringHttpMessageConverter
l SourceHttpMessageConverter
l AllEncompassingFormHttpMessageConverter
6.3.3 自定义HttpMessageConverter
<!-- 自定义RequestMappingHandlerAdapter -->
<bean class="org.springframework.web.servlet.mvc.method
.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
<bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
</list>
</property>
</bean>