Struts2框架4

上一章 Struts2框架的上传和下载

一、拦截器

导读

拦截器可谓struts2的核心,其最基本的bean的注入(即使用)就是通过默认的拦截器实现的,一般在struts.xml的配置中,package内直接或间接继承了struts-default.xml,这样struts2默认的拦截器就会起作用.

小结:Struts2框架的拦截器是写在了struts-default.xml文件中的

Struts2之所以强大就是因为有了拦截器

1.什么是拦截器

是在AOP(Aspect-Oriented Programming==面向切面编程)中针对某一个方法或者字段被访问之前,进行拦截然后在之前或者之后加入某些操作的,例如我们做web开发时经常用的技术。
比如:权限控制、日志等。我们也可以将多个Interceptor连在一起组成Interceptor栈

备注:1)AOP是一种面向切面的编程思想

2)拦截器是AOP的一个实现

2.拦截器实现的原理

拦截器是通过动态代理的方式来调用的,其实拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行。同时也是提供了一种可以提取action中可重用的部分的方式。

简而言之: 就是可以在Action执行的前或者后进行一些处理的类

代理模式是Java中常见的设计模式之一,其分为两大类:  
    1.静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。
 在程序运行前,代理类的.class文件就已经存在了
    2.动态代理:在程序运行时,运用反射机制动态创建而成,常见的有jdk
 代理和cglib代理

3.拦截器的作用

拦截器可以帮助实现很多公共的内容,其中有重复提交,类型转换,对象初始化,验证,文件上传,页面初始化,传参的编码等等。由于每个拦截器都可以像热插拔的模块,所以可以在我们定义的Action中正确地去使用需要的拦截器
简而言之:就是在一个Action执行时,让我们为它再提升一些功能,给Action更好的的实现效果

4.拦截器的分类

  1.struts2自带的拦截器
  2.自定义拦截器:就是为了提升struts2现有的或者就是满足项目所特殊需
求的经由自己创建并实现的拦截器(就是一些java类)

5.拦截器与过滤器的区别

①拦截器是基于java的反射机制的,而过滤器是基于函数回调。

②拦截器不依赖于servlet容器,过滤器依赖与servlet容器。

③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。

④拦截器可以访问action上下文、值栈里的对象(通过ActionContext这个类),而过滤器不能访问。

⑤在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。

⑥拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。

ps:
过滤器和拦截器触发时机不一样:
过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前

二、自定义拦截器

导读

作为框架,我们知道可扩展性是不可或缺的,因为世上没有是完全是不变的。虽然,Struts 2为我们提供如此丰富的拦截器实现,但是这并不意味我们失去创建自定义拦截器的能力,恰恰相反,在Struts 2自定义拦截器是相当容易的一件事

1.实现自定义拦截器的两种方法

  • 实现Interceptor接口 ,重写/实现intercept()方法即可 。
  • 继承AbstractInterceptor类, 重写intercept()方法即可 。(其实AbstractInterceptor类也就是实现了Interceptor接口)

2.简单实现自定义拦截器

1.创建UserLoginInterceptor.java这个java类并实现 Interceptor接口
	1.1)重写intercept()方法:
	@Override
	public String intercept(ActionInvocation action) throws Exception {
		System.out.println("自定义拦截器:");
		action.invoke();//在StudentAction.java执行之后进行拦截
		Map<String, Object> session = ActionContext.getContext().getSession();
		Object value = session.get("name");
		System.out.println("在自定义拦截器中获取session中name="+value);
		if (value!=null) {
			System.out.println("session中有值,正常放行");
		}
		ActionContext.getContext().put("error", "您没有登录");
		
		return "message";
	}

2.在struts.xml中配置,将刚才自定义的拦截器配置一下
 2.1将自定义的拦截器和struts2的默认的拦截器栈搭配在一起构建城一个新的拦截器栈
	<interceptors>
    		<interceptor name="userLoginInterceptor" class="com.rj.bd.intector.action.UserLoginInterceptor">
    		</interceptor>
    		<interceptor-stack name="myInterceptorNewStack">
    			<interceptor-ref name="defaultStack" />
    			<interceptor-ref name="userLoginInterceptor"/>
    		</interceptor-stack>
    </interceptors>
    
 2.2针对自定义拦截器UserLoginInterceptor.java中
    return "message"在struts.xml中配置一个全局结果节点
    
         <global-results>  
           <result name="message">/jsp/error.jsp</result>  
         </global-results> 
         
 3.创建两个jsp分别叫做error.jsp和list.jsp都放在/jsp/目录下
     error.jsp:<s:property value="error"/>
     list.jsp:简单的写上:登录成功即可(只是验证自定义拦截器)
 
 4.创建一个StudentAction.java类
 
package com.rj.bd.student.action;

import java.util.Map;

import com.opensymphony.xwork2.ActionContext;
/**
 * @desc  模拟用户登录
 * @author HYZ
 * @time  2021年3月15日
 */
