Struts2总结
1.概述:
Struts2是基于MVC的一个经典框架。
它以webwork为核心,采用拦截器机制处理用户的请求,与servletaAPI完全解耦合,低入侵式设计,面向切面的设计思想,使用动态代理反射机制,线程安全。核心控制器是filterDispatcher.
2.框架
M:Model模型层 由JavaBean 和EJB(Enterprise JavaBean)组成 负责业务逻辑处理,数据库访问
V:view视图层 jsp文件,struts2标签库,Ognl 负责显示页面,与用户交互,接收用户信息
C:由FilterDispatcher和action组成:
FilterDispatcher:核心控制器(升级版:strutsPrepareAndExecuteFilter)
Interceptors:拦截器,对请求进行一系列的拦截过滤。
Action类:由开发人员编码实现,负责调用模型、数据传递和视图转向
3.struts1VSstruts2
Struts2:
- 与servletAPI解耦合,易于测试
- 线程安全,action存在于当前线程中,每次请求产生一个新的actionContext
- 面向切面的设计思想,低入侵式设计
- 采用动态代理和反射机制
Strutst1:
- 与servletAPI耦合较高
- 非线程安全,容易产生并发现象。
- 高入侵式的设计
4.执行过程:
5.核心配置文件:
Web.xml
<!-- 配置FilterDispatcher 2.3 -->
<filter>
<filter-name>struts</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
<!—
配置FilterDispatcher 2.0
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
-->
</filter>
<filter-mapping>
<filter-name>struts</filter-name>
<url-pattern>/*</url-pattern>(不仅拦截action请求,还拦截普通请求实现通用功能)
</filter-mapping>
struts.xml
<struts>
<!-- 设置webapp为开发模式 -->
<constant name="struts.devMode" value="true" />
<!-- 设置字符集 -->
<constant name="struts.i18n.encoding" value="UTF-8" />
<!-- 设置UI -->
<constant name="struts.ui.theme" value="simple" />
<!-- 设置上传图像最大值 -->
<constant name="struts.multipart.maxSize" value="10701096" />
<package name="basePack" namespace="/" extends="struts-default">
<!-- 声明interceptors -->
<interceptors>
<interceptor-stack name="myDefaultStack">
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<!—引用interceptors -->
<default-interceptor-ref name="myDefaultStack"></default-interceptor-ref>
<global-results>
<result>/index.jsp</result>
</global-results>
</package>
<include file="com/guigu/config/user.xml"></include>
</struts>
Userx.xml
<struts>
<package name="userLogic" namespace="/user" extends="basePack">
<!-- 初始化部门编号 -->
<action name="initDept" class="com.guigu.action.UserAction" method="initDept"> <result>/user/addUser.jsp</result>
</action>
<action name="addUser" class="com.guigu.action.UserAction" method="addUser">
<result>/user/showUser.jsp</result>
</action>
</package>
</struts>
关于常量
常量可以定义在多个文件中,默认情况下我们按照下面的顺序来寻找常量,后面的将覆盖前面的设置:
struts-default.xml
struts-plugin.xml
struts.xml
struts.properties
web.xml
前3个xml文件的格式是一样的,因为它们使用同一个DTD文件,在xml文件中Constant元素有两个必须的属性:name和value;在struts.properties文件中,每一个entry都被视为一个常量;在web.xml文件中FilterDispatcher的初始化参数被载入为常量。
下面分别给出3中常量形式的例子。
struts.xml文件中常量
<struts>
<constant name="struts.devMode" value="true" />
</struts>
struts.properties文件中常量
struts.devMode = true
web.xml文件中常量
<filter>
<filter-name>struts</filter-name>
<filter-class>
org.apache.struts2.dispatcher.FilterDispatcher
</filter-class>
<init-param>
<param-name>struts.devMode</param-name>
<param-value>true</param-value>
</init-param>
</filter>
5.视图模型
<result type="" name="">/user/showUser.jsp</result>
type:
转发: |
dispatcher(默认) |
转发至url(指jsp文件,不能转发至.action的url) |
chain |
转发至action |
|
重定向 |
redirect |
重定向至url |
redirectAction |
重定向至action |
name: 视图模型对应的名称
success: success
input:验证失败返回的视图模型 如:<result name="input">/student/addStu.jsp</result>
6.struts2验证机制
6.1安全性验证:
1.客户端 通过js验证
2.服务器端
服务器代码验证:必须
数据库验证:非必须
6.2 struts2验证
分为validate验证和action验证
Validate验证:主要是与业务无关的验证,如用户名不能为空
Action验证:与业务相关的验证,如用户名重复的验证
实现:
1.action类extends ActionSupport类
2validate验证
.重写validate()/validateXxx()方法,this.addFieldError("", "");
validate方法在对应的action方法执行前执行,若验证失败会自动返回“input”视图模型
例:
/**
* 验证所有的action
*/
public void validate(){
if(stu==null||stu.getStu_id()==null||stu.getStu_id().trim().equals("")){
this.addFieldError("stu_id", "学号不能为空");
}
if(stu==null||stu.getStu_name()==null||stu.getStu_name().trim().equals("")){
this.addFieldError("stu_name", "姓名不能为空");
}
}
validate Addstu ()只验证特定的action
3.action验证,
this.addActionError("");return Action.INPUT;需要显示的返回input视图模型
/**
* 添加学生
*/
public String addstu(){
if("s001".equals(stu.getStu_id())){
this.addActionError("用户已被注册");
return Action.INPUT;
}
stuSer.addStu(stu);
System.out.println("添加学生");
return "success";
}
4,页面显示错误信息
<s:fielderror fieldName="stu_id"></s:fielderror>
<s:actionerror/>
7.struts2与servlet API(application interface)交互
有两种方式:
- ServletActionContext
耦合较高,获取真实的servlet API
使用:
ServletActionContext.getRequest()/getResponse()/getServletContext
- ActionContext
低耦合,struts2封装了的servlet API(主要用传值)
使用:
Map<String,Object> session = ActionContext.getContext().getSession();/getApplication()
session.put("userList", userList);
Map<String,Object>request=(Map)ActionContext.getContext().get("request");/get(“response”);
request.put("deptList", deptList);
原理:
ActionContext容器,每个线程产生一个actioncontext,用于管理该线程下的action.请求第一次到达时创建actioncontext,以及action实例,以后请求到达时重新创建action实例,线程安全。
8.ognl(object graph navigation language,对象图形导航语言)
Context 与作用域通信对象的进行交互,不推荐使用
|
ValueStack 与action属性进行交互,每次取栈顶元素的属性 |
主要标签:
<s:property value="user.user_id"/>取出action的属性值(该属性必须给get/set方法)
<s:property value="#session[‘user_id’] "/>取作用域通信对象的值,map的值
<s:iterator value="#session['userList']">(iterator用于从List/Map等集合中取值)
<s:property value="user_id"/>
</s:iterator>
<s:textfield name="user.user_id">
<s:radio name="user.user_sex" list="#{0:'男',1:'女'}" ></s:radio>
<s:checkboxlist name="user.user_hobby" list="#{0:'唱歌',1:'跳舞',2:'绘画'}" value="user.user_hobby"></s:checkboxlist>(value和name给一个就可以的)
<s:select name="user.dept_id" list="deptList" listKey="dept_id" listValue="dept_name" ></s:select>
</s:from>
#的用法:
#parameters.id[0]
#request['deptList'].dept_id/#request.deptList.dept_id
#session['userList']/#session.userList
#application['user']/#application.user
关于<s:>和${}、html
html标签中可以放置<s:>和${}
<a href="showAUser.action?user.user_id=<s:property value="user_id"/>">修改</a>
<a href="delUser.action?user.user_id=${user_id }">删除</a>
.<s:>标签中不能放置<s:>和${}
<s:form action="${basePath}">错误
<s:textfield value="<s:text name='submit'></s:text>"/>
9.拦截器(interceptors)
9.1概念:
使用动态代理机制,(依赖于字节码工具,如asm)使得普通的action类具有处理请求的能力。
拦截器在Action执行之前和之后拦截请求,执行逻辑处理;
Struts2大多数核心功能都是通过拦截器实现的;
使用拦截器有利于系统解耦,使系统功能具有了可拔插性。
9.2工作顺序
按照配置文件中拦截器的顺序执行,返回时反顺序执行。
9.3 自定义拦截器
1.编写interceptor类,extends AbstractInterceptor
2.重写 intercept(ActionInvocation invocation) throws Exception {
String result = invocation.invoke();
}
3.配置拦截器:
<interceptors>
<interceptor name="mylogger" class="com.guigu.interceptor.MyLoggerInterceptor" />
</interceptors>
3.action中引用拦截器
<action name="addUser" class="com.guigu.action.UserAction" method="addUser">
<result>/user/showUser.jsp</result>
<interceptor-ref name="defaultStack" /> (必须引用默认拦截器)
<interceptor-ref name="mylogger" />
</action>
9.4扩展:
拦截器栈
声明拦截器栈
<interceptors>
<interceptor-stack name="myDefaultStack">
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
引用拦截器栈
<default-interceptor-ref name="myDefaultStack"></default-interceptor-ref>
9.5应用:避免表单重复提交
1.原理:请求到达时页面生成令牌,并在session中也存入该令牌,action中判断两者的令牌是否相同,若相同认为是有效的请求,并进行处理。若不相同,返回到无效的页面。
2.struts中通过TokenInterceptor和TokenSessionInterceptor来避免重复提交
3.实现:
a)页面:<s:token/>放置令牌
b) action中引用interceptor
1.token
<interceptor-ref name="token"/>
<interceptor-ref name="defaultStack"/>
<result type="chain">personList</result>
<result name="invalid.token">/error.jsp</result>(显示给出错误页面)
2.sessiontoken
<interceptor-ref name="tokenSession"/>
<interceptor-ref name="defaultStack"/>
<result type="chain">personList</result>
<result name="invalid.token">/error.jsp</result>(可以不显式给出错误页面)
c) 在全局资源文件中,使用下面的键自定义错误提示信息:struts.messages.invalid.token
d)显示错误信息<s:actionerror>
10上传
步骤:
1)配置上传文件的最大容量:
<constant name="struts.multipart.maxSize" value="10701096" />
2)页面上的表单:
<s:form action=" " method="post" enctype="multipart/form-data">
<s:file name="img" label="上传头像"></s:file>
3)action中处理:
private File img;
private String imgContentType;
private String imgFileName;
public String addUser(){
basePath = ServletActionContext.getRequest().getRealPath("/");
FileUtils.copyFile(img, new File(basePath,imgFileName));
}
(提示:如果存数据库的话:user.setUser_photo(imgFileName)
写工具renameFile System.currentTimeMillis()+fileName.substring(fileName.lastIndexOf("."))
11.国际化:
1.配置:
<!-- 国际化配置 -->
<constant name="struts.custom.i18n.resources" value="lan" />
2.写属性文件:
lan_en_US.properties
lan_zh_CN.properties
中文加密:C:\Program Files\Java\jdk1.6.0_22\bin\>native2ascii 1.txt 2.txt,其中,1.tx是中文源文件,2.txt为加密后的文件)
12.类型转换器
Struts2内置了常用的类型转换器,编者可以自行编制类型转换器
实现:
- 类extends StrutsTypeConverter
- 重写
private static final SimpleDateFormat df = new SimpleDateFormat("yyyy-mm-dd");
@Override
public Object convertFromString(Map arg0, String[] values, Class arg2) {
try {
return df.parse(values[0]);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
@Override
public String convertToString(Map arg0, Object date) {
return df.format(date);
}
- 编写properties文件
全局:src下xwork-conversion.properties
java.util.Date=com.guigu.convert.MyDateConvert
指定action:
在action包下编写 UserAction-conversion.properties
User.user_id=com.guigu.convert.MyDateConvert