谈一谈struts2和springmvc的拦截器

最近涉及到了两个项目,都需要考虑全局的拦截器,其功能就是判断session的登陆状态,如果session信息完好,可以从中取得相应的信息,则放行,否则拦截,进入重定向的uri。

既然是全局的拦截器,其拦截的东西当然会很多也就是会很忙,相应的其功能也会非常丰富,可以在其中进行多种功能的拦截,本文就只考虑session的拦截。

以前是使用Filter加一个全局的过滤器,过滤web.xml中配置的url,通过request获取session,如果符合判断条件,则放行,否则做出相应的处理。从原理上来说,使用框架的拦截器跟Filter是一样的,只不过封装的更好,更能更加强大,通用性更强。

从源码上来看:

Filter接口:

public interface Filter {

	public void init(FilterConfig filterConfig) throws ServletException;

    	public void doFilter ( ServletRequest request, ServletResponse response, FilterChain chain ) throws IOException, ServletException;

	public void destroy();

}

SpringMVC拦截器接口:

public interface HandlerInterceptor {

	boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception; void postHandle(
HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception; void afterCompletion(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception; }

struts2拦截器接口:

public interface Interceptor extends Serializable {

    void destroy();

    void init();

    String intercept(ActionInvocation invocation) throws Exception;
}

可以看到接口中都是有三个方法,作用就是在做前置工作、本职工作、后续工作。但配置上稍有不同,先谈SpringMVC:

<servlet>
<servlet-name>JeeCmsAdmin</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/jeecms-servlet-admin.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
        <servlet-name>JeeCmsAdmin</servlet-name>
        <url-pattern>/jeeadmin/jeecms/*</url-pattern>
</servlet-mapping>

jeecms-servlet-admin.xml(部分)

<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<list>
<ref bean="adminContextInterceptor"/>
<ref bean="adminLocaleIntercept"/>
<ref bean="fireWallInterceptor"/>
</list>
</property>
</bean>
<bean id="adminContextInterceptor" class="com.jeecms.cms.web.AdminContextInterceptor">
<property name="auth" value="true"/>
<property name="loginUrl" value="/jeeadmin/jeecms/login.do"/>
<property name="returnUrl" value="/jeeadmin/jeecms/index.do"/>
<property name="excludeUrls">
<list>
<value>/login.do</value>
<value>/logout.do</value>
</list>
</property>
</bean>
<bean id="adminLocaleIntercept" class="com.jeecms.cms.web.AdminLocaleInterceptor"/> <bean id="fireWallInterceptor" class="com.jeecms.cms.web.FireWallInterceptor">
</bean>

AdminContextInterceptor.java(部分)

  1. /**
  2. * 在业务处理器处理请求之前被调用
  3. * 如果返回false
  4. *     从当前的拦截器往回执行所有拦截器的afterCompletion(),再退出拦截器链
  5. *
  6. * 如果返回true
  7. *    执行下一个拦截器,直到所有的拦截器都执行完毕
  8. *    再执行被拦截的Controller
  9. *    然后进入拦截器链,
  10. *    从最后一个拦截器往回执行所有的postHandle()
  11. *    接着再从最后一个拦截器往回执行所有的afterCompletion()
  12. */ 
    public boolean preHandle(HttpServletRequest request,
    HttpServletResponse response, Object handler) throws Exception {
    // 获得站点
    CmsSite site = getSite(request, response);
    CmsUtils.setSite(request, site);
    // Site加入线程变量
    CmsThreadVariable.setSite(site);

    // 获得用户
    CmsUser user = null;
    if (adminId != null) {
    // 指定管理员(开发状态)
    user = cmsUserMng.findById(adminId);
    if (user == null) {
    throw new IllegalStateException("User ID=" + adminId
    + " not found!");
    }
    } else {
    // 正常状态
    Integer userId = authMng
    .retrieveUserIdFromSession(session, request);
    if (userId != null) {
    user = cmsUserMng.findById(userId);
    }
    }
    // 此时用户可以为null
    CmsUtils.setUser(request, user);
    // User加入线程变量
    CmsThreadVariable.setUser(user);

    String uri = getURI(request);
    // 不在验证的范围内
    if (exclude(uri)) {
    return true;
    }
    // 用户为null跳转到登陆页面
    if (user == null) {
    response.sendRedirect(getLoginUrl(request));
    return false;
    }
    // 用户不是管理员,提示无权限。
    if (!user.getAdmin()) {
    request.setAttribute(MESSAGE, MessageResolver.getMessage(request,
    "login.notAdmin"));
    response.sendError(HttpServletResponse.SC_FORBIDDEN);
    return false;
    }
    // 不属于该站点的管理员,提示无权限。
    if (!user.getSites().contains(site)) {
    request.setAttribute(MESSAGE, MessageResolver.getMessage(request,
    "login.notInSite"));
    response.sendError(HttpServletResponse.SC_FORBIDDEN);
    return false;
    }
    boolean viewonly = user.getViewonlyAdmin();
    // 没有访问权限,提示无权限。
    if (auth && !user.isSuper()
    && !permistionPass(uri, user.getPerms(), viewonly)) {
    request.setAttribute(MESSAGE, MessageResolver.getMessage(request,
    "login.notPermission"));
    response.sendError(HttpServletResponse.SC_FORBIDDEN);
    return false;
    }
    return true;
    }

struts2的拦截器:

web.xml

<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.FilterDispatcher
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

从这个配置可以看出,struts2依然采取过滤器的方式,这个配置与过滤器一模一样,只是struts2进行了若干封装而已。

struts.xml配置:

<struts>
<constant name="struts.objectFactory" value="spring" />
<constant name="struts.devMode" value="true" />
<constant name="struts.i18n.encoding" value="UTF-8"/>
<!-- 全局拦截器 add by fdk -->
<package name="checkLogin" extends="struts-default">
<interceptors>
<interceptor name="noLogin"
class="com.tjhq.exception.AuthorityInterceptor" />
<interceptor-stack name="appStack">
<interceptor-ref name="defaultStack" />(必须加,否则出错)
</interceptor-stack> <interceptor-stack
name="defaultPaginationInterceptorStack">(这句是设置所有Action自动调用的拦截器堆栈)
<interceptor-ref name="noLogin" />
</interceptor-stack>
</interceptors>
<default-interceptor-ref
name="defaultPaginationInterceptorStack" /> <global-results>
<result name="login" type="redirect">${pageContext.request.contextPath}/login.jsp</result>
</global-results>
</package> <package name="strutsCheckLogin" extends="struts-default">
<interceptors>
<interceptor name="noLogin"
class="com.tjhq.exception.AuthorityInterceptor" />
<interceptor-stack name="appStack">
<interceptor-ref name="defaultStack" />
</interceptor-stack>
<interceptor-stack
name="defaultPaginationInterceptorStack">
<interceptor-ref name="noLogin" />
<interceptor-ref name="appStack" />
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="defaultPaginationInterceptorStack" /> <global-results>
<result name="login" type="redirect">${pageContext.request.contextPath}/login.jsp</result>
<result name="noframe" type="redirect">${pageContext.request.contextPath}/pages/error.jsp</result>
</global-results> <global-exception-mappings>
<exception-mapping result="noframe" exception="com.tjhq.exception.AppException"></exception-mapping>
</global-exception-mappings>
</package>
<include file="struts2/pub.xml" />
<include file="struts2/collect.xml" />
<include file="struts2/audit.xml" />
<include file="struts2/publish.xml" />
<include file="struts2/search.xml" />
<include file="struts2/statistics.xml" />
<include file="struts2/sysmanager.xml" />
<include file="struts2/portal.xml" />
<include file="struts2/compre.xml" />
</struts>

AuthorityInterceptor.java

public String intercept(ActionInvocation ai) throws Exception {

		ActionContext ctx = ai.getInvocationContext();
Map session = ctx.getSession();
if(ServletActionContext.getRequest().getSession().getAttribute(Constants.USER_ID_SESSION)==null){
this.setSessionByUserId(session);
}
String ACCOUNT_ID = (String)session.get(Constants.USER_ID_SESSION);
SysUserBean sb = (SysUserBean)session.get(Constants.USER_ACCOUNT_SESSION);
if(sb != null &&
ACCOUNT_ID != null && ACCOUNT_ID.length()>0){
_logger.info("user loginning");
return ai.invoke();//放行,进入下一个拦截器
}
_logger.info("intercept user is not login");
session.put("message", Dresource.getPropertie(Constants.PropertyKeys.NOT_LOGIN));
return "login";//进入上文蓝色位置
}
上一篇:.Net Core在Centos7上初体验


下一篇:使用XML设计某大学主页站点地图--ASP.NET