Struts2框架自学之路——拦截器

目录

Struts2拦截器概述

  Struts2框架封装了很多功能,而这些功能大多在拦截器中。Struts2内置了许多现成的拦截器,Struts2的某些功能如数据转换、数据校验等也是基于拦截器实现的。这些拦截器配置在struts2-core.jar中的struts-default.xml文件中。此外,并不是每次访问这些内置的拦截器都会执行,而只会执行一些默认的拦截器(这些默认执行的拦截器在struts-default.xml文件中做了配置),如:

<interceptor-stack name="defaultStack">
    <interceptor-ref name="exception"/>
    <interceptor-ref name="alias"/>
    <interceptor-ref name="servletConfig"/>
    <interceptor-ref name="i18n"/>
    <interceptor-ref name="prepare"/>
    <interceptor-ref name="chain"/>
    <interceptor-ref name="scopedModelDriven"/>
    <interceptor-ref name="modelDriven"/>
    <interceptor-ref name="fileUpload"/>
    <interceptor-ref name="checkbox"/>
    <interceptor-ref name="datetime"/>
    <interceptor-ref name="multiselect"/>
    <interceptor-ref name="staticParams"/>
    <interceptor-ref name="actionMappingParams"/>
    <interceptor-ref name="params"/>
    <interceptor-ref name="conversionError"/>
    <interceptor-ref name="validation">
        <param name="excludeMethods">input,back,cancel,browse</param>
    </interceptor-ref>
    <interceptor-ref name="workflow">
        <param name="excludeMethods">input,back,cancel,browse</param>
    </interceptor-ref>
    <interceptor-ref name="debugging"/>
    <interceptor-ref name="deprecation"/>
</interceptor-stack>

  Struts2的拦截器interceptor类似于Filter,在执行Action方法前后执行。它提供了一种机制使开发者能把相对独立的代码抽象出来,配置到Action前后执行。
  Struts2的拦截器是在Action对象创建之后,Action方法执行之前执行的。

重要知识点

Servlet和Action的区别
(1)Servlet默认第一次被请求访问时创建,且创建一次,成功创建后驻留在内存,以供下次访问,是一个单实例对象。
(2)Action每次访问时被创建,为多实例对象。

过滤器和拦截器的区别
(1)过滤器理论上可以任何请求的内容进行“过滤”,如:HTML、JSP、Servlet、图片路径等。
(2)拦截器只可以拦截Action,在Action方法执行前操作。

自定义拦截器

  有时,Struts2中内置的拦截器并不满足我们的需求,这时可能需要我们自定义拦截器进行实现。在讲解如何自定义拦截器之前,我们先来看一下拦截器的结构。

拦截器的结构

  以模型驱动封装(将表单提交的数据封装到实体类对象中去)的拦截器为例:

com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor

  该拦截器继承了AbstractInterceptor抽象类,如下:

public class ModelDrivenInterceptor extends AbstractInterceptor {

  AbstractInterceptor抽象类又实现了Interceptor接口,如下:

package com.opensymphony.xwork2.interceptor;

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

public abstract class AbstractInterceptor implements Interceptor {
    public AbstractInterceptor() {
    }

    public void init() {
    }

    public void destroy() {
    }

    public abstract String intercept(ActionInvocation var1) throws Exception;
}

  Interceptor接口

package com.opensymphony.xwork2.interceptor;

import com.opensymphony.xwork2.ActionInvocation;
import java.io.Serializable;

public interface Interceptor extends Serializable {
    void destroy();

    void init();

    String intercept(ActionInvocation var1) throws Exception;
}

  在自定义拦截器的过程中,我们可以继承AbstractInterceptor抽象类或实现Interceptor接口。但是在实际开发中,我们建议使用另外一个方式,让类继承于MethodFilterInterceptor类进行实现,这种方式可以让Action中某个方法不进行拦截操作。
  根据AOP思想,并不由Action调用拦截器的方法,而是通过配置文件的方式让Action与拦截器建立联系。
  下面将通过对案例的讲解来看下如何自定拦截器。

自定义登录拦截器

  在很多Web应用中,要求用户访问某些页面时需要先进行登录,才可访问。针对这样的需求,自定义登录拦截器作为本次讲解的案例。这里省略前期环境的配置步骤,直接开车上路!

创建登录访问的首页

  采用MVC设计模式,IndexAction在这里只作为显示View的Controller。
  访问首页的 IndexAction.java

package com.wm103.action;
import com.opensymphony.xwork2.ActionSupport;

public class IndexAction extends ActionSupport {
    @Override
    public String execute() throws Exception {
        return SUCCESS;
    }
}

  配置IndexAction的访问:

<?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>
    <package name="demo" extends="struts-default" namespace="/">
        <action name="index" class="com.wm103.action.IndexAction">
            <result name="success">/WEB-INF/jsp/index.jsp</result>
        </action>
    </package>
</struts>

  index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>首页——自定义拦截器</title>
</head>
<body>
    <h3>欢迎您,${sessionScope.user}!!!</h3>
</body>
</html>

登录页面以及登录操作

  创建一个UserAction用于显示登录页面和处理登录请求,如下:
  UserAction.java

package com.wm103.action;

import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.ServletActionContext;
import javax.servlet.http.HttpServletRequest;

public class UserAction extends ActionSupport {
    public String login() {
        return SUCCESS;
    }

    public String doLogin() {
        HttpServletRequest request = ServletActionContext.getRequest();
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        if("admin".equals(username) && "123".equals(password)) {
            request.getSession().setAttribute("user", username);
            return "login_success";
        } else {
            return "login";
        }
    }
}

