DispatcherServlet在Spring当中充当一个前端控制器的角色,它的核心功能是分发请求。请求会被分发给对应处理的Java类,Spring MVC中称为Handle。在Spring 2.5版本之前,开发一个Handle的唯一方法是实现org.springframework.web.servlet.mvc.Controller接口。Controller接口必须实现一个方法
ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception
Controller接口的实现类可以通过handleRequest方法传递的参数访问对应请求的HttpServletRequest和HttpServletResponse对象,处理完业务请求之后,必须返回一个包含模型对象和视图路径的ModelAnView对象。
但Controller接口的实现类智能处理一个单一的请求动作,而Spring 2.5之后新增的基于注解的控制器可以支持同时处理多个请求动作,并且无需实现任何接口,其更加灵活,下一节会详细介绍。
下面我们介绍一下基于Controller接口控制器的基本应用(默认我们已经添加了Spring支持)
1.配置前端控制器DispatcherServlet(/WEB-INF/web.xml)
<servlet> <servlet-name>springmvc</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/springmvc-config.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <!-- 让Spring MVC的前端控制器拦截所有请求 --> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
web.xml文件的内容告诉Web容器,将使用Spring MVC的DispatcherServlet,并通过配置url-pattern元素的值为"/",将所有的URL映射到该Servlet
2.配置Spring MVC的Controller(/WEB-INF/springmvc-config.xml)
<!-- 配置Handle,映射"/hello"请求 --> <bean name="/hello" class="org.fkit.controller.HelloController"/> <!-- 处理映射器将bean的name作为url进行查找,需要在配置Handle时指定name(即url) --> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/> <!-- SimpleControllerHandlerAdapter是一个处理器适配器,所有处理适配器都要实现 HandlerAdapter接口--> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/> <!-- 视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"/>
springmvc-config.xml声明了HelloController业务控制器类,并将其映射到/hello请求。
配置映射处理器BeanNameUrlHandlerMapping,这样可以Bean的名称为url进行查找;同时配置了处理器适配器SimpleControllerHandlerAdapter,来完成对HelloController类的handleRequest方法的调用;最后配置了视图解析器InterResourceViewResolver来解析视图,将View呈现给用户。
在Spring4.0之后,如果不配置处理映射器,处理适配器和视图解析器,也会使用默认的完成Spring内部MVC工作。
3.Controller类的实现
HelloController实现了Controller接口,用来处理/hello请求
package org.fkit.controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; /** * HelloController是一个实现Controller接口的控制器 * 可以处理单一的请求动作 */ public class HelloController implements Controller{ private static final Log logger = LogFactory .getLog(HelloController.class); /** * handleRequest是Controller接口必须实现的方法 * 该方法的参数是对应请求的HttpServletRequest和HttpServletResponse * 该方法必须返回一个包含视图名或视图名和模型的ModelAndView对象 * */ @Override public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { logger.info("handleRequest 被调用"); // 创建准备返回的ModelAndView对象,该对象通常包含了返回视图名,模型的名称以及模型对象 ModelAndView mv = new ModelAndView(); // 添加模型数据,可以是任意的POJO对象 mv.addObject("message", "Hello World!"); // 设计逻辑视图名,视图解析器会根据该名称解析到具体的视图页面 mv.setViewName("/WEB-INF/content/welcome.jsp"); // 返回ModelAndView对象 return mv; } }
本例返回的模型中包含了一个名为message的字符串对象,返回的视图路径为/WEB-INF/content/welcome.jsp,因此,请求会被转发到welcome.jsp页面
Spring MVC建议把所有的视图页面存放在WEB-INF文件夹下,这样可以保护视图页面,避免直接向视图页面发送请求
4.View页面(/WEB-INF/content/welcome.jsp)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!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> <!-- 页面可以访问Controller传递传递出来的message --> ${requestScope.message} </body> </html>
5. 测试应用
URL:http://localhost:8080/SpringMVCTest/hello
使用MVC框架就应该严格遵守MVC思想,MVC框架不赞成浏览器直接访问Web应用的视图页面,用户的所有请求都只应向控制器发送,由控制器调用模型组件,视图组件向用户呈现数据