要说Controller接口的实现类使用与说明之前,先简要说明一下SpringMVC的工作原理。
①客户端发出一个请求,web服务器接受了这个请求后,就会与web.xml中配置的DispatcherServlet中的映射路径相匹配,如果有对应的匹配路径存在,那么这个请求将会交给DispatcherServlet处理(这个Dispatcher Servlet也是SpringMvc的核心);
②DispactherServlet接受请求后,根据URL寻找恰当的处理器映射来处理这个请求;
③处理器处理完之后,就会返回一个ModelAndView对象给DispatcherServlet,这个ModelAndView对象封装了模型数据信息以及视图图逻辑名(视图逻辑名常指跳转的jsp页面);
④但是ModelAndView对象封装的只是视图逻辑名,而不是一个真正的视图对象,所以DispatcherServlet需要通过ViewResolver来进行对视图逻辑名的解析;
⑤解析得到视图对象后,DispatcherServlet将模型数据交给View对象进行渲染;
⑥最后将结果返回到客户端,这个结果可以是一个页面,也可以是一个Excel这类的视图形式。
换句话说,DispatcherServlet是SpringMVC的核心,在web.xml里面配置DispatcherServlet:
<servlet> <servlet-name>spring</servlet-name><!-- 这里的取servlet名字为spring,意味着解析时,服务器会找到WEB-INF目录下的一个叫做spring-servlet.xml的文件 --> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>
spring-servlet.xml的文件是用来配置处理器映射、控制器的定义、视图解析器等。
SpringMVC的控制器基础时org.springframework.web.servlet.mvc.Controller接口,spring提供的Controller实现类有三个:AbstractCommandController、SimpleFormController和MultiActionController。
下面是讲解这三个控制器类在使用上的区别:
一、AbstractCommandController(命令控制器):
使用命令控制器时的spring-servlet.xml配置主要分了3个步骤:
①处理器映射配置,这里使用org.springframework.web.servlet.SimpleUrlHandlerMapping;
②定义控制器(这里是配置自定义控制器,因为自定义控制器已经继承了SpringMVC提供的控制器)
③配置视图解析器,这里使用org.springframework.web.servlet.view.InternalResourceViewResolver
自定义一个控制器类继承AbstractCommandController后,下面的代码是在spring-servlet.xml的配置,
<!--配置处理器映射-->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="login.do">loginController</prop> <!--key值表示url的值,如果两者匹配,则处理交给id为loginController的类处理--> </props> </property> </bean> <!--配置控制器--> <bean id="loginController" class="com.controller.LoginController"> <!--配置自定义控制器类,这里的id值对应上面的id值,换句话说,上面的处理操作交给这里对应的LoginController类--> <property name="commandClass" value="com.entity.Users"></property> <!--配置注入类--> </bean>
<!--配置视图解析器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/"></property> <property name="suffix" value=".jsp"></property> </bean>
public class LoginController extends AbstractCommandController { @Override protected ModelAndView handle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, BindException arg3) throws Exception { Users user = (Users) arg2;
//指定视图逻辑名 ModelAndView mav = new ModelAndView("success"); mav.addObject("user", user); return mav; } }
当LoginController执行结束后,就会将ModelAndView对象返回给InternalResourceViewResolver解析,视图解析器类就会根据mav里面的指定视图逻辑名进行渲染,以这里为例子,就是找到success.jsp的文件,然后跳转。
二、SimpleFormController(表单控制器):
自定义控制器类继承SimpleFormController后,在spring-servlet.xml里的配置主要有两个步骤:
①配置处理器映射
②配置控制器
<!--配置处理器映射-->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="reg.do">regController</prop> </props> </property> </bean> <!--配置控制器--> <bean id="regController" class="com.controller.RegController"> <property name="commandClass" value="com.entity.Users"></property> <property name="formView" value="register.jsp"></property> <!--指定表单数据加载后,跳转的页面--> <property name="successView" value="show.jsp"></property> <!--指定表单执行成功后跳转的页面--> </bean>
public class RegController extends SimpleFormController { protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors)throws Exception{ Users user = (Users)command; ModelAndView mav = new ModelAndView("show.jsp"); mav.addObject("user", user); return mav; } protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception{ binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true)); } protected Map referenceData(HttpServletRequest request) throws Exception{ Map<String, Object> model = new HashMap<String, Object>(); model.put("hobbyList", new String[]{"Swimming", "Running"}); return model; } }
从上面两段代码可以知道,当url的值为reg.do的时候,DispatcherServlet就会将处理请求交给id=regController的类(即RegController)处理,此时并不是执行onSubmit()方法,而是执行referenceData()方法,因为没有点击submit按钮。因为此方法
里面没有指定视图逻辑名,所以当referenceData()执行结束后,就会找到配置控制器<property name="formView" value="register.jsp"></property>这条语句,这里的value=register.jsp,即下一步会跳转到register.jsp页面,相应的数据也会加载到
register.jsp页面上。当在register.jsp页面上点击submit按钮时,又会将请求交给RegController处理(因为form标签的action=reg.do),此时就会执行onSubmit()方法.
对比AbstractCommandController和SimpleFormController的配置,就会发现,SimpleFormController少了配置视图解析器,而且自定义控制器类里指定视图逻辑名是用了“.jsp”后缀。其实这是成对出现的,配置视图解析器,就不需要后缀,因为后缀已经在视图解析器
里有配置好,两种方法效果一样。
三、MultiSimpleController(多动作控制器):
多动作控制器是为了减少大量的定义控制器类,可以实现多个动作在同一个类里面操作,实现功能集成。
MultiSimpleController的配置相对简单一点:
①配置处理器映射
②配置自定义控制器
③配置自定义控制器的响应策略
<!--配置处理器映射-->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="user.do">userController</prop> </props> </property> </bean>
<!--配置自定义控制器--> <bean id="userController" class="com.controller.UserController"> <property name="methodNameResolver" ref="methodNameResolver"></property> </bean>
<!--配置自定义控制器响应策略--> <bean id="methodNameResolver" class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver"> <property name="paramName" value="method"></property> </bean>
上面同样的也没有配置视图解析器,所以自定义控制类的视图逻辑名要加上后缀(即使用路径+文件全名).
在自定义控制器的配置里面,相对于AbstractCommandController和SimpeFormController来说,这里不需要配置封装类“commandClas”,因为使用了ParameterMethodNameReslover策略,作用是根据url请求匹配自定义控制器类里的方法名字,进而
进行动作处理。
当使用基于配置来实现SpringMVC的的动作响应时,就会发现AbstractCommandController和SimpleFormController被显示为已过期,因为SpringMVC框架是推荐使用注解的形式。