原文链接:https://www.codemore.top/cates/Backend/post/2018-04-21/spring-mvc-handler-methods

由注解@RequestMapping注解修饰的处理请求的函数的签名非常的灵活,可以使用controller函数支持的一系列参数和返回值。

函数参数

下列表格列出了controller方法可以接受的参数,稍后会对其进行详细的解释。 对于 JDK 8的java.util.Optional 可以在包含required属性的注解中使用,例如:@RequestParam,@RequestHeader等,相当于required=false

函数参数 解释
WebRequest,NativeWebRequest 无需直接使用Servlet API来访问请求参数,请求属性和session的属性。
javax.servlet.ServletRequest,javax.servlet.ServletResponse 可以是指定的请求和响应类型例如ServletRequestHttpServletRequest,也可以是Spring的MultipartRequest,MultipartHttpServletRequest
HttpSession 参数永不为null,访问session非线程安全,如果多个请求访问一个session,需要设置RequestMappingHandlerAdaptersynchronizeOnSession为true。
PushBuilder Servlet 4.0 支持HTTP/2 push的API,如果客户端不支持则为null
Principal 当前授权用户。
HttpMethod 请求的HTTP方法
Locale 当前请求的区域,由LocaleResolver解析
TimeZone,ZoneId LocaleContextResolver解析的当前请求的时区
InputStream,Reader 访问由Servlet API暴露的请求体
OutputStream,Writer 访问由Servlet API 暴露的响应体
@PathVairable 访问URI变量
@MatrixVariable 访问URI中的name-value值。例如 pets/42;q=11 @MatrixVariable int q
@Requestparam 访问请求中参数
@RequestHeader 访问请求头
@CookieValue 访问cookie值
@RequestBody 访问请求体,将请求体转换为相应类型
HttpEntity<B> 访问请求头和请求体
Map,Model,ModelMap 访问会在渲染模板时使用的变量。
RedirectAttributes 重定向时使用的属性
@ModelAttribute 访问model中的属性,同时进行数据绑定和校验
Errors, BindingResult 访问在数据绑定和校验是出现的错误。

类级别的 @SessionAttributes,SessionStatus | 在不同的请求中存储session UriComponentsBuilder | 相对于当前请求的host,port,scheme等 @SessionAttribute | 访问session中的属性 @RequestAttribute| 访问请求的属性。 其他类型 | 如果参数非上述类型,那么将当成@RequestParam来处理

返回值

下列表格列出了支持的返回类型

返回值类型 解释
@ResponseBody 返回值由HttpMessageConverters转换,直接写到响应体
HttpEntity<B>ResponseEntity<B> 返回值包括,http header和body
HttpHeaders 只返回HTTP header
String ViewResolver解析出具体的模板渲染。
View 返回具体的视图
Map,Model model包含的属性,视图由RequestToViewNameTranslator解析
@ModelAttribute 返回添加到Model的属性,视图由RequestToViewNameTranslator解析.
ModelAndView 返回具体视图和添加的model
void 返回void,则Spring MVC会认为Controller内部已经处理好响应内容了。
DeferredResult<V> 异步返回结果,可以由任意线程处理
Callback<V> 异步返回,现成由Spring MVC管理
ListenableFuture<V>,CompletionStage<V>,CompletableFuture<V> DefferedResult
ResponseBodyEmitter,SseEmitter 使用HttpMessageConverter异步将对象以流的方式发到响应。
StreamingResponseBody 异步将响应发送的输出流
Reactor, RxJava, 等Reactive类型 DeferredResult
其他类型 如果不返回以上类型,默认当作视图名称处理。
类型转换

一些需要参数的注解,例如@RequestParam,@RequestHeader,@PathVariabl,@MatrixVariable@CookieValue,如果他么的参数并非String,那么久需要进行类型转换。 类型转换自动由Spring MVC中注册的转换器来进行转换,默认情况下支持,int,long,Date等简单类型。对于不支持的类型可以通过WebDataBinder或者由FormattingConversionService注册的Formatter来进行转换。

Matrix 变量

RFC 3986规定了在路径中添加name-value对。在Spring MVC中,将其定义为matrix变量。 Matrix变量可以出现在任意的路径中,每个变量由分号隔开,多个值由逗号隔开,例如:/cars;color=red,green;year=2012。多个值同样可也可是通过分离名字来指定,例如:color=red;color=green。 如果想要在路径中添加Matrix变量,那么就必须保证相应的controller方法包含接收matrix变量,并且请求映射不收到Matrix变量的影响。例如:

