Struts2.1
官方文档:
1. set标签处value的String改为object
2. struts2标签的type为String表示字符串,为Object表示Ognl表达式
一:Myeclipse的简单操作
1. 将类进行源码展示:
右击Jar包->Properties->Java Source Attachment->
F:/JAR_Total/Struts/struts2.x/struts-2.1.8.1/src/core/src/main/java
2. 文档的展示:
右击Jar包->Properties->JavaDoc Loction->
file:/F:/JAR_Total/Struts/struts2.x/struts-2.1.8.1/docs/struts2-core/apidocs/
之后出现新类的时候直接按F1就可以在Myeclipse中查看文档
3. Struts.xml不自动提示
a) window – preferences – 搜索 catalog
b) 选择key type为URI
c) key: http://struts.apache.org/dtds/struts-2.0.dtd
d) location: 对应的dtd文件,位于struts-core包中,解压开,指定相应位置,如:D:\share\0750_Struts2.1.6\soft\struts-2.1.6\lib\struts2-core-2.1.6\struts-2.0.dtd
4. 右击项目->java->compliance->compiler compliance level->1.6
5. 常量的配置保存在struts2-core-2.1.8.1.jar->org.apache.struts2->default.properties
6. <constant name="struts.devMode" value="true" />:此时表示正处于开发模式,可以不用重新启动服务器而直接访问修改后的内容
一.1:Struts2流程
Struts2多实例,多线程
Servlet单实例,多线程
二:NameSpace
a) namespace决定了action 的访问路径,默认为“”,可以接收所有路径的action,例如
http://localhost:8080/Test/asdfasdfas/sdgsdg/sdfsdfsd/index.action
b) 当将现有的项目拷贝出来一份以后,一定要记得,右击项目->Properties->Myeclipse->Web,将Web Context-root修改掉。
三:Action
a) 具体视图的返回可以由用户自己定义的Action来决定
b) 具体的手段是根据返回的字符串找到对应的配置项,来决定试图的内容
c) 具体Action的实现可以是一个普通的Java类,里面有public String execute()方法即可
d) 修改默认编码:windows->preference->JSP
e) Struts2的Action在每次访问时必定会new一个,而Struts1的Action在每次访问的时候可能只有new了一个
f) 实现Action的三种方法:
1. 直接写类名称+execute()方法
2. 继承自ActionSupport类+execute()方法
3. 实现自Action接口+execute()方法
四:Path_路径问题
a) Struts2中的路径问题是根据Action的路径而不是Jsp的路径来确定,所以尽量不要使用相对路径<br>虽然可以用Redirect方式解决,但是Redirect方式并非必要的。<br>解决方法非常简单,统一使用绝对路径(在Jsp中使用request.getContextRoot方式来拿到webapp的路径,或者使用Myeclipse自己写的)
五:ActionMethod
1. Action执行的时候不一定要执行execute方法,可以在配置文件中配置Action的时候用method=来制定执行哪个方法 ,也可以在在url地址中动态制定(动态方法调用DMI),还可以使用通配符来进行操作
(user是命名空间,userAdd是Actino的名称)
http://localhost:8080/Struts2_0400_Path_ActionMethod/user/userAdd
(action!method.action,user是Action的名称,userAdd是方法名)
http://localhost:8080/Struts2_0400_Path_ActionMethod/user!userAdd
六:ActionWildcard(通配符)
使用通配符,将配置降到最低,不过,一定要遵循“约定优于配置”原则
<action name="*_*" class="com.bjsxt.struts2.action.{1}Action">
<result>/{1}_{2}_success.jsp</result>
</action>
七:接收参数的方式
用Action的属性接收参数
<a href="<%=basePath%>user/user!add?name=lp&age=20">用Action的参数接收属性</a>
private String nameString;
private int age;
public void setName(String name){(name的名称与参数名称一致就行了)
this.nameString = name;
}
用DomainModel接收参数(SSI框架中可以省去user.name中的user)
private User user;(加入setter()和getter()方法)
public String show(){
//User user = getUser();
System.out.println("取得名称:"+ user.getName());
System.out.println("取得年龄:"+ user.getAge());
return "show";
}
<a href="user/user!show?user.name=a&user.age=8">添加用户</a>
用ModelDriven接收参数(SSI中继承自BaseActionSupport使用此种方法)
<a href="user/user!add?name=a&age=8">添加用户</a>
//实现ModelDriven接口(记住使用泛型,否则需要类型强制转换)
public class UserAction extends ActionSupport implements ModelDriven<User>{
//此处必须实例化对象,而不是使用setter和getter方法
private User user = new User();
@Override
public User getModel() {
return user;
}
public String show(){
User model = getModel();
System.out.println("取得名称:"+model.getName());
System.out.println("取得年龄:"+model.getAge());
return "show";
}
八:简单数据验证
简单数据验证1
Action
if(name == null || !name.equals("admin")){
this.addFieldError("name", "name is error");
return ERROR;
}
JSP,
<s:fielderror fieldName="name" theme="simple"/>
<br />
<s:property value="errors.name[0]"/> 专门取得valueStack和Stack中的Context中的值
<s:debug></s:debug>
Value Stack Contents
Object Property Name Property Value
com.model.Test name 刘鹏
age 20
com.demo.TestAction texts null
model com.model.Test@59c8b5
actionErrors []
errors {name=[name is error!]}
fieldErrors {name=[name is error!]}
errorMessages []
locale zh_CN
actionMessages []
com.opensymphony.xwork2.DefaultTextProvider texts null
九:访问web元素(详见另外一份文档)
十:模块包含(IncludeModlus)
Struts.xml:
<struts>
<include file=”login.xml”>
</struts>
Login.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="login" extends="struts-default" namespace="/login">
<action name="login" class="com.bjsxt.struts2.user.action.LoginAction">
<result>/user_login_success.jsp</result>
</action>
</package>
</struts>
十一:默认Action
<struts>
<package name="default" extends="struts-default" namespace="/">
<default-action-ref name="index"></default-action-ref>
<action name="index" class="com.bjsxt.struts2.user.action.LoginAction">
<result>/user_login_success.jsp</result>
</action>
</package>
</struts>
十二:默认Result_Type
1. Dispatcher //显示action地址
2. Redirect //显示jsp地址
3. Chain
4. redirectAction
5. freemarker
6. httpheader
7. stream
8. velocity
9. xslt
10. plaintext
11. tils
<struts>
<package name="resultTypes" extends="struts-default" namespace="/r">
<action name="r1" class="com.bjsxt.struts2.user.action.LoginAction">
<!-- 服务器端跳转,不能跳转到Action,只能跳转到试图 -->
<result type="dispatcher">/user_login_success.jsp</result>
</action>
<action name="r2" class="com.bjsxt.struts2.user.action.LoginAction">
<!-- 客户端跳转,不能跳转到Action,只能跳转到试图 -->
<result type="redirect">/user_login_success.jsp</result>
</action>
<action name="r3" class="com.bjsxt.struts2.user.action.LoginAction">
<!-- 使用forward(服务器端跳转)的方式访问Action -->
<result type="chain">
<param name="actionName">a</param>
<param name="namespace">/a</param>
</result><!-- aaa/r1 -->
</action>
<action name="r4" class="com.bjsxt.struts2.user.action.LoginAction">
<!-- 客户端跳转,跳转到Action -->
<result type="redirectAction">r2</result>
</action>
</package>
</struts>
十三: Global_Results(全局结果集)
可以用于全局错误页的配置等等需要统一使用的模块
Struts.XML代码:
<package name="user" extends="struts-default" namespace="/user">
<global-results>
<result name="mainpage">/main.jsp</result>
</global-results>
<action name="user" class="com.action.UserAction">
<result name="success">/ success.jsp</result>
<result name="error">/error.jsp</result>
</action>
</package>
<!-- 为在其他包中任然可以使用此结果集,继承自那个包 -->
<package name="admin" namespace="/admin" extends="user">
<action name="admin" class="com.action.AdminAction">
<result>/admin.jsp</result>
</action>
</package>
UserAction代码:
public String execute(){
if(type==1){
return SUCCESS;
}else if(type==2){
return ERROR;
}else {
return "mainpage";
}
}
AdminAction代码:
public String admin(){
return "mainpage";
}
十四: Dynamic_Results(动态结果集)
Action代码:
private int type;(setter()和getter())
private String r; (setter()和getter())
public String execute() throws Exception {
if(type == 1) r="/user_success.jsp";
else if (type == 2) r="/user_error.jsp";
return "success";
}
XML代码:
<package name="default" namespace="/" extends="struts-default">
<action name="test" class="com.demo.TestAction">
<result>${r}</result>
<!--由于r是action的属性,存在valuestack中,所以${r}可以取得到-->
</action>
</package>
十五:带参数的结果集(客户端跳转时候才用到)
XML代码:
<package name="default" namespace="/" extends="struts-default">
<action name="test" class="com.demo.TestAction">
<result type="redirect">/success.jsp?t=${type}</result>
</action>
</package> <!-- 原本过程所有Action公用一个值栈(一次request只有一个值栈,服务器端forward共享一个值栈),可以直接访问type属性,现在进行客户端跳转,不共享同一个值栈了,不可以再访问到type属性,所以使用以上方式进行参数的传递 -->
Action代码:
private int type;(setter()和getter())
public String test(){
return SUCCESS;
}
JSP代码:
<!-- s:property是从值栈中取值,XML中客户端重新发了一次请求给JSP,但是此时值栈中已经为null了,故而取不到 -->
from valueStack:<s:property value="t"/><br> 取不出来
from actionContext:<s:property value="#parameters.t"/> 取得出来
访问地址:
http://localhost:8080/.../...?type=1
十六:OGNL(Object Graph Navigation Language对象图导航语言)
OGNL1(访问普通属性)(value stack直接取值,stack Context使用#取值)
Xml代码:
<package name="ognl" extends="struts-default">
<action name="ognl" class="com.lp.OgnlAction">
<result name="success">/ognl.jsp</result>
</action>
</package>
Model代码:
private String age = "";(setter()/getter())
Action代码:
private Test test;
<!—初始化model可以自己new;也可以传参数,但此时model需要存在空构造方法 -->
<!-- 使用domainModel时候只有传入类似test.age才能将实体类实例化 -->
private String username = "";
private String password = ""; (setter()/getter())
public String execute(){
HttpServletRequest request = ServletActionContext.getRequest();
request.setAttribute("name", "liupeng");
return SUCCESS;
}
JSP代码:
访问值栈中action的普通属性:username=<s:property value="username"/><br>
访问值栈中model的普通属性(getter/setter):<s:property value="test.age"/>
<s:property value="test[‘age’]"/>
<s:property value="test[\”age\”]"/>
<s:debug></s:debug>
访问属性范围中的普通属性:<s:property value="#request.name"/>
访问:
http://localhost:8080/OGNL/ognl!execute?username=liupeng&password=1111&test.age=10
OGNL2(访问普通属性)
Action代码:
private Cat cat;(setter/getter)
Model代码:
Cat.java:
private Dog friend;(setter/getter)
Dog.java:
public Dog(){
}
private String name = "";(setter/getter)
JSP代码:
访问值栈中model的普通属性:<s:property value="cat.friend.name"/>
访问:
http://localhost:8080/OGNL/ognl!execute?username=liupeng&password=1111&test.age=10&cat.friend.name=wanghan
OGNL3(访问普通方法)
Action代码:
private String password = "";(set/get)
public String m(){
return "hello";
}
JSP代码:
访问值栈中action属性的普通方法:<s:property value="password.length()"/>
访问值栈中model的普通方法:<s:property value="cat.miaomiao()"/>
访问值栈中action的普通方法:<s:property value="m()"/>
访问:
http://localhost:8080/OGNL/ognl!execute?password=1111
OGNL4(访问静态属性和方法)
Struts2.x访问静态属性和方法需要在XML文件中加上<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
Action代码:
public static String STR = "static string";
public static String s(){
return "static method";
}
JSP代码:
访问静态方法:<s:property value="@com.lp.OgnlAction@s()"/><br>
访问静态属性:<s:property value="@com.lp.OgnlAction@STR"/><br>
访问Math类的静态方法:<s:property value="@@math(2,3)"/>
<!-- 两个@只能访问一个类的静态方法 -->
OGNL4(访问普通类的构造方法)
JSP代码:
访问普通类的构造方法:<s:property value="new com.model.Test(8)"/>
OGNL4(访问集合)
Action代码:
注意集合作为了Action的属性存在
private List<Test> tests = new ArrayList<Test>();
private Set<Dog> dogs = new HashSet<Dog>();
private Map<String, Dog> dogMap = new HashMap<String, Dog>();
加入setter和getter方法
public OgnlAction(){
tests.add(new Test(1));
tests.add(new Test(2));
tests.add(new Test(3));
dogs.add(new Dog("dog1"));
dogs.add(new Dog("dog2"));
dogs.add(new Dog("dog3"));
dogMap.put("dog100", new Dog("dog100"));
dogMap.put("dog101", new Dog("dog101"));
dogMap.put("dog102", new Dog("dog102"));
}
JSP代码:
访问List:<s:property value="tests"/><br>
访问List中某个元素:<s:property value="tests[0]"/><br>
访问List中元素某个属性的集合<s:property value="tests.{age}"/>
访问List中元素某个属性的集合中的特定值:<s:propertyvalue="tests[0].age"/>
<s:property value="tests.{age}[0]"/>
访问Set:<s:property value="dogs"/><br>
访问Set中某个元素:<s:property value="dogs[1]"/><br>
<!-- set以上是访问不到的,因为set是无序的 -->
访问Map:<s:property value="dogMap"/>
访问Map中某个元素:<s:property value="dogMap.dog101"/>
<s:property value="dogMap['dog101']"/>
<s:property value="dogMap[\"dog101\"]"/>
访问Map中所有的key:<s:property value="dogMap.keys"/>
访问Map中所有的value:<s:property value="dogMap.values"/>
访问容器的大小:<s:property value="dogMap.size()"/>
OGNL4(投影)
投影或者说过滤的是集合中的属性
Action代码:
注意集合作为了Action的属性存在
private List<Test> tests = new ArrayList<Test>();
加入setter和getter方法
public OgnlAction(){
tests.add(new Test(1));
tests.add(new Test(2));
tests.add(new Test(3));
}
JSP代码:
投影(过滤):<s:property value="tests.{?#this.age==1}.{age}"/><br>
投影:<s:property value="tests.{^#this.age>1}.{age}"/><br>
投影:<s:property value="tests.{$#this.age>1}.{age}"/><br>
投影:<s:property value="tests.{$#this.age>1}.{age}==null"/>
<!-- ^代表开头,$代表结尾,?代表过滤条件,this表示循环过程中tests对象 -->
OGNL5( 用[]访问元素)
[]:<s:property value="[0] "/>
<s:property value="[0].username "/>
<!-- 访问的是valueStack的从上往下的某个元素 -->
十七:Struts标签
1. 通用标签
a) property
Action代码:
private String username ;
private String password;(set/get)
public String execute(){
this.addFieldError("fielderror.test", "wrong");
return SUCCESS;
}
JSP代码:
property:<s:property value="username"/><br>
<!—上面username为Ognl表达式-->
property取值为字符串:<s:property value="'username'"/><br>
property设定默认值:<s:property value="admin" default="管理员"/><br>
property设定HTML:<s:property value="'<hr/>'" escape="false"/><br>
<!-- escape=true表示不解析html;反之表示解析html -->
b) set
I. 默认为action scope,会将值放入request和ActionConrtext中
II. page、request、session、application
JSP代码:
set设定adminName值(默认为request和ActionContext):<s:set var="adminName" value="username"></s:set>
set从request取值:<s:property value="#request.adminName"/>
set从ActionContext取值:<s:property value="#adminName"/>
set设定范围:<s:set name="adminPassword" value="password" scope="page"></s:set>
set从相应范围值:<%=pageContext.getAttribute("adminPassword") %><br>
set设定var,范围为ActionContext:<s:set var="a" value="password"></s:set>
set使用#取值:<s:property value="#a"/>
访问:
http://localhost:8080/Struts-tags/tags/tags?username=liupeng&password=1111
c) bean
bean:<s:bean name="com.model.Tags" var="mytag">
<s:param name="userName" value="'liupeng'"></s:param>
</s:bean>
<!-- var要写才能在debug中看到;
param的name应该写Tags的属性,value默认当成Ognl表达式处理
-->
读取:<s:property value="#mytag.userName"/>
<!-- 如果不写var,bean标签会在执行过程中生成一个model对象放到栈顶,但在执行结束后又会消失,使用var就会将值放入ActionContext中,在其他地方也可以使用#访问 -->
d) include
<s:set var="incPage" value="'/_include.html'"></s:set>
<s:include value="%{#incPage}"></s:include>
<!-- value为String类型,使用%{}将其视为Ognl表达式处理 -->
e) param
在bean标签处体现
f) debug
<s:debug></s:debug>
2. 控制标签
a) if elseif else
JSP代码:
if elseif else:<br>
age:<s:property value="#parameters.age[0]"/><br>
<!-- paramaters参数的集合,哪怕只有一个age,也需要精确的定位 -->
<s:if test="parameters.age[0]<0">wrong age!</s:if><br>
<s:elseif test="#parameters.age[0]<30">tooyoung!</s:elseif><br>
<s:else>yeah!</s:else>
访问:
http://localhost:8080/Struts-tags/tags/tags? age=20
b) iterator
JSP代码:
遍历集合1:<br>
<s:iterator value="{1,2,3}">
<s:property/>|
<!-- {1,2,3会当成集合,property遍历输出} -->
</s:iterator>
遍历集合2:
<s:iterator value="#request.weiboList" var="user">
<s:property value="#user.getId()"/>
自定义变量:<br>
<s:iterator value="{'aaa','bbb','ccc'}" var="x">
<s:property value="#x.toUpperCase()"/>
</s:iterator>
带有status的遍历:
<s:iterator value="{'aaa','bbb','ccc'}" status="status">
<s:property/>|
遍历过的元素总数:<s:property value="#status.count"/>|
遍历过的元素索引:<s:property value="#status.index"/>|
当前访问的个数是偶数:<s:property value="#status.even"/>|
当前访问的个数是奇数:<s:property value="#status.odd"/>|
是first?<s:property value="#status.first"/>|
是last?<s:property value="#status.last"/><br>
</s:iterator>
遍历Map集合:<br>
<s:iterator value="#{1:'a',2:'b',3:'c'}">
<s:property value="key"/>|<s:property value="value"/>
</s:iterator>
<s:iterator value="#{1:'a',2:'b',3:'c'}" var="x">
<s:property value="#x.key"/>|<s:property value="#x.value"/>
</s:iterator>
c) subset
3. UI标签
a) theme(simple/xhtml(默认)/css_xhtml/ajax)
Xml代码:
<constant name="struts.ui.theme" value="simple"></constant>
<package name="theme" namespace="/" extends="struts-default">
<action name="theme" class="com.action.ThemeAction">
<result name="success">/theme.jsp</result>
</action>
</package>
JSP代码:
在struts.xml中控制theme,默认为xhtml,可以设置为:simple/css_html/ajax<br>
<s:form>
<div class="formFieldError">
<s:fielderror></s:fielderror>
</div>
<s:textfield name="aaa"></s:textfield>
</s:form>
<style type="text/css">
.formFieldError ul{
list-style-type:none
}
.formFieldError ul li{
list-style-type:none
}
</style>
4.AJAX标签
5.$#%的区别
$用于i18n和struts配置文件
#取得ActionContext值
%{}将原本的文本属性解析为ognl,对于本来就是ognl的属性不起作用
十七:常用常量
<!-- 指定默认编码集,作用于HttpServletRequest的setCharacterEncoding方法 和freemarker 、velocity的输出 -->
<constant name="struts.i18n.encoding" value="UTF-8"/>
<!-- 该属性指定需要Struts 2处理的请求后缀,该属性的默认值是action,即所有匹配*.action的请求都由Struts2处理。
如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开。 -->
<constant name="struts.action.extension" value="do"/>
<!-- 设置浏览器是否缓存静态内容,默认值为true(生产环境下使用),开发阶段最好关闭 -->
<constant name="struts.serve.static.browserCache" value="false"/>
<!-- 当struts的配置文件修改后,系统是否自动重新加载该文件,默认值为false(生产环境下使用),开发阶段最好打开 -->
<constant name="struts.configuration.xml.reload" value="true"/>
<!-- 开发模式下使用,这样可以打印出更详细的错误信息 -->
<constant name="struts.devMode" value="true" />
<!-- 默认的视图主题 -->
<constant name="struts.ui.theme" value="simple" />
<!– 与spring集成时,指定由spring负责action对象的创建 -->
<constant name="struts.objectFactory" value="spring" />
<!–该属性设置Struts 2是否支持动态方法调用,该属性的默认值是true。如果需要关闭动态方法调用,则可设置该属性为false。 -->
<constant name="struts.enable.DynamicMethodInvocation" value="false"/>
<!--上传文件的大小限制-->
<constant name="struts.multipart.maxSize" value=“10701096"/>
十八:自定义类型转换器
HelloWordAction.Java
public class HelloWordAction {
private Date createtime;
public Date getCreatetime() {
return createtime;
}
public void setCreatetime(Date createtime) {
this.createtime = createtime;
}
public String execute(){
System.out.println(createtime);
return "success";
}
}
MyDateCVT.Java
public class MyDateCVT extends DefaultTypeConverter{
@Override public Object convertValue(Map context, Object value, Class toType) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy|MM|dd");
try {
if(toType == Date.class){//当字符串向Date类型转换时
String[] params = (String[]) value;// Request.getParameterValues()
return dateFormat.parse(params[0]);
}else if(toType == String.class){//当Date转换成字符串时
Date date = (Date) value;
return dateFormat.format(date);
}
} catch (ParseException e) {} catch (java.text.ParseException e) {
e.printStackTrace();
}
return null;
}
}
访问
http://localhost:8080/servlet/hello?createtime=2013|11|11
十八:自定义全局类型转换器
将上面的类型转换器注册为全局类型转换器:
在WEB-INF/classes下放置xwork-conversion.properties文件 。在properties文件中的内容为:
待转换的类型=类型转换器的全类名
对于本例而言, xwork-conversion.properties文件中的内容为:
java.util.Date= cn.itcast.conversion.DateConverter
十九:自定义拦截器
Action:
package com.filter;
import java.sql.Timestamp;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
public class LogIC implements Interceptor{
public void destroy() {
}
public void init() {
}
public String intercept(ActionInvocation invocation) throws Exception {
String actionName = invocation.getAction().getClass().getName();
//入口
System.out.println("Action execute start at"+new Timestamp(System.currentTimeMillis()));
String result = invocation.invoke(); //保证拦截器往下执行
//出口
return result;
}
}
XML:
<package name="hello" namespace="/" extends="struts-default">
<interceptors>
<interceptor name="LogIC" class="com.filter.LogIC" />
<interceptor-stack name="LogStack">
<interceptor-ref name="defaultStack" />
<interceptor-ref name="LogIC" />
</interceptor-stack>
</interceptors>
<action name="hello" class="com.test.HelloAction" method="execute">
<result name="success">/hello.jsp</result>
<interceptor-ref name="LogStack"/>
<!-- <default-interceptor-ref name="LogStack"/> 默认的拦截器配置-->
</action>
</package>
因为struts2中如文件上传,数据验证,封装请求参数到action等功能都是由系统默认的defaultStack中的拦截器实现的,所以我们定义的拦截器需要引用系统默认的defaultStack,这样应用才可以使用struts2框架提供的众多功能。
如果希望包下的所有action都使用自定义的拦截器,可以通过<default-interceptor-ref name=“permissionStack”/>把拦截器定义为默认拦截器。注意:每个包只能指定一个默认拦截器。另外,一旦我们为该包中的某个action显式指定了某个拦截器,则默认拦截器不会起作用
或者使用如下方式:
<package name="hello" abstract="true" extends="struts-default">
<interceptors>
<interceptor name="LogIC" class="com.filter.LogIC" />
<interceptor-stack name="LogStack">
<interceptor-ref name="defaultStack" />
<interceptor-ref name="LogIC" />
</interceptor-stack>
</interceptors>
</package>
<package name="helloTwo" extends="hello">
<action name="hello" class="com.test.HelloAction" method="execute">
<result name="success">/hello.jsp</result>
</action>
</package>
二十:文件或图片上传
1. 前台:
2. <struts:form action="weiboAction!uploadPicture.shtml" enctype="multipart/form-data" namespace="/" method="post">
3. <struts:file name="image" label="文件"></struts:file>
4. <struts:submit value="上传"/>
5. </struts:form>
6.
7.
8. 后台:
9. /**
10. * 作者:刘鹏
11. * 时间:2013-07-07
12. * 描述:微博列表中的图片和文件上传显示
13. * @return
14. */
15.
16. /*****************以下为上传部分*******************************/
17. private File image; //得到上传的文件
18. private String imageFileName; //得到文件的名称,写法是固定的
19. private String imageContentType; //得到文件的类型
20.
21. public String getImageContentType() {
22. return imageContentType;
23. }
24. public void setImageContentType(String imageContentType) {
25. this.imageContentType = imageContentType;
26. }
27. public String getImageFileName() {
28. return imageFileName;
29. }
30. public void setImageFileName(String imageFileName) {
31. this.imageFileName = imageFileName;
32. }
33. public File getImage() {
34. return image;
35. }
36. public void setImage(File image) {
37. this.image = image;
38. }
39. public String addUI(){
40. return SUCCESS;
41. }
42. public String uploadPicture(){
43. HttpServletRequest request = ServletActionContext.getRequest();
44. //保存到根目录下的Images文件夹下
45. String realPath = ServletActionContext.getServletContext().getRealPath("/uploadOImages"); //取得真实路径
46. System.out.println(realPath);
47. System.out.println(imageFileName);
48. System.out.println(imageContentType);
49.
50. //自动命名
51. Random random = new Random(99999);
52. int tempInt = random.nextInt();
53. Date date = new Date();
54. SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddhhmmss");
55. int last = imageFileName.lastIndexOf(".");
56. String head = imageFileName.substring(0,last);
57. String type = imageFileName.substring(last);
58. imageFileName = simpleDateFormat.format(date) + tempInt + type;
59. System.out.println("新的文件名称是:"+imageFileName);
60.
61. //创建父文件夹
62. if(image!=null){
63. File saveFile = new File(new File(realPath), imageFileName);
64. if(!saveFile.getParentFile().exists()){ //如果Images文件夹不存在
65. saveFile.getParentFile().mkdirs(); //则创建新的多级文件夹
66.
67. }
68. try {
69. FileUtils.copyFile(image, saveFile); //保存文件
70. ActionContext.getContext().put("message", "上传成功!");
71. request.setAttribute("uploadsuccess", imageFileName);
72. } catch (IOException e) {
73.
74. e.printStackTrace();
75. }
76. }
77. return "upload";
78. }
79.
80.
81. /*****************以上为上传部分*******************************/
82.
83. 后台将图片的地址保存到数据库中
84. //先从数据库中将所有数据读出来,放入到request中
85. request.setAttribute("weibotest", list);
86.
87. 前台使用OGNL语言读取出图片地址,并且显示图片
88. <s:iterator value="#request.weibotest" var="user">
89. <s:property value="#user.getContent()"/>
90. <img src ='<s:property value ="#user.getImage()" />' width="200"> //显示图片
91. </s:iterator>
二十一:多文件上传
第一步:在WEB-INF/lib下加入commons-fileupload-1.2.1.jar、commons-io-1.3.2.jar。这两个文件可以从http://commons.apache.org/下载。
第二步:把form表的enctype设置为:“multipart/form-data“,如下:
<form enctype="multipart/form-data" action="${pageContext.request.contextPath}/xxx.action" method="post">
<input type="file" name="uploadImages">
<input type="file" name="uploadImages">
</form>
第三步:在Action类中添加以下属性,属性红色部分对应于表单中文件字段的名称:
public class HelloWorldAction{
private File[] uploadImages;//得到上传的文件
private String[] uploadImagesContentType;//得到文件的类型
private String[] uploadImagesFileName;//得到文件的名称
//这里略省了属性的getter/setter方法
public String upload() throws Exception{
String realpath = ServletActionContext.getServletContext().getRealPath("/images");
File file = new File(realpath);
if(!file.exists()) file.mkdirs();
for(int i=0 ;i<uploadImages.length; i++){ File uploadImage = uploadImages[i];
FileUtils.copyFile(uploadImage, new File(file, uploadImagesFileName[i]));
}
return "success";
}}
二十二:手工编写代码方式实现对Action中所有方法输入校验
通过重写validate() 方法实现, validate()方法会校验action中所有与execute方法签名相同的方法。当某个数据校验失败时,我们应该调用addFieldError()方法往系统的fieldErrors添加校验失败信息(为了使用addFieldError()方法,action可以继承ActionSupport ),如果系统的fieldErrors包含失败信息,struts2会将请求转发到名为input的result。在input视图中可以通过<s:fielderror/>显示失败信息。
action:
public class Validate extends ActionSupport{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String execute(){
return "success";
}
public void validate() {
if(name==null||"".equals(name)){
this.addFieldError("name", "用户名为空!");
}else{
if(name.length()<2||name.length()>10){
this.addFieldError("name", "用户名长度有误!");
}
}
}
}
xml:
<action name="validate" class="com.test.Validate">
<result name="input">/index.jsp</result>
<result name="success">/hello.jsp</result>
</action>
jsp:
<s:fielderror/>
二十三:手工编写代码方式实现对Action中指定方法输入校验
通过validateXxx()方法实现, validateXxx()只会校验action中方法名为Xxx的方法。其中Xxx的第一个字母要大写。当某个数据校验失败时,我们应该调用addFieldError()方法往系统的fieldErrors添加校验失败信息(为了使用addFieldError()方法,action可以继承ActionSupport ),如果系统的fieldErrors包含失败信息,struts2会将请求转发到名为input的result。在input视图中可以通过<s:fielderror/>显示失败信息。
action:
public String add(){
return "success";
}
public void validateAdd(){
if(name==null||"".equals(name.trim()))
this.addFieldError("name", "用户名不能为空");
}
xml:
<action name="validate" class="com.test.Validate">
<result name="input">/index.jsp</result>
<result name="success">/hello.jsp</result>
</action>
jsp:
<s:fielderror/>
访问:
http://localhost:8080/struts/validate!add
二十四:输入校验流程
1。类型转换器对请求参数执行类型转换,并把转换后的值赋给action中的属性。
2。如果在执行类型转换的过程中出现异常,系统会将异常信息保存到ActionContext,conversionError拦截器将异常信息添加到fieldErrors里。不管类型转换是否出现异常,都会进入第3步。
3。系统通过反射技术先调用action中的validateXxx()方法,Xxx为方法名。
4。再调用action中的validate()方法。
5。经过上面4步,如果系统中的fieldErrors存在错误信息(即存放错误信息的集合的size大于0),系统自动将请求转发至名称为input的视图。如果系统中的fieldErrors没有任何错误信息,系统将执行action中的处理方法。
二十五:基于XML配置方式实现对action的所有方法进行输入校验
使用基于XML配置方式实现输入校验时,Action也需要继承ActionSupport,并且提供校验文件,校验文件和action类放在同一个包下,文件的取名格式为:ActionClassName-validation.xml,其中ActionClassName为action的简单类名,-validation为固定写法。如果Action类为cn.itcast.UserAction,那么该文件的取名应为:UserAction-validation.xml。
action:
public class Validate extends ActionSupport{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String execute(){
return "success";
}
xml:
Validate-validation.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.3//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.3.dtd">
<validators>
<field name="name">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>用户名不能为空!</message>
</field-validator>
</field>
</validators>
struts.xml:同上
jsp:
<s:fielderror/>
访问:
http://localhost:8080/struts/validate!add
二十六:基于XML配置方式实现对action的制定方法进行输入校验
当校验文件的取名为ActionClassName-validation.xml时,会对 action中的所有处理方法实施输入验证。如果你只需要对action中的某个action方法实施校验,那么,校验文件的取名应为:ActionClassName-ActionName-validation.xml,其中ActionName为struts.xml中action的名称。
action:
public class Validate extends ActionSupport{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String execute(){
return "success";
}
public String add(){
return "success";
}
}
xml:
Validate-validate-validation.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.3//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.3.dtd">
<validators>
<field name="name">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>用户名不能为空!</message>
</field-validator>
</field>
</validators>
struts.xml:
<action name="validate" class="com.test.Validate">
<result name="input">/index.jsp</result>
<result name="success">/hello.jsp</result>
</action>
jsp:
<s:fielderror/>
访问:
http://localhost:8080/struts/validate!add
二十七:struts2提供的校验器列表
系统提供的校验器如下:
required (必填校验器,要求field的值不能为null)
requiredstring (必填字符串校验器,要求field的值不能为null,并且长度大于0,默认情况下会对字符串去前后空格)
stringlength(字符串长度校验器,要求field的值必须在指定的范围内,否则校验失败,minLength参数指定最小长度,maxLength参数指定最大长度,trim参数指定校验field之前是否去除字符串前后的空格)
regex(正则表达式校验器,检查被校验的field是否匹配一个正则表达式.expression参数指定正则表达式,caseSensitive参数指定进行正则表达式匹配时,是否区分大小写,默认值为true)
int(整数校验器,要求field的整数值必须在指定范围内,min指定最小值,max指定最大值)
double(双精度浮点数校验器,要求field的双精度浮点数必须在指定范围内,min指定最小值,max指定最大值)
fieldexpression(字段OGNL表达式校验器,要求field满足一个ognl表达式,expression参数指定ognl表达式,该逻辑表达式基于ValueStack进行求值,返回true时校验通过,否则不通过)
email(邮件地址校验器,要求如果field的值非空,则必须是合法的邮件地址)
url(网址校验器,要求如果field的值非空,则必须是合法的url地址)
date(日期校验器,要求field的日期值必须在指定范围内,min指定最小值,max指定最大值)
conversion(转换校验器,指定在类型转换失败时,提示的错误信息)
visitor(用于校验action中的复合属性,它指定一个校验文件用于校验复合属性中的属性)
expression(OGNL表达式校验器,expression参数指定ognl表达式,该逻辑表达式基于ValueStack进行求值,返回true时校验通过,否则不通过,该校验器不可用在字段校验器风格的配置中)
二十八:校验器的使用例子
required 必填校验器
<field-validator type="required">
<message>性别不能为空!</message>
</field-validator>
requiredstring 必填字符串校验器
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>用户名不能为空!</message>
</field-validator>
stringlength:字符串长度校验器
<field-validator type="stringlength">
<param name="maxLength">10</param>
<param name="minLength">2</param>
<param name="trim">true</param>
<message><![CDATA[产品名称应在2-10个字符之间]]></message>
</field-validator>
email:邮件地址校验器
<field-validator type="email">
<message>电子邮件地址无效</message>
</field-validator>
regex:正则表达式校验器
<field-validator type="regex">
<param name="expression"><![CDATA[^1[358]\d{9}$]]></param>
<message>手机号格式不正确!</message>
</field-validator>
int:整数校验器
<field-validator type="int">
<param name="min">1</param>
<param name="max">150</param>
<message>年龄必须在1-150之间</message>
</field-validator>
字段OGNL表达式校验器
<field name="imagefile">
<field-validator type="fieldexpression">
<param name="expression"><![CDATA[imagefile.length() <= 0]]></param>
<message>文件不能为空</message>
</field-validator>
</field>
二十九:基于XML校验的一些特点
当为某个action提供了ActionClassName-validation.xml和ActionClassName-ActionName-validation.xml两种规则的校验文件时,系统按下面顺序寻找校验文件:
1。AconClassName-validation.xml
2。ActionClassName-ActionName-validation.xml
系统寻找到第一个校验文件时还会继续搜索后面的校验文件,当搜索到所有校验文件时,会把校验文件里的所有校验规则汇总,然后全部应用于action方法的校验。如果两个校验文件中指定的校验规则冲突,则只使用后面文件中的校验规则。
当action继承了另一个action,父类action的校验文件会先被搜索到。
假设UserAction继承BaseAction:
<action name="user" class="cn.itcast.action.UserAction" method="{1}">
</action>
访问上面action,系统先搜索父类的校验文件:BaseAction-validation.xml, BaseAction-user-validation.xml,接着搜索子类的校验文件: UserAction-validation.xml, UserAction-user-validation.xml。应用于上面action的校验规则为这四个文件的总和。
三十:国际化
准备资源文件,资源文件的命名格式如下:
baseName_language_country.properties
baseName_language.properties
baseName.properties
其中baseName是资源文件的基本名,我们可以自定义,但language和country必须是java支持的语言和国家。如:
中国大陆: baseName_zh_CN.properties
美国: baseName_en_US.properties
现在为应用添加两个资源文件:
第一个存放中文:itcast_zh_CN.properties
内容为:welcome=欢迎来到传智播客
第二个存放英语(美国): itcast_en_US.properties
内容为: welcome=welcome to itcast
对于中文的属性文件,我们编写好后,应该使用jdk提供的native2ascii命令把文件转换为unicode编码的文件。命令的使用方式如下:
native2ascii 源文件.properties 目标文件.properties
配置全局资源与输出国际化信息
当准备好资源文件之后,我们可以在struts.xml中通过struts.custom.i18n.resources常量把资源文件定义为全局资源文件,如下:
<constant name="struts.custom.i18n.resources" value="itcast" />
itcast为资源文件的基本名。
后面我们就可以在页面或在action中访问国际化信息:
在JSP页面中使用<s:text name=“”/>标签输出国际化信息:
<s:text name=“user”/>,name为资源文件中的key
在Action类中,可以继承ActionSupport,使用getText()方法得到国际化信息,该方法的第一个参数用于指定资源文件中的key。
在表单标签中,通过key属性指定资源文件中的key,如:
<s:textfield name="realname" key="user"/>
国际化—输出带占位符的国际化信息
资源文件中的内容如下:
welcome= {0},欢迎来到传智播客{1}
在jsp页面中输出带占位符的国际化信息
<s:text name="welcome">
<s:param><s:property value="realname"/></s:param>
<s:param>学习</s:param>
</s:text>
在Action类中获取带占位符的国际化信息,可以使用getText(String key, String[] args)或getText(String aTextName, List args)方法。
国际化—JSP中直接访问某个资源文件
struts2为我们提供了<s:i18n>标签,使用<s:i18n>标签我们可以在类路径下直接从某个资源文件中获取国际化数据,而无需任何配置:
<s:i18n name="itcast">
<s:text name=“welcome”/>
</s:i18n>
Itcast为类路径下资源文件的基本名。
如果要访问的资源文件在类路径的某个包下,可以这样访问:
<s:i18n name=“cn/itcast/action/package">
<s:text name="welcome">
<s:param>小张</s:param>
</s:text>
</s:i18n>
上面访问cn.itcast.action包下基本名为package的资源文件。
实例:
properties:
csst.properties
main.company:CSST
main.addr:haidian,Beijing,china
csst_zh_CN.properties
main.company:中软培训
main.addr:海淀南路,北京,中国
csst_en_US.properties
main.company:&&qq
main.addr:**ss
XML:
<constant name="struts.custom.i18n.resources" value="csst" />
<action name="il8n" class="com.il8n.IL8NAction">
<result name="success">/IL8N.jsp</result>
</action>
action:
success
jsp:
名称:<s:text name="main.company"/><br>
地址:<s:text name="main.addr"/>
访问:
http://localhost:8080/struts/il8n?request_locale=en_US
Struts2.1笔记
最新推荐文章于 2015-06-28 18:35:00 发布