Struts2拦截器的简单应用,登录权限拦截器及与过滤器的区别(八)下

简介: Struts2拦截器的简单应用,登录权限拦截器及与过滤器的区别(八)

四 MethodFilterInterceptor类 源码分析


在实际开发中,配置拦截器,常常使用的是 MethodFilterInterceptor,


从方法名称中,也可以看出,拦截的是Action中的某些方法。


尝试着分析一下源码.(老蝴蝶偷偷不要脸一次)


package com.opensymphony.xwork2.interceptor;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.omg.CORBA.PRIVATE_MEMBER;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptorUtil;
import com.opensymphony.xwork2.util.TextParseUtil;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
//继承了AbstractInterceptor类,实现的方法由以前的interceptor()方法改成了doIntercept()方法
public abstract class MethodFilterInterceptor extends AbstractInterceptor {
  private static final long serialVersionUID = 1L;
  protected transient Logger log = LoggerFactory.getLogger(getClass());
  /**
   * MethodFilterInterceptor 类的两个参数 ,均用Set集合
   * 学到一招,在类中实例时时,不要在private Set<User> userSet=new HashSet<User>();了
   * 试试Collections.emptySet()实例化. List时用Collections.emptyList();方法
   * @param excludeMethods 不拦截器的方法. 如注册,找回密码等方法
   * @param includeMethods 要拦截的方法, 如登录,查看用户列表等方法
   */
  protected Set<String> excludeMethods = Collections.emptySet();
  protected Set<String> includeMethods = Collections.emptySet();
  //实现两个参数的setter和getter方法
  public void setExcludeMethods(String excludeMethods) {
    //这个方法如下
    this.excludeMethods = TextParseUtil.commaDelimitedStringToSet(excludeMethods);
    /*
     * 这个方法很明显,就是将字符串按照,进行分隔,然后分别放置到set集合中。
     *public static Set<String> commaDelimitedStringToSet(String s)
         {
            Set<String> set = new HashSet();
            String[] split = s.split(",");
            for (String aSplit : split) {
              //你看看人处理的,先将两边的空格去掉.
              String trimmed = aSplit.trim();
              //又判断一下长度
               if (trimmed.length() > 0)
                   set.add(trimmed);
                }
              return set;
           }
       */
  }
  public Set<String> getExcludeMethodsSet() {
    return excludeMethods;
  }
  public void setIncludeMethods(String includeMethods) {
    this.includeMethods = TextParseUtil.commaDelimitedStringToSet(includeMethods);
  }
  public Set<String> getIncludeMethodsSet() {
    return includeMethods;
  }
  //实现了intercept()方法.
  public String intercept(ActionInvocation invocation) throws Exception {
    if (applyInterceptor(invocation)) {
      //如果包括的方法,执行这一个
      return doIntercept(invocation);
    }
    //不是包括的方法,执行这一个。
    return invocation.invoke();
  }
  protected boolean applyInterceptor(ActionInvocation invocation) {
    //利用代理模式的方式得到方法
    String method = invocation.getProxy().getMethod();
    /*
     * 进入看了看这个方法,如果是排除的方法,就返回false.
     *        如果是包括的方法,就返回true。
     */
    boolean applyMethod = MethodFilterInterceptorUtil.applyMethod(excludeMethods, includeMethods, method);
    if ((log.isDebugEnabled()) && (!applyMethod)) {
      log.debug("Skipping Interceptor... Method [" + method + "] found in exclude list.", new String[0]);
    }
    return applyMethod;
  }
  //需要实现的核心方法
  protected abstract String doIntercept(ActionInvocation paramActionInvocation) throws Exception;
}


五. MethodFilterInterceptor类 的具体使用


用一个具体的登录实例验证一下吧。


其中实例是按照第四章的两个小例子进行相应的仿写的。


五.一 编写控制器类UserAction


在UserAction中常用的方法如下:


