JavaWeb框架_Struts2_(三)---->Struts2的拦截器-程序员宅基地

技术标签: java  开发工具  web.xml  

2. Struts2的拦截器(使用拦截器实现权限控制)

 

2.1 拦截器的概述

 

  拦截器是Struts2的核心组成部分,它可以动态的拦截Action调用的对象,类似与Servlet中的过滤器。Struts2的拦截器是AOP(Aspect-Object-Programming,面向切面编程)的一种实现策略,是可插拔的,需要某一个功能时就“插入”这个功能的拦截器,不需要这个功能就“拔出”拦截器。开发者只需要提供拦截器的实现类,并将其配置在Struts.xml中即可。

 

2.1.2 拦截器的工作原理

 

  通常情况下,拦截器都是一代理的方式调用的,它在一个Action执行前后进行拦截,围绕着Action和Result的执行而执行,其工作方式如下图所示,

  Struts2拦截器实现原理与Servlet过滤器实现原理类似,它以链式执行,对真正要执行的方法(execute())进行拦截。首先执行Action配置的拦截器,在Action和Result执行之后,拦截器会再次执行(与先前调用的顺序相反),在此链式执行的过程中,每一个拦截器都可以直接返回,从而终止余下的拦截器、Action及Result的执行。

  

2.1.3 拦截器的配置

 

(1) 拦截器

  拦截器的配置在struts.xml文件中完成的,它通常以<interceptor>标签开头,以</interceptor>标签结束。定义拦截器的语法格式如下:

 <interceptor name="interceptorName" class="interceptorClass">
            <param name="paramName">paramValue</param>
 </interceptor>

  上述语法格式中,name属性用来指定拦截器的名称,class属性用于指定拦截器的实现类。在定义时,使用<param>标签传入参数。

(2) 拦截器栈

  在实际开发中,在Action执行前同时执行多个拦截动作,如用户登陆检查等,这时可以把多个拦截器组成拦截器栈。在使用时,可以将栈内的多个拦截器当成一个整体来引用。当拦截器栈被附加到一个Action上时,在执行Action之前必须先执行拦截器栈中的每一个拦截器。

  定义拦截器栈使用<interceptors>和<interceptor-stack>子元素,当配置多个拦截器时,需要使用<interceptor-ref>元素来指定多个拦截器,配置语法如下:

   <interceptors>
          <interceptor-stack name="interceptorStackName">
              <interceptor-ref name="interceptorName"/>
              ...
          </interceptor-stack>
   </interceptors>

  上述语法中,interceptorStackName值表示配置的拦截器栈的名称,interceptorName值表示拦截器的名称。除此之外,在一个拦截器栈中还可以包含另一个拦截器栈,实例如下:

    <package name="default"namespace="/"extends="struts-default">
        <!--拦截器的声明-->
        <interceptors>
            <interceptor name="interceptor1" class="interceptorClass"/>
            <interceptor name="interceptor2" class="interceptorClass"/>
            <!--定义一个拦截器栈mystack,该拦截器栈中包括两个拦截器和一个拦截器栈-->
            <interceptor-stack name="mystack">
            <interceptor-ref name="defaultStack"/>
            <interceptor-ref name="interceptor1"/>
            <interceptor-ref name="interceptor2"/>
            </interceptor-stack>
        </interceptors>
    </package>

  上述代码中定义的拦截器栈是myStack,在myStack栈中,除了引用了两个自定义的拦截器interceptor1和interceptor2外,还引用了一个内置拦截器栈defaultStack,这个拦截器是必须要引入的。

(3) 默认拦截器栈

   默认拦截器可以对其指定包中的所有Action起到拦截的作用。一旦为某个包指定了默认拦截器,并且该包中的Action未显式地指定拦截器,则会使用默认拦截器。默认拦截器需要使用<default-interceptor-ref>元素,此元素为<package>元素的子元素。其语法格式如下:

 <default-interceptor-ref name="拦截器(栈)的名称"/>

  上述语法格式中,name属性的值必须是已经存在的拦截器或拦截器栈的名称。下面用该语法格式配置一个默认拦截器,示例代码如下:

<package name="default" namespace="/" extends="struts-default">

        <!--拦截器的声明-->
        <interceptors>
        <default-interceptor-ref name="拦截器栈的名称"/>
        <interceptors>
            <interceptor name="interceptor1" class="interceptorClass"/>
            <interceptor name="interceptor2" class="interceptorClass"/>
            <!--定义一个拦截器栈mystack,该拦截器栈中包括两个拦截器和一个拦截器栈-->
            <interceptor-stack name="mystack">
            <interceptor-ref name="defaultStack"/>
            <interceptor-ref name="interceptor1"/>
            <interceptor-ref name="interceptor2"/>
            </interceptor-stack>
        </interceptors>
        <!-- 配置该包下的默认拦截器,既可以是拦截器,也可以是拦截器栈 -->
        <default-interceptor-ref name="mystack"/>
        <action name="login"class="cn.itcast.action.LoginAction">
            <result name="input">/login.jsp</result>
        </action>

    </package>

  上述代码中,指定了包下的默认拦截器是一个拦截器栈,该拦截器栈将会作用于包下所有的Action。

  Notice:一个包下只能定义一个默认拦截器,如果需要多个拦截器作为默认拦截器,则可以将这些拦截器定义为一个拦截器栈,再将这个拦截器栈作为默认拦截器即可。

 

2.2 Struts2的内建拦截器

 

2.2.1 内建拦截器的介绍

  只要自定义的包继承了Struts2的struts-default包,就可以使用默认包中的拦截器,否则需要自己定义拦截器。在Struts-default.xml中每一个拦截器都具有不同的意义(具体拦截器说明--->省略)。

2.2.2 内建拦截器的配置

  前面2.1已经介绍过相关配置,此处不再赘述。

 

2.3 Struts2自定义拦截器

   

  struts2的内置拦截器可以实现大部分的拦截任务,但是一些与系统逻辑相关的通用功能(如权限的控制、用户登陆控制等),则需要通过自定义拦截器来实现。本节详讲如何自定义拦截器。

 

2.3.1 实现自定义拦截器

 

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

import com.opensymphony.xwork2.DefaultActionInvocation;
import java.io.Serializable;
public interface Interceptor extends Serializable { void init(); void destroy(); String interceptor (DefaultActionInvocation)throws Exception; }

  该接口提供一下三个方法:

  • void init():该方法在拦截器被创建后会立即被调用,它在拦截器的生命周期只有内只被调用一次。可以在该方法中对相关的资源进行必要的初始化;
  • void destroy():该方法与init()方法相对应,在拦截器实例被销毁之前,将调用该方法来释放与拦截器相关的资源。它在拦截器的生命周期内也只被调用一次。
  • Spring intercept(ActionInvocation invocation)throws Exception:该方法是拦截器的核心方法,用来真正执行拦截工作的代码,实现具体的拦截工作。

 

2.3.2 应用案例-----使用拦截器实现权限控制

 

  通过之前对拦截器学习,可以将自定义拦截器的使用分为一下三个步骤:

  1. 用户自定义拦截器类,必须实现Interceptor接口或者继承AbstractInterceptor类;
  2. 需要在struts.xml中,定义自定义拦截器;
  3. 在struts.xml中的Action中使用拦截器。

 

具体步骤如下:

 

(1)在intellij idea中创建Struts2的项目(可参考之前的博客 http://www.cnblogs.com/Mairr/p/7846747.html)

(2)web.xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!--首页(这一块儿是自己加进来的)-->
    <welcome-file-list>
        <welcome-file>main.jsp</welcome-file>
    </welcome-file-list>
</web-app>

(3)在src目录下创建java包,如下

(4)User.java

package cn.Mairr.domin;

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;
    }
}

(5)LoginAction.java

package cn.Mairr.action;

import cn.Mairr.domin.User;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

public class LoginAction extends ActionSupport implements ModelDriven <User> {
    private static final long serialVersionUID = 1L;
    private User user = new User();

    public User getModel() {
        return user;
    }

    @Override
    public String execute() throws Exception {
        //获取ActionContext
        ActionContext actionContext = ActionContext.getContext();

        if ("Mairr".equals(user.getUsername()) && "123".equals(user.getPassword())) {
            actionContext.getSession().put("user", user);
            return SUCCESS;
        } else {
            actionContext.put("msg", "用户名或者密码不正确");
            return INPUT;
        }
    }
}

(6) BookAction.java

package cn.Mairr.action;

import com.opensymphony.xwork2.ActionSupport;

public class BookAction extends ActionSupport {
    public String add(){
        System.out.println("book add");
        return SUCCESS;
    }
    public String del(){
        System.out.println("book del");
        return SUCCESS;
    }
    public String update(){
        System.out.println("book update");
        return SUCCESS;
    }
    public String find(){
        System.out.println("book find");
        return SUCCESS;
    }
}

(7)PrivilegeInterceptor.java