// GET /pets/42;q=11;r=22

@GetMapping("/pets/{petId}")
public void findPet(@PathVariable String petId, @MatrixVariable int q) { // petId == 42
// q == 11
}

因为所有的路径都有可能包办Matrix变量,可以通过指定路径的形式分辨某个Matrix变量属于哪个路径例如:

@GetMapping("/owners/{ownerId}/pets/{petId}")
public void findPet(
@MatrixVariable(name="q", pathVar="ownerId") int q1,
@MatrixVariable(name="q", pathVar="petId") int q2) { // q1 == 11
// q2 == 22
}

Matrix变量可以是可选的,指定默认值.例如:

// GET /pets/42

@GetMapping("/pets/{petId}")
public void findPet(@MatrixVariable(required=false, defaultValue="1") int q) { // q == 1
}

可以使用MultiValueMap获取所有的Matrix变量,例如:

// GET /owners/42;q=11;r=12/pets/21;q=22;s=23

@GetMapping("/owners/{ownerId}/pets/{petId}")
public void findPet(
@MatrixVariable MultiValueMap<String, String> matrixVars,
@MatrixVariable(pathVar="petId") MultiValueMap<String, String> petMatrixVars) { // matrixVars: ["q" : [11,22], "r" : 12, "s" : 23]
// petMatrixVars: ["q" : 22, "s" : 23]
}

默认情况下Spring MVC是不启用Matrix变量的,如果是用Java配置,可以通过配置UrlPathHelperremoveSemicolonContent=false启用,如果是使用XML配置,可以使用<mvc:annotation-driven enable-matrix=variable="true"/>启用。

@RequestParam

@RequestParam可以将Servlet请求参数绑定到controller函数中的变量.例如:

@Controller
@RequestMapping("/pets")
public class EditPetForm { // ... @GetMapping
public String setupForm(@RequestParam("petId") int petId, Model model) {
Pet pet = this.clinic.loadPet(petId);
model.addAttribute("pet", pet);
return "petForm";
} // ... }

@RequestParam的变量required 默认情况下是true,如果不希望必须指定某个参数可以设置required=false或者如果使用Java 8 可以使用java.util.Optional。 如果函数的参数非String类型,那么将会进行自动类型转换。 如果@RequsetParam修饰的是Map<String,String>或者MultiValueMap<String,String>那么就会获取所有的请求参数。

@RequestHeader

@RequestHeader将header的值绑定到controller的方法参数中。 例如一下作为请求header:

Host                    localhost:8080
Accept text/html,application/xhtml+xml,application/xml;q=0.9
Accept-Language fr,en-gb;q=0.7,en;q=0.3
Accept-Encoding gzip,deflate
Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive 300

下列代码就可以获取Accept-EncodingKeep-Aliveheader

@GetMapping("/demo")
public void handle(
@RequestHeader("Accept-Encoding") String encoding,
@RequestHeader("Keep-Alive") long keepAlive) {
//...
}

同样,如果参数非String类型,也会自动进行类型转换,如果修饰的是Map<String,String>,MultiValueMap<String,String>或者HttpHeaders,也是获取所有的header值

@CookieValue

使用@CookieValue将cookie值绑定到controller的方法参数中 例如以下cookie:

JSESSIONID=415A4AC178C59DACE0B2C9CA727CDD84

下列代码即可获取:

@GetMapping("/demo")
public void handle(@CookieValue("JSESSIONID") String cookie) {
//...
}

同样的,如果参数类型非String,会自动进行类型转换。

@ModelAttribute

使用@ModelAttribute修饰的函数参数可以访问Model中的属性,或者其未初始化是初始化。方法参数名和请求参数名相同,model 属性同样也可以覆盖其请求参数,这样就不需要自己再从请求参数中解析了。例如:

@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@ModelAttribute Pet pet) { }

Pet 示例的获取:

  • 如果Model中存在,则从Model中解析
  • 通过@SessionAttributes获取
  • 从URI的路径变量中获取
  • 通过默认的构造函数获取
  • 通过和Servlet请求参数相匹配的带参数的构造函数获取。参数名由@ConstructorProperties获取或者字节码获取。

当然一般都是使用Model来填充其值的,另一个选择使用URI的路径变量,其值通过注册的Converter<String,T>转换。下面这个例子就是@ModelAttribute修饰的值和路径匹配,通过Converter<String,Account>进行类型转换。

@PutMapping("/accounts/{account}")
public String save(@ModelAttribute("account") Account account) {
// ...
}

