Handler处理器在Spring MVC中占据着重要位置,它主要负责请求的处理和结果的返回。在MVC架构中,Handler扮演了控制层(Controller)的角色。
在日常开发中最常用的处理器映射器和适配器是基于注解的处理器映射器和适配器配置,即annotation-driven标签。它会自动注册处理器映射器和处理器适配器,并且除此之外还提供了数据绑定支持。利用Spring MVC提供的默认的注解配置,可以省去许多的开发配置,因此提高了开发效率。具体配置如下:
<mvc:annotation-driven/>
在使用annotation-driven标签时,处理器Handler的类型要符合annotation-driven标签指定的处理器映射器和适配器类型。annotation-driven标签指定的默认处理器映射器和适配器在Spring 3.1之前为DefaultAnnotationHandlerMapping、AnnotationMethodHandlerAdapter,在Spring 3.1之后为RequestMappingHandlerMapping和RequestMappingHandlerAdapter。
在配置了注解的处理器映射器的情况下,当使用@Controller注解去标识一个类时,其实就是告诉Spring MVC该类是一个Handler控制器类。在配置了component-scan标签后,当Spring初始化Bean信息时,会扫描到所有标注了@Controller注解的类,并将其作为Handler来加载。
提示:可以在@Controller注解上指定一个请求域,表示整个Controller的服务请求路径在该域下访问。
基于注解的Handler必须在类中实现处理请求逻辑的方法,并且使用注解标注它们处理的URL路径。在@Controller中编写的方法需要标注@RequestMapping注解,表明该方法是一个处理前端请求的方法。
@RequestMapping注解的作用是为控制器指定可以处理哪些URL请求,该注解可以放置在类上或者方法上。当放置在类上时,提供初步的URL请求映射信息,即一个前置请求路径(相对于Web应用的根目录),当放置在方法上时,提供进一步的细分URL映射信息,相对于类定义处的URL。若类定义处未标注@RequestMapping,则方法处标记的URL相对于Web应用的根目录。
使用@RequestMapping注解时,如果为其指定一个URL映射名,则指定其value属性即可。而一般不在@RequestMapping中配置其他属性时,可以省去value参数名,直接编写一个代表URL映射信息的字符串即可,@RequestMapping会默认匹配该字符串为value属性的值。但需要注意的是,如果@RequestMapping中配置了value属性之外的其他属性时,则必须声明value属性,不可省略。
下面是一个@RequestMapping注解的例子,这里只为其中的方法设置了RequestMapping注解,代码如下:
package com.ccff.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class MyController {
@RequestMapping("/test")
public String test(){
return "success";
}
}
假设工程名为“SpringMVC”,默认后缀名为“.action”。那么这里test()处理的URL请求路径为:http://localhost:8080/SpringMVC/test.action。
如果在类上也添加@RequestMapping注解,就会为整个Handler类的@RequestMapping的URL添加一个前缀路径,代码如下:
package com.ccff.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/test")
public class MyController {
@RequestMapping("/userTest")
public String userTest(){
return "success";
}
}
假设工程名为“SpringMVC”,默认后缀名为“.action”。那么这里test()处理的URL请求路径为:http://localhost:8080/SpringMVC/test/userTest.action。
除此之外,注解@RequestMapping还可以限定请求方法、请求参数和请求头。
对于请求方法,@RequestMapping的method属性可以指定“GET”或“POST”请求类型,表明该URL只能以某种请求方式请求才能获得响应,代码如下:
package com.ccff.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
@RequestMapping("/test")
public class MyController {
@RequestMapping(value = "/userTest", method = RequestMethod.GET)
public String userTest(){
return "success";
}
}
这里访问“/test/userTest.action”时,只能接受GET请求类型。可以看到,指定的“GET”或“POST”请求类型需要由RequestMethod枚举类来表示,以达到一种规范。
对于请求参数,@RequestMapping的param属性可以指定某一种参数名类型,当请求数据中含有该名称的请求参数时,才能进行响应,具体代码如下:
package com.ccff.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/test")
public class MyController {
@RequestMapping(value = "/userTest", params = "username")
public String userTest(){
System.out.println("只接受username参数");
return "success";
}
}
该配置表示,当一个URL请求中不含有名称为“username”的参数时,该方法就拒绝此次请求。
对于请求头,@RequestMapping的headers属性可以指定某一种请求头类型,当请求数据头的类型符合指定的值时,才能进行响应,具体代码如下:
package com.ccff.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/test")
public class MyController {
@RequestMapping(value = "/userTest", headers = "Content-Type:text/html;charset=UTF-8")
public String userTest(){
System.out.println("只接受请求头中Content-Type为text/html;charset=UTF-8的请求");
return "success";
}
}
该配置表示,当一个请求头中的Content-Type为“text/html;charset=UTF-8”的参数时,该方法才会处理此次请求。
还有两个属性,分别是consumes和produces。其中consumes表示处理请求的提交内容类型(Content-Type),例如“application/json,text/html”。而produces表示返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型时才返回。
下面是一个consumes的例子,具体代码如下:
package com.ccff.controller;
import com.ccff.model.Fruits;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class MyController {
@RequestMapping(value = "/fruits", method = RequestMethod.POST, consumes = "application/json")
public void addFruit(Fruits fruit, Model model){
//implements omitted
}
}
该配置表示方法仅处理request的Content-Type为“application/json”类型的请求。
下面是一个produces的例子,具体代码如下:
package com.ccff.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class MyController {
@RequestMapping(value = "/getFruits", method = RequestMethod.GET, produces = "application/json")
@ResponseBody
public void addFruit(int id, Model model){
//implements omitted
}
}
该配置表示方法仅处理request请求中Accept头中包含“application/json”的请求,同时暗示了返回的内容类型为application/json。
小贴士:指定consumes和produces可以规范请求的Content-Type内容类型。