Java框架学习之Struts2(拦截器,校验,文件上传下载,标签使用)

第一节 Struts2拦截器概述
拦截器:Struts2拦截器是在访问某个Action或Action的某个方法之前或之后实施拦截,并且Struts2拦截器是可插拔的,拦截器是 Spring AOP的一种实现.
AOP:面向切面编程.其实现原理:动态代理模式—>留给Spring
WebWork中文文档解释:拦截器是动态拦截Action调用的对象。它提供了一种机制使开发者可以定义在一个Action执行的前后执行的代码,也可以在一个action执行前阻止其执行。同时也提供了一种可以提取Action中可重用的代码的方式。
拦截器栈(Interceptor Stack):Struts2拦截器栈就是将拦截器按一定的顺序连接成一条链。在访问被拦截的方法或字段时,Struts2拦截器链中的拦截器就会按其之前定义的顺序被调用。
Java框架学习之Struts2(拦截器,校验,文件上传下载,标签使用)_第1张图片
第二节 Struts2内置拦截器
Struts2之所有强大,是因为它内置了很多拦截器,Struts2框架中自定义的,可以直接拿来使用的拦截器.
不同的拦截器栈(interceptor-stack)是不同拦截器的组合,用户根据不同的需求选择不同的拦截器栈.
内置拦截器在哪里,如何去看,如何去用,分别有什么作用?
找到:struts-default.xml文件:

  <interceptors>
            <interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
            <interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>
            <interceptor name="chain" class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/>
            <interceptor name="conversionError" class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/>
            <interceptor name="cookie" class="org.apache.struts2.interceptor.CookieInterceptor"/>
            <interceptor name="cookieProvider" class="org.apache.struts2.interceptor.CookieProviderInterceptor"/>
            <interceptor name="clearSession" class="org.apache.struts2.interceptor.ClearSessionInterceptor" />
            <interceptor name="createSession" class="org.apache.struts2.interceptor.CreateSessionInterceptor" />
            <interceptor name="debugging" class="org.apache.struts2.interceptor.debugging.DebuggingInterceptor" />
            <interceptor name="execAndWait" class="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor"/>
            <interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>
            <interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>
            <interceptor name="i18n" class="com.opensymphony.xwork2.interceptor.I18nInterceptor"/>
            <interceptor name="logger" class="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/>
            <interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
            <interceptor name="scopedModelDriven" class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/>
            <interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
            <interceptor name="actionMappingParams" class="org.apache.struts2.interceptor.ActionMappingParametersInteceptor"/>
            <interceptor name="prepare" class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>
            <interceptor name="staticParams" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>
            <interceptor name="scope" class="org.apache.struts2.interceptor.ScopeInterceptor"/>
            <interceptor name="servletConfig" class="org.apache.struts2.interceptor.ServletConfigInterceptor"/>
            <interceptor name="timer" class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/>
            <interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/>
            <interceptor name="tokenSession" class="org.apache.struts2.interceptor.TokenSessionStoreInterceptor"/>
            <interceptor name="validation" class="org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/>
            <interceptor name="workflow" class="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/>
            <interceptor name="store" class="org.apache.struts2.interceptor.MessageStoreInterceptor" />
            <interceptor name="checkbox" class="org.apache.struts2.interceptor.CheckboxInterceptor" />
            <interceptor name="datetime" class="org.apache.struts2.interceptor.DateTextFieldInterceptor" />
            <interceptor name="profiling" class="org.apache.struts2.interceptor.ProfilingActivationInterceptor" />
            <interceptor name="roles" class="org.apache.struts2.interceptor.RolesInterceptor" />
            <interceptor name="annotationWorkflow" class="com.opensymphony.xwork2.interceptor.annotations.AnnotationWorkflowInterceptor" />
            <interceptor name="multiselect" class="org.apache.struts2.interceptor.MultiselectInterceptor" />
            <interceptor name="deprecation" class="org.apache.struts2.interceptor.DeprecationInterceptor" />
</interceptors>

常见的拦截器:
1:params拦截器
这个拦截器偷偷的把请求参数设置到相应的Action的属性去的,并自动进行类型转换。
2.modelDriven拦截器
如果Action实现ModelDriven接口,它将getModel()取得的模型对象存入OgnlValueStack中。
3.execption拦截器
顾名思义,在抛出异常的时候,这个拦截器起作用。最好把它放在第一位,让它能捕获所有的异常。
4.validation拦截器
调用验证框架读取 *-validation.xml文件,并且应用在这些文件中声明的校验。
5.token拦截器
核对当前Action请求(request)的有效标识,防止重复提交Action请求。
6.fileUpload拦截器
用来处理文件上传
7.workflow拦截器
调用Action的validate方法,一旦有错误返回,重新定位到INPUT结果视图
在校验的时候,如果有错误,将将错误信息放到一个List 集合中
此时workflow拦截器来判断List集合中是否有数据,如果有就返回一个逻辑试图名称为input
8.servletConfig
通过感知接口,获取感应对象

第三节 自定义拦截器
自定义拦截器:CheckLoginInterceptor:
步骤1.定义拦截器类
方式1:实现com.opensymphony.xwork2.interceptor.Interceptor接口.
方式2:继承com.opensymphony.xwork2.interceptor.AbstractInterceptor类.

public class CheckLoginInterceptor extends AbstractInterceptor{
	private static final long serialVersionUID = 1L;
	@Setter
	private String loginName;
	@Override
	public String intercept(ActionInvocation invocation) throws Exception {
		//获取session对象
		 Object user = invocation.getInvocationContext().getSession().get("USER_IN_SESSION");
		//判断是否有值
		if(user==null){
			//只要是需要跳转,就返回一个逻辑视图名称 
			return loginName;
		}
		//放行
		return invocation.invoke();
	}	
}

步骤2.在struts.xml中注册拦截器,告诉Struts2框架来帮我管理CheckLoginInterceptor.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
        <constant name="struts.devMode" value="true" />
        <package name="interceptorPkg" extends="struts-default" >
                <!-- 注册拦截器(注意顺序) -->
                <interceptors>
                        <interceptor name="checkLogin" class="com.fym.interceptor.CheckLoginInterceptor">
                                <!-- 为当前拦截器配置参数,解决硬编码问题 -->
                                <param name="loginName">login</param>
                        </interceptor>
                        <!-- 打包(将我们需要的打成一个包) -->
                        <interceptor-stack name="mystack">
                                <interceptor-ref name="checkLogin"/>
                                <interceptor-ref name="defaultStack"/>
                        </interceptor-stack>
                </interceptors>
                <default-interceptor-ref name="mystack"/>
                <!-- 设置一个 全局的逻辑视图名称-->
                <global-results>
                        <result name="login" type="redirect">/login.jsp</result>
                </global-results>
                <action name="login" class="com.fym.action.LoginAction">
                        <!-- 引用自己需要的拦截器 -->
                        <interceptor-ref name="defaultStack"/>
                        <!-- 使用URL重定向到main Action -->
                        <result name="success" type="redirectAction">main</result>
                </action>
                <action name="main">
                        <!-- 引用拦截器(谁需要拦截,就在哪里设置) -->
                        <result>/welcome.jsp</result>
                </action>
        </package>
</struts>

第四节 OGNL和ValueStack(值栈)

(1)OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目。
Struts2框架使用OGNL作为默认的表达式语言。
EL(表达式语言),OGNL就是EL的升级版.
作用:Action和视图(JSP)之间数据交互的桥梁.

(2)2.什么是ValueStack
值栈是对应每一个请求对象的轻量级的内存数据中心。
每一次请求的时候,都会创建一个新的ValueStack对象,该ValueStack对象封装了这一次请求相关的数据信息.
1).ValueStack实际是一个接口,在Struts2中利用OGNL时,实际上使用的是实现了该接口的OgnlValueStack类,这个类是Struts2利用OGNL的基础。
2).ValueStack贯穿整个Action的生命周期(一次请求):每个Action类的实例都拥有一个ValueStack对象。 ValueStack相当于数据的中转站,在其中保存该次请求和当前Action对象和其他相关对象信息。
3).Struts2框架把ValueStack对象保存在名为“struts.valueStack”的request属性中。
新的请求发出:
ValueStack vs = Struts2框架创建ValueStack对象;
request.setAttribute(“struts.valueStack”,vs);

(3)如何获取ValueStack.

  //方式1: 因为ValueStack在请求中,属性名为:struts.valueStack.
         ValueStack vs = request.getAttribute("struts.valueStack");
         ValueStack vs = ServletActionContext.getRequest().getAttribute("struts.valueStack");
         ValueStack vs = ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
 // 方式2: 通过ActionContext对象获取
         ValueStack vs = ActionContext.getContext().getValueStack();
 // 以上两种方式获取的是同一个ValueStack对象.

(4)ValueStack内部结构
ValueStack对象中有两个很重要的属性,这两个属性就是ValueStack的主要内部结构:

root: 类型: CompoundRoot extends ArrayList : 表示栈的数据结构(后进先出)
context: 类型: Map: : 上下文

root:主要存储Action对象相关的数据信息. action的成员信息
context:主要存储映射关系数据(key-value).Map List
context存在用root对象的引用(只要拿到context对象就可以获取到root对象):

context中还存在request、session、application、attr、parameters对象的引用。
获取到context,就可以获取ValueStack中所有的数据.
从root中获取数据: 直接使用属性名获取. —>
从context中获取数据: #key —>
Java框架学习之Struts2(拦截器,校验,文件上传下载,标签使用)_第2张图片
Java框架学习之Struts2(拦截器,校验,文件上传下载,标签使用)_第3张图片
(5)把数据放入ValueStack.
1).把数据放入root中:(栈,ArrayList.每次都是压在栈顶)
方式1:ValueStack对象.getRoot().add(0, Obejct val);//把数据压入栈顶
方式2:ValueStack对象.getRoot().push(Object val):等价于valueStack对象.getRoot().add(0, Obejct val);
方式3:ValueStack对象.set(String propertyName,Object value);
方式4.在Action中提供一个可访问的属性(getter方法).
一般的,把单个对象可放入root中,就在栈顶.

2).把数据放入context中:
方式1:ValueStack对象.getContext().put(String key,Object value); 太长了.
方式2:ActionContext对象.put(String key,Object value);
一般的:把集合中的数据放入context中.

(6).如何从JSP中取出ValueStack中的数据:
此时必须使用Struts2的标签.—>先引入Struts2标签
<%@ taglib uri="/struts-tags" prefix=“s”%>
Struts2的调试标签: :主要用来观察数据在哪一个空间(root,context).
访问方式:

1).获取root中数据:
若:放入root中的数据,没有属性名:
若:放入root中的数据有属性名:

2).把context中数据:

EL可以访问ValueStack中的数据:
不建议这么做:
为什么可以呢: Struts2重新包装而来请求对象.${msg}—><%=pageContext.findAttribute(“msg”) %>
StrutsRequestWrapper:先从ValueStack中取出数据,再放入request中.

第五节 Struts2的输入校验
输入校验:
一.客户端校验: 过滤正常用户的误操作,通过JS代码完成(可以绕开).
二.服务端校验: 整个应用阻止非法数据的最后防线(必须),使用Java代码.
三.数据库校验: 在数据库中通过约束来限制列的存储.

Struts2校验方式:
1.编写代码方式校验:开发中常用;
2.配置校验:
2.1.基于XML配置校验(推荐使用)。
2.2.基于Annotation配置校验。

Struts2中做校验:
Action中
* 要继承ActionSupport
* 重写Validateable接口中的validate()方法 ,在该方法中完成验证
* 步骤如下:
* validate()方法在其他的业务方法之前执行
* 验证出错转向的页面
struts.xml配置/validate/login.jsp
其中input转向是在action中已经定义好的.
public static final String INPUT = “input”;
* 什么时候表示验证出错(转向input所指向的页面)
* super.addFieldError(“字段名称”, “错误信息”);
* 当集合不为空时,转向错误页面.
* 若校验失败,不会再执行Action中的业务方法.

public class ValidateAction extends ActionSupport implements Validateable{
	private static final long serialVersionUID = 1L;
	@Getter
	private String username;
	@Getter
	private String password;
	@Override
	public String execute() throws Exception {
		if("fanyaming".equals(username)&&"1234567".equals(password)){
			ActionContext.getContext().getSession().put("USER_IN_SESSION", username);
			return SUCCESS;
		}
		System.out.println("登录失败哦");
		return NONE;
	}
	public String list() throws Exception {
		System.out.println("列表查询");
		return NONE;
	}
	public String delete() throws Exception {
		System.out.println("删除数据");
		return NONE;
	}
	@Override
	public void validate() {		
	}
	//用validate作为前缀,后面跟上方法名,表示只在这个方法前进行数据校验,而不会在其他方法之前进行数据校验
	public void validateExecute() {
		//该方法在执行业务方法之前执行
		System.out.println("数据校验");
		if(username==null||username.trim().length()<6){
			super.addFieldError("username", "账号不能为空,或者不能少于6位");
		}
		if(password==null||password.trim().length()<6){
			super.addFieldError("password", "密码不能为空,或者不能少于6位");
		}
	}
}
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
		<s:debug/>
		<s:property value="fieldErrors.username[0]"/>
		<s:property value="fieldErrors.password[0]"/>
		<form action="/crm/vs" method="post">
			账号:<input name="username"/></br>
			密码:<input name="password" type="password"/></br>
			<input type="submit" value="登录"/>
		</form>
