Struts2.1笔记

来源:互联网 发布:recuva数据恢复 编辑:程序博客网 时间:2024/06/03 14:31

最近在学习Struts2,正好看见这篇文章,果断转了!!很不错,帮助很大啊!

原文:http://blog.csdn.net/liupeng_family/article/details/18964935

Struts2.1官方文档:1.set标签处value的String改为object2.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/java2.文档的展示:右击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为URIc)key: http://struts.apache.org/dtds/struts-2.0.dtdd)location: 对应的dtd文件,位于struts-core包中,解压开,指定相应位置,如:D:\share\0750_Struts2.1.6\soft\struts-2.1.6\lib\struts2-core-2.1.6\struts-2.0.dtd4.右击项目->java->compliance->compiler compliance level->1.65.常量的配置保存在struts2-core-2.1.8.1.jar->org.apache.struts2->default.properties6.<constant name="struts.devMode" value="true" />:此时表示正处于开发模式,可以不用重新启动服务器而直接访问修改后的内容一.1:Struts2流程Struts2多实例,多线程Servlet单实例,多线程 二:NameSpacea)namespace决定了action 的访问路径,默认为“”,可以接收所有路径的action,例如http://localhost:8080/Test/asdfasdfas/sdgsdg/sdfsdfsd/index.actionb)当将现有的项目拷贝出来一份以后,一定要记得,右击项目->Properties->Myeclipse->Web,将Web Context-root修改掉。三:Actiona) 具体视图的返回可以由用户自己定义的Action来决定b) 具体的手段是根据返回的字符串找到对应的配置项,来决定试图的内容c) 具体Action的实现可以是一个普通的Java类,里面有public String              execute()方法即可d)修改默认编码:windows->preference->JSPe)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自己写的) 五:ActionMethod1.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();@Overridepublic User getModel() {    return user;}public String show(){User model = getModel();System.out.println("取得名称:"+model.getName());System.out.println("取得年龄:"+model.getAge());return "show";}八:简单数据验证 简单数据验证1Actionif(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 ContentsObjectProperty NameProperty Valuecom.model.Testname刘鹏age20com.demo.TestActiontextsnullmodelcom.model.Test@59c8b5actionErrors[]errors{name=[name is error!]}fieldErrors{name=[name is error!]}errorMessages[]localezh_CNactionMessages[]com.opensymphony.xwork2.DefaultTextProvidertextsnull九:访问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_Type1.Dispatcher   //显示action地址2.Redirect     //显示jsp地址3.Chain        4.redirectAction  5.freemarker6.httpheader7.stream8.velocity9.xslt10.plaintext11.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=10OGNL2(访问普通属性)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=wanghanOGNL3(访问普通方法)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=1111OGNL4(访问静态属性和方法)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)propertyAction代码: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)setI.默认为action scope,会将值放入request和ActionConrtext中II.page、request、session、applicationJSP代码:    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=1111c)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 elseJSP代码: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=20b)iteratorJSP代码: 遍历集合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)subset3.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.Javapublic 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.Javapublic 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.xml2。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.propertiesbaseName_language.propertiesbaseName.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.propertiesmain.company:CSSTmain.addr:haidian,Beijing,chinacsst_zh_CN.propertiesmain.company:中软培训main.addr:海淀南路,北京,中国csst_en_US.propertiesmain.company:&&qqmain.addr:**ssXML:<constant name="struts.custom.i18n.resources" value="csst" /><action name="il8n" class="com.il8n.IL8NAction"><result name="success">/IL8N.jsp</result></action>action:successjsp:    名称:<s:text name="main.company"/><br>地址:<s:text name="main.addr"/>访问:http://localhost:8080/struts/il8n?request_locale=en_US


0 0