struts2第四天——拦截器和标签库

一、拦截器(interceptor)概述

  struts2是个框架,里面封装了很多功能,封装的很多功能都是在拦截器里面。
  (属性封装、模型驱动等都是封装在拦截器里面)
  struts2里面封装了很多功能,有很多拦截器,每次执行一部分拦截器,比如一些默认拦截器等
  默认拦截器的位置在 core的jar包的struts-default.xml里边<interceptor>标签里边

二、拦截器基本原理

  拦截器在什么时候执行:
    在action对象创建之后和action方法执行之前进行执行(使用在相关位置打断点,并使tomcat在debug处进行调试验证) 

  拦截器的底层原理:
    主要原理:

        AOP思想:

         AOP (Aspect Oriented Programming)思想:面向切面编程      

          (有基本功能,想拓展功能,不用修改源代码
          而是其他方式(增加配置文件等)来实现功能拓展)
          (例如,给基本的登陆功能增加权限判断,不修改源代码增加权限判断)
          这是第一个浅的层次:不修改源代码,增强、拓展功能
          更深层次见 spring

    所以AOP的本质是在一系列纵向的控制流程中,把那些相同的子流程提取成一个横向的面

       责任链模式: ((诸多设计模式的一种,有点类似web阶段过滤链))     

          过滤链:每个请求可以有多个过滤器,只有每个过滤器放行了才能到下一个
          责任链模式:有多个操作:添加 修改 删除
          只有添加后做类似“放行”操作才能到修改,修改后再放行,才能到删除

    AOP思想和责任链模式如何运用到拦截器里:
      拦截器在action对象创建之后和action方法执行之前进行执行,执行过程使用AOP思想
      在action里面并没有直接调用拦截器的方法,而是通过配置文件进行操作执行
      要执行很多拦截器,需要用到责任链模式,拦截器1执行之后,放行;拦截器2执行,放行...action方法执行
      (拦截器有很多功能,要用到什么功能给什么功能)(类似做手术,每个助手拿着不同的器具,主治医生需要什么器具,助手递过去什么器具)

    可以通过查看源代码进一步理解上面的流程(看web.xml中过滤器那个类的源码)
    (1)执行action
    (2)创建action对象,使用动态代理
    (3)执行action的方法
    (4)执行很多拦截器 ,遍历执行 if(interceptors.hasNext())
    (5)类似于放行的方法 return invocation.invoke()

    重要的概念:
      过滤器和拦截器的区别(另外一个重要的概念是前一天的servlet 和 action的区别)
      (1)过滤器:理论上可以过滤任意资源(HTML ,JSP...)
      (2)拦截器:只会可以拦截action (是在action创建后方法执行前,故只能拦截action)

三、自定义拦截器 

  1) 在struts2中有很多拦截器,struts2中封装了很多拦截器,可能存在我们需要而
    struts2中不存在的拦截器。
  2)  拦截器的结构:通过查看源码查看一下结构(例如modeDrivern)
    继承了 AbstractInterceptor(此抽象类实现了接口Interceptor)
  接口里有三个方法:
    init() ==初始化
    destroy() ==销毁
    interceptor() ==拦截操作
  可以通过自定义类继承抽象类实现
  实际开发中使用的是 继承 MethodFilterInterceptor类

  实现接口时必须实现所有方法,即使这个方法什么也不做;所以可以选择继承类来替代(当继承类和实现接口都可以时)
  可以让action里某个方法不进行拦截
  让自定义拦截器和action有关联,需要用到AOP思想;通过配置文件而不是调用方法的方式

  自定义登陆拦截器:
    1) 需求:实现只有登陆状态才能点击action的超链接,非登陆状态点击超链接跳转到登陆页面
        判断登陆状态是通过 session 实现:
        登陆成功后往session里放值,检查session里是否有值来进行判断
    2) 基本过程:
      继承类:MethodFilterInterceptor;
      重写方法;
      注册拦截器(让拦截器和action有关联);
        注册基本步骤:
          在action所在的包package里声明拦截器(可以找默认的拦截器借看声明格式)
          在具体的action标签里使用拦截器
          但是这样会出现 默认拦截器都不会执行的问题
          解决方案是把默认拦截器再手动使用一次:
          不会使用直接全部复制一份
          把拦截器中默认的那一份里
        <interceptor-stack name="defaultStack">
        <interceptor-ref name="exception"/>
        <interceptor-ref name="alias"/>
        <interceptor-ref name="servletConfig"/>
        <interceptor-ref name="i18n"/>
        <interceptor-ref name="prepare"/>
        ...
      把defaultStack 这个name引入即可
      <!-- 把默认拦截器再手动使用一次 -->
      <interceptor-ref name="defaultStack"></interceptor-ref>

package cn.action.interceptor;