public class UserAction extends BaseAction<User>{
  private static final long serialVersionUID = 1L;
  private Logger logger=Logger.getLogger(UserAction.class);
  private UserService userSerive=new UserService();
  /**
   * 转到登录的页面
   */
  public String toLogin(){
    logger.info("跳转到登录的界面");
    return "toLogin";
  }
  /**
   * 具体的登录方法
   */
  public String login(){
    logger.info("执行具体的登录操作");
    User user=userSerive.login(getModel());
    if(user!=null) {
      //说明存在这个用户
      //登录成功后,将登录的用户放置到session中.
      ActionContext.getContext().getSession().put("currentUser",user);
      return LOGIN;
    }else {
      HttpServletRequest request=ServletActionContext.getRequest();
      request.setAttribute("message","用户名或者密码错误");
      return "toLogin";
    }
  }
  /**
   * 跳转到注册的页面
   */
  public String toRegisterUI(){
    logger.info("跳转到注册的界面");
    return "toRegisterUI";
  }
  /**
   * 进行用户的注册,注册成功之后跳转到登录的界面
   * 注册成功之后,不把数据带到登录页面进行填充.
   */
  public String register(){
    logger.info("执行具体的注册功能");
    return "toLogin";
  }
  /**
   * 用户点击忘记密码后跳转到忘记密码的界面
   */
  public String forgetPasswordUI(){
    logger.info("跳转到忘记密码的界面");
    return "forgetPasswordUI";
  }
  /**
   * 用户在忘记密码界面添加新的密码后执行修改密码
   * 修改密码成功后跳转到登录界面
   */
  public String forgetPassword(){
    logger.info("添加新的密码后修改密码");
    return "toLogin";
  }
  /**
   * 显示列表
   */
  public String list(){
    logger.info("显示用户列表");
    List<User> userList=userSerive.findAll();
    ActionContext.getContext().put("userList",userList);
    return "list";
  }
  /**
   *跳转到添加的界面
   */
  public String addUI(){
    logger.info("跳转到添加的界面");
    return "addUI";
  }
  /**
   *执行具体的添加操作后,返回到list列表显示。
   */
  public String add(){
    logger.info("执行具体的添加操作");
    return "toList";
  }
  /**
   * 跳转到修改的界面
   */
  public String editUI(){
    logger.info("跳转到修改的界面");
    return "editUI";
  }
  /**
   * 执行具体的修改操作,修改完成后返回到列表的界面
   */
  public String edit(){
    logger.info("执行具体的修改操作");
    return "toList";
  }
  /**
   * 执行具体的删除操作,删除成功后返回到列表的界面
   */
  public String delete(){
    logger.info("执行具体的删除操作");
    return "toList";
  }
  /**
   * 点击名字,显示具体的详情
   */
  public String detailUI(){
    logger.info("显示具体的详情操作");
    return "detailUI";
  }
}


其中

toLogin(); login(); toRegisterUI(); register();forgetPasswordUI();forgetPassword();是不需要进行登陆拦截的,


list()及其以下方法,是需要登录拦截的。


如果toRegisterUI()方法也被拦截的话,那么是无法进行注册功能的。


五.二 根据Action中的返回值配置相应的struts.xml文件


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
  "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
  "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
  <!--修改国际化编码 -->
  <constant name="struts.i18n.encoding" value="UTF-8"></constant>
  <!--修改是否为开发者模式 -->
  <constant name="struts.devMode" value="true"></constant>
  <!--修改ui样式表 -->
  <constant name="struts.ui.theme" value="simple"></constant>
  <package name="methodInterceptor" extends="struts-default" namespace="/">
    <!-- 配置全局错误页面 -->
    <global-results>
      <result name="error">/WEB-INF/content/error.jsp</result>
    </global-results>
    <action name="User_*" class="com.yjl.web.action.UserAction" method="{1}">
        <!-- 转到登录页面的配置 -->
        <result name="toLogin">/WEB-INF/content/login.jsp</result>
        <!-- 登录的配置 -->
        <result name="login" type="redirectAction">User_list.action</result>
        <result name="toRegisterUI">/WEB-INF/content/register.jsp</result>
        <result name="forgetPasswordUI">/WEB-INF/content/forgetPassword.jsp</result>
        <result name="list">/WEB-INF/content/list.jsp</result>
        <result name="addUI">/WEB-INF/content/add.jsp</result>
        <result name="toList" type="redirectAction">User_list.action</result>
        <result name="editUI">/WEB-INF/content/edit.jsp</result>
        <result name="detailUI">/WEB-INF/content/detail.jsp</result>
        <result name="success">/WEB-INF/content/form.jsp</result>
    </action>
  </package>
</struts>


五.三 根据struts.xml中的配置视图编写相应的jsp页面


20200413111523904.png


每一个jsp 页面 都引入了 struts2 标签库


<%@ taglib uri="/struts-tags"  prefix="s"%>


五.三.一 编写登录页面 /content/login.jsp


<body>
  ${message}
  <s:form action="User_login.action" namespace="/" method="post">
      用户名: <s:textfield  name="name"/>  <br/>
      密码: <s:password name="password"/><br/>
      <s:a action="User_forgetPasswordUI" namespace="/">忘记密码</s:a><br/>
      <s:a action="User_toRegisterUI" namespace="/">注册新用户</s:a><br/>
        <s:submit value="提交"/>
        <s:reset value="重置"/>
  </s:form>
</body>


五.三.二 编写注册页面 /content/register.jsp


