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

来源:互联网 发布:php生成8位唯一邀请码 编辑:程序博客网 时间:2024/06/05 08:54

目录

  • 目录
  • 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>