七、Struts2的拦截器

  通过前面的学习,我们了解到Action才是具体处理用户的业务实现部分,但有的时候我们需要在Action处理业务之前进行有效性校验或数据类型转换,或者在Action处理业务之后进行日志记录或转换等,而且这些操作是低耦合,可自定义动态拆卸的。因此,就引入了Struts2拦截器的概念。

主要内容:

1.什么是Struts拦截器;
2.Struts拦截器的工作原理;
3.如何在struts.xml中配置使用Struts拦截器;
4.Struts2框架所提供的内置拦截器;
5.自定义Struts拦截器。
6.案例:自定义拦截器实现用户登录权限控制

1.什么是Struts拦截器

  拦截器是Struts2框架的重要组成部分,Struts2的很多功能都是构建在拦截器之上的,如数据校验、转换器、国际化等。
作用:它可以动态拦截Action调用的对象,类似于Servlet中的过滤器。
其中,
单个拦截器:可以完成单个功能。
(多个)拦截器链:不同功能的拦截器按照一定的顺序排列在一起形成的链。
拦截器栈:拦截器链组成的集合。

2.Struts拦截器的工作原理;

  Struts2的拦截器是AOP (Aspect-Object-Programming,面向切面编程)的一种实现策略,是可插拔的。它可以任意地组合Action提供的附加功能,而不需要修改Action的代码,开发者只需要提供拦截器的实现类,并将其配置在struts.xml中即可。

七、Struts2的拦截器_第1张图片
拦截器与Action之间的执行顺序

  当用户触发事件,系统会在struts.xml配置文件中寻找对应的Action配置信息时,根据配置信息会先执行附加到Action之上的拦截器,然后再执行Action对象。

3.如何在struts.xml中配置使用Struts拦截器;

  因为拦截器与Action之间处在一种关联关系,因此,我们需要现在struts.xml中声明它们的这种关系,系统才能根据配置信息顺序执行。
  在struts.xml中声明拦截器,使用的是标签

1.配置单个拦截器


    paramValue

七、Struts2的拦截器_第2张图片
struts.xml中配置单个拦截器

2.配置拦截器栈(多个拦截器)


    
        
        ...
    

七、Struts2的拦截器_第3张图片
struts.xml中配置拦截器栈.png

3.配置当前所使用的默认拦截器


七、Struts2的拦截器_第4张图片
struts.xml中配置默认拦截器

4.Struts2框架所提供的内置拦截器;

  Struts2利用其内建的拦截器其实已经可以完成大部分的操作, 当内置拦截器不能满足时,开发者也可以自己扩展。
  Struts2中内置了许多拦截器,这些拦截器以name-class对的形式配置在struts-default.xml文件中。

name 是拦截器的名称,也就是引用的名字;
class 是指定了该拦截器所对应的实现类。

  在项目中,只要自定义的包继承了Struts2的struts-default包,就可以使用默认包中所定义的这些内建拦截器。在struts-default.xml中,每一个拦截器都具有不同的意义和功能。

在struts-core-2.3.24.jar包中的根目录下找到struts-default.xml文件,打开后找到元素下的内建拦截器和拦截器栈。

5.自定义Struts拦截器。

  在实际的项目开发中,Struts2的内置拦截器可以完成大部分的拦截任务。但是,一些与系统逻辑业务逻辑相关的通用功能(如权限的控制、用户登录控制等),则需要通过自定义拦截器类来实现功能。

方法一:实现Interceptor接口

  在程序开发过程中,如果需要开发自己的拦截器类,就需要直接或间接的实现com.opensymphony.xwork2.interceptor.Interceptor接口。

public interface Interceptor extends Serializable {
        void init();
        void destroy();
        String intercept(ActionInvocation invocation) throws Exception;
}

  如果需要自定义拦截器,只需要实现Interceptor接口的三个方法即可。

  • init()方法在拦截器被创建后会立即被调用, 它在拦截器的生命周期内只被调用一次. 可以在该方法中对相关资源进行必要的初始化。
  • destroy()方法与init()方法相对应,在拦截器实例被销毁之前,将调用该方法来释放和拦截器相关的资源。它在拦截器的生命周期内,也只被调用一次。
  • Intercep()方法是拦截器的核心方法,用来添加真正执行拦截工作的代码,实现具体的拦截操作。它返回一个字符串作为逻辑视图,系统根据返回的字符串跳转到对应的视图资源。每拦截一个动作请求, 该方法就会被调用一次。该方法的ActionInvocation参数包含了被拦截的Action的引用,可以通过该参数的invoke()方法,将控制权转给下一个拦截器或者转给Action的execute()方法。

方法二:继承AbstractIntercepter类(建议)

  该类实现了Interceptor接口,并且提供了init()方法和destroy()方法的空实现。使用时,可以直接继承该抽象类,而不用实现那些不必要的方法。因此,使用更为简单方便。

public abstract class AbstractInterceptor implements Interceptor {
        public void init() {}
        public void destroy() {}
        public abstract String intercept(ActionInvocation invocation) 
              throws Exception;
}

用法:

  只需继承AbstractInterceptor类,实现interceptor()方法就可以创建自定义拦截器。
  只有当自定义的拦截器需要打开系统资源时,才需要覆盖AbstractInterceptor类的init()方法和destroy()方法。

  • 总结:自定义拦截器的流程
    1.必须实现Interceptor接口或继承AbstractInterceptor类;
    2.需要在Struts.xml中声明自定义的拦截器;
    3.在Struts.xml中的Action中使用拦截器。

6.案例:自定义拦截器实现用户登录权限控制

1.web.xml:引入Struts框架的包,并把Struts框架配置到项目中;
2.login.jsp:用户登录页面
3.User.java:模型实体类(JavaBean),作为传输参数Model;
4.LoginAction:验证登录的业务处理;
5.main.jsp:用户登录成功后,自动跳转到主页;
6.OperationAction:(用户登录后)用户操作的业务处理;
7.PrivilegeInterceptor.java:自定义拦截器,用于拦截没登录的用户。
8.success.jsp:用户操作成功所跳转到的模拟页面;
9.struts.xml:Struts框架的路由配置文件。

1.web.xml

先创建Web项目LoginPower,把Struts框架的包都引入到项目WebContent—WEB-INF—lib中,并把Struts框架配置到项目的web.xml中;



  
    struts2
    org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
  
  
    struts2
    /*
  
  
    main.jsp
  

2.login.jsp

在WebContent目录下新建用户登录页面login.jsp。

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>



登录


${requestScope.msg}

3.User.java

模型实体类(JavaBean),作为传输参数Model;
在项目Java Resource—src中新建一个cn.demo.domain包,用于存放所有的Model,并在里面新建一个JavaBean实体类:User用户类

package cn.demo.domain;
public class User {
    private String username; //用户名
    private String password; //密码
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}

4.LoginAction

验证登录的业务处理;
在项目Java Resource—src中新建一个cn.demo.action包,用于存放所有的Action类。在里面新建LoginAction.java用于实现用户登录验证的功能。

package cn.demo.action;

import cn.demo.domain.User;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
public class LoginAction extends ActionSupport implements ModelDriven {
    private static final long serialVersionUID = 1L;
    private User user = new User();
    @Override
    public User getModel() {
        return user;
    }
    @Override
    public String execute() throws Exception {
        //获取ActionContext
        ActionContext actionContext = ActionContext.getContext();
        if ("xiao".equals(user.getUsername())
                && "zhbit".equals(user.getPassword())) {
            // 将用户存储在session中.
            actionContext.getSession().put("user", user);
            return SUCCESS;
        } else {
            actionContext.put("msg", "用户名或密码不正确");
            return INPUT;
        }
    }
}

5.main.jsp

在WebContent目录下新建main.jsp;用于用户登录成功后,自动跳转到主页;

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>


    
    main.jsp
  
  
    增加功能
更新功能
删除功能
查询功能

6.OperationAction

(用户登录后)用户操作的业务处理;
在项目Java Resource—src的cn.demo.action包中,新建OperationAction.java用于实现用户登录后可执行的操作。

package cn.demo.action;

import com.opensymphony.xwork2.ActionSupport;
@SuppressWarnings("serial")
public class OperationAction extends ActionSupport {
    public String add() {
        System.out.println("增加功能 执行代码……");
        return SUCCESS;
    }
    public String del() {
        System.out.println("删除功能 执行代码……");
        return SUCCESS;
    }
    public String update() {
        System.out.println("更新功能 执行代码……");
        return SUCCESS;
    }
    public String find() {
        System.out.println("查询功能 执行代码……");
        return SUCCESS;
    }
}

7.PrivilegeInterceptor.java

自定义拦截器,用于拦截没登录的用户。
在项目Java Resource—src中新建一个cn.demo.interceptor包,用于存放所有的自定义拦截器。在里面新建PrivilegeInterceptor.java用于实现拦截没登录成功的用户。

package cn.demo.interceptor;

import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class PrivilegeInterceptor extends AbstractInterceptor {
    private static final long serialVersionUID = 1L;
    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        ActionContext actionContext = invocation.getInvocationContext();// 得到ActionContext.
        Object user = actionContext.getSession().get("user");//获取user对象
        if (user != null) {
            return invocation.invoke(); // 继续向下执行.
        } else {
            actionContext.put("msg", "您还未登录,请先登录");
            return Action.LOGIN; //如果用户不存在,返回login值
        }
    }
}

8.success.jsp

在WebContent目录下新建success.jsp,用于用户操作成功所跳转到的成功提示页面;

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>



操作成功页面


    用户:${user.username} 执行管理操作成功!


9.struts.xml

Struts框架的路由配置文件。
在src文件中新建struts.xml配置文件,用于本项目中所有的包、拦截器、Action等。




    
        
        
            
            
            
            
                
                
            
        
        
        
        
            /main.jsp
            /login.jsp
        
        
        
            /success.jsp
            /login.jsp
            
            
        
    

运行效果

1.项目启动时,默认访问登录页面login.jsp


七、Struts2的拦截器_第5张图片
项目默认启动login.jsp

2.但如果用户直接访问main.jsp时,也能显示相应功能。此时,就需要通过Interceptor拦截器控制用户权限。


七、Struts2的拦截器_第6张图片
main.jsp主页

3.如果用户点击操作功能,则拦截,并返回登录页面
七、Struts2的拦截器_第7张图片
拦截后返回login.jsp登录页

4.只有用户输入用户名:xiao和密码:zhbit后,才被拦截器放行。


七、Struts2的拦截器_第8张图片
登录后可执行操作

作者: 肖sir@ZHBIT
2018 年 09月 27日


你可能感兴趣的:(七、Struts2的拦截器)