  在struts.xml中添加配置,如下:

<!-- 显示登录页面 -->
<action name="login" class="com.wm103.action.UserAction" method="login">
    <result name="success">/WEB-INF/jsp/login.jsp</result>
</action>
<!-- 处理登录请求 -->
<action name="doLogin" class="com.wm103.action.UserAction" method="doLogin">
    <result name="login">/WEB-INF/jsp/login.jsp</result>
    <result name="login_success" type="redirectAction">index</result>
</action>

  登录页面 login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录——自定义拦截器</title>
    <style>
        form {
            width: 300px;
            margin: 80px auto;
        }
    </style>
</head>
<body>
<form action="${pageContext.request.contextPath}/doLogin.action" method="post">
    <p><label for="username">用户名 </label><input type="text" id="username" name="username"></p>
    <p><label for="password">密 码 </label><input type="password" id="password" name="password"></p>
    <p><input type="submit" value="登录"></p>
</form>
</body>
</html>

添加登录拦截器功能

  至此,上述完成了一个登录成功后进入首页的完整流程,但是,在这样的情况下,我们并未对直接访问首页的操作进行限制。这里我们需要对首页的访问进行拦截,判断用户是否已登录,如登录则直接进入首页,否则跳转登录页面。
  自定义拦截器的实现过程,如下:
第一步 创建一个继承于MethodFilterInterceptor类;
第二步 重写MethodFilterInterceptor类中的doIntercept方法,编写拦截器的具体逻辑;
第三步 在struts.xml中配置Action和拦截器的关系(也叫注册拦截器),为Action注册拦截器:
(1)(struts.xml)在要拦截的action标签所在的package标签中声明拦截器,如:

<interceptors>
    <interceptor name="loginIntercept" class="com.wm103.interceptor.LoginInterceptor"></interceptor>
</interceptors>

(2)在要注册拦截器的action标签中使用声明的拦截器,如:

<interceptor-ref name="loginIntercept"></interceptor-ref>

(3)在struts2中默认访问Action会自动执行很多拦截器,但是如果我们在action中配置了自定义拦截器,则默认的这些拦截器就不会执行了。为此我们需要再手动注册下这些默认拦截器,除非我们这个action可以不需要到这些拦截器。如:

<interceptor-ref name="defaultStack"></interceptor-ref>

  注:配置拦截器后,默认对action中所有的方法都进行了拦截。如果不对action中某些方法进行拦截可以如下操作:这使用拦截器的地方,添加param标签,具体说明如下述注释中的内容。

<interceptor-ref name="loginIntercept">
    <!--
        在这里可以配置Action中某些不进行拦截的方法,使用param标签,
        name属性值为excludeMethods,标签体内容为Action中不进行拦截的方法,
        如 login,多个方法的话采用英文逗号隔开。如下:
    -->
    <param name="excludeMethods">login</param>
</interceptor-ref>

  案例中登录拦截器定义如下(根据session中是否保存有user属性判断用户是否已经登录):
  LoginInterceptor.java

package com.wm103.interceptor;

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

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

public class LoginInterceptor extends MethodFilterInterceptor {

    /**
     * 拦截器的具体逻辑
     * @param actionInvocation
     * @return
     * @throws Exception
     */
    @Override
    protected String doIntercept(ActionInvocation actionInvocation) throws Exception {
        // 通过判断session中是否保存user值来确定用户是否登录
        HttpServletRequest request = ServletActionContext.getRequest();
        Object obj = null;
        HttpSession session = request.getSession(false);
        if(session != null) {
            obj = session.getAttribute("user");
        }
        if(obj != null) { // 已登录
            // 做类似放行操作,执行Action的方法
            return actionInvocation.invoke();
        }

        // 未登录
        // 不执行Action中的方法,返回登录页面
        return "login"; // 这里会到当前访问的Action中找到name属性为login的result标签,根据标签做转发或重定向操作
    }
}

  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>
    <package name="demo" extends="struts-default" namespace="/">
        <!-- 1. 声明拦截器 -->
        <interceptors>
            <interceptor name="loginIntercept" class="com.wm103.interceptor.LoginInterceptor"></interceptor>
        </interceptors>

        <!-- 显示登录页面 -->
        <action name="login" class="com.wm103.action.UserAction" method="login">
            <result name="success">/WEB-INF/jsp/login.jsp</result>
        </action>
        <!-- 处理登录请求 -->
        <action name="doLogin" class="com.wm103.action.UserAction" method="doLogin">
            <result name="login">/WEB-INF/jsp/login.jsp</result>
            <result name="login_success" type="redirectAction">index</result>
        </action>

        <action name="index" class="com.wm103.action.IndexAction">
            <!-- 2. 使用自定义拦截器-->
            <!-- 这里拦截IndexAction中的方法 -->
            <interceptor-ref name="loginIntercept">
                <!--
                    在这里可以配置Action中某些不进行拦截的方法,使用param标签,
                    name属性值为excludeMethods,标签体内容为Action中不进行拦截的方法,
                    如 login,多个方法的话采用英文逗号隔开。如下:
                -->
                <!--<param name="excludeMethods">login</param>-->
            </interceptor-ref>

            <!-- 3. 手动添加默认拦截器的使用 -->
            <interceptor-ref name="defaultStack"></interceptor-ref>

            <result name="success">/WEB-INF/jsp/index.jsp</result>
            <result name="login">/WEB-INF/jsp/login.jsp</result>
        </action>
    </package>
</struts>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值