struts2学习笔记
.struts2(2.1)知识基础部分
Ø 1 .struts2概述
Action、基本数据验证、Result、常用的配置文件、OGNL和ValueStack、Struts2 Tags
类型转换、上传下载、防止重复提交、Interceptor(拦截器)、MVC设计思想、Struts2基于webWork
Ø 2 .Action相关内容
<1>action入门 <2>namespace
<3>自定义Action <4>路径设置
<5>调用action中定义的方法
<6>通配符 <7>接受用户输入的3中方式
<8>乱码问题解决 <9>简单的数据校验 <10>aciton中访问web元素
<11>包含模块的文件 <12>默认的action
Ø 3 .struts2入门
ü 构建项目
<1>整合jar包
需要的核心jar包freemarker-2.3.13 、ognl-2.6.11、 struts2-core-2.1.6、xwork-2.1.2
<2>增加struts2的核心过滤器
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>
</filter-mapping>
其中StrutsPrepareAndExecuteFilter包含两个过滤器
<3>增加struts2的配置文件
Struts.xml放到根目录下内容如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
"http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
<constant name="struts.devMode" value="true"></constant>
<package name="front" namespace="/struts2test" extends="struts-default" >
<action name="hello">
<result>/page/hello.jsp</result>
</action>
</package>
</struts>
以上例子用没有实际的action类,而是中间转发过程
访问此程序地址为:http://localhost:9080/struts2_001/struts2test/hello
访问规则为地址+命名包空间名称+action的名称
ü 常用小技巧
<1>struts2.xml配置开发模式,使的修改配置文件之后不用重新启动,访问直接生效
配置strtus2常量
<constant name="struts.devMode" value="true"></constant>
<2>查看jar对应的源码
在eclipse中切换到package查看模式,选中查看的包,右击属性
可以绑定到特定的项目空间(workspace)、特定的文件、特定的文件夹;
绑定到源代码文件夹,之后遍可以直接访问源码;
<3>绑定java doc可以查看api文档
查看方式,选种类或方法之后F1后,可以查看api文档
Ø 4 .struts2工作机制
Struts2.xml中的package元素的namespace元素和访问路径一一对应的
访问路径中的后缀名action可以进行省略
Ø 5 .namespace元素
ü Namesapce的作用
ü 详解说明
<package name="firstTest" namespace="/" extends="struts-default">
<action name="helloAction">
<result>/page/hello.jsp</result>
</action>
</package>
- A. package包含三个属性name、namespace、extends,package作用是为了防止重复(类似于java中的包的作用);
- B. action:必须增加name属性,可以增加具体实现class属性
- C. result:可以添加name属性以及对应值,不增加此属性,默认为success(具体值可以在action中进行转发定义)
- D. namespace默认为空(namespace=””),可以访问任何一个action(匹配的),任何对应的路径(namespace 下)的action都可以访问
copy项目的时候,由于webContext还是原来定义的名字,进行如下修改
项目右击属性web配置,对项目的访问上下文进行修改
Ø 6 .action
ü 核心内容
action控制视图的转向,可以自己定义action,action可以是一个普通的类,只要类中有方法execute即可
统一修改jsp中代码的编码方式
<package name="firstTest" namespace="" extends="struts-default">
<action name="hello" class="com.action.HelloAction">
<result>/page/hello.jsp</result>
</action>
</package>
不配置action的class属性值的时候,默认使用了ActionSupport类
编写action的三种方式
<1>Action可以实现action接口
<2>继承ActionSupport(用此种)
<3>可以是普通的java类,必须包含execute方法
Action实现视图转发的类都是返回字符串数据,和具体result中的属性name对应
Ø 7 .路径(path)问题
在页面中链接(<a href=”index.jsp”>index.jsp<a>)以及提交到某一地址,由于struts2中运用了namespace概念,访问任意地址,都先便利struts2.xml中的namespace信息,如果找不到对应的命名空间信息,会链接到非预期的地址,为了访问具体地址,一般用绝对路径解决此问题
通常struts2访问的原理,首先请求信息寻找(web.xml),之后通过过滤器,进行请求转发
,过滤器读取配置问题struts2.xml,根据namespace和action具体具体转发的action类,如果找寻不到
具体的namepace和action,则请求转发给web容器进行处理
具体访问路径可以根据服务器信息进行绝对定位,struts2的访问路径是根据action的请求地址,而不是jsp的地址进行
请求转发,对于jsp的路径尽量使用如下方式
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
url:basePath+path+jspname;
String path = request.getContextPath();
String basePath
= request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
<a href="<%=basePath %>page/index.jsp">index.jsp</a>
Ø 8 . 动态方法调用
action执行的时候,默认执行execute方法,但可以自己定义方法
<1>方式1:
配置文件中增加method属性,可以提供给请求转发进行调用,可以配置参数method属性
在配置文件struts2.xml中配置信息如下
<package name="user" namespace="user" extends="struts-default">
<action name="userAction" class="actionClassPath" method="methodName">
<result name="adduser">/page/useradd.jsp</action>
</action>
</package>
缺点:如果存在多个方法(add,delete,update,query),每个方法都需要单独配置一个action块
,不推荐使用
<2>方式2(建议使用):动态方法调用(dmi dynamic method invoke)
在配置文件struts2.xml中,不用配置属性method,只需要配置一个action,请求调用时候直接动态调用
(不同的方法,各自需要返回自己的视图,需要配置多个result)
<package name="user" namespace="user" extends="struts-default">
<action name="userAction" class="actionClassPath">
<result name="adduser">/page/useradd.jsp</action>
<result name="deleteuser">/page/userdelete.jsp</action>
<result name="updateuser">/page/userupdate.jsp</action>
</action>
</package>
请求地址格式为:basePath+path+namespace/+action!methodName;
Ø 9.请求action的地址通配符形式
利用*通配符号,并且结合参数占位符{1}{2}.....
约定优于配置(提前约定好jsp页面以及action中方法的命名规则),用通用的配置,匹配所有的路径调用信息
<package name="user" namespace="/user" extends="struts-default">
<action name="user*" class="com.action.UserAction" method="{1}">
<result name="{1}_page">/page/user.jsp</result>
<result name="{1}_user">/page/user.jsp</result>
<result name="{1}_user">/page/user.jsp</result>
</action>
</package>
{1}代表第一个*
{2}代表第二个*
Ø 10.action接受请求参数
注意请求地址中的namespace前不用增加"/"(action="namespace/actionname!methodname")
action中有三种接受参数值的方式
<1>属性接受(普通属性,基本类型的参数和复合类型的参数)
数组和基本属性相同增加setter和getter方法
注意:基本类型的数据必须提供setter和getter方法
对Map类型的数据,只要提供getter方法就可以(struts2内部调用的是Map的put方法)
struts2的action接受属性值是对应的getName中的Name并不是属性的值
在action中增加属性定义字段,并且增加对应的setter和getter方法
如下:
1)action中增加属性
public class UserAction extends ActionSupport{
private String userName;
private String password;
public String add(){
System.out.println("add_page");
return "add_page";
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
2)form表单地址
<form name="userForm" method="post" action="user/user!add">
username:<input name="userName" type="text"/>
password:<input name="password" type="text"/>
<input type="submit" name="sb" value="submit"/>
</form>
<3>调试属性信息,通过调试信息可以很对定位读取属性的信息
<%@taglib uri="/struts-tags" prefix="s" %>
<s:property value="userName"/>
<s:debug></s:debug> 调试信息
<2>domainModel域模型接受参数
将属性封装到vo(pojo)中,之后在action进行引用
不用new vo,struts2已经对vo进行了对象初始化
并在vo提供对应属性的setter和getter方法
在表单属性的名称需要引用vo的名称
user.userName
user.password
如下:
1)定义action并引用User
public class UserAction extends ActionSupport{
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String add(){
System.out.println("add_page");
return "add_page";
}
2)表单元素名称定义
<form name="userForm" method="post" action="user/user!add">---注意地址访问信息中命名空间
username:<input name="user.userName" type="text"/>
password:<input name="user.password" type="text"/>
<input type="submit" name="sb" value="submit"/>
</form>
3)获得属性的值
<s:property value="user.userName"/>
<s:property value="user.password"/>
<s:debug></s:debug>
<3>ModelDriven(模型驱动)接受属性参数(这种方式不常用)
action实现接口ModelDriven<T>,且实现getModel方法
此时引用vo必须进行new
如下:
1)action内容
public class UserAction extends ActionSupport implements ModelDriven<User>{
private User user = new User();
public String add(){
System.out.println("add_page");
return "add_page";
}
public User getModel() {
return user;
}
}
2)请求页面参数名称
<form name="userForm" method="post" action="user/user!add">
username:<input name="userName" type="text"/>
password:<input name="password" type="text"/>
<input type="submit" name="sb" value="submit"/>
</form>
3)读取参数的值进行显示
<s:property value="userName"/>
<s:property value="password"/>
<s:debug></s:debug>
Ø 11.中文乱码
Struts2.xml文件中新增配置属性
<constant name=”struts.i18n.encoding” encode=”GBK”/>
在struts2中如果在版本2.1中利用新的filter即
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
即使增加编码配置方式,对于汉字也是乱码
可以换回原来的过滤器
org.apache.struts2.dispatcher.FilterDispatcher
汉字的乱码问题就解决了
Ø 12.简单的数据校验
<1>简单介绍
ActionSupport中的方法addFieldError和标签<s:fielderror fieldName=””/>进行简单的数据校验
实际上errors的校验的信息在Map中
如下:
public class UserAction extends ActionSupport{
private String userName;
public String add(){
System.out.println("userName:"+userName);
if(!this.userName.equals("wuoguoqing")){
this.addFieldError("userName", "输入信息错误");
}
return "add_user";
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
页面
<s:fielderror fieldName="userName" theme="simple"/>
<s:property value="errors.userName"/>
<s:debug></s:debug>
有关错误调试以及ValueStack信息
<s:debug></s:debug>用于显示页面中的值栈中的信息
<2>可以对同一个字段指定多个错误信息
if(!this.userName.equals("wuoguoqing")){
this.addFieldError("userName", "输入信息错误1");
this.addFieldError("userName", "输入信息错误2");
this.addFieldError("userName", "输入信息错误3");
this.addFieldError("userName", "输入信息错误4");
return "add_user";
}
Ø 13.action访问web页面中的元素
action中如何web元素对象request,session,application中的内容
通常有四种方式ActionContext(Map),(RequestAware、SessionAware、ApplicationAware)、ServletActionContext、ServletRequestAware
<1>ActionContext方式
通过ActionContext对象获得web元素对象的内容,
ActionContext封转了web元素存储访问的功能
通过Map进行访问,并且struts2可以将Map中的内容映射成HttpServletRequest中的内容,可以在页面中
直接通过jsp方式进行访问(request.getAttribute()),这种方式依赖于容器中的ActionContext,ActionContext并不是
单例形式,内部通过ThreadLocal实现
如下:
public class UserAction extends ActionSupport {
private Map request;
private Map session;
private Map application;
public UserAction(){
request= (Map)ActionContext.getContext().get("request");
session= (Map)ActionContext.getContext().getSession();
application= (Map)ActionContext.getContext().getApplication();
}
public String add(){
request.put("rusername","username");
session.put("susername","susername");
application.put("ausername","ausername");
System.out.println("add_page");
return "add_page";
}
}
将web元素的内容通过jsp或ognl方式进行访问显示
<%=request.getAttribute("rusername")%>
<s:property value="#request.rusername"/>
<2>实现对应接口(RequestAware、SessionAware、ApplicationAware由struts2提供)
在调用Action类的时候,先检查此action是否实现了上述接口,如果实现了调用对应的
setter方法,实例化web元素,由struts2实现
Aware:得知、知道
实现对应接口就知道对应web元素中的内容了
如下:
对初始化工作request/session/application由容器实现(DI dependcy injection)
public class UserAction extends ActionSupport implements RequestAware,
SessionAware, ApplicationAware {
private Map<String, Object> request;
private Map<String, Object> session;
private Map<String, Object> application;
public String add() {
request.put("rusername", "username");
session.put("susername", "susername");
application.put("ausername", "ausername");
System.out.println("add_page");
return "add_page";
}
public void setRequest(Map<String, Object> arg0) {
this.request = arg0;
}
public void setSession(Map<String, Object> arg0) {
this.session = arg0;
}
public void setApplication(Map<String, Object> arg0) {
this.application = arg0;
}
}
<3>通过ServletActionContext获得对应的web元素的内容
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class UserAction extends ActionSupport {
private HttpServletRequest request;
private HttpSession session;
private ServletContext application;
public UserAction(){
request = ServletActionContext.getRequest();
session = request.getSession();
application = session.getServletContext();
}
public String add() {
request.setAttribute("rusername", "rusername");
System.out.println("add_page");
return "add_page";
}
}
<4>实现ServletRequestAware接口
如下:
public class UserAction extends ActionSupport implements ServletRequestAware {
private HttpServletRequest request;
private HttpSession session;
private ServletContext application;
public String add() {
System.out.println("add_page");
return "add_page";
}
public void setServletRequest(HttpServletRequest arg0) {
this.request = arg0;
this.session=this.request.getSession();
this.application = this.session.getServletContext();
}
}
Ø 14.配置文件中包含模块配置文件(struts2.xml)
此中方式可以根据模块划分,将配置文件进行分块规划
<struts>
<constant name="struts.devMode" value="true"></constant>
<include file="user.xml"></include>
<package name="user" namespace="/user" extends="struts-default">
<action name="user" class="com.action.UserAction">
<result name="add_page">/page/user.jsp</result>
</action>
</package>
</struts>
Ø 15.默认action(默认定位访问那个页面,访问不存在的就调转到指定页面)
<package name="default" namespace="/" extends="struts-default">
<default-action-ref name="index">
<result>/page/user.jsp</result>
</default-action-ref>
</package>
Action总结
Ø 16.Result的配置
result的类型:
如果result如果不指定类型(type),默认为dispather(只能跳转到页面)
常用的包含:
dispatcher、redirect、chain、rediectAction
freemarker、stream、velocity......
<1>dispatcher:默认result使用此种方式(地址显示action的地址信息)
<2>redirect:客户端跳转(地址显示jsp)
<3>redirectAction:直接跳转到另一个action
<4>chain:从可以action直接跳转到另一个action
注意chain跳转到其他package下的action中
配置如下:
<action name="r3">
<result type="chain">
<param name="actionName">actionname</param><!--指定action的名字-->
<param name="namespace">namespace</param><!--指定namespace的名字-->
</result>
</action>
<package name="default" namespace="/" extends="struts-default">
<default-action-ref name="index" >
</default-action-ref>
<action name="index">
<result>/index.jsp</result>
</action>
<global-results>
<result name="mainpage">/index.jsp</result>
</global-results>
</package>
<package name="result" namespace="/result" extends="struts-default">
<action name="r1">
<result type="dispatcher">/page/r1.jsp</result>
</action>
<action name="r2">
<result type="redirect">/page/r2.jsp</result>
</action>
<action name="r3">
<result type="chain">r1</result>
</action>
<action name="r4">
<result type="redirectAction">r2</result>
</action>
</package>
Ø 17.全局结果集(Globals_Result)
一般用于维护公共的结果集合,其他包中若使用此结果集可以通过extends集成实现(如错误页面、主页面)
在同一个包中(struts2.xml中package)中,如果多个action公用相同的结果集,可以将公用的result写入到
<global-results>元素中如:
<global-results>
<result name="mainpage">/index.jsp</result>
</global-results>
同一包级下的action可以使用定义的globalresult
如果不在同一个包中,可以在包元素中使用extends属性使用其他包中的全局结果集
Ø 18.动态结果集
action中根据传递的参数,动态确定放回结果集的信息
如下:
public class DynamicAction extends ActionSupport implements ServletRequestAware {
private HttpServletRequest request;
private String type;
private String url;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public void setServletRequest(HttpServletRequest arg0) {
this.request=arg0;
}
public String execute(){
System.out.println("type:"+type);
if("1".equals(type)){
url="/page/r1.jsp";
}else{
url="/page/r2.jsp";
}
return "sucess";
}
配置文件如下:
<package name="dynamic" namespace="/dynamic" extends="default">
<action name="dynamic" class="com.action.DynamicAction">
<result name="sucess">${url}</result>
</action>
</package>
Ø 19.L(Object Graph navigation language)
Action中调用ServletActionContext获得Request
每一个特定的Action都有一个对应的ValueStack,struts2把相关action的属性信息存入其中,
以供页面或其他程序中调用
ü 访问对象的属性(普通属性
注意:
如果要访问action中定义的属性以及对象并在jsp运用ognl表达式进行显示,
在action中的属性以及对象必须设置setter/getter,这样struts2才会把相应的属性以及对象存放在action的栈中,页面才能进行数据访问
public class UserAction extends ActionSupport {
private String name;
private String password;
private User user = new User();
private List<User> list = new ArrayList<User>();
。。。。。。setter/getter
}
userName:<s:property value="name"/><br/>
password:<s:property value="password"/><br/>
user:<s:property value="user.userName"/><br/>
user static method:<s:property value="@com.vo.User@say()"/><br/>
<s:property value="'<hr/><hr/>'" escape="false"/>
List:<br>
<s:property value="list.get(0).userName"/><br/>
<s:property value="list.size()"/>
<1>访问valueStack中的普通属性
public class UserAction extends ActionSupport {
private String userName;
private String password;
。。。。。。
}
页面直接访问属性的值
<s:property value="userName"/><br/>
<s:property value="password"/><br/>
<2>访问valueStack中的vo
一般情况下action中vo可以不进行new(地址中传递vo.attribute,struts2会自动创建vo对象,否则的需要自己创建,如地址信息中传递user.name=nm&&user.pwd=p,自动构建user对象),也可以直接new一个vo对象
public class UserAction extends ActionSupport {
private User user;
private User user = new User();
。。。。。。
}
页面中访问对象的属性值
<s:property value="user.name"/><br/>
<s:property value="user.pwd"/><br/>
<3>ognl对象图导航语言
传值cat.friend.name=nm
通过此种语言可以对聚合对象进行导航,以便访问对象中的属性
<s:property value="cat.friend.name"/>
即访问对象的属性
vo.vo1….attibute
ü 访问对象的方法(普通方法)
可以访问action的普通方法
或访问action中属性(对象)的基本方法
<s:property value="user.pwd.length()"/><br/>
<s:property value="cat.say()”/>//对象中的方法
<s:property value="method()”/> //action中普通方法
ü 访问对象静态方法
<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
格式@静态类@静态方法()
格式@静态类@静态属性
ü 访问普通对象的构造方法
<s:property value="new com.vo.User()"/><br/>
ü 访问集合属性的内容
Ø 20.struts-tags
通用标签、控制标签、UI标签
ü <1>通用标签
l property标签
有关property的说明:
<s:property value=”objectName”/>访问valuestack中的objectName对象的值(通过ognl表达式)
<s:property value=”‘stringconstant’e”/>直接显示字符串的值
如果增加default属性,相当于如果栈中存在对应的对象,就显示默认值
l set标签
相关属性var/name scope,name属性高级版本已经去掉
<1><s:set var=”varname” value=”object”/>
设置一个变量var,并给予赋值object(此处为对象类型,可以通过ognl表达式进行访问)
如果不指定存贮范围,默认存贮在request中
可以通过#varname对变量的内容(从ActionContext)进行访问
<s:set var="param" value="user"></s:set>
<s:property value="#param"/>
<%=request.getAttribute("param") %>
<2>设定范围
<s:set var="param" value="user" scope=”page”></s:set>
设定范围后,通过#paraname无法访问,指定在指定范围内进行范围才可以
<s:set var="pageparam" value="'reeerwwerwererwr'" scope="session"></s:set><br>
<s:debug></s:debug>
<s:property value="#session.pageparam"/>
注意:<s:debug/>标签可以嵌套在其他标签中(其他标签之下,查看当前标签的在栈中的内容),指定valueStack的调试范围
l bean标签
引入对象,存放到ActionContext中,以供调用
<s:property value="%{setvalue}"/>
%{setvalue} 表示强制将setvalue作为ognl表达式访问,而不是作为字符串处理
一般标签只要设置了var相当于在valuestack中建立了对应的对象以及内容
在整个页面的任何位置都可以进行访问(ActionContext)
<s:bean name="com.vo.User" var ="users">
<s:param name="userName" value="'ppppppuser'"></s:param>
//给User对象设置属性值
</s:bean>
<s:property value="#users.userName"/>
<s:debug></s:debug>
可以利用#objectName访问valuestack中的对象
l include标签
<s:include value=”/config/sss.jsp”/>
l fielderror标签
<s:fielderror fieldName="struts.errorname" theme="simple"></s:fielderror>
l if标签
<s:set var="count" value="'12'"></s:set>
<s:if test="count>1">
very big
</s:if>
<s:elseif test="count>13">
veryvery big
</s:elseif>
<s:else>
very
</s:else>
注意:test中的对象的类型,如果是数值的话如何比较