这是一种比较简单的 Handler, HttpRequestHandler接口只有一个handleRequest方法,传入 HttpServletRequest 和HttpServletResponse两个参数,没有返回值。这种 Handler 只为处理简单的HTTP 请求, 其中不涉及复杂的过程, 执行完handleRequest方法执行就结束了。
注意:
该 Handler并不算完整的MVC 组件,因为其中并没有包含视图的查找解析等过程,但是这种 Handler的简单特性也为其带来了好处,如一些不需要视图解析的静态资源,就可以使用这种 Handler来实现。下面看一个简单的示例。
public class MyHttpRequestHandler implements HttpRequestHandler {
@ Override
public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 使用 response的 writer输出一段文字
response. getWriter(). println(" Hello HttpRequestHandler");
}
}
在仅配置了 Handler 时,该 Handler 并不能被使用, 因为 Handler 的查找和执行是分离的。要想令此 Handler 生效, 并在适当的时候使用此 Handler 处理请求, 还需要把这个 Handler 注册到 Mapping 中。可以选用上一篇博客中的任意方式注册该 Handler。因为@RequestMapping 是注册方法的,上例中的 Handler 是以类的形式创建的,所以需要用另外两种方式。下面以SimpleUrlHandlerMapping为例演示
@ Bean
public SimpleUrlHandlerMapping MyHttpRequestHandler() {
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
//设置高优先
mapping. setOrder( Ordered. HIGHEST_PRECEDENCE);
mapping.setUrlMap( Collections.singletonMap("httpRequestHandler",
new MyHttpRequestHandler()));
return mapping;
}
启动项目,访问 localhost:8080/httpRequestHandler,可以看到页面中显示:Hello HttpRequestHandler
这里的 Controller是指 org. springframework. web. servlet. mvc 包下的 Controller接口, 该类型的 Handler 更接近于 MVC 定义中的 Controller。同样只有 handleRequest 方法,传入HttpServletRequest 和 HttpServletResponse 两个参数。与 HttpRequestHandler 不同的是, Controller的返回值类型是 ModelAndView,其中封装了 Model 数据和 View视图, 后面会详细讲解。示例代码如下:
// 声明BeanName为/myController, 使用BeanNameUrlHandlerMapping注册这个 Handler
@Component("/myController")
public class MyController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request,HttpServletResponse response) throws Exception {
// Model 数据支持使用 Map类型
Map< String, Object> model = new HashMap<>(2);
model. put(" name", " Kanglingfeng") ;
// 返回视图 Mycontroller, 视图绑定的数据为 Model
return new ModelAndView("defaultView", model);
}
}
defaultView视图内容如下:
< html xmlns: th=" http://www.thymeleaf.org ">
< body>
body>
html>
通过浏览器访问 localhost:8080/myController, 渲染的结果是: Hello Controller, visitor is Kanglingfeng!
Controller 类型的 Handler 与 HttpRequestHandler 的最大区别就是返回值, 这里返回了ModelAndView, 提供了对视图和模型绑定的功能,这也是一个完整的控制器中应该有的功能,在HttpRequestHandler中,如果要实现 Controller中返回视图并绑定 Model 渲染的功能,是非常复杂的。所以这里的 Controller接口就是基本的控制器雏形。
HandlerMethod 类型的 Handler 是@RequestMapping 注解标记的方法的封装。请求处理时, 先通过RequestMappingHandlerMapping查找满足筛选条件的@RequestMapping注解,之后为该注解所标记的方法封装为 HandlerMethod, HandlerMethod 中包含该方法所在的 Bean及该方法的引用。该类型比前面两种类型更为强大, 功能更多。
HandlerMethod 类型虽然也可以自己通过 SimpleUrlHandlerMapping 或者 BeanNameUrl-HandlerMapping绑定映射关系, 但是一般是与RequestMappingHandlerMapping结合使用, 只需要为处理方法所在的 Bean 声明为@ Controller, 处理方法上标记@RequestMapping 即可,参考示例如下:
// 声明为 Controller控制器 Bean, 该 Bean中被注解@RequestMapping标记的方法会被RequestMappingHandlerMapping 扫描并包装为HandlerMethod
@Controller
public class MyRequestMapping {
// 映射 URL 为/MyRequestMapping, 支持GET类型的请求
@RequestMapping( path= "/myRequestMapping", method = RequestMethod.GET)
public String requestMappingGet( String name, Map< String, Object> model) {
// name 参数可以从请求参数中自动获取并绑定, model 参数也会自动作为Mode1 模型绑定到参数中
model. put (" name", name) ;
//返回视图名, 同上面例子
return "defaultView";
}
}
该示例为请求添加了一个参数 name, 尝试通过 URL 访问该请求: localhost:8080/myRequestMapping? name= Kanglingfeng。可以看到页面输出与 Controller例子相同, 也是 Hello Controller, visitor is Kanglingfeng!。
虽然结果相同, 但是它们的实现方式有以下几种不同。
请 求参数的自动绑定。在@RequestMapping 中,请求参数可以自动绑定到处理方法的参数中。而如果要使用 Controller类型的 Handler 实现获取请求参数 name 的值的功能, 还需要添加从 request获取参数的逻辑, 即 request. getParameter(" name")。
Model 模型的自动绑定。参数中声明了 Map 类型的 model, 此时 RequestMapping-HandlerAdapter 会自动为其生成 Model 模型并绑定到方法参数中,供处理器逻辑对其数据进行存取。而在 Controller类型的 Handler中, 则是自行创建出来的。
视图的自动查找。通过返回 String类型的视图名,一般是视图文件名,RequestMappingHandlerAdapter可以自动查找相应名称的视图, 并与参数中的 Model 模型数据自动绑定。而在 Controller类型的 Handler中, ModelAndView 是我们自行创建的。
可以看到这3 种 Handler 的功能是递进的关系, HttpRequestHandler 是对原始的 Request和 Response进行处理的处理器。 Controller则是 MVC 中定义的 Controller 功能, 返回了模型与视图。
而 RequestMapping则更进一步,在原始的 Request 和 Response 中抽象了一层处理层,可以使用普通的 Java对象作为控制器,添加了参数绑定、返回值处理等功能,不需要再暴露原始的请求和响应,即可完成请求与响应的处理。使得开发者只需要关注自己需要的请求参数和要返回的结果,而无须对原始请求和响应做加工。