</body>
</html>

第六节 输入校验的原理
问题1:为什么在执行input方法之前,没有执行validate方法.
在validation拦截器中,标识需要排除的方法:

问题2:为什么校验失败,默认跳转到input结果视图.
在workflow拦截器中,如果有错误,默认的结果视图就是input.
Java框架学习之Struts2(拦截器,校验,文件上传下载,标签使用)_第4张图片
问题3:Action中某些方法不需要校验,却也执行了validate方法,如何避免问题.
比如,我们在做员工列表,或者员工删除的时候,没必要执行校验的功能.
只有表单的提交,才有必要执行校验.
在不需要被校验的方法上,使用标签:@SkipValidation.

问题4.开发中在一个Action中,被校验的方法是少数,大多数方法都不需要校验.
难道大多数方法都要使用@SkipValidation标签吗?—>麻烦.
解决方案: 就只针对于需要被校验的方法,编写校验规则的方法.
public void validate(){}:默认对Action中所有方法做校验.
public void validateXxx():Xxx表示需要被校验的方法名称,那么该方法就只对xxx方法做校验.
比如针对save方法: public void validateSave(){};

问题5:从workflow的拦截可以看出,校验失败会跳到默认的结果视图(“input”).
比如,要求校验失败之后不要挑战到input视图,而是edit视图.
解决方案:在被校验的方法上,使用@InputConfig标签.
在这里插入图片描述
第七节 Struts2标签
Struts2的标签库:
Struts2中表单标签将在 HTML 里input元素不同的type被呈现为一个表单元素.
使用表单标签的优点:
表单数据回显
对页面进行布局和排版

Struts2标签:
通用标签
控制标签/数据标签
UI标签
引用标签库:
<%@ taglib uri="/struts-tags" prefix=“s”%>
Java框架学习之Struts2(拦截器,校验,文件上传下载,标签使用)_第5张图片
1:控制流程的标签:if-else if-else.
Java框架学习之Struts2(拦截器,校验,文件上传下载,标签使用)_第6张图片
2:迭代标签::
Java框架学习之Struts2(拦截器,校验,文件上传下载,标签使用)_第7张图片
Java框架学习之Struts2(拦截器,校验,文件上传下载,标签使用)_第8张图片
Java框架学习之Struts2(拦截器,校验,文件上传下载,标签使用)_第9张图片
Java框架学习之Struts2(拦截器,校验,文件上传下载,标签使用)_第10张图片

第八节 Struts2的文件上传
文件上传准备:
注意:
1):表单必须使用POST方式提交;
2):使用二进制编码:multipart/form-data;

     3):<input type="file" name=""/>

Java框架学习之Struts2(拦截器,校验,文件上传下载,标签使用)_第11张图片
Java框架学习之Struts2(拦截器,校验,文件上传下载,标签使用)_第12张图片
Struts2文件上传的细节:
Struts2中的FileUploadInterceptor拦截器完成了文件上传的操作.
Struts2中支持哪些上传的组件:
Java框架学习之Struts2(拦截器,校验,文件上传下载,标签使用)_第13张图片
Struts2支持cos,pell,jakarta文件上传组件,默认使用的jakarta(Apache).
struts.multipart.saveDir= 上传文件的临时目录,默认是在Tomcat下面.
struts.multipart.maxSize=2097152 一次请求允许上传文件的最大字节数,默认是2M.

控制上传文件的大小和文件类型.
1):控制单个文件的最大字节.
2):控制上传文件的类型,比如png,jpg,jpeg,bmp.
问题:上传失败之后,提示信息看不懂.
解决方案:把提示信息作出国际化.支持中文.
提示信息都在struts-messages.properties 文件里预定义. (org.apache.struts2包下)
在struts.xml中引用资源文件:

 <constant name="struts.custom.i18n.resources" value="fileuploadMsg"/>

Java框架学习之Struts2(拦截器,校验,文件上传下载,标签使用)_第14张图片
第九节 文件下载
Struts2提供了stream结果类型,该结果类型就是专门用于支持文件下载功能的。
(阅读stream结果集代码)
指定stream结果类型 需要指定一个 inputName参数,该参数指定一个输入流,提供被下载文件的入口
Java框架学习之Struts2(拦截器,校验,文件上传下载,标签使用)_第15张图片
Java框架学习之Struts2(拦截器,校验,文件上传下载,标签使用)_第16张图片
Java框架学习之Struts2(拦截器,校验,文件上传下载,标签使用)_第17张图片

你可能感兴趣的:(web,项目,框架)