import javax.interceptor.InvocationContext;
import javax.servlet.http.HttpSession;

import org.apache.struts2.ServletActionContext;

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

/**
 * 自定义的登陆拦截器
 * @author jiangbei01
 *
 */
public class LoginInterceptor extends MethodFilterInterceptor{

    //重写拦截的逻辑
    @Override
    protected String doIntercept(ActionInvocation invocation) throws Exception {
        HttpSession session = ServletActionContext.getRequest().getSession();
        String session_username = (String)session.getAttribute("username");
        if(session_username != null){
            //放行
            return invocation.invoke();
        }else{
            //到result标签里,找name匹配前往页面
            return "login";
        }

    }
}

配置文件如下:

<?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="demo1" extends="struts-default" namespace="/">
        <!-- 声明拦截器 -->
        <interceptors>
            <!-- 分别是拦截器名字和类的全路径 -->
            <interceptor name="logininterceptor" class="cn.action.interceptor.LoginInterceptor">
            </interceptor>
        </interceptors>
        <action name="login_*" class="cn.action.interceptor.LoginInterceptor" method="{1}">
            <!-- 使用拦截器,name出填上面的name即可 -->
            <interceptor-ref name="logininterceptor">
                <!-- 设置某些方法不拦截,name值为excludeMethods,标签内容为方法不拦截名 -->
                <param name="excludeMethods">login,regist</param>
            </interceptor-ref>
            <!-- 把默认拦截器再手动使用一次 -->
            <interceptor-ref name="defaultStack"></interceptor-ref>
            <result name="login">/login.jsp</result>
        </action>
    </package>
</struts>    

产生的问题是 登陆功能也进行拦截,此时登陆也检查session进行拦截,产生永远登陆不进去的问题
解决的思路是让 login()方法不进行拦截
方法是通过配置文件配置某些方法不拦截
<!-- 设置某些方法不拦截,name值为excludeMethods,标签内容为方法不拦截名 -->
<param name="excludeMethods">login,regist</param>

四、struts2的标签库  

  注意标签库的引入!

  常用
    1. <s:propertiry> 和OGNL表达式在JSP页面中获取值栈数据
    2. <s:iterator> 获取值栈中list集合的数据
    3. <s:dubug> 可以查看值栈的结构和数据
    其它 <s:if> <s:else> <s:a>(超链接) 等相对不太常用的标签

  表单标签(会用):
    html表单回顾 form action method enctype
    <input .../>(详见HTML小结)
    select option
    textareas
    struts2对应html表单标签大多都有对应
  见案例:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">

    <title>My JSP ‘struts2_tag.jsp‘ starting page</title>

    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->

  </head>

  <body>
    <!-- 对应form标签 -->
    <s:form name="" action="">
        <!-- 普通输入项,不能直接在前面写,否则不在同一行,
        应当使用label标签,查看源代码可以看到,是不在一个table里面
        代码在一个表格中,不用自己写<br/换行>
         -->
        <s:textfield name="username" label="用户名"></s:textfield>
        <!-- 密码输入项,冒号不用自己写 -->
        <s:password name="password" label="密码"></s:password>
        <!-- 单选框,将value值和显示值设置为一致 -->
        <s:radio list="{‘女‘,‘男‘}" name="sex" label="性别"></s:radio>
        <!-- 构建使value和显示值不一样,使用map方式 -->
        <s:radio list="#{‘girl‘:‘女‘,‘boy‘:‘男‘ }"></s:radio>
        <!-- 复选框,注意是checkboxlist -->
        <s:checkboxlist list="{‘吃饭‘,‘睡觉‘,‘打豆豆‘}" name="love" label="爱好"></s:checkboxlist>
        <!-- 下拉框 -->
        <s:select list="{‘学士‘,‘硕士‘,‘博士‘}" name="xueli" label="学历"></s:select>
        <!-- 文件上传项 -->
        <s:file name="file" label="文件上传"></s:file>
        <!-- 隐藏项 -->
        <s:hidden name="hidden" value="隐藏项"></s:hidden>
        <!-- 提交 -->
        <s:submit value="提交"></s:submit>
        <!-- 重置 -->
        <s:reset value="重置"></s:reset>
        <!-- 文本域 -->
        <s:textarea cols="10" rows="5"></s:textarea>
    </s:form>
  </body>
</html>

    小问题,提交和重置不在同一行,这是局限性(框架集问题见HTML小结

时间: 2024-12-15 07:15:13

struts2第四天——拦截器和标签库的相关文章

【struts2】预定义拦截器

1)预定义拦截器 Struts2有默认的拦截器配置,也就是说,虽然我们没有主动去配置任何关于拦截器的东西,但是Struts2会使用默认引用的拦截器.由于Struts2的默认拦截器声明和引用都在这个Struts-default.xml里面,因此我们需要到这个文件的struts-default包里去看一下.定义如下: 1 <interceptors> 2 <interceptor name="alias" class="com.opensymphony.xwor