public class StudentAction {
	public String login(){
	//1.获取一个Map结构的session对象
	 Map<String, Object> session = ActionContext.getContext().getSession();

	 //2.存入一组数据
	 session.put("name", "凌异州");
	 
	 System.out.println("写入到session中的数据:"+session);
	 
	 return "success";
	}
}


5.在struts.xml中配置这个action,且配置的时候要让该action用上我们的新的默认的拦截器栈
  <action name="student" class="com.rj.bd.action.student.StudentAction"    > 
	<interceptor-ref name="myInterceptorNewStack"/>
	<result name="success" type="dispatcher">/jsp/list.jsp</result>
  </action> 
  

6.在index.jsp进行一个登录访问:
	<a href="<%=request.getContextPath()%>/student!login.action">
		通过Action请求来测试自定义拦截器
	</a>
	
PS: 
	一旦在struts.xml中自定义了拦截器,就意味着会使得struts2这个
框架的默认的拦截器栈失效,所以要配置的时候最好是配置成一个新拦截器栈  

3.注解的使用

1.在web.xml中配置struts2的启动的过滤器

<!-- 启动Struts2框架 -->
<filter>
<filter-name>StrutsPrepareAndExecuteFilter</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>StrutsPrepareAndExecuteFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

2.在StudentAction.java类中进行操作
@ParentPackage(value = "std")//父母包,对应<package extends="struts-default">
@Namespace(value = "/student")//当前模块的名字,可以省略不写
PS:这些是需要写在StudentAction.java的类名字上
/**
* @Action,这个注解对应<action>节点
* value(),表示action的请求名称,也就是<action>节点中的name属性
* results(),表示action的多个result;这个
属性是一个数组属性,因此可以定义多个Result
* interceptorRefs(),表示action的多个拦截器。
这个属性也是一个数组属性,因此可以定义多个拦截器;
* exceptionMappings(),这是异常属性,它是一
个ExceptionMapping的数组属性,表示action的异常,
在使用时必须引用相应的拦截器
* 
* 
* 
*/
PS:这些是需要写在Action类中方法上
@Action(value="login",
 results={
  @Result(name="sucss",location="/inters/list.jsp",type="dispatcher"),
  @Result(name="error",location="/inters/error.jsp",type="dispatcher")
},//表示结果跳转
//注解式异常处理,此时还是不需要使用struts.xml,且当前的			
 exceptionMappings={
  @ParentPackage(value = "struts-default")必须是struts-default
  @ExceptionMapping(exception="java.lang.Exception",result="error")
}
//interceptorRefs={@InterceptorRef("myInterceptorNewStack")}
//如果你要是用新的拦截器栈的话 那就要再次配上struts.xml,且当前Action
类中的@Parentpackage的value要与struts.xml中的package节点中的name属性值要保存一样
	

三、Struts2与Servlet的关系

  • Struts2是一个基于MVC设计形式的Web应用框架,它本质上相当于一个servlet,在MVC设计形式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互
  • Strtus2不是Servlet,是使用了Filter过滤器来作为控制器,使用了拦截器,组成拦截器栈,是对Filter的改善,封装,简化

Struts2中获取servlet的3种方式

  • 获取Map对象

PS: 是由Strust2中提供的ActionContext对象实现的

ActionContext  context=ActionContext.getContext();  //得到Action执行的上下文  
  
Map  request=(Map)context.get("request"); //得到HttpServletRequest的Map对象  
  
Map  session=context.getSession();//得到HttpSession的Map对象  
  
Map  application=context.getApplication();//得到ServletContext的Map对象

  • IOC(控制反转)获取servletAPI

PS: 通过spring将request,session,application等对象注入到XXXAction.java类中

(本质上不是由Struts2提供的)

public class SampleAction implementsAction,
RequestAware, SessionAware, ApplicationAware{  
    private Map request;  
    private Map session;  
    private Map application;  

    @Override  
    public void setRequest(Map request){
    	this.request = request;
    }  

    @Override  
    public void setSession(Map session){
    	this.session = session;
    }  

    @Override  
    public void setApplication(Map application){
    	this.application = application;
    }  
}  

  • 与Servlet API耦合的访问方式(不到万不得已不要使用)

PS: 是通过Struts2框架中的ServletActionContext这个对象获取Servlet的API

	直接访问Servlet API将使你的Action与Servlet环境耦合在一起,
我们知道对于HttpServletRequest、 HttpServletResponse和
ServletContext这些对象,它们都是由Servlet容器来构造的,与这些
对象绑定在一起,测试时就需要有Servlet容器,不便于Action的单元测
试。但有时候,我们又确实需要直接访问这些对象,那么当然是以完成任务
需求为主。要直接获取HttpServletRequest和ServletContext对象,
可以使用org.apache.struts2. ServletActionContext类,该类是
ActionContext的子类,在这个类中定义下面两个静态方法.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值