获取了属性值的实例后就可以开始进行数据绑定了。WebDataBinder类通过匹配Servlet 的请求参数名(查询参数和form字段)来将字段名对应到对象中。当类型转换完之后填充匹配的字段。DataBinderValidation将在后面章节详细描述。 数据绑定是会产生错误的,默认情况下会抛出BindException异常,为了在controller的方法中捕获这个异常,可以在方法参数中加入BindingResult获取异常。例如:

@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result) {
if (result.hasErrors()) {
return "petForm";
}
// ...
}

某些情况下只想要访问属性之而不需要数据绑定。这种情况下可以将设置@ModelAttribute(binding=false)。例如:

@ModelAttribute
public AccountForm setUpForm() {
return new AccountForm();
} @ModelAttribute
public Account findAccount(@PathVariable String accountId) {
return accountRepository.findOne(accountId);
} @PostMapping("update")
public String update(@Valid AccountUpdateForm form, BindingResult result,
@ModelAttribute(binding=false) Account account) {
// ...
}

添加javax.util.validation.Valid或者Spring的@Validated注解,在数据绑定完成后会自动校验。例如:

@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@Valid @ModelAttribute("pet") Pet pet, BindingResult result) {
if (result.hasErrors()) {
return "petForm";
}
// ...
}
@SessionAttributes

@SessionAttributes用于在不同的请求间存储Servlet session的属性值。主要是列出需要在接下来的请求访问的session的值自动的保存到session中。例如:

@Controller
@SessionAttributes("pet")
public class EditPetForm {
// ...
}

第一次请求后这个带有pet名字的属性值将会自动的存到session中。直到另外一个带有SessionStatus参数的方法将其清除。例如:

@Controller
@SessionAttributes("pet")
public class EditPetForm { // ... @PostMapping("/pets/{id}")
public String handle(Pet pet, BindingResult errors, SessionStatus status) {
if (errors.hasErrors) {
// ...
}
status.setComplete();
// ...
}
}
}
@SessionAttribute

如果想要访问一个之前存在的session的属性,可以使用@SessionAttribute访问。例如:

@RequestMapping("/")
public String handle(@SessionAttribute User user) {
// ...
}

请他情况下,需要添加或者删除session的时候,可以通过注入org.springframework.web.context.request.WebRequest或者javax.servlet.http.HttpSession实现Session的管理。

@RequestAttribute

@SessionAttribute相似,@RequestAttribute可以访问请求之前(例如,Filter,HandlerInterceptor)创建的请求属性。例如:

@GetMapping("/")
public String handle(@RequestAttribute Client client) {
// ...
}
重定向属性值

默认情况下,在重定向url中所有的属性值都通过URI的模版变量暴露。 例如:

@PostMapping("/files/{path}")
public String upload(...) {
// ...
return "redirect:files/{path}";
}
Flash属性值

Flash属性值可以保存一个请求的数据使得另一个请求可以使用他的数据。最常用的场景就是重定向,例如:Post/Redirect/Get模式。在重定向之前临时将Flash属性保存(一般保存在session中)。这样在另一个请求中就可以获取保存值,之后就会被立即删除。 Spring MVC 通过FlashMapFlashMapManager支持Flash属性。FlashMap保存值,FlashMapManager用来保存,查询,管理FlashMap实例。 Flash属性默认开启,如果不使用则不会创建HTTP session。对于每个请求来说都有一个input的FlashMap,包含了上一个请求传递的属性和一个output的FlashMap包含需要传递的属性。这两个FlashMap都可以通过RequestContextUtils中的静态方法来获取。 一般来讲controller不会直接使用FlashMap。其方法参数RedirectAttributes默认情况下使用flash map存储需要重定向的数据,保存到output的FlashMap中,重定向后,自动从input的FlashMap中获取数据添加到Model中。

Multipart

启用MultipartResolver后,如果POST请求包含了multipart/form-data,则其将会解析请求参数,获取Multipart。下面是上次文件的示例:

@Controller
public class FileUploadController { @PostMapping("/form")
public String handleFormUpload(@RequestParam("name") String name,
@RequestParam("file") MultipartFile file) { if (!file.isEmpty()) {
byte[] bytes = file.getBytes();
// store the bytes somewhere
return "redirect:uploadSuccess";
} return "redirect:uploadFailure";
} }

如果使用Servlet 3.0 则可以用javax.servlet.http.Part代替Spring的MultipartFile。 Multipart 的内容同样可以作为数据绑定的一部分,例如:

class MyForm {

    private String name;

    private MultipartFile file;

    // ...

}

@Controller
public class FileUploadController { @PostMapping("/form")
public String handleFormUpload(MyForm form, BindingResult errors) { if (!form.getFile().isEmpty()) {
byte[] bytes = form.getFile().getBytes();
// store the bytes somewhere
return "redirect:uploadSuccess";
} return "redirect:uploadFailure";
} }

Multipart请求同样可以通过非浏览器提交,例如:下面是一个JSON的示例:

POST /someUrl
Content-Type: multipart/mixed --edt7Tfrdusa7r3lNQc79vXuhIIMlatb7PQg7Vp
Content-Disposition: form-data; name="meta-data"
Content-Type: application/json; charset=UTF-8
Content-Transfer-Encoding: 8bit {
"name": "value"
}
--edt7Tfrdusa7r3lNQc79vXuhIIMlatb7PQg7Vp
Content-Disposition: form-data; name="file-data"; filename="file.properties"
Content-Type: text/xml
Content-Transfer-Encoding: 8bit
... File Data ...

可以通过@RequestParam来获取元信息,但是更好的做法是使用@RequestPart来获取其元信息。例如:

@PostMapping("/")
public String handle(@RequestPart("meta-data") MetaData metadata,
@RequestPart("file-data") MultipartFile file) {
// ...
}

@RequestPart可以和javax.validation.Valid或者Spring的@Validated注解一同使用,通过标准的bean验证来校验数据的准确性。默认情况下校验错误抛出MethodArgumentNotValidException的异常,会直接返回404的错误。同样可以通过BindingResult来自己处理异常情况。

@RequestBody

使用了@RequestBody的参数通过HttpMessageConverter来将请求体反序列化成一个对象。下面是使用@RequestBody的示例:

@PostMapping("/accounts")
public void handle(@RequestBody Account account) {
// ...
}

@RequestBody同样可以和javax.validation.Valid或者Spring的@Validated注解一同使用。默认抛出的异常是MethodArgumentNotValidException处理方法同@RequestPart

@PostMapping("/accounts")
public void handle(@Valid @RequestBody Account account, BindingResult result) {
// ...
}
HttpEntity

HttpEntity的使用和@RequestBody相似,不过他可以同时包含header和body。使用方法如下:

@PostMapping("/accounts")
public void handle(HttpEntity<Account> entity) {
// ...
}
@ReponseBody

在方法中使用@ResponseBody修饰,则会自动的将返回值通过HttpMessageConverter的转换写入到响应体中。 使用方法如下:

@GetMapping("/accounts/{id}")
@ResponseBody
public Account handle() {
// ...
}

@ResponseBody同样支持类级别,如果修饰controller类,那么所有的方法都会继承这个注解。这个和@RestController一样,@RestController就是@Controller@RequestBody的组合。

ResponseEntity

ResponseEntity@ResponseBody相似,只是其同时包含了响应的header和body。使用如下:

@PostMapping("/something")
public ResponseEntity<String> handle() {
// ...
URI location = ... ;
return ResponseEntity.created(location).build();
}
Jackson JSON

Spring MVC 内监了对Jackson序列化视图的支持。在使用ResponseEntity@ResponseBody的时候可以使用@JsonView来启动序列化的视图类。使用如下:

public class UserController {

    @GetMapping("/user")
@JsonView(User.WithoutPasswordView.class)
public User getUser() {
return new User("eric", "7!jd#h23");
}
} public class User { public interface WithoutPasswordView {};
public interface WithPasswordView extends WithoutPasswordView {}; private String username;
private String password; public User() {
} public User(String username, String password) {
this.username = username;
this.password = password;
} @JsonView(WithoutPasswordView.class)
public String getUsername() {
return this.username;
} @JsonView(WithPasswordView.class)
public String getPassword() {
return this.password;
}
}

如果controller的方法返回的是一个字符串的视图,可以将其放到model中启用:

@Controller
public class UserController extends AbstractController { @GetMapping("/user")
public String getUser(Model model) {
model.addAttribute("user", new User("eric", "7!jd#h23"));
model.addAttribute(JsonView.class.getName(), User.WithoutPasswordView.class);
return "userView";
}
}
Jackson JSONP

为了开启@ResponseBodyResonseEntity的JSONP的支持,可以通过定义一个@ControllerAdvice的bean继承AbstractJsonpResponseBodyAdvice,其默认构造参数就是JSONP的查询参数,使用如下:

@ControllerAdvice
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice { public JsonpAdvice() {
super("callback");
}
}

