1.DispatcherServlet
SpringMVC具有统一的门户dispatcher servlet,所有请求都通过dispatcher servlet。
dispatcher servlet是一个前端控制器,位于web.xml文件中。 被阻止的请求由servlet自己定义块匹配规则,根据某个规则将被阻止的请求分发到目标控制器进行处理。 现在,将以下配置添加到web.xml中:
! 初始化- dispatcher servlet时,框架将在web APP应用程序的WEB-INF目录中查找名为[ servlet-name ]-servlet.XML的文件,并定义其关联的Beans 全局定义的bean-- servlet servlet-namespringmybatis/重写servlet-name servlet-class org.spring framework.web.servlet.diss ion servlet-class load-on-startup1/load-stup servlet servlet-mapping servlet-namespringmybatis/servlet-namagespring -所有请求都由dispatcher servlet处理--- UE
2.静态资源不拦截
如果配置为仅阻止url (如*.do格式),则可以访问静态资源,但如果配置为阻止所有请求(如上面配置的“/”),则静态资源(如js文件、css文件和图像文件)
实现典型的拦截器主要是为了权限管理,主要是阻止一些url请求,因此不会阻止静态资源。 过滤静态资源一般有两种方法。
第一种采用MVC : default-servlet-handler /。 (由于典型web APP应用程序服务器的缺省servlet名称为“default”,因此现在将激活Tomcat的defaultServlet
! -这个servlet是tomcat, 提供给jetty等容器,将静态资源映射从/更改为/static/目录,以访问http://localhost/foo.css,但当前为http://localhost/static/foo.css -- -静态文件--servlet-mapping servlet-name default/servlet-name URL-pattern/js/*/URL-pattern URL -。
Tomcat,Jetty,JBoss,and GlassFish的默认servlet的名称-- 'default '
Resin默认servlet的名称-- 'resin-file '
WebLogic默认servlet的名称--' file servlet '
WebSphere默认servlet的名称-- 'SimpleFileServlet '
如果所有web APP应用程序服务器的缺省servlet名称不是" default ",则必须在“default-servlet-name属性”视图中指定。
MVC : default-servlet-handler default-servlet-name='使用的Web服务器缺省servlet名称' /
第二,使用mvc:resources /,将以下代码添加到springmvc配置文件中:
<mvc:resources mapping="/js/**" location="/static_resources/javascript/"/> <mvc:resources mapping="/styles/**" location="/static_resources/css/"/> <mvc:resources mapping="/images/**" location="/static_resources/images/"/>
3.自定义拦截器
SpringMVC的拦截器HandlerInterceptorAdapter对应提供了三个preHandle,postHandle,afterCompletion方法。preHandle在业务处理器处理请求之前被调用,postHandle在业务处理器处理请求执行完成后,生成视图之前执行,afterCompletion在DispatcherServlet完全处理完请求后被调用,可用于清理资源等 。所以要想实现自己的权限管理逻辑,需要继承HandlerInterceptorAdapter并重写其三个方法。
首先在springmvc.xml中加入自己定义的拦截器我的实现逻辑CommonInterceptor,
<!--配置拦截器, 多个拦截器,顺序执行 --> <mvc:interceptors> <mvc:interceptor> <!-- 匹配的是url路径, 如果不配置或/**,将拦截所有的Controller --> <mvc:mapping path="/" /> <mvc:mapping path="/user/**" /> <mvc:mapping path="/test/**" /> <bean class="com.alibaba.interceptor.CommonInterceptor"></bean> </mvc:interceptor> <!-- 当设置多个拦截器时,先按顺序调用preHandle方法,然后逆序调用每个拦截器的postHandle和afterCompletion方法 --> </mvc:interceptors>
我的拦截逻辑是“在未登录前,任何访问url都跳转到login页面;登录成功后跳转至先前的url”,具体代码如下:
/** * */package com.alibaba.interceptor;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.web.servlet.ModelAndView;import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;import com.alibaba.util.RequestUtil;/** * @author tfj * 2014-8-1 */public class CommonInterceptor extends HandlerInterceptorAdapter{private final Logger log = LoggerFactory.getLogger(CommonInterceptor.class);public static final String LAST_PAGE = "com.alibaba.lastPage";/* * 利用正则映射到需要拦截的路径 private String mappingURL; public void setMappingURL(String mappingURL) { this.mappingURL = mappingURL; } */ /** * 在业务处理器处理请求之前被调用 * 如果返回false * 从当前的拦截器往回执行所有拦截器的afterCompletion(),再退出拦截器链 * 如果返回true * 执行下一个拦截器,直到所有的拦截器都执行完毕 * 再执行被拦截的Controller * 然后进入拦截器链, * 从最后一个拦截器往回执行所有的postHandle() * 接着再从最后一个拦截器往回执行所有的afterCompletion() */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if ("GET".equalsIgnoreCase(request.getMethod())) { RequestUtil.saveRequest(); } log.info("==============执行顺序: 1、preHandle================"); String requestUri = request.getRequestURI();String contextPath = request.getContextPath();String url = requestUri.substring(contextPath.length()); log.info("requestUri:"+requestUri); log.info("contextPath:"+contextPath); log.info("url:"+url); String username = (String)request.getSession().getAttribute("user"); if(username == null){ log.info("Interceptor:跳转到login页面!"); request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response); return false; }else return true; } /** * 在业务处理器处理请求执行完成后,生成视图之前执行的动作 * 可在modelAndView中加入数据,比如当前时间 */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { log.info("==============执行顺序: 2、postHandle================"); if(modelAndView != null){ //加入当前时间 modelAndView.addObject("var", "测试postHandle"); } } /** * 在DispatcherServlet完全处理完请求后被调用,可用于清理资源等 * * 当有拦截器抛出异常时,会从当前拦截器往回执行所有的拦截器的afterCompletion() */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { log.info("==============执行顺序: 3、afterCompletion================"); } }
注:上述代码里我写了一个RequestUtil,主要实现获取当前Request、Session对象,保存和加密页面,取出等功能。
至此,拦截器已经实现了,效果如图:
我直接访问/test/hello,会被拦截
登录成功后会跳转至/test/hello对应的页面