Struts2框架之Struts拦截器

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

1、拦截器概念

过滤器Filter这个概念我们在Java Web中接触过,而Struts拦截器与它相比,在功能、概念可以说是几乎一样(大佬就是喜欢折腾,老是搞几套一样的东西)。拦截器在Struts非常重要,比如前面使用过的表单参数自动注入,模型转换等等。

Struts默认的拦截器配置在文件struts-default.xml
在这里插入图片描述

2、拦截器的执行时机

拦截器按照在struts.xml配置文件调用的顺序进行拦截,结果视图后逆序执行。(有点像递归算法,后面的有多个拦截器同时拦截的实例。)
在这里插入图片描述

3、拦截器的部分类结构

在这里插入图片描述

4、自定义拦截器

实例1:自定义实现单个拦截器

第一步:创建一个拦截器,并继承AbstractInterceptor抽象类,实现intercept方法。

package cn.hestyle.web.interceptor;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class MyInterceptor extends AbstractInterceptor {
    @Override
    public String intercept(ActionInvocation actionInvocation) throws Exception {
        System.out.println("开始拦截...");
        String invoke = actionInvocation.invoke();
        System.out.println(invoke);
        System.out.println("拦截放行...");
        return invoke;
    }
}

第二步:在struts.xml申明自定义的拦截器
在这里插入图片描述第三步:在struts.xml中将拦截器运用于Action

在这里插入图片描述
浏览器访问hello.action控制台输出
在这里插入图片描述

实例2:自定义实现多个拦截器

创建两个拦截器

package cn.hestyle.web.interceptor;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class MyInterceptor1 extends AbstractInterceptor {
    @Override
    public String intercept(ActionInvocation actionInvocation) throws Exception {
        System.out.println("开始拦截1...");
        String invoke = actionInvocation.invoke();
        System.out.println(invoke);
        System.out.println("拦截放行1...");
        return invoke;
    }
}
package cn.hestyle.web.interceptor;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class MyInterceptor2 extends AbstractInterceptor {
    @Override
    public String intercept(ActionInvocation actionInvocation) throws Exception {
        System.out.println("开始拦截2...");
        String invoke = actionInvocation.invoke();
        System.out.println(invoke);
        System.out.println("拦截放行2...");
        return invoke;
    }
}

struts.xml配置文件
在这里插入图片描述浏览器访问hello.action控制台输出
在这里插入图片描述

5、拦截器应用(用户登录)

业务逻辑:
首先准备login.jspmain.jsp, studentList.jsp, teacherList.jsp 页面
只有登录了才能访问main.jsp, studentList.jsp, teacherList.jsp 页面
当登录成功后,跳转到main.jspmain.jsp可以跳转到学生和老师列表

①、Demo结构

在这里插入图片描述

②、动作类
package cn.hestyle.web.action;

import cn.hestyle.model.User;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import org.apache.struts2.ServletActionContext;
//通过ModelDriven<User>将表单转换为User模型
public class loginAction extends ActionSupport implements ModelDriven<User> {
    private User user = new User();

    public String login(){
        //检测账号合法性
        if ("hestyle".equals(user.getUsername()) && "123456".equals(user.getPassword())){
            //将user账号信息存到session中
            ServletActionContext.getRequest().getSession().setAttribute("user", user);
            return "success";
        } else {
            return "toLogin";
        }
    }

    @Override
    public User getModel() {
        return user;
    }
}
package cn.hestyle.web.action;

import com.opensymphony.xwork2.ActionSupport;


public class MainAction extends ActionSupport {
    public String main(){
        return "success";
    }
}
package cn.hestyle.web.action;

import com.opensymphony.xwork2.ActionSupport;


public class StudentListAction extends ActionSupport {
    public String stuList(){
        return "success";
    }
}
package cn.hestyle.web.action;

import com.opensymphony.xwork2.ActionSupport;


public class TeacherListAction extends ActionSupport {
    public String tchList(){
        return "success";
    }
}
③、拦截器
package cn.hestyle.web.interceptor;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import org.apache.struts2.ServletActionContext;