SpringMVC 教程 - Handler Method的更多相关文章

  1. Springmvc的handler method参数绑定常用的注解

    转自:http://blog.longjiazuo.com/archives/1149   1. 简介: handler method参数绑定常用的注解,我们根据他们处理的Request的不同内容部分 ...

  2. SpringMVC教程4

    SpringMVC教程3 一.数据回写 数据回写:在做数据更新的时候服务端查询的数据自动填充到表单中. 1.1默认方式 通过前面讲解的 Map Mode ModelMap绑定数据 @RequestMa ...

  3. Java系列教程-SpringMVC教程

    SpringMVC教程 1.SpringMVC概述 1.回顾MVC 1.什么是MVC MVC是模型(Model).视图(View).控制器(Controller)的简写,是一种软件设计规范. 是将业务 ...

  4. SpringMVC教程3

    SpringMVC教程2 一.文件上传 1.引入相关jar包 maven坐标 <!-- fileUpload 解析上传的文件用到的jar --> <dependency> &l ...

  5. SpringMVC教程1

    一.SpringMVC介绍 1.MVC介绍 ==模型-视图-控制器(MVC== 是一个众所周知的以设计界面应用程序为基础的设计模式.它主要通过分离模型.视图及控制器在应用程序中的角色将业务逻辑从界面中 ...

  6. SpringMVC教程2

    接上篇文章-SpringMVC教程1 五.基本操作 1.响应请求的方式 1.1ModeAndView /** * 查询方法 * @return */ @RequestMapping("/qu ...

  7. spring 笔记2:Spring MVC : Did not find handler method for 问题的解决

    日志显示为: Looking up handler method for path /***Did not find handler method for [/***]No mapping found ...

  8. handler method 参数绑定

    handler method 参数绑定常用的注解,我们根据他们处理的Request的不同内容部分分为四类:(主要讲解常用类型) A.处理requet uri 部分(这里指uri template中va ...

  9. handler method 参数绑定常用注解

    handler method 参数绑定常用的注解,我们根据他们处理的Request的不同内容部分分为四类: A.处理requet uri 部分(这里指uri template中variable,不含q ...

随机推荐

  1. 微信小程序配置WSS协议

    配置的是nginx转发,前提是你已经安装了nginx的软件并已经正常打开网页,安装好SSL协议,能打开https网页 下面是配置: 需要的话可以根据需求修改 server { listen 80; s ...

  2. html标记语言 --超链接

    html标记语言 --超链接 四.超链接 1. 基本语法 <a href="" target="打开方式" name="页面锚点名称" ...

  3. __new__方法首先调用并返回一个实例化对象

    >>> class CapStr(str): def __new__(cls,string): string = string.upper() return str.__new__( ...

  4. Java基础学习(五)-- Java中常用的工具类、枚举、Java中的单例模式之详解

    Java中的常用类 1.Math : 位于java.lang包中 (1)Math.PI:返回一个最接近圆周率的 (2)Math.abs(-10):返回一个数的绝对值 (3)Math.cbrt(27): ...

  5. PyCharm 2018 永久激活

    PyCharm是一种Python IDE,带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具,比如调试.语法高亮.Project管理.代码跳转.智能提示.自动完成.单元测试.版本控制. ...

  6. Junit简单配置

    Junit简单配置的步骤如下: 1.在WEB-INF目录下的lib里面放一个junit包,我用的是junit-4.9.jar: 2.选定要测试的类,右键单击该类,新建一个Junit Test Case ...

  7. [HNOI 2014]画框

    Description 题库链接 \(T\) 组询问,每组询问给你个 \(2\times N\) 的带权二分图,两个权值 \(a,b\) ,让你做匹配使得 \[\sum a\times \sum b\ ...

  8. [PA 2014]Iloczyn

    Description 斐波那契数列的定义为:k=0或1时,F[k]=k:k>1时,F[k]=F[k-1]+F[k-2].数列的开头几项为0,1,1,2,3,5,8,13,21,34,55,…你 ...

  9. 成也DP,败也DP(AFO?)

    不知道想说什么.. 从来没写过博客,markdown什么的也不会,凑合着看一下吧. 初中的时候开始搞OI,学了两个月后普及组爆零就退赛了. 初三直升的时候说每个人都要选竞赛,抱着混一混的心态选了信息, ...

  10. 勤拂拭软件系列教程 - java web开发

    勤拂拭软件工作室持续推出Java Web开发系列教程与案例,供广大朋友分享交流技术经验,帮助喜欢java的朋友们学习进步: 1. 勤拂拭软件 java web 开发教程(1) - 开发环境搭建 勤拂拭 ...