SpringMVC屬於Spring Framework的後續產品,已經融合到Spring Web Flow中。SpringMVC基於Model2而實現,利用處理器分離了模型對象、視圖、控制,達到了鬆散耦合的效果,提升了系統的可重用性、可維護性以及可擴展性。其功能與Struts相似,只是實現原理和方式上有所不一樣。css
優勢:html
SpringMVC框架主要由DispatcherServlet、HandlerMapping、Controller、ViewResolver四個接口組成。前端
是整個SpringMVC的核心。從名稱來看,它是一個Servlet,負責統一分發全部請求。web
在web.xml文件中進行配置,負責接收HTTP請求、組織協調SpringMVC的各個組成部分。spring
<servlet> <servlet-name>springMVC</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:/springMVC.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springMVC</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
若是不指定<param-value>
的值,則默認配置文件爲/WEB-INF/<servlet-name>
-servlet.xml。<load-on-startup>
是啓動順序,一般讓Servlet跟隨Servlet容器一塊兒啓動。<url-pattern>
定義要攔截的URL請求。安全
攔截規則:併發
*.xxx
,指定要攔截的特定類型,最簡單實用的方式,而且不會攔截靜態文件/
,使用REST風格進行攔截,可是會致使靜態文件被攔截不能正常顯示/*
,不能像Struts那樣使用,會致使不能訪問jsp若是使用/
進行攔截,而且但願正常訪問靜態文件,能夠在DispatcherServlet以前,使用DefaultServlet先攔截特定類型的請求(如:*.js、*.css等)。mvc
負責完成請求到控制器的映射。在servlet的配置文件中,進行uri與控制器的映射。同時,還能夠對控制器進行攔截。app
SpringMVC默認的處理器映射,直接將uri與實現類進行綁定,書寫方便,可是耦合性高。框架
<bean id="defaultHandlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/> <bean name="/hello.html" class="com.demo.ssm.HelloController"></bean>
使用SimpleUrlHandlerMapping,將uri與類的id進行綁定,彼此的耦合性低,更加靈活。
<bean id="simpleUrlHandlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="urlMap"> <map> <entry key="/hello.html" value-ref="hello"></entry> </map> </property> </bean> <bean id="hello" class="com.demo.ssm.controller.HelloController"></bean>
對控制器進行攔截,首先聲明攔截器:
<bean id="myInterceptor" class="com.demo.ssm.interceptor.MyInterceptor"></bean>
而後利用SimpleUrlHandlerMapping,映射攔截器與控制器:
<property name="interceptors"> <list> <ref bean="myInterceptor" /> </list> </property>
負責處理用戶請求,完成以後返回ModelAndView對象給前端控制器。由於須要考慮併發,因此必須保證線程安全而且可重用。
SpringMVC中的Controller與Struts中的Action基本相同。經過實現Controller接口或繼承父類的方式編寫控制器。
實現Controller接口:
public class HelloController implements Controller { // 至關於servlet的doGet和doPost方法 public ModelAndView handleRequest(HttpServletRequest request,HttpServletResponse response) throws Exception { // 接收數據 // 調用服務層 return new ModelAndView("success","username","sean"); } }
繼承AbstractController類,該類與接口相似,須要重寫裏邊的方法。
繼承MultiActionController類,能夠實現多個方法,處理多個請求。
public class MultiController extends MultiActionController { // 自定義處理請求的方法 public ModelAndView insert(HttpServletRequest request,HttpServletResponse response) throws Exception { return new ModelAndView("insertSuccess"); } public ModelAndView update(HttpServletRequest request,HttpServletResponse response) throws Exception { return new ModelAndView("updateSuccess"); } }
相應的配置文件:
<bean id="multi" class="com.demo.ssm.controller.MultiController"></bean> <bean id="simpleUrlHandlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="urlMap"> <map> <!-- 使用通配符進行模糊匹配 --> <entry key="/multi-*.html" value-ref="multi"></entry> </map> </property> </bean> <bean id="multiActionController" class="org.springframework.web.servlet.mvc.multiaction.MultiActionController"> <property name="methodNameResolver" ref="methodNameResolver"></property> <property name="delegate"> <ref bean="multi" /> </property> </bean> <bean id="methodNameResolver" class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver"> <property name="mappings"> <props> <prop key="/multi-insert.html">insert</prop> <prop key="/multi-update.html">update</prop> </props> </property> </bean>
繼承AbstractCommandController類,用於獲取頁面的參數,將參數封裝到指定的對象模型中。
public class CommandController extends AbstractCommandController { public CommandController() { // User是用於接收請求參數的數據模型類 this.setCommandClass(User.class); } protected ModelAndView handle(HttpServletRequest request,HttpServletResponse response, Object command, BindException errors) throws Exception { // command參數是指定的數據模型對象 User user = (User)command; return new ModelAndView("command"); } }
負責對ModelAndView對象的解析,並查找對應的View對象。SpringMVC框架默認經過轉發進行頁面跳轉,若是想經過重定向的方式進行跳轉,有如下幾種實現方式。
在控制器中,返回一個RedirectView對象,由對象來指定重定向的URL:
View view = new RedirectView("/index.jsp"); return new ModelAndView(view);
經過配置文件設置,在控制器返回對象的方法中只須要設置一個與bean id一致的字符串便可:
<bean id="viewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver"></bean> <bean id="index" class="org.springframework.web.servlet.view.RedirectView"> <property name="url" value="/index.jsp"></property> </bean> return new ModelAndView("index");
直接跳轉:
return "redirect:/index.jsp";
若是一個配置文件中出現多個視圖解析器,能夠經過設置order屬性來設定優先級。值越低,優先級越高。
<servlet-name>
servlet.xml的配置,查找HandlerMappingSpring提供了HandlerInterceptor接口和HandlerInterceptorAdapter適配器。實現這個接口或繼承此類,就能夠實現本身的攔截器。接口HandlerInterceptor包含三個方法,每一個方法的參數handler,用來指向下一個攔截器。
在實現了接口以後,就能夠在配置文件中進行攔截器的配置。
攔截全部url:
<mvc:interceptors> <bean class="com.core.mvc.MyInteceptor" /> </mvc:interceptors>
攔截匹配的url:
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/user/*" /> <bean class="com.core.mvc.MyInteceptor" /> </mvc:interceptor> </mvc:interceptors>
HandlerMapping上的攔截器:
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> <property name="interceptors"> <list> <bean class="com.core.mvc.MyInteceptor" /> </list> </property> </bean>
注意:若是配置了<mvc:annotation-driven />
,會自動註冊DefaultAnnotationHandlerMapping與AnnotationMethodHandlerAdapter這兩個bean。這樣就不能再注入interceptors屬性,也就沒法指定攔截器了。
能夠在配置文件中設置SimpleMappingExceptionResolver,也能夠實現HandlerExceptionResolver接口,編寫本身的異常處理。經過exceptionMappings屬性的配置,能夠將不一樣的異常映射到不一樣的頁面。經過defaultErrorView屬性的配置,能夠爲全部異常指定一個默認的異常處理頁面。
<bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="defaultErrorView"> <value>/error/error</value> </property> <property name="defaultStatusCode"> <value>500</value> </property> </bean>
首先在配置文件中添加:
<bean class="com.xxxx.SpringContextHolder" lazy-init="false" />
而後定義一個Spring上下文持有類:
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; public class SpringContextHolder implements ApplicationContextAware { // 聲明靜態變量, 保證在任何代碼任何地方任什麼時候候可以取得ApplicaitonContext private static ApplicationContext applicationContext; // 實現ApplicationContextAware接口的context注入函數, 將其存入靜態變量 public void setApplicationContext(ApplicationContext applicationContext) { SpringContextHolder.applicationContext = applicationContext; } // 取得ApplicationContext public static ApplicationContext getApplicationContext() { return applicationContext; } // 從靜態變量ApplicationContext中取得Bean, 自動轉型爲所賦值對象的類型 @SuppressWarnings("unchecked") public static <T> T getBean(String name) { return (T) applicationContext.getBean(name); } @SuppressWarnings("unchecked") public static <T> T getBean(Class<T> clazz) { return (T) applicationContext.getBeansOfType(clazz); } // 清除applicationContext靜態變量 public static void cleanApplicationContext() { applicationContext = null; } }
參考文章: