Struts2学习小结
1 基础
使用:导入 jar 包,配置 web.xml,并引入 struts.xml 文件
DMI:动态方法调用,调用时使用!分隔 action 名与方法名,如 index ! add.action,可以进行快捷测试
<!-- 需要修改配置文件,默认为false,需要修改为true -->
<constant name="struts.enable.DynamicMethodInvocation" value="true" />
通配符:
<action name="\*_*" class="action.{1}Action" method="{2}">
<result>{1}_{2}.jsp</result>
</action>
结果类型:
- dispatcher:默认为此项,转发到某个页面
- chain:跳转到一个action
- redirect:重定向到页面或action,会丢失参数
redirectAction:重定向到某个action
跳转到另一个包中的action
<result name="loginSuccess" type="redirectAction">
<param name="namespace">/</param>
<param name="actionName">index</param>
<param name="method">index</param>
</result>
- 带参数的结果集:
<result name="params" type="redirect">/params.jsp?t=${type}</result>
接收参数
- 直接在 Action 中增加属性
- 使用 domainModel,在 Action 中持有一个 Bean 的引用
- 实现 ModelDriven 接口
访问web元素(request,session等)
- 直接定义,使用 ActionContext.getContext().getSession() 获取
- 使用 ServletActionContext 类的静态方法
- IoC,实现相应的 Aware 接口(ServletRequestAware,SessionAware等)
Struts2读取配置文件顺序:
- struts-default.xml
- struts-plugin.xml
- struts.xml
- struts.properties
- web.xml
JSP转发到action失败,strus2默认不接受转发。解决:修改web.xml:
<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>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
2 数据校验
必须添加如下配置:/login.jsp
使用struts2标签,非simple主题自动显示错误信息,simple主题可以使用标签 或 EL/OGNL 表达式获取错误信息
编程式验证:
- 重写 validate() 方法,使用 addFieldError() 或 addActionError() 返回错误信息
- 在不需要验证的方法上增加注解:@SkipValidation
声明式验证:xwork里的validation拦截器
在action包下添加ActionClassName-validation.xml(针对所有方法)
添加ActionClassName-alias-validation.xml(针对某个方法),alias为struts.xml下action标签的name属性
<validators>
<!-- 字段验证,fielderror -->
<field name="age">
<!-- 短路验证 -->
<field-validator short-circuit="true" type="conversion">
<message>类型转换出错</message>
</field-validator>
<field-validator type="int">
<param name="min">18</param>
<param name="max">70</param>
<!-- key引用国际化配置文件中的name -->
<message key="error.message"></message>
<!-- 在国际化配置文件中添加如下信息 -->
<!--
error.message=$(getText(fieldName)) needs to be betweents ${min} and ${max}
age=年龄
count=数量
-->
</field-validator>
</field>
<!-- 非字段验证,actionerror -->
<validator type="expression">
<param name="expression"><![CDATA[password==password2]]></param>
<message>两次密码输入不一致</message>
</validator>
</validators>
3 OGNL
访问静态方法:<s:property value="@com.ma.OgnlAction@test()"/>
Math类的静态方法:<s:property value="@@max(2,3)"/>
List: <s:property value="users.{name}[1]"/>
Map.keys: <s:property value="map.keys"/>
Map.values: <s:property value="map.values"/>
size: <s:property value="map.size()"/>
// 投影:抽取集合中的某一列数据
// 选择:从集合中选取满足条件的数据
// ?表示获取满足指定条件的所有元素
选择所有的:<s:property value="users.{?#this.age == 18}[0].name"/>
选择第一个:<s:property value="users.{^#this.age > 20}.{name}"/>
选择最后一个:<s:property value="users.{$#this.age > 20}.{name}"/>
判断为空:<s:property value="users.{$#this.age > 20}.{name} == null"/>
中括号[],从第0个开始遍历所有值栈: <s:property value="[0]" />
4 Struts2标签库
数据标签:
<!-- 判断value里的内容是否为ognl表达式须看文档中的value是什么类型,强转需要使用%{} -->
property取值为字符串 : <s:property value="username"/>
property设定默认值 : <s:property value="admin" default="admin"/>
property解析html : <s:property value="<hr/>" escape="false" />
set设定adminName值(默认存放在request和ActionContext(Stack Context)中)
<s:set var="adminName" value="username" scope="session" />
//注意使用%{str}将str强转为ognl表达式, 并注意OGNL与EL的结合使用
//<s:property/>标签中的value属性直接以ognl表达式解析
//其他标签都需要使用 % 将字符串强转为ognl表达式
<!-- select的两种用法:struts标签和jstl标签 -->
<s:select list="departments" listKey="id" listValue="name" value="model.department.id" headerKey="" headerValue="---请选择---"/>
<select>
<c:forEach items="${departments}" var="dept">
<!-- 注意相等是用 "==" 表示 -->
<option value="${dept.id}" <c:if test="${dept.id == model.department.id}">selected="selected"</c:if>>${dept.name }</option>
</c:forEach>
</select>
<!-- <s:select/>自定义列表内容 -->
<s:select list="#{'I':'调入','O':'调出'}" key="ajustLogModel.flag" headerKey="" headerValue="--请选择--"></s:select>
5 $,%,#的用法
- $用于 struts.xml 文件和 i18n 中引用 ognl 表达式
- #用于取 ActionContext ( Stack Context,堆栈 ) 中的对象
- %用于将字符串强转为 ognl 表达式
6 处理ajax请求
1.通用的方式:
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("This is an ajax response from a struts Action.");
out.flush();
return null;
2.使用struts2中的流的方式
private InputStream inputStream;
public String delete() throws UnsupportedEncodingException {
trainService.delete(ids);
inputStream = new ByteArrayInputStream("1".getBytes("utf-8"));
return SUCCESS;
}
<!-- 以stream的方式传输ajax请求 -->
<result type="stream" name="deleteSuccess">
<param name="contneType">text/html</param>
<param name="inputName">inputStream</param>
</result>
7 文件上传
form表单必须以 multipart/form-data 方式提交
//文件上传需要的参数,多文件改成数组即可
private File upload; //文件,名称对应input中file类型的name值
private String uploadFileName; //文件名称,setter方法必须为:setUploadFileName
private String uploadContentType; //文件的MIME类型,setter方法必须为:setUploadContentType
private void upload(Product product) throws IOException {
//删除上传的图片
String path = product.getImage();
if (path != null) {
String realPath = ServletActionContext.getServletContext().getRealPath("/" + path);
File file = new File(realPath);
file.delete();
}
if (upload != null) {
//获取文件上传的磁盘的绝对路径
String realPath = ServletActionContext.getServletContext().getRealPath("/products");
//创建一个文件
File diskFile = new File(realPath + "//" + uploadFileName);
//文件上传
org.apache.commons.io.FileUtils.copyFile(upload, diskFile);
product.setImage("products/" + uploadFileName);
}
}
<!-- 配置其它上传参数需要使用拦截器 -->
<constant name="struts.multipart.maxSize" value="107374182400" />
<interceptor-ref name="fileUpload">
<param name="allowedTypes">image/bmp,image/jpeg,image/jpg,image/png,image/gif</param>
<param name="maximumSize">2M</param>
</interceptor-ref>
8 全局异常处理
<global-exception-mappings>
<exception-mapping result="error" exception="java.lang.NullPointerException"></exception-mapping>
</global-exception-mappings>
需要为error配置一个全局结果集,前台使用struts标签或ognl表达式获取:${exception.message}
9 拦截器
自定义拦截器:实现Interceptor接口,或继承MethodFilterInterceptor(推荐)
默认使用 defaultStack,若使用自定义拦截器则需要显示调用自定义的和默认的,或定义自己的拦截器栈
在package下注册自定义拦截器并添加拦截器栈:
<interceptors>
<interceptor name="timer" class="interceptor.MyInterceptor" />
<interceptor-stack name="myStack">
<interceptor-ref name="defaultStack" />
<interceptor-ref name="timer" />
</interceptor-stack>
</interceptors>
在action中引入自定义拦截器(栈):<interceptor-ref name="myStack"/>
拦截器和过滤器区别
- 过滤器是J2EE的标准,任何的一个程序都可以使用;拦截器是struts2框架的一个标准,不能离开struts2框架,必须依赖struts2框架。
- 拦截器是基于java的反射机制的,而过滤器是基于函数回调。
- 拦截器不依赖于servlet容器,过滤器依赖于servlet容器。
- 拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
- 拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
- 在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
- 拦截器可以注入IOC容器中的bean,而过滤器不行,这点很重要,如在拦截器里注入Service,可以调用业务层方法
- 执行的顺序:过滤器 -----> 拦截器。
- 过滤器拦截的是web.xml配置文件。其他的拦截工作就都交给了拦截器。
10 设置编码方式
- struts2.3.x以后默认为utf-8
- struts2.3.x中的 default.properties 中的默认配置即为utf-8
- 在 struts.xml 中配置常量:
<constant name="struts.i18n.encoding" value="utf-8"></constant> - 在web.xml中为struts2的核心过滤器设置初始化参数
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
<init-param>
<param-name>struts.i18n.encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
几个配置文件加载顺序:default.properties > struts.xml > web.xml
11 核心流程源码解析:

首先,客户端发出请求,经三个过滤器(ActionContextCleanUp(可选),其他过滤器,到StrutsPrepareAndExecuteFilter(新版),此过滤器询问ActionMapper该请求是否属于struts2请求,是就将请求处理交给ActionProxy,ActionProxy通过ConfigurationManager 加载配置文件struts.xml,找到请求对应的Action类,然后创建一个ActionInvocation实例,根据配置文件struts-default.xml循环调用action相关的拦截器,每执行完一个拦截器,会继续调用invocation的invoke方法,把请求传给下个拦截器,所有的拦截器执行完以后,会调用Action,action执行完毕后返回一个result,通常是jsp或FreeMarker模板,渲染结果生成动态页面(struts2标签等),此时还没有完毕,继续按照相反顺序调用相关拦截器,最后将结果返回。
Struts2学习小结的更多相关文章
- flex学习小结
接触到flex一个多月了,今天做一个学习小结.如果有知识错误或者意见不同的地方.欢迎交流指教. 画外音:先说一下,我是怎么接触到flex布局的.对于正在学习的童鞋们,我建议大家没事可以逛逛网站,看看人 ...
- Python 学习小结
python 学习小结 python 简明教程 1.python 文件 #!/etc/bin/python #coding=utf-8 2.main()函数 if __name__ == '__mai ...
- react学习小结(生命周期- 实例化时期 - 存在期- 销毁时期)
react学习小结 本文是我学习react的阶段性小结,如果看官你是react资深玩家,那么还请就此打住移步他处,如果你想给一些建议和指导,那么还请轻拍~ 目前团队内对react的使用非常普遍,之 ...
- objective-c基础教程——学习小结
objective-c基础教程——学习小结 提纲: 简介 与C语言相比要注意的地方 objective-c高级特性 开发工具介绍(cocoa 工具包的功能,框架,源文件组织:XCode使用介绍) ...
- pthread多线程编程的学习小结
pthread多线程编程的学习小结 pthread 同步3种方法: 1 mutex 2 条件变量 3 读写锁:支持多个线程同时读,或者一个线程写 程序员必上的开发者服务平台 —— DevSt ...
- [原创]java WEB学习笔记75:Struts2 学习之路-- 总结 和 目录
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- [原创]java WEB学习笔记66:Struts2 学习之路--Struts的CRUD操作( 查看 / 删除/ 添加) 使用 paramsPrepareParamsStack 重构代码 ,PrepareInterceptor拦截器,paramsPrepareParamsStack 拦截器栈
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- ExtJs学习笔记之学习小结LoginDemo
ExtJs学习小结LoginDemo 1.示例:(登录界面) <!DOCTYPE html> <html> <head> <meta charset=&quo ...
- 点滴的积累---J2SE学习小结
点滴的积累---J2SE学习小结 什么是J2SE J2SE就是Java2的标准版,主要用于桌面应用软件的编程:包括那些构成Java语言核心的类.比方:数据库连接.接口定义.输入/输出.网络编程. 学习 ...
随机推荐
- python--easygui
1.msgbox import easygui as eg # msgbox # 一般使用三个参数,msg:内容,title:标题,ok_button:按钮内容 eg.msgbox(msg=" ...
- 用RegisterHotKey注册系统热键
函数功能:该函数定义一个系统范围的热键. 函数原型:BOOL RegisterHotKey(HWND hWnd,int id,UINT fsModifiers,UINT vk): 参数: hWnd:接 ...
- Logstash 最佳实践
https://doc.yonyoucloud.com/doc/logstash-best-practice-cn/index.html
- Guava源码学习(二)Ordering
基于版本:Guava 22.0 Wiki:Ordering 0. Ordering简介 Guava的Ordering提供了链式风格的比较器的实现,我们可以用Ordering轻松构建复杂的比较器. 1. ...
- vi / vim 设置
一.vi下方向键输入后,出现ABCD,解决方法: 在vi中输入:set nocp 按回车即可. 二.设置TAB缩进4个空格: 为了vim更好的支持python写代码,修改tab默认4个空格有两种设置方 ...
- NEUQOJ 1999: 三角形or四边形?【搜索联通块/模拟】
http://newoj.acmclub.cn/problems/1999 1999: 三角形or四边形? 描述 题目描述: JiangYu很无聊,所以他拿钉子在板子上戳出了一个由.#组成的10*10 ...
- servlet方法
1.每一个Servlet都必须要实现Servlet接口,GenericServlet是个通用的.不特定于任何协议的Servlet,它实现了Servlet接口,而HttpServlet继承于Generi ...
- 日志采集客户端 filebeat 安装部署
linux----------------1. 下载wget https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-5.5.1- ...
- docker环境准备及理论
1.预热 内核运行在内核空间,进程运行在用户空间,linux进程特性:父进程负责子进程的创建和回收,白发人送黑发人.容器就是为了保护它里面的内容物,不受其他容器干扰,也不去干扰其他容器.容器让进程认为 ...
- 链接服务器 "(null)" 的 OLE DB 访问接口 "SQLNCLI11" 指示该对象没有列,或当前用户没有访问该对象的权限。
原文:链接服务器 "(null)" 的 OLE DB 访问接口 "SQLNCLI11" 指示该对象没有列,或当前用户没有访问该对象的权限. SELECT * F ...