import javax.servlet.http.HttpSession;

/**
 * 检测是否登录过
 */
public class CheckLoginInterceptor extends AbstractInterceptor {
    @Override
    public String intercept(ActionInvocation actionInvocation) throws Exception {
        //获取session
        HttpSession session = ServletActionContext.getRequest().getSession();
        //检查session中是否有user登录账号信息
        if (session.getAttribute("user") != null) {
            //放行
            String invoke = actionInvocation.invoke();
            return invoke;
        } else {
            return "toLogin";
        }
    }
}

④、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="p1" extends="struts-default">
        <!-- 申明checkLogin拦截器 -->
        <interceptors>
            <interceptor name="checkLoginInterceptor" class="cn.hestyle.web.interceptor.CheckLoginInterceptor"></interceptor>
        </interceptors>
        <!-- 全局结果视图 -->
        <global-results>
            <result name="toLogin">/login.jsp</result>
        </global-results>
        <!-- 登录action -->
        <action name="login" class="cn.hestyle.web.action.loginAction" method="login">
            <result name="success">/WEB-INF/main.jsp</result>
        </action>
        <!-- 访问main.jsp的动作,需要使用checkLoginInterceptor拦截器检测是否登录 -->
        <action name="main" class="cn.hestyle.web.action.MainAction" method="main">
            <interceptor-ref name="checkLoginInterceptor"></interceptor-ref>
            <interceptor-ref name="defaultStack"></interceptor-ref>
            <result name="success">/WEB-INF/main.jsp</result>
        </action>
        <!-- 访问studentList.jsp的动作,需要使用checkLoginInterceptor拦截器检测是否登录 -->
        <action name="stuList" class="cn.hestyle.web.action.StudentListAction" method="stuList">
            <interceptor-ref name="checkLoginInterceptor"></interceptor-ref>
            <interceptor-ref name="defaultStack"></interceptor-ref>
            <result name="success">/WEB-INF/studentList.jsp</result>
        </action>
        <!-- 访问teacherList.jsp的动作,需要使用checkLoginInterceptor拦截器检测是否登录 -->
        <action name="tchList" class="cn.hestyle.web.action.TeacherListAction" method="tchList">
            <interceptor-ref name="checkLoginInterceptor"></interceptor-ref>
            <interceptor-ref name="defaultStack"></interceptor-ref>
            <result name="success">/WEB-INF/teacherList.jsp</result>
        </action>
    </package>
</struts>

\color{red}注意 :如果一个动作配置了自定义拦截器,则struts不会再使用默认的拦截器,需要手动添加<interceptor-ref name="defaultStack"></interceptor-ref>默认拦截器!

⑤、浏览器访问效果

必须先登录过,在session中记录user信息,才能访问main.jsp, studentList.jsp, teacherList.jsp 页面。
在这里插入图片描述 \color{red}优化
在上面的struts.xml配置文件中,不难看出mainstuListtchList三个动作需要登录session拦截器、默认拦截器组拦截,登录拦截器需要使用默认拦截器组拦截,拦截器配置有些冗余。下面将对其进行优化:

方式一:抽取一个抽象包,声明一个新的拦截器组,放置登录session拦截器、默认拦截器组。
<?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="p1" extends="struts-default" abstract="true">
        <!-- 申明checkLogin拦截器 -->
        <interceptors>
            <interceptor name="checkLoginInterceptor" class="cn.hestyle.web.interceptor.CheckLoginInterceptor"></interceptor>
            <!-- 申明一个拦截器分组:包含自定义拦截器、默认拦截器组 -->
            <interceptor-stack name="myInterceptorStack">
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <interceptor-ref name="checkLoginInterceptor"></interceptor-ref>
            </interceptor-stack>
        </interceptors>

        <!-- 全局结果视图 -->
        <global-results>
            <result name="toLogin">/login.jsp</result>
        </global-results>
    </package>

    <!-- 继承p1包 -->
    <package name="p2" extends="p1">
        <!-- 登录action -->
        <action name="login" class="cn.hestyle.web.action.loginAction" method="login">
            <result name="success">/WEB-INF/main.jsp</result>
        </action>
        <!-- 访问main.jsp的动作,使用myInterceptorStack拦截器组 -->
        <action name="main" class="cn.hestyle.web.action.MainAction" method="main">
            <interceptor-ref name="myInterceptorStack"></interceptor-ref>
            <result name="success">/WEB-INF/main.jsp</result>
        </action>
        <!-- 访问studentList.jsp的动作,使用myInterceptorStack拦截器组 -->
        <action name="stuList" class="cn.hestyle.web.action.StudentListAction" method="stuList">
            <interceptor-ref name="myInterceptorStack"></interceptor-ref>
            <result name="success">/WEB-INF/studentList.jsp</result>
        </action>
        <!-- 访问teacherList.jsp的动作,使用myInterceptorStack拦截器组 -->
        <action name="tchList" class="cn.hestyle.web.action.TeacherListAction" method="tchList">
            <interceptor-ref name="myInterceptorStack"></interceptor-ref>
            <result name="success">/WEB-INF/teacherList.jsp</result>
        </action>
    </package>
</struts>
方式二:方式一还是有些不彻底,我们修改默认拦截器分组为我们自定义的拦截器分组,那么所有包中的所有action都被登录session拦截器、struts的拦截器组拦截。
<?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="p1" extends="struts-default" abstract="true">
        <!-- 申明checkLogin拦截器 -->
        <interceptors>
            <interceptor name="checkLoginInterceptor" class="cn.hestyle.web.interceptor.CheckLoginInterceptor"></interceptor>
            <!-- 申明一个拦截器分组:包含自定义拦截器、默认拦截器组 -->
            <interceptor-stack name="myInterceptorStack">
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <interceptor-ref name="checkLoginInterceptor"></interceptor-ref>
            </interceptor-stack>
        </interceptors>

        <!-- 修改包中的默认拦截器组为自定义拦截器组 -->
        <default-interceptor-ref name="myInterceptorStack"></default-interceptor-ref>

        <!-- 全局结果视图 -->
        <global-results>
            <result name="toLogin">/login.jsp</result>
        </global-results>
    </package>

    <!-- 继承p1包 -->
    <package name="p2" extends="p1">
        <!-- 包中的四个action都被已修改的拦截器组myInterceptorStack拦截 -->
        <action name="login" class="cn.hestyle.web.action.loginAction" method="login">
            <result name="success">/WEB-INF/main.jsp</result>
        </action>
        <action name="main" class="cn.hestyle.web.action.MainAction" method="main">
            <result name="success">/WEB-INF/main.jsp</result>
        </action>
        <action name="stuList" class="cn.hestyle.web.action.StudentListAction" method="stuList">
            <result name="success">/WEB-INF/studentList.jsp</result>
        </action>
        <action name="tchList" class="cn.hestyle.web.action.TeacherListAction" method="tchList">
            <result name="success">/WEB-INF/teacherList.jsp</result>
        </action>
    </package>
</struts>

这样也会造成一个问题,就是登录action也被登录session拦截器拦截了,所以需要修改登录session拦截器的实现。
首先来看一下AbstractInterceptor抽象类的子类MethodFilterInterceptor
在这里插入图片描述
我们只要将CheckLoginInterceptor修改为实现抽象类MethodFilterInterceptor,并且在struts.xml配置中,把login这个动作排除不拦截即可。
在这里插入图片描述
设置myInterceptorStack拦截器组中的checkLoginInterceptor拦截器不拦截login。

在这里插入图片描述
这样login被defaultStack拦截器组拦截,main、stuList、tchList被defaultStack拦截器、登录session验证拦截器组拦截,符合业务需求。

可能有部分道友被后面拦截器组的定义、修改啥的绕蒙了,建议多看几遍,其实并不难理解。

猜你喜欢

转载自blog.csdn.net/qq_41855420/article/details/102724910