eclipse学习(第二章:初识ssh)——6.struts2的拦截器
我是看着这个网址学习做的一些内容记录,方便自己以后查找。学习的话可以自己去看
https://www.w3cschool.cn/struts_2/struts_interceptors.html
拦截器的定义
拦截器在概念上与servlet过滤器或JDK代理类相同。拦截器允许横切功能,把action以及框架分开实现。你可以使用拦截器实现以下操作:
- 在调用action之前提供预处理逻辑。
- 在调用action后提供后处理逻辑。
- 捕获异常,以便可以执行备用处理。
Struts2框架中提供的许多功能都是使用拦截器实现的,包括异常处理,文件上传,生命周期回调和验证等。事实上,由于Struts2将其大部分功能基于拦截器,因此不太可能为每个action分配7个或8个拦截器。
Struts2框架拦截器
序号 | 拦截器和说明 |
---|---|
1 | alias 允许参数在请求之间使用不同的别名。 |
2 | checkbox 通过为未检查的复选框添加参数值false,以辅助管理复选框。 |
3 | conversionError 将字符串转换为参数类型的错误信息放置到action的错误字段中。 |
4 | createSession 自动创建HTTP会话(如果尚不存在)。 |
5 | debugging 为开发人员提供一些不同的调试屏幕。 |
6 | execAndWait 当action在后台执行时,将用户发送到中间的等待页面。 |
7 | exception 映射从action到结果抛出的异常,允许通过重定向自动处理异常。 |
8 | fileUpload 便于文件上传。 |
9 | i18n 在用户会话期间跟踪选定的区域。 |
10 | logger 通过输出正在执行的action的名称提供简单的日志记录。 |
11 | params 设置action上的请求参数。 |
12 | prepare 这通常用于执行预处理工作,例如设置数据库连接。 |
13 | profile 允许记录action的简单分析信息。 |
14 | scope 在会话或应用程序范围内存储和检索action的状态。 |
15 | ServletConfig 提供可访问各种基于servlet信息的action。 |
16 | timer 以action执行时间的形式提供简单的分析信息。 |
17 | token 检查action的有效性,以防止重复提交表单。 |
18 | validation 提供action的验证支持。 |
使用struts来实现拦截器
jar包拉取到lib文件夹下
创建action
创建一个MyAction 处理请求
package com.czx.action;
import com.opensymphony.xwork2.ActionSupport;
public class MyAction extends ActionSupport {
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
private String username;
@Override
public String execute() throws Exception {
System.out.println("现在跳转进入到action方法了");
return "success";
}
}
创建自定义的拦截器
拦截器接口如下(该类不需要写,需要看理解)
init()方法提供了一种初始化拦截器的方法,而destroy()方法为拦截器清理提供了一个工具。与action不同,拦截器在请求之间重复使用,需要线程安全,特别是intercept()方法。
ActionInvocation对象可访问运行时的环境。它允许访问action本身以及方法来调用action,并确定action是否已被调用。
如果你不需要初始化或清理代码,可以扩展AbstractInterceptor类,以实现init()和destroy()的默认的无操作指令。
public interface Interceptor extends Serializable{
void destroy();
void init();
String intercept(ActionInvocation invocation)
throws Exception;
}
自己创建拦截器MyIntercept
实际中action将通过拦截器使用invocation.invoke()调用执行,所以你可以根据你的需求做一些预处理和一些后处理。
框架本身通过第一次调用ActionInvocation对象的invoke()来启动进程。每次调用invoke()时,ActionInvocation都会查询其状态,并执行下一个拦截器。
package com.czx.intercept;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class MyIntercept extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation invocation) throws Exception {
//预处理
String output = "Pre-Processing,预处理";
System.out.println(output);
//让我们调用行动(action)或者是下一个拦截器
String result = invocation.invoke();
System.out.println("调用行动或者是下一个拦截器的情况:"+result);
//让我们做一些后期处理
output = "调用action或者是下一个拦截器之后的结果";
System.out.println(output);
return result;
}
}
修改web.xml
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>ssh_learn_intercept</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
加入页面
index.jsp(登录页)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>欢迎来到登录页面</h1>
<form action="hi">
请输入密码<br/>
<input type="text" name="username"/>
<input type="submit" value="提交">
</form>
</body>
</html>
hiWorld.jsp(登录成功后进入该页面)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录成功来到登录页</title>
</head>
<body>
登录成功来到登录页,刚刚输入内容为<s:property value="username"/>
</body>
</html>
创建struts.xml
struts.xml
你可以在标签内注册多个拦截器,同时可以在标签内调用多个拦截器,也可以用不同的action调用同一个拦截器。name必须唯一
可以在包内自定义拦截器,外面这个interceptors是多个拦截器,interceptor是自己定义的拦截器,interceptor-stack是自己定义的拦截器堆栈,这里的堆栈是按顺序一个个来拦截的。
这里的interceptor-ref是用来引用拦截器的名称,其次,这里定义的拦截器只有一个且该拦截器不包含params,那么你想通过action传递参数会失败。
params拦截器,目的是将请求参数发送给action。使用timer拦截器,目的是测量执行action方法所需的时间,会在控制台中输出结果。
这里引用的拦截器也可以是拦截器堆栈的名称。
用户访问是从左边开始访问进入到右边系统处理完了之后再往左边响应对应的结果。(拦截器堆栈示例)
<?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>
<constant name="struts.devMode" value="true"></constant>
<package name="hiWorld" extends="struts-default">
<!-- 可以在包内自定义拦截器,外面这个interceptors是多个拦截器,interceptor是自己定义的拦截器,interceptor-stack是自己定义的拦截器堆栈,这里的堆栈是按顺序一个个来拦截的 -->
<interceptors>
<interceptor name="myIntercept" class="com.czx.intercept.MyIntercept"></interceptor>
<interceptor-stack name="multiIntercept">
<interceptor-ref name="exception"></interceptor-ref>
<interceptor-ref name="servletConfig"></interceptor-ref>
<interceptor-ref name="prepare"></interceptor-ref>
<interceptor-ref name="checkbox"></interceptor-ref>
<interceptor-ref name="params"></interceptor-ref>
<interceptor-ref name="conversionError"></interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- 这里的interceptor-ref是用来引用拦截器的名称,其次,这里定义的拦截器只有一个且该拦截器不包含params,那么你想通过action传递参数会失败。
params拦截器,目的是将请求参数发送给action。使用timer拦截器,目的是测量执行action方法所需的时间,会在控制台中输出结果。
这里引用的拦截器也可以是拦截器堆栈的名称,
-->
<action name="hi" class="com.czx.action.MyAction" method="execute">
<interceptor-ref name="timer"></interceptor-ref>
<interceptor-ref name="params"></interceptor-ref>
<interceptor-ref name="myIntercept"></interceptor-ref>
<result name="success">hiWorld.jsp</result>
</action>
</package>
</struts>
测试
访问:http://localhost:8080/ssh_learn_intercept/
输入“这是密码”,然后点击提交按钮
这个时候你可以发现后台控制台会出现以下内容
途中遇到的一个bug
如果直接使用那个网站的话,我遇到得一个bug
Caused by: Unable to find interceptor class referenced by ref-name servlet-config - interceptor-ref
这个意思是找不到这个servlet-config这个引用名的拦截器对应的类。
然后百度了一下发现还没有好的解决方案。然后我自己在看了一下,觉得是没有这个名称对应的类,于是去找了struts-default.xml这个文件。
https://struts.apache.org/download.cgi
来下载一个strut2,下载个all版本的吧,解压缩,然后去找对应的文件夹下面找structs\struts-2.3.37\src\core\src\main\resources,找到之后打开struts-default.xml
好了答案显而易见,你没有定义这个对应的拦截器,所以你引用servlet-config这个名称自然而然就会报错,改为servletConfig就可以了。
细想了一下问题所在,其实应该就是我引用的struts相关jar包问题,不同版本所以导致名称需要转变一下罢了。
示例代码
这个仓库里面的ssh_learn_intercept
https://gitee.com/mrchen13427566118/ssh_learn.git
如果不会怎么弄到eclipse的话,就看这里
https://blog.csdn.net/weixin_43987277/article/details/116936221