<body>
  这是注册的界面
  <s:form action="User_register" namespace="/" method="post">
    <s:submit value="注册"></s:submit>
  </s:form>
</body>


五.三.三 编写忘记密码页面 /content/forgetPassword.jsp


<body>
  这是忘记密码的界面
  <s:form action="User_forgetPassword" namespace="/" method="post">
    <s:submit value="确认找回密码"></s:submit>
  </s:form>
</body>


五.三.四 编写查看页面 /content/list.jsp


<body>
  <div class="container">
    <div class="row">
      <table class="table table-bordered table-hover">
        <caption>查看学生信息</caption>
        <thead>
          <tr>
            <th class="col-xs-2">姓名</th>
            <th class="col-xs-2">性别</th>
            <th class="col-xs-2">年龄</th>
            <th class="col-xs-2">关系</th>
            <th class="col-xs-4" colspan="3">相关操作 
                  <span style="padding-left:40px">
                      <s:a action="User_addUI" namespace="/">添加</s:a>
                  </span>
            </th>
          </tr>
        </thead>
        <tbody>
          <s:iterator var="user" value="%{userList}">
              <tr>
                <td><s:a action="User_detailUI?id=%{id}" namespace="/">${user.name}</s:a></td>
                <td>${user.sex}</td>
                <td>${user.age}</td>
                <td>${user.relation}</td>
                <td>
                  <s:a action="User_editUI?id=%{id}" namespace="/">修改</s:a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                  <s:a action="User_delete?id=%{id}" namespace="/">删除</s:a>
              </tr>
          </s:iterator>
        </tbody>
      </table>
    </div>
  </div>
</body>


五.三.五 编写添加页面 /content/add.jsp


<body>
  这是添加的界面
  <s:form action="User_add" namespace="/" method="post">
    <s:submit value="添加"></s:submit>
  </s:form>
</body>


五.三.六 编写修改页面 /content/edit.jsp


<body>
  这是修改的界面
  <s:form action="User_edit" namespace="/" method="post">
    <s:submit value="修改"></s:submit>
  </s:form>
</body>


五.三.七 编写查看详情页面 /content/detail.jsp


<body>
  这是修改的界面
  <s:form action="User_edit" namespace="/" method="post">
    <s:submit value="修改"></s:submit>
  </s:form>
</body>


五.四 重启服务器,看各个链接是否正常跳转


输入网址: http://localhost:8080/Struts_Interceptor/User_toLogin


点击各个链接,发现各个功能正常跳转,


链接跳转显示页面正确,日志打印输出正确。


五.五 编写登录拦截器 LoginInterceptor


package com.yjl.web.interceptor;
import javax.servlet.http.HttpSession;
import org.apache.log4j.Logger;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
import com.yjl.pojo.User;
/**
* @author 两个蝴蝶飞
* @version 创建时间:Aug 27, 2018 8:49:26 AM
* 类说明  登录拦截器
*/
public class LoginInterceptor extends MethodFilterInterceptor{
  private static final long serialVersionUID = 1L;
  private static Logger logger=Logger.getLogger(LoginInterceptor.class);
  @Override
  protected String doIntercept(ActionInvocation actionInvocation) throws Exception {
    HttpSession session=ServletActionContext.getRequest().getSession();
    User currentUser=(User) session.getAttribute("currentUser");
    //判断currentUser的值
    if(currentUser==null){
      //获取请求的方法
      String method=actionInvocation.getProxy().getMethod();
      //为空,表示没有登录
      logger.info(method+"方法需要被拦截,必须登录后使用");
      //没有登录,就跳转到登录的页面
      return "toLogin";
    }else{
      //登录,就放行  实际操作中,还有一个权限的判断
      String result=actionInvocation.invoke();
      logger.info("我操作:"+result);
      return result;
    }
  }
}


五.六 在struts.xml 配置登录拦截器,注意拦截和不需拦截方法的配置


