[学习笔记] Struct2之拦截器
# 学习 # · 2021-03-25
Struts2架构分析
1、Struts2体系结构:
2、Struts2的核心接口和类:
(1)ActionMapper:根据请求的URI查找是否存在对应Action调用。
(2)ActionMapping:保存调用Action的映射信息,如namespace、name等。
(3)ActionProxy:在XWork和真正的Action之间充当代理。
(4)ActionInvocation:表示Action的执行状态,保存拦截器、Action实例。
(5)Interceptor:在请求处理之前或者之后执行的Struts 2组件。
3、Struts2的执行流程:
(1)客户端初始化一个指向Servlet容器的请求HttpServletRequest。
(2)请求经过一系列的过滤器Filter到达核心控制器FilterDispather。
(3)FilterDispather询问ActionMapper决定这个请求是否需要调用某个Action。
(4)如果ActionMapper决定需要调用某个Action,FilterDispather把请求的处理交给ActionProxy。
(5)ActionProxy通过ConfigurationManager(配置管理者)询问框架配置文件(Struts.xml),通过层层的拦截器找到需要调用的核心控制器Action类。
(6)ActionProxy创建一个ActionInvocation的实例。
(7)ActionInvocation实例使用命名模式来调用,在调用Action的过程前后涉及到相关拦截器Intercepter的调用。
(8)一旦Action执行完毕,ActionInvocation负责根据Struts.xml中的配置找到对应的返回结果。
Struts2的拦截器
1、为什么需要拦截器:
(1)早期MVC框架将一些通用操作硬编码在核心控制器中,致使框架灵活性不足、可扩展性降低。
(2)Struts 2将核心功能放到多个拦截器中实现,拦截器可自由选择和组合,增强了灵活性,有利于系统的解耦。
2、拦截器:
(1)Struts 2大多数核心功能是通过拦截器实现的,每个拦截器完成某项功能。
(2)拦截器方法在Action执行之前和之后执行。
(3)拦截器栈:从结构上看,拦截器栈相当于多个拦截器的组合;在功能上看,拦截器栈也是拦截器。
3、拦截器的工作原理:拦截器的执行过程是一个递归的过程。
(1) 第一周期:做一些Action执行前的预处理。
(2)第二周期:将控制交给后续拦截器或返回结果字符串。
(3)第三周期:做一些Action执行后的处理。
// 继承AbstractInterceptor,重写intercept()方法
public class MyTimerInterceptor extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation invocation) throws Exception {
//1、执行Action之前的工作:获取开始执行时间
long startTime = System.currentTimeMillis();
System.out.println("执行Action之前的工作,开始时间" + startTime);
//2、 执行后续拦截器或ACtion
String result = invocation.invoke();
//3、执行Action之后的工作:计算并输出执行时间
long endTime = System.currentTimeMillis();
long execTime = endTime - startTime;
System.out.println("执行Action后的,结束时间" + endTime);
System.out.println("总共用时" + execTime);
//返回结果字符串
return result;
}
}
4、拦截器配置:在struts.xml中定义和使用拦截器。
(1)定义拦截器:
<interceptors>
<!-- interceptor:定义拦截器 -->
<interceptor name="..." class="..."></interceptor>
<!-- interceptor-stack:定义拦截器栈 -->
<interceptor-stack name="...">
<!-- interceptor-ref指定引用的拦截器 -->
<interceptor-ref name="..."></interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- 定义默认的拦截器引用 -->
<default-interceptor-ref name="..."></default-interceptor-ref>
(2)使用拦截器:
<action name="MyTimer" class="com.aduo.action.MyTimerAction">
<result>/index.jsp</result>
<!-- interceptor-ref:指定引用的拦截器 -->
<interceptor-ref name="..."></interceptor-ref>
<interceptor-ref name="..."></interceptor-ref>
<!-- 其他配置 -->
</action>
5、Struts2内置拦截器:
(1)params拦截器:负责将请求参数设置为Action属性。
(2)servletConfig拦截器:将源于Servlet API的各种对象注入到Action。
(3)fileUpload拦截器:对文件上传提供支持。
(4)exception拦截器:捕获异常,并且将异常映射到用户自定义的错误页面。
(5)validation拦截器:调用验证框架进行数据验证。
(6)workflow拦截器:调用Action类的validate(),执行数据验证。
(7)staticParams拦截器:将在配置文件中通过action元素的子元素param设置的参数设置到对应的Action的属性中。
6、Struts2内置拦截器栈:struts-default.xml中定义一个defaultStack拦截器栈,并将其指定为默认拦截器。只要在定义包的过程中继承struts-default包,那么defaultStack将是默认的拦截器。
7、自定义拦截器:
(1)方法一:实现Interceptor接口。
void init() //初始化拦截器所需资源
void destroy() //释放在init()中分配的资源
String intercept(ActionInvocation ai) throws Exception //实现拦截器功能
(2)方法二:继承AbstractInterceptor类。
/**
* 权限验证检查拦截器
*/
public class AuthorizationInterceptor extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation invocation) throws Exception {
// 获取用户会话信息
Map<String, Object> session = invocation.getInvocationContext().getSession();
User user = (User)session.get("user");
if(user == null){
// 终止执行,返回登录页面
return Action.LOGIN;
} else {
// 继续执行剩余的拦截器和Action
return invocation.invoke();
}
}
}
Struts2实现文件上传
1、前端页面:表单提交属性设置为multipart/form-data。
<s:form action="upload.action" enctype="multipart/form-data" method="post">
文件一:<s:file name="upload" label="选择文件"/><br/>
<s:submit name="submit" value="上传文件"/>
</s:form>
2、开发实现文件上传的Action:
public class UploadAction extends ActionSupport {
// 封装上传文件属性
private File upload;
// 获取提交的文件类型
private String uploadContentType;
// 封装上传文件名称
private String uploadFileName;
// 获取文件上传的路径
private String savePath;
// 省略getter/setter
public String getSavePath() {
return ServletActionContext.getServletContext().getRealPath(savePath);
}
@Override
public String execute() throws Exception {
byte[] buffer = new byte[1024];
// 读取文件
FileInputStream fis = new FileInputStream(this.getUpload());
// 保存文件,并设置保存目录的路径
FileOutputStream fos = new FileOutputStream(getSavePath()+"\\"+this.getUploadFileName());
int length = fis.read(buffer);
while (length>0) {
fos.write(buffer,0, length);
length=fis.read(buffer);
}
fis.close();
fos.flush();
fos.close();
return SUCCESS;
}
}
(3)配置Action:
<action name="upload" class="com.aduo.action.UploadAction">
<!-- 通过param参数设置保存目录的路径 -->
<param name="savePath">/upload</param>
<result name="success">/upload_success.jsp</result>
</action>
4、实现多文件上传:多文件上传表单提交时,会提交一个数组。
public class UploadAction extends ActionSupport {
// 获取提交的多个文件
private File[] upload;
// 获取提交的文件类型
private String[] uploadContentType;
// 封装上传文件名称
private String[] uploadFileName;
// 获取文件上传的路径
private String savePath;
// 省略getter/setter
public String getSavePath() {
return ServletActionContext.getServletContext().getRealPath(savePath);
}
@Override
public String execute() throws Exception {
byte[] buffer = new byte[1024];
for (int i = 0; i < upload.length; i++) {
FileInputStream fis = new FileInputStream(getUpload()[i]);
FileOutputStream fos = new FileOutputStream(getSavePath()+"\\"+this.getUploadFileName()[i]);
int length=fis.read(buffer);
while (length>0) {
fos.write(buffer,0, length);
length=fis.read(buffer);
}
fis.close();
fos.flush();
fos.close();
}
return SUCCESS;
}
}
Struts2实现文件下载
1、stream结果类型:将文件数据(通过InputStream获取)直接写入响应流。
名称 | 作用 |
---|---|
contentType | 设置发送到浏览器的MIME类型 |
contentLength | 设置文件的大小 |
contentDisposition | 设置响应的HTTP头信息中的Content-Disposition参数的值 |
inputName | 指定Action中提供的inputStream类型的属性名称 |
bufferSize | 设置读取和下载文件时的缓冲区大小 |
2、contentType类型设置:
文件类型 | 类型设置 |
---|---|
Word | application/msword |
Excel | application/vnd.ms-excel |
PPT | application/vnd.ms-powerpoint |
图片 | image/gif , image/bmp,image/jpeg |
文本文件 | text/plain |
html网页 | text/html |
任意二进制数据 | application/octet-stream |
3、实现文件下载:
(1)编写Action:
public class FileDownAction extends ActionSupport {
// 读取下载文件的目录
private String inputPath;
// 下载文件的文件名
private String fileName;
// 读取下载文件的输入流
private InputStream inputStream;
// 下载文件的类型
private String conetntType;
// 省略getter/setter
// 创建InputStream输入流
public InputStream getInputStream() throws FileNotFoundException{
String path = ServletActionContext.getServletContext().getRealPath(inputPath);
return new BufferedInputStream(new FileInputStream(path+"\\"+fileName));
}
@Override
public String execute() throws Exception {
return SUCCESS;
}
}
(2)配置Action:
<action name="download" class="cn.houserent.action.FileDownAction">
<param name="inputPath">/upload</param>
<result name="success" type="stream">
<param name="contentType">application/octet-stream</param>
<param name="inputName">inputStream</param>
<param name="contentDisposition">attachment;filename="${fileName}"</param>
<param name="bufferSize">4096</param>
</result>
</action>
(3)前端页面:
<a href="download.action?fileName=334.jpg">点击此处下载文档</a>
如若转载,请注明出处:一木林多 - https://www.l5v.cn/archives/275/
评论