走进Struts2(二) — Struts2的基石(拦截器)

拦截器(Interceptor)是Struts2的基石,拦截器的主要作用是在Action执行之前和Result执行之后进行一些特定功能的处理机制. 如图,拦截器是用来负责在Action执行之前和Result执行之后处理一些功能的类.每个不同的拦截器,它们分别执行不同的功能处理,而运行的时机就是在Action执行之前和Result执行之后,需要注意的是在执行Action之前和Result之后,拦截器的执行顺序是正好相反的. 一.拦截器的好处 1.简化Action的实现,可以把很多功能从Action

struts2学习笔记---自定义拦截器

什么是拦截器? struts2中拦截器分为Struts2定义好的拦截器和自定义的拦截器.其作用是在一个Action执行之前进行拦截,在Action执行之后又加入某些操作. 实现原理 当请求一个Action时,struts2会查找配置文件,并根据这个Action的配置实例化对应的拦截器对象,然后串成一个列表(list),最后一个一个地调用列表中的拦截器. 拦截器的执行流程 1.对Action进行预处理.(正序执行) 2.拦截器自身决定该不该执行后续的拦截器(由invoke()方法的返回值决定).

SpringMVC笔记(四)拦截器

一.拦截器:Spring MVC也可以使用拦截器对请求进行拦截处理,用户可以自定义拦截器来实现特定的功能,自定义的拦截器必 须实现HandlerInterceptor接口 二.实现步骤: 1.自定义实现类实现HandlerInterceptor接口 2.在springMVC中配置文件中的配置相应的拦截器 实现的代码: 1.自定义实现类 package com.neuedu.springmvc.interceptor; import javax.servlet.http.HttpServletRe

Struts2基础学习(五)&mdash;拦截器

一.概述 1.初识拦截器      Interceptor 拦截器类似前面学过的过滤器,是可以在action执行前后执行的代码,是我们做Web开发经常用到的技术.比如:权限控制.日志等.我们也可以将多个Interceptor 连在一起组成Interceptor 栈.     Struts2拦截器,每个拦截器类只有一个对象实例,即采用单例模式,所有引用这个拦截器的Action都共享这一拦截器类的实例,因此在拦截器中如果使用类变量,要注意同步的问题.      注意:              (1

struts2(六)拦截器机制

拦截器简述 拦截器是一组动态拦截Action调用的对象.拦截器的处理代码可以定义在action执行前或者执行后.同时,拦截器能够拦截一个Action的执行.拦截器可以将一些通用功能封装成可重用形式以供一个Action或多个 Actions使用. 拦截器必须是无状态的,原因是Struts 2不能保证为每一个请求或者Action创建一个实例,所以如果拦截器带有状态,会引发并发问题.不要使用在API提供的ActionInvocation之外的任何东西. 在概念上,interceptors相近于Serv

Struts2拦截器和标签

一.struts2拦截器 1.struts2是框架,封装了很多的功能,struts2里面封装的功能都是在拦截器里面. 2 struts2里面封装了很多的功能,有很多拦截器,不是每次这些拦截器都执行,每次执行默认的拦截器. 3 struts2里面默认拦截器位置,在struts2-core.jar jar包里面有一个struts-default.xml文件,在里面配置了默认拦截器. 4拦截器在action被创建之后,方法执行之前执行. 5拦截器的底层使用的两个原理 (1)aop思想:struts2的

Struts2请求数据处理及拦截器(二)

简介 以后如果没有特殊的要说,就在简介中介绍一下大概的知识点.今天主要学习封装请求参数及类型转换.用户输入校验.国际化.拦截器 Struts2封装请求参数的方式 方式一: Action 本身作为model对象,通过成员setter封装(一个名字为params的拦截器实现的) 产生疑问:使用第一种数据封装方式,数据封装到Action属性中,不可能将Action对象传递给 业务层 * 需要再定义单独JavaBean ,将Action属性封装到 JavaBean,得出第二种方式 方式二: 动作类和模型

struts2(三) 输入校验和拦截器

前面知道了struts2的架构图和struts2的自动封装表单参数和数据类型自动转换,今天来学struts2的第三第四个东西,输入校验和拦截器, --WH 一.输入校验 在以前我们写一个登录页面时,并没有限制用户的输入,不管用户输入什么,我们都存入数据库中,很显然这是不行的,我们需要检测用户输入的文本是否合法,是否符合我们需要的文本格式,符合菜放行,而struts2中就有这种功能,能帮我们在服务器段进行判断,比如用户名不能为空,年龄只能在0-100之间等.现在我们就来说说如何使用struts2中