1:struts2是一个基于MVC设计模式的WEB应用框架,本质是一个servlet
2:struts2是在struts1和Webwork的技术基础上进行了合并的全新的框架,以Webwork为核心,采用拦截器机制来处理用户的需求,这样的设计也使得业务逻辑控制器能够与ServletAPI完全脱离开
3:struts2的工作流程
1、客户端初始化一个指向Servlet容器(例如Tomcat)的请求;
2、这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin);
3、接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper来决定这个请求是否需要调用某个Action;
4、如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy;
5、ActionProxy通过Configuration Manager询问框架的配置文件(struts.xml),找到需要调用的Action类;
6、ActionProxy创建一个ActionInvocation的实例。
7、ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。
8、一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。在表示的过程中可以使用Struts2框架中继承的标签。在这个过程中需要涉及到ActionMapper。
4:struts2框架的搭建
1:下载源文件包(此版本)
2:核心包: struts2-core(核心)
xwork-core(基本)
freemarker (展示数据模板)
ognl(struts2的默认表达式语言)
javaassist()(操作字节码)
commons.lang3.StringUtils(语言包)
commons.fileupload(文件上传)
commons.io(IO输入输出)
3:配置struts2的启动过滤器
<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>
4:在类编译路径下面新建一个固定名称的配置文件:struts.xml
1:校验文件
2:<struts>
<pakage name,extend,namespace>
<actionname,class,method>
<resultname,type></result>
</action>
</pakage>
</struts>
5:简单的页面访问(包括常量配置<constantname=”” value=”” />)
1) 新建一个struts2对应action类[普通java类]
2) 配置struts2的核心功能[让自定义包继承struts2的默认配置]
Name: 指定包的名称用于继承唯一标识
Extend:继承父类包
Namespace:访问时,包空间作为地址
Abstract:是否为抽象包,用于继承
3) 配置action:
name: 指定访问的映射路径
class: 处理请求的类路径
method: 请求处理方法的名称
4) 配置result
name: 视图名称必须和调用方法的返回值一致
type: 结果类型(转发,重定向......)
内容: 需要展示的页面路径
5) 访问路径:
项目内容路径+命名空间+action名称+后缀名称
eg:http://127.0.0.1:8088/Struts2_Dev/hello/helloActionXxxx.action
6) Struts的默认配置
<!--
默认配置
action->class: com.opensymphony.xwork2.ActionSupport
action->method:execute
result->name: success
-->
<actionname="indexAction">
<result>/WEB-INF/index.jsp</result>
</action>
6:访问的结果类型
<!-- 配置包 -->
<package name="pkg"extends="struts-default" namespace="/test">
重定向
<ahref="test/redAction.action">重定向</a><br/>
<!--redirect 一般使用重定向到页面(错误页面,登录页) -->
<actionname="redAction" class="com.demo.ActionTypes"method="red">
<resultname="red" type="redirect">redirect.jsp</result>
</action>
转发
<ahref="test/disAction.action">转发</a><br/>
<!--dispatcher 默认的结果类型 -->
<actionname="disAction" class="com.demo.ActionTypes" method="dis">
<resultname="dis"type="dispatcher">/WEB-INF/dispatcher.jsp</result>
</action>
同包下面的action之间的跳转
<ahref="test/redactionAction.action">同包下面的action之间的跳转</a><br/>
<!--redirectAction 重定向Action -->
<actionname="redactionAction">
<resulttype="redirectAction">disAction</result>
</action>
不同包下面的action之间的跳转(继承实现)
<ahref="test1/redactionAction1.action">不同包下面的action之间的跳转(继承实现)</a><br/>
<!--定义包(继承,不推荐) -->
<packagename="pkg1" extends="pkg" namespace="/test1">
<actionname="redactionAction1">
<resulttype="redirectAction">disAction</result>
</action>
</package>
不同包下面的action之间的跳转(注入参数,推荐)
<ahref="test2/redactionAction2.action">不同包下面的action之间的跳转(注入参数)</a><br/>
<!--定义包(注入参数) -->
<packagename="pkg2" extends="struts-default"namespace="/test2">
<actionname="redactionAction2">
<resulttype="redirectAction">
<paramname="namespace">/test</param>
<paramname="actionName">disAction.action</param>
</result>
</action>
</package>
测试PlainText明码文本结果类型
<ahref="test/ptAction.action">测试PlainText结果类型</a><br/>
<!--定义PlainText结果类型 -->
<actionname="ptAction" class="com.demo.ActionTypes"method="plainText">
<resultname="pt" type="plainText">
<paramname="charset">UTF-8</param>
<paramname="location">/WEB-INF/dispatcher.jsp</param>
</result>
</action>
</package>
7:struts2的常用常量配置
<!-- 修改访问后缀名称-->
注意:web.xml里面配*.acction就不能识别.do
<constantname="struts.action.extension" value="do" />
<!-- 开发阶段不需要缓存静态内容浏览器是否缓存静态内容-->
<constantname="struts.serve.static.browserCache" value="false" />
<!-- 动态方法调用-->
struts2.1之前开启,之后关闭
<!—
动态调用action中方法配置:
actionName!方法名称+后缀
eg: userAction!add.do
-->
<!--<constant name="struts.enable.DynamicMethodInvocation" value="false"/> -->
设置是否可以在action中使用斜线,默认为false不可以,想使用需设置为true.
<constantname="struts.enable.SlashesInActionNames" value="true"/>
<!-- 开启开发者模式-->
<constantname="struts.devMode" value="true" />
8:struts2的分散配置
通常情况下package不能重名
Struts.xml
<!--模块配置文件包含到struts.xml文件中 -->
<includefile="config/struts-user.xml" />
<includefile="config/struts-tea.xml" />
<includefile="config/struts-book.xml" />
<!--
新建base包
abstract="true"定义为抽象包[下面不能定义action]
-->
<packagename="base" extends="struts-default"abstract="true">
</package>
Struts-user.xml
<packagename="pkg" extends="base" namespace="/test">
</package>
9:Action的配置方式(分散配置)
UserAction
private String message;
/**
* @return the message
*/
public String getMessage() {
return message;
}
public String add() {
this.message ="添加";
return "add";
}
1:普通方式配置Action
<fieldset>
<legend>普通方式配置Action</legend>
<p><ahref="user/addAction.do">添加</a></p>
<p><ahref="user/delAction.do">删除</a></p>
<p><ahref="user/updateAction.do">修改</a></p>
<p><ahref="user/queryAction.do">查询</a></p>
</fieldset>
<!-- 普通方式 -->
<packagename="pkg"extends="base"namespace="/user">
<actionname="addAction"class="com.user.action.UserAction"method="add">
<resultname="add">/WEB-INF/user/add.jsp</result>
</action>
………………….
</package>
2: 动态方法方式配置Action
(动态方法的调用可能会带来安全隐患(通过URL可以执行Action中的任意方法)
<fieldset>
<legend>动态方法方式配置Action</legend>
<p><ahref="user/userAction!add.do">添加</a></p>
<p><ahref="user/userAction!del.do">删除</a></p>
<p><ahref="user/userAction!update.do">修改</a></p>
<p><ahref="user/userAction!query.do">查询</a></p>
</fieldset>
<!-- 动态调用action中方法配置:
actionName!方法名称+后缀
eg:userAction!add.do
-->
<packagename="pkg1"extends="base"namespace="/user">
<actionname="userAction"class="com.user.action.UserAction">
<resultname="add">/WEB-INF/user/add.jsp</result>
<resultname="del">/WEB-INF/user/del.jsp</result>
<resultname="update">/WEB-INF/user/update.jsp</result>
<resultname="query">/WEB-INF/user/query.jsp</result>
</action>
</package>
3: 通配符方式配置Action
<fieldset>
<legend>通配符方式配置Action</legend>
<p><ahref="user/userAction/add.do">添加</a></p>
<p><ahref="user/userAction/del.do">删除</a></p>
<p><ahref="user/userAction/update.do">修改</a></p>
<p><ahref="user/userAction/query.do">查询</a></p>
</fieldset>
<packagename="pkg2"extends="base"namespace="/user">
<actionname="userAction/*"class="com.user.action.UserAction"method="{1}">
<resultname="{1}">/WEB-INF/user/{1}.jsp</result>
</action>
</package>
10:类型封装
// 简单类型
Action
privateInteger userId;
privateString username;
privateString password;
get,set
/**
* 定义用户注册的方法
* @return
*/
publicString register() {
return"success";
}
Index.jsp
<fieldset>
<legend>用户注册(简单数据类型)</legend>
<formaction="user/userAction_register.do" method="post">
<p>ID:<inputname="userId" /></p>
<p>账号:<inputname="username" /></p>
<p>密码:<inputname="password" /></p>
<p><inputtype="submit" value="注册"/></p>
</form>
</fieldset>
Struts.xml
<package name="pgk"extends="struts-default" namespace="/user">
<actionname="userAction_*"class="com.encapusulation.demo.UserAction" method="{1}">
<result>/WEB-INF/user/list.jsp</result>
</action>
</package>
List.jsp
用户信息如下:
<hr/>
<p>ID:${userId }</p>
<p>账号:${requestScope.username }</p>
<p>密码:${password }</p>
//复合类型(生日默认只支持yyyy-MM-dd格式)
实体类user
private IntegeruserId;
privateString username;
privateString password;
privateDate birthday;
get,set
Action
privateUser user;
get,set
/**
* 定义用户注册的方法
* @return
*/
publicString register() {
return"success";
}
Index.jsp
<fieldset>
<legend>用户注册(复合类型数据)</legend>
<formaction="user/userAction_register.do" method="post">
<p>ID:<inputname="user.userId" /></p>
<p>账号:<inputname="user.username" /></p>
<p>密码:<inputname="user.password" /></p>
<p>生日:<inputname="user.birthday" /></p>
<p><inputtype="submit" value="注册"/></p>
</form>
</fieldset>
List.jsp
<p>ID:${user.userId}</p>
<p>账号:${requestScope.user.username}</p>
<p>密码:${user.password}</p>
<p>生日:${user.birthday}</p>
//集合类型
实体类user
private IntegeruserId;
privateString username;
privateString password;
get,set
Action
privateList<User> userlist;
get,set
index.jsp
<fieldset>
<legend>用户注册(复合类型数据[List])</legend>
<formaction="user/userAction_register.do" method="post">
<p>ID:<inputname="userList[0].userId" /></p>
<p>账号:<inputname="userList[0].username" /></p>
<p>密码:<inputname="userList[0].password" /></p>
<p>ID:<inputname="userList[1].userId" /></p>
<p>账号:<inputname="userList[1].username" /></p>
<p>密码:<inputname="userList[1].password" /></p>
<p>ID:<inputname="userList[2].userId" /></p>
<p>账号:<inputname="userList[2].username" /></p>
<p>密码:<inputname="userList[2].password" /></p>
<p><inputtype="submit" value="注册"/></p>
</form>
</fieldset>
List.jsp
记得导<%@taglib prefix="s" uri="/struts-tags" %>包
<s:iteratorvalue="userList">
<p>ID:${userId}</p>
<p>账号:${username}</p>
<p>密码:${password}</p>
</s:iterator>
11:自定义转换器(Converter)
1:新建的自定义类型转换器类需要继承
DefaultTypeConverter(2.1.xxx),StrutsTypeConverter(2.2.xxx以上版本)
a. 实现对应2个抽象方法(具体实现看代码)
publicclass MyDateConverter extends StrutsTypeConverter{
/**
* 从字符串到对象的转换
* request.getParameterValues() == String[]
*/
publicObject convertFromString(Mapcontext, String[] paramters, Class clazz) {
Objectobj = null;
//获取需要转换的字符串对象
Stringdate = paramters[0];
Stringpattern = "yyyyMMdd";
//判断格式
if(date.contains("-")) {
pattern= "yyyy-MM-dd";
}else if (date.contains("/")) {
pattern= "yyyy/MM/dd";
}else if (date.contains(" ")) {
pattern= "yyyy MM dd";
}else if (date.contains("年")) {
pattern= "yyyy年MM月dd日";
}
obj= DateUtil.StringToDate(date, pattern);
returnobj;
}
/**
* 把一个对象转换成一个字符串
*/
publicString convertToString(Mapcontext, Object obj) {
Stringresult = null;
//判断obj是否是Date类型对象
if(obj instanceof Date) {
Datedate = (Date)obj;
result= DateUtil.dateToString(date);
}
returnresult;
}
}
2:日期与字符串之间的转换类
publicclass DateUtil {
/**
* 把日期转换为字符串对象
*/
public static String dateToString(Datedate){
SimpleDateFormatsdf= newSimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(date);
}
/**
* 把字符串转换为日期转对象
*/
public static Date StringToDate(StringdateString,Stringpattern){
Datedate= null;
SimpleDateFormatsdf= newSimpleDateFormat(pattern);
try {
date = sdf.parse(dateString);
}catch(Exception e) {
e.printStackTrace();
}
return date;
}
}
3: 类型转换器二选一
a. 局部类型转换器
① 在需要转换的action类的同一个目录下面创建一个文件
文件名称必须为:ActionClassName-conversion.properties
② 配置的格式为:action中需要转换的属性名称= 使用自定义转换器的全路径
UserAction-conversion.properties
user.birthday =com.encapusulation.converter.MyDateConverter
b. 全局类型转换器
① 在类的编译目录下面(resource)创建一个文件
文件名称必须为:xwork-conversion.properties
② 配置的格式为: 需要转换的数据类型的全路径 = 使用自定义转换器的全路径
eg: java.util.Date =com.encapusulation.converter.MyDateConverter
xwork-conversion.Properties
java.util.Date =com.encapusulation.converter.MyDateConverter
12:Action作用域的方式(展示信息用1;项目2;文件上传3(拿到服务器端路径))
使用ActionContext对象
Index.jsp
<p>
<ahref="test/testAction_TestAction_testScope.do">ActionContext
</a>
</p>
TestAction
public String testScope() {
// request对象
ActionContextctx= ActionContext.getContext();
ctx.put("req", "request值");
Map<String,Object>session= ctx.getSession();
session.put("ses","session值");
Map<String,Object>application= ctx.getApplication();
application.put("app","application值");
return "success";
}
Result.jsp
<p>request:${requestScope.req }</p>
<p>session:${sessionScope.ses }</p>
<p>application:${applicationScope.app }</p>
Struts.xml
<packagename="testpkg"extends="struts-default"namespace="/test">
<actionname="testAction_*_*"class="com.scope.demo.{1}"method="{2}">
<result>/result.jsp</result>
</action>
</package>
IOC方式
Index.jsp
<p>
<ahref="test/testAction_TestIOCAction_testScope.do">IOC</a>
</p>
TestIOCAction
public class TestIOCAction extendsActionSupportimplements RequestAware, SessionAware,ApplicationAware {
/**
*
*/
private static final long serialVersionUID= 1L;
privateMap<String,Object>request;
privateMap<String,Object>session;
privateMap<String,Object>application;
@Override
public voidsetApplication(Map<String, Object> application) {
this.application =application;
}
@Override
public voidsetSession(Map<String, Object> session) {
this.session =session;
}
@Override
public voidsetRequest(Map<String, Object> request) {
this.request =request;
}
/**
* 定义一个使用IOC获取Scope对象的方法
*/
public String testScope() {
request.put("req","request值");
session.put("ses","session值");
application.put("app","application值");
return SUCCESS;
}
}
Result.jsp
<p>request:${requestScope.req }</p>
<p>session:${sessionScope.ses }</p>
<p>application:${applicationScope.app }</p>
Struts.xml
<packagename="testpkg"extends="struts-default"namespace="/test">
<actionname="testAction_*_*"class="com.scope.demo.{1}"method="{2}">
<result>/result.jsp</result>
</action>
</package>
3、非IOC[直接使用ServletAPI]
Index.jsp
<p>
<ahref="test/testAction_TestServletAPIAction_testScope.do">非IOC</a>
</p>
TestServletAPIAction
public class TestServletAPIAction extends ActionSupport {
/**
*
*/
private static final long serialVersionUID= 1L;
public String testScope() {
ServletContextapplication= ServletActionContext.getServletContext();
application.setAttribute("app","application值");
HttpServletRequestrequest= ServletActionContext.getRequest();
request.setAttribute("req","request值");
HttpSessionsession= request.getSession();
session.setAttribute("ses","session值");
returnSUCCESS;
}
}
Result.jsp
<p>request:${requestScope.req}</p>
<p>session:${sessionScope.ses }</p>
<p>application:${applicationScope.app }</p>
Struts.xml
<packagename="testpkg"extends="struts-default"namespace="/test">
<actionname="testAction_*_*"class="com.scope.demo.{1}"method="{2}">
<result>/result.jsp</result>
</action>
</package>
13:拦截器
实体类UserInfo
private String username;
private String password;
Action
public class UserAction extends ActionSupport {
private UserInfo user;
/**
* @return the user
*/
public UserInfo getUser() {
return user;
}
/**
* @param user the user to set
*/
public void setUser(UserInfo user) {
this.user =user;
}
/**
*
*/
private static final long serialVersionUID= 1L;
public String login() {
ActionContextctx= ActionContext.getContext();
Stringresult= LOGIN;
if (user.getUsername().equals("admin")&&user.getPassword().equals("123")) {
// 保存用户名称
ctx.getSession().put("username",user.getUsername());
result = SUCCESS;
}else{
ctx.put("message","<font color='red' size='+1'>输入的用户名或者密码错误</font>");
}
return result;
}
public String add() {
ActionContext.getContext().put("message","<font color='green' size='+1'>添加用户</font>");
return SUCCESS;
}
public String del() {
ActionContext.getContext().put("message","<font color='green' size='+1'>删除用户</font>");
return SUCCESS;
}
}
Login.jsp(注意绝对路径)
message:${message}<hr/>
<!-- 类拦截器 -->
<%-- <form action="${pageContext.request.contextPath}/user/loginAction.do" method="post"> --%>
<!-- 方法拦截器 -->
<form action="${pageContext.request.contextPath}/user/UserAction_login.do"method="post">
<p>账号:<inputname="user.username"/></p>
<p>密码:<inputname="user.password"/></p>
<p><inputtype="submit"value="登录"/></p>
</form>
Result.jsp
message:${message }<hr/>
<a href="${pageContext.request.contextPath }/user/UserAction_add.do">添加</a><br/>
<a href="${pageContext.request.contextPath }/user/UserAction_del.do">删除</a>
1:类拦截器
ClassIntercepter(模板设计模式继承使用需要的方法)
public class MyInterceptor extends AbstractInterceptor{
/**
*
*/
private static final long serialVersionUID= 1L;
/**
* 拦截器方法的实现
*/
public String intercept(ActionInvocationinvocation)throwsException {
Stringresult= null;
System.out.println(invocation.getAction());
System.out.println(invocation.getInvocationContext().getName());
ActionContextctx= invocation.getInvocationContext();
Objectobj= ctx.getSession().get("username");
if (obj !=null) {
result = invocation.invoke();
}else{
ctx.put("message","<font color='red' size='+1'>无权访问,请登录</font>");
result = Action.LOGIN;
}
return result;
}
}
Struts.xml
a. 配置自定义拦截器
b. 配置自定义拦截器栈
c. 引用拦截器栈
<packagename="testpkg"extends="struts-default"namespace="/user">
<!-- 配置拦截器 -->
<interceptors>
<!-- 配置自定义拦截器对象 -->
<interceptorname="permissionInterceptor"class="com.demo.interceptor.MyInterceptor"/>
<!-- 自定义拦截器栈 -->
<interceptor-stackname="myStack">
<!-- 引用默认拦截器栈,才会有struts2的核心功能 -->
<interceptor-refname="defaultStack"/>
<interceptor-refname="permissionInterceptor"/>
</interceptor-stack>
</interceptors>
<actionname="loginAction"class="com.demo.UserAction"method="login">
<result>/result.jsp</result>
<resultname="login">/login.jsp</result>
</action>
<actionname="*_*"class="com.demo.{1}"method="{2}">
<result>/result.jsp</result>
<resultname="login">/login.jsp</result>
<!-- 引用自定义拦截器栈 -->
<interceptor-refname="myStack"/>
</action>
</package>
2:方法拦截器
MethodInterceptor
public class MyMethodInterceptor extends MethodFilterInterceptor{
private static final long serialVersionUID= 1L;
@Override
protected StringdoIntercept(ActionInvocationinvocation) throwsException {
Stringresult= null;
System.out.println(invocation.getAction());
System.out.println(invocation.getInvocationContext().getName());
ActionContextctx= invocation.getInvocationContext();
Objectobj= ctx.getSession().get("username");
if (obj !=null) {
result = invocation.invoke();
}else{
ctx.put("message","<font color='red' size='+1'>无权访问,请登录</font>");
result = Action.LOGIN;
}
return result;
}
}
Struts.xml
<packagename="testpkg"extends="struts-default"namespace="/user">
<!-- 配置拦截器 -->
<interceptors>
<!-- 配置自定义拦截器对象 -->
<interceptorname="permissionInterceptor"class="com.demo.interceptor.MyMethodInterceptor"/>
<!-- 自定义拦截器栈 -->
<interceptor-stackname="myStack">
<!-- 引用默认拦截器栈,才会有struts2的核心功能 -->
<interceptor-refname="defaultStack"/>
<interceptor-refname="permissionInterceptor">
<!-- 排除不需要拦截器的方法 -->
<paramname="excludeMethods">login</param>
<!-- 配置需要拦截器的方法 -->
<!-- <param name="includeMethods"></param>-->
</interceptor-ref>
</interceptor-stack>
</interceptors>
<actionname="*_*"class="com.demo.{1}"method="{2}">
<result>/result.jsp</result>
<resultname="login">/login.jsp</result>
<!-- 引用自定义拦截器栈 -->
<interceptor-refname="myStack"/>
</action>
</package>
14:OGNL
1: <s:debug></s:debug>将OGNL里的对象全部展示出来
2:value stack和request、session、application、parameter的访问区别
值栈:可以直接访问
后面四者:需要加#访问
3:简单的取栈值:
ValueStackvalueStack = ActionContext.getContext().getValueStack();
valueStack.push(“www”);
<s:propertyvalue="www"/>
4:取map集合的值
Map<String,Object> map = newHashMap<String,Object>();
map.put("key","value");
valueStack.push(map);
<s:property value="key"/>
5:取栈里面的值
//先入后出,先进后出
Stack<String> stack = new Stack<String>();
stack.push("AAAA");
stack.push("NBBBB");
stack.push("VVVVV");
System.out.println(stack);//[AAAA, NBBBB,VVVVV]
// 取出栈顶元素
System.out.println(stack.peek());//VVVVV
// 出栈元素
System.out.println(stack.pop());//VVVVV
System.out.println(stack);//[AAAA, NBBBB]
6:向值栈里设值、取值(注意字符串要加’’)
<s:setvar="name" value="'zhangsan'"/>
<s:propertyvalue="name"/>
<s:setname="ssss1"value="24"/>
<s:setname="ssss2"value="'24'"/>
<s:setname="ssss3"value="24"/>
<s:propertyvalue="ssss1"/><!--int-->
<s:propertyvalue="ssss2"/><!--字符串 -->
<s:propertyvalue="#ssss3"/><!-- value的值是int或long类型输出的时候加# -->
7:在各个域中取值(scope默认是存储在该action中。)
attr.***默认是从 page,request, session, application顺序
<s:setvar="name1" value="'zhangsan1'" scope="action"/>
<s:property value="name"/>
<s:property value="#name"/>
<s:property value="#attr.name"/>
<s:setvar="p"value="'pppp'"scope="page"/>
<s:propertyvalue="#attr.p"/>
<s:setvar="r"value="'rrrr'"scope="request"/>
<s:propertyvalue="#attr.r"/>
<s:propertyvalue="#request.r"/>
<s:setvar="s"value="'ssss'"scope="session"/>
<s:propertyvalue="#attr.s"/>
<s:propertyvalue="#session.s"/>
<s:setvar="a"value="'aaaa'"scope="application"/>
<s:propertyvalue="#attr.a"/>
<s:propertyvalue="#application.a"/>
8:在集合中取值
List
<s:setvar="list"value="{1,2,3,4,'fds','gfggg'}"/>
<s:iteratorvalue="list">
<s:property/><br/>
</s:iterator>
Map
<s:setvar="map"value="#{'key':'value','age':100,'sex':'女'}"/>
<s:iteratorvalue="map">
<s:property value="key"/>---<s:propertyvalue="value"/><br/>
</s:iterator>
9:URL跳转页面并带参数链接
<s:urlid="url"action="HelloWorld">
<s:paramname="request_locale">en</s:param>
</s:url>
<s:avalue="%{url}">提交</s:a>
<s:ahref="%{url}">English</s:a>
<s:avalue="%{getName()}">提交</s:a>
10:调用静态方法
<constantname="struts.ognl.allowStaticMethodAccess" value="true"/>
<s:propertyvalue="@@min(1,2)"/>
11:调用方法:
publicstatic String getDesc() {
return"王五是换人";
}
<s:propertyvalue="@com.action.OGNLAction@getDesc()"/>
12:简单的表单(多选框必须加name)
<s:formaction=""method="post">
<s:textfieldlabel="账号"name="name"/>
<s:passwordlabel="密码" />
<s:selectlist="#map"label="选择内容"headerKey="-1"headerValue="--请选择--"listKey="key"listValue="value"/>
<s:checkboxlistname="ke1"list="#map"label="爱好"listKey="key"listValue="value"/>
<s:submit/>
</s:form>
15:文件上传、下载 <constantname="struts.multipart.maxSize" value="4096000000000" />
1:单文件上传
Upload.jsp
<s:fielderror></s:fielderror>
<fieldset>
<legend>单文件上传</legend>
<formaction="${pageContext.request.contextPath }/upload/uploadAction.do"enctype="multipart/form-data"method="post">
文件:<inputtype="file"name="upload"/>
<inputtype="submit"value="上传"/>
</form>
</fieldset>
UploadAction.java
public class UploadAction extends ActionSupport {
private static final long serialVersionUID= 1L;
//提交过来的file的名字
private StringuploadFileName;
//文件上传过来存放在临时文件夹下面的文件
private Fileupload;
public StringgetUploadFileName() {
returnuploadFileName;
}
public void setUploadFileName(StringuploadFileName){
this.uploadFileName =uploadFileName;
}
public File getUpload() {
returnupload;
}
public void setUpload(File upload) {
this.upload =upload;
}
/**
* 定义上传文件的方法
*/
public String uploadFile() {
// 获取服务器端文件上传的真实路径
StringuploadPath= ServletActionContext.getServletContext().getRealPath("/files/uploads");
// 判断上传到服务器端的路径是否存在
FileuploadDir= newFile(uploadPath);
if (!uploadDir.exists()) {
// 创建上传目录
uploadDir.mkdirs();// 创建多级目录
}
// 判断上传文件是否选择
if (null !=upload) {
// 在目标目录创建上传的空白文件
FilesaveFile= newFile(uploadPath,uploadFileName);
// 通过工具类完成文件内容拷贝
try {
FileUtils.copyFile(upload,saveFile);
this.addFieldError("message","上传成功");
}catch(IOExceptione) {
this.addFieldError("message","上传失败");
e.printStackTrace();
}
}else{
this.addFieldError("message","请选择需要上传的文件");
}
return SUCCESS;
}
}
Struts.xml
<packagename="pkg"extends="struts-default"namespace="/upload">
<actionname="uploadAction"class="com.upload.demo.UploadAction"method="uploadFile">
<result>/upload.jsp</result>
</action>
</package>
2:多文件上传
Upload.jsp
<fieldset>
message:${fieldErrors.message[0] }
<legend>多文件上传</legend>
<formaction="${pageContext.request.contextPath}/upload/uploadsAction.do"enctype="multipart/form-data"method="post">
文件:<inputtype="file"name="uploads"/><br/>
文件:<inputtype="file"name="uploads"/><br/>
文件:<inputtype="file"name="uploads"/><br/>
文件:<inputtype="file"name="uploads"/><br/>
文件:<inputtype="file"name="uploads"/><br/>
<inputtype="submit"value="上传"/>
</form>
</fieldset>
public classUploadsAction extends ActionSupport {
private static final long serialVersionUID= 1L;
private String[]uploadsFileName;
private File[]uploads;
public String[]getUploadsFileName() {
returnuploadsFileName;
}
public voidsetUploadsFileName(String[] uploadsFileName) {
this.uploadsFileName =uploadsFileName;
}
public File[] getUploads() {
returnuploads;
}
public void setUploads(File[] uploads) {
this.uploads =uploads;
}
/**
* 定义上传文件的方法
*/
public String uploadsFile() {
// 获取服务器端文件上传的真实路径
StringuploadPath= ServletActionContext.getServletContext().getRealPath("/files/uploads");
// 判断上传到服务器端的路径是否存在
FileuploadDir= newFile(uploadPath);
if (!uploadDir.exists()) {
// 创建上传目录
uploadDir.mkdirs();// 创建多级目录
}
// 判断上传文件是否选择
if (null !=uploads && uploads.length > 0) {
booleanflag = true;
for (inti = 0; i < uploads.length; i++) {
// 在目标目录创建上传的空白文件
FilesaveFile= newFile(uploadPath,uploadsFileName[i]);
// 通过工具类完成文件内容拷贝
try {
FileUtils.copyFile(uploads[i],saveFile);
}catch(IOExceptione) {
this.addFieldError("message","上传失败");
e.printStackTrace();
flag = false;
break;
}
}
if (flag) {
this.addFieldError("message","上传成功");
}
}else{
this.addFieldError("message","请选择需要上传的文件");
}
return SUCCESS;
}
}
Struts.xml
<packagename="pkg"extends="struts-default"namespace="/upload">
<actionname="uploadsAction"class="com.upload.demo.UploadsAction"method="uploadsFile">
<result>/upload.jsp</result>
</action>
</package>
3:文件下载
<ahref="${pageContext.request.contextPath}/download/downloadAction_initFiles.do">文件下载</a>
Download.jsp
<fieldset>
<legend>文件下载列表</legend>
<ul>
<s:iteratorvalue="files">
<li><ahref="${pageContext.request.contextPath }/download/downloadAction_downloadFile.do?downloadName=${name }">${name }</a></li>
</s:iterator>
</ul>
</fieldset>
DownLoadAction.java
publicclass DownloadAction extends ActionSupport {
private File[]files;
private StringdownloadName;
public StringgetDownloadName() {
StringchineseName= null;
try {
chineseName = URLEncoder.encode(downloadName,"UTF-8");
}catch(UnsupportedEncodingExceptione) {
e.printStackTrace();
}
returnchineseName;
}
public void setDownloadName(String downloadName) {
this.downloadName =downloadName;
}
public File[] getFiles() {
returnfiles;
}
private static final long serialVersionUID= 1L;
/**
* 定义一个初始化下载列表的方法
*/
public String initFiles() {
// 获取服务器端下载路径
StringdownloadPath= ServletActionContext.getServletContext().getRealPath("/files/uploads");
// 创建下载文件目录
FiledownloadDir= newFile(downloadPath);
// 获取该目录下面所有文件
this.files =downloadDir.listFiles();
return"init_download";
}
/**
* 定义把下载的文件转换为流的方法
*/
public InputStreamgetDownloadStream() {
return ServletActionContext.getServletContext().getResourceAsStream("/files/uploads/"+downloadName);
}
/**
* 定义下载文件的方法
*/
public String downloadFile() {
return SUCCESS;
}
}
Struts.xml
<packagename="pkg1"extends="struts-default"namespace="/download">
<actionname="downloadAction_*"class="com.download.demo.DownloadAction"method="{1}">
<resultname="init_download">/download.jsp</result>
<resulttype="stream">
<paramname="contentType">application/octet-stream</param>
<paramname="contentDisposition">attachment;fileName=${downloadName}</param>
<paramname="inputName">downloadStream</param>
<paramname="bufferSize">4096</param>
</result>
</action>
</package>