<package name="methodInterceptor" extends="struts-default" namespace="/">
    <!-- 配置拦截器  注意顺序,放在global-results前面-->
    <interceptors>
      <interceptor name="loginInterceptor" class="com.yjl.web.interceptor.LoginInterceptor">
      </interceptor>
    </interceptors>
    <!-- 配置全局错误页面 -->
    <global-results>
      <result name="error">/WEB-INF/content/error.jsp</result>
      <!-- 转到登录页面的配置 -->
      <result name="toLogin">/WEB-INF/content/login.jsp</result>
    </global-results>
    <action name="User_*" class="com.yjl.web.action.UserAction" method="{1}">
        <interceptor-ref name="defaultStack"></interceptor-ref>
        <interceptor-ref name="loginInterceptor">
          <param name="excludeMethods">toLogin,login,toRegisterUI,register,forgetPasswordUI,forgetPassword</param>
          <param name="includeMethods">list,toList,addUI,add,editUI,edit,delete,detail</param>
        </interceptor-ref>
        <!-- 转到登录页面的配置 -->
        <result name="toLogin">/WEB-INF/content/login.jsp</result>
        <!-- 登录的配置 -->
        <result name="login" type="redirectAction">User_list.action</result>
        <result name="toRegisterUI">/WEB-INF/content/register.jsp</result>
        <result name="forgetPasswordUI">/WEB-INF/content/forgetPassword.jsp</result>
        <result name="list">/WEB-INF/content/list.jsp</result>
        <result name="addUI">/WEB-INF/content/add.jsp</result>
        <result name="toList" type="redirectAction">User_list.action</result>
        <result name="editUI">/WEB-INF/content/edit.jsp</result>
        <result name="detailUI">/WEB-INF/content/detail.jsp</result>
        <result name="success">/WEB-INF/content/form.jsp</result>
    </action>
</package>


开发中,不需要拦截的方法少, 一般只需要注入参数excludeMethods即可。


excludeMethods为不需要拦截的方法,


includeMethods为需要拦截的方法。


如果拦截的和不拦截的都有,那么以拦截为主。


五.七 重启服务器,验证拦截器是否起作用


重启服务器,


未登录成功时:


输入 http://localhost:8080/Struts_Interceptor/User_addUI 等网址,会跳转到登录页面,


输入 http://localhost:8080/Struts_Interceptor/User_forgetPasswordUI 等网址,会跳转到指定的 jsp页面。


登录成功后:


输入 http://localhost:8080/Struts_Interceptor/User_addUI 等网址,会正常跳转到指定的 jsp页面。


六. 拦截器与过滤器的区别


摘录于 https://www.cnblogs.com/joyang/p/4973435.html


过滤器,是在java web中,你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,

然后再传入servlet或者struts的 action进行业务逻辑,

比如过滤掉非法url(不是login.do的地址请求,如果用户没有登陆都过滤掉),

或者在传入servlet或者 struts的action前统一设置字符集,或者去除掉一些非法字符


拦截器,是在面向切面编程的就是在你的service或者一个方法,前调用一个方法,

或者在方法后调用一个方法比如动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),

也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作。


拦截器是基于java的反射机制的,而过滤器是基于函数回调。

拦截器不依赖与servlet容器,过滤器依赖与servlet容器。

拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。

拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。

在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次


这一章是关于拦截器的介绍,非常重要。


本章节的代码链接为:


链接:https://pan.baidu.com/s/18lQmPQzMVfpLF7lyfPKKHQ 
提取码:enw4


谢谢您的观看!!!

相关文章
|
6月前
过滤器&拦截器
过滤器&拦截器
55 0
过滤器&拦截器
|
Java 容器
过滤器和拦截器的区别
Filter 也称为过滤器,基于Servlet实现,拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行,基于AOP思想,对方法进行增强。和servlet 中的过滤器类似,都是对用户请求进行处理。
81 0
|
JSON 缓存 安全
自定义配置拦截器
自定义配置拦截器
120 0
|
Java 应用服务中间件 API
过滤器和拦截器
过滤器和拦截器
168 0
|
XML 存储 前端开发
struts2中的拦截器Interceptor,拦截器栈,Token口令拦截
struts2中的拦截器Interceptor,拦截器栈,Token口令拦截
143 0
struts2中的拦截器Interceptor,拦截器栈,Token口令拦截
|
前端开发 Java 数据安全/隐私保护
SpringMVC拦截器实现登录权限控制
SpringMVC的处理器拦截器,类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。 依赖于web框架,在实现上基于Java的反射机制,属于面向切面编程(AOP)的一种运用。由于拦截器是基于 web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个 controller生命周期之内可以多次调用。
|
JSON 运维 数据格式
[SpringMVC]拦截器②(拦截器参数、拦截器链配置)
拦截器②(拦截器参数、拦截器链配置)
[SpringMVC]拦截器②(拦截器参数、拦截器链配置)
|
Java 应用服务中间件 调度
SpringMVC——核心技术:拦截器(一个/多个、权限拦截器)
SpringMVC——核心技术:拦截器(一个/多个、权限拦截器)
SpringMVC——核心技术:拦截器(一个/多个、权限拦截器)
SpringMVC:拦截器和过滤器的区别
SpringMVC:拦截器和过滤器的区别
123 0
SpringMVC:拦截器和过滤器的区别
Struts2拦截器的简单应用,登录权限拦截器及与过滤器的区别(八)上
Struts2拦截器的简单应用,登录权限拦截器及与过滤器的区别(八)
151 0
Struts2拦截器的简单应用,登录权限拦截器及与过滤器的区别(八)上