package cn.Mairr.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;
    public String intercept(ActionInvocation invocation)throws Exception{
        //得到ActionContext
        ActionContext actionContext = invocation.getInvocationContext();
        //获取user对象
        Object user = actionContext.getSession().get("user");
        if(user != null){
            return invocation.invoke();
        }else {
            actionContext.put("msg","您还未登录,请先登陆");
            return Action.LOGIN;       //用户如果不存在,返回login直
        }
    }
}

(8) main.jsp

<%--
  Created by IntelliJ IDEA.
  User: mairr
  Date: 17-11-28
  Time: 下午5:18
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>main.jsp</title>
</head>
<body>
    <a href="success.jsp">book del</a><br>
    <a href="success.jsp">book add</a><br>
    <a href="success.jsp">book update</a><br>
    <a href="success.jsp">book find</a><br>

</body>
</html>

(9) login.jsp

<%--
  Created by IntelliJ IDEA.
  User: mairr
  Date: 17-11-28
  Time: 下午5:17
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登陆</title>
</head>
<body>
   <center>
        ${requestScope.msg}<br>
        <form action="login.action" method="post">
            <table>
                <tr>
                    <td><label style="text-align: right;">用户名:</label></td>
                    <td><input type="text" name="username"></td>
                </tr>
                <tr>
                    <td><label style="text-align: right;">密码:</label></td>
                    <td><input type="password" name="password"></td>
                </tr>
                <tr>
                    <td align="right" colspan="2">
                        <input type="submit" value="登陆">
                    </td>
                </tr>
            </table>
        </form>
   </center>
</body>
</html>

(10)success.jsp

<%--
  Created by IntelliJ IDEA.
  User: mairr
  Date: 17-11-28
  Time: 下午5:42
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>成功页面</title>
</head>
<body>
用户${user.username}操作成功
</body>
</html>

(11) struts.xml配置:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
        "http://struts.apache.org/dtds/struts-2.5.dtd">

<struts>
    <package name="struts2" namespace="/" extends="struts-default">
        <!--声明拦截器-->
        <interceptors>
            <interceptor name="privilege" class="cn.Mairr.interceptor.PrivilegeInterceptor"/>
            <interceptor-stack name="mystack">
                <interceptor-ref name="defaultStack"/>
                <interceptor-ref name="privilege"/>
            </interceptor-stack>
        </interceptors>
        <!--用户登陆操作-->
        <action name="login" class="cn.Mairr.action.LoginAction">
            <result>/main.jsp</result>
            <result name="input">/login.jsp</result>
        </action>
        <!--关于book操作-->
        <action name="book_*" class="cn.Mairr.action.BookAction" method="{1}">
            <result>/success.jsp</result>
            <result name="login">/login.jsp</result>
            <!--在action中使用自定义拦截器-->
            <interceptor-ref name="mystack"/>
        </action>
    </package>
</struts>

 

 

  完成上述程序之后,发布程序,登录本机http端口,查看拦截器实现功能;(http://localhost:8080/login.jsp)

  • 登录界面如下:

 

--------->(登陆失败)

 

  • 登陆成功(用户名:Mairr   密码:123 )

----------->(登陆成功,页面跳转到操作界面)

 

-------->(选择操作)

 

  上面的案例中,创建了一个方法过滤拦截器PrivilegeInterceptor,然后在Struts.xml中配置了该拦截器,如果用户没有登陆,则无法对页面进行相应的操作,只有登陆后才有权操作页面的相应功能。

 

转载于:https://www.cnblogs.com/Mairr/p/7906086.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_30425949/article/details/97794673

智能推荐

gcc详解-程序员宅基地

文章浏览阅读282次。2019独角兽企业重金招聘Python工程师标准>>> ..._gcc.tar.gz的作用

python tornado中cookie_secret的生成方法-程序员宅基地

文章浏览阅读5.3k次。python tornado中cookie_secret的生成方法 from base64 import b64encode from uuid import uuid4 b64encode(uuid4().bytes + uuid4().bytes) 得到: 如 urnqS8z4RB6CENU+jEPvLqjXbinxQEsJlTwdp/ehx9Y=..._cookie_secret

sql服务启动不了(解决方法之一)_sql服务器无法启动-程序员宅基地

文章浏览阅读5.2k次。如果尝试了网上的各种方案,还是解决不了自启问题,可以尝试以下我的解决方案,在我自己的电脑上可行一开始我也在网上找了很多关于自动启动sql服务,可是一直都没有什么变化,也还是不能够自动启动,后面我无意之中发现了一种方法,可以解决开机自动启动sql服务首先,我们还是需要找到sql服务,并设置成自动或自动延时启动然后再找到下边这个界面点击更改当前不可用的设置,将启用快速启动取消掉即可,注:原本启用快速启动默认是选择的,我们只需要把这个选项取消就可以了,但是取消掉这个后,电脑启动时会延长_sql服务器无法启动

JavaWeb之相关点_java tiko爬虫-程序员宅基地

文章浏览阅读68次。_java tiko爬虫

关于selenium实现滑块验证-程序员宅基地

文章浏览阅读202次。python2.7+selenium2实现淘宝滑块自动认证参考链接:https://blog.csdn.net/ldg513783697/article/details/51583641selenium、python模拟登陆淘宝参考链接:https://blog.csdn.net/mighty13/article/details/78035088..._selesnuim滑块验证

随便推点

计算机主机主板单元,计算机组成原理——主板篇-程序员宅基地

文章浏览阅读1.8k次。微机(Micro Computer)是电子计算机中的一个分类,其他的还有巨型机、大型机、中型机和小型机。不同类型的电子计算机之间的差别主要在体积与运算速度和存储容量上划分。微机系统由硬件系统和软件系统组成,硬件(Hardware)系统主要有主机、存储设备、多媒体设备、网络设备、输入输出设备组成,软件(Software)系统主要由系统软件与应用软件组成。微机的一个显著的特点在于它的CPU的功能都由一..._电脑主机主板供电单元是什么

log4j:WARN No appenders could be found for logger 解决办法-程序员宅基地

文章浏览阅读9.5w次,点赞70次,收藏101次。使用log4j时不起作用,每次执行完出现以下提示:log4j:WARN No appenders could be found for logger (org.apache.ibatis.logging.LogFactory).log4j:WARN Please initialize the log4j system properly.log4j:WARN See http://logging.a..._log4j:warn no appenders could be found for logger (org . apache . pdfbox . pdmodel. graphics. color . pddevicergb)

Delphi的程序单元、结构、基础知识(转)-程序员宅基地

文章浏览阅读137次。1 Object Passal的程序结构很特殊,与其它语言如C++,Object Windows等结构都不同。一个Delphi程序由多个称为单元的源代码模块组成。使用单元可以把一个大型程序分成多个逻辑相关的模块,并用来创建在不同程序中使用的程序库。 2 8.1 Program单元 3   Program单元就是Delphi中的项目文件。 4   Program单元..._delphi 父级单元子级单元

人物志:一个平庸程序员的想法_程序员人物侧记-程序员宅基地

文章浏览阅读649次。前天晚上,老婆和我偎在床上说悄悄话,大致的意思是所有她的同学都有房子了,有些还当上了管理人员,并带着少许调侃说我以后也就这样了,1年10多万,失业就会掉头发。 我今年28,一个C++/Java程序员,跟大多数人一样,天资平平,虽然爱学习,但没有上一个好大学,工作这么几年也没有混上一个管理人员,有时候在自己看来,稍稍有些可悲。因为官本位的残留+农耕文化,在中国搞技术历来就是一个吃力不讨好的事情。搞技_程序员人物侧记

P1025 [NOIP2001 提高组] 数的划分-程序员宅基地

文章浏览阅读93次。有两种方法 :1.DP(也可以说是递推法):2:DFS对于递推法:我们用二维数组M[i][j] 来表示 i个数分成j份有多少次分法,这样我们递推下去,M[n][k]就是所求结果递推关系: M[i][j]=M[i-1][j-1]+M[i-j][j];其实就是 对于每次i所加的1 让他去哪,第一种方法,让这个1单独为1组,就是M[i-1][j-1];还有就是让 每一组都加上1来改变分组情况 就是M[i-j][j];#include<bits/stdc++.h&..._[noip2001 提高组] 数的划分

正在做 ESP32 , STM32 , 树莓派 RaspberryPi 的创客工具-程序员宅基地

文章浏览阅读301次。先随便写写一些思路, 以后再整理.这段时间笔者做了一些硬件开发, 领悟了一些事情.1 - 在常规创客的角度上, 硬件开发所需的知识面比较广, 非常广, 但不算太深.2 - 发现硬件开发由于其特殊环境的原因, 开发难度很大, 难度绝大部分来源于很麻烦, 效率很低.一般的开发者, 如果他们入门就直接学硬件, 他们是感觉不到这问题的. 没有对..._esp32如何当做stm32

推荐文章

热门文章

相关标签