首页 > 代码库 > Struts 2.0全面分析
Struts 2.0全面分析
Struts 2.0 struts 1---前端控制+应用控制+命令模式 webwork ---控制器+拦截器+代理 Struts 2.0 继承了WebWork的设计理念,并没有继承struts 1,所以与struts 1是截然不同的~! ------------------------------------------------------- Struts 2.0的简单实例: web.xml中 <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> ------------------------------ action类继承 Action接口或者ActionSupport接口 如:public class LoginAction implements Action{ private String name=null; 然后提供set,get方法 //封装参数名为name的值,对应前台的参数 private String password=null; 然后提供set,get方法//封装参数名为password的值,对应前台的参数 private UserVo user=null; 然后提供set,get方法// 用对象的方式,封装对象UserVo的值 public String execute() throws Exception{ System.out.println(name+" "+password); System.out.println(user.name+user.password);//那么在前台jsp页面中要写成<input type="text" name="user.name"/> 和<input type="password" name="user.password"/>这样前台和action之中的属性保持一致! return Action.SUCCESS; } } ------------------------------------------------------------ struts.xml 不同以往,写在src目录下~! <?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>--用于组织拦截器,action对象,返回类配置的一套逻辑单位 -name 标识名称 -namespace package映射的url地址(可有可无,倘若配置上名为girl,那么工程要加入girl这一层目录 -abstruct:若为true时,struts2 框架不会使用该配置生成配置封装信息 <result-types>--用于定义返回值类型,struts2的执行结果可以生成哪些响应格式 <interceptor>--在action的执行中,需加入的拦截器对象 <action> -name action的组件标识名 //前台页面请求action="…….action" 不再是…….do -class action类名 -method 讲请求转发到指定的方法中 <result>要返回的类型,或路径 -name 返回名称(success error input login 这些是默认的,是跟着execute方法返回值) 补充:Struts2 中通配符在struts.xml的使用! <action name="test*" class="cn.com.action.loginAction" method="test{1}"> <result name="result{1}">/jsp/result{1}.jsp</result> </action> 若一个action中多个方法 调用其中一个方法可以用 login!method1.action 这样他会自我调用method1方法 -------------------------------------------------------------------------------------------- <?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="shushine" extends="struts-default"> 继承struts的默认包,里面有大量的配置信息 <action name="login" class="cn.com.action.LoginAction"> //前台页面请求action="login.action" 不再是login.do <result name="success">index.jsp</result> <result name="input">login.jsp</result> //这个是验证失败的话 </action> </package> </struts> ----------------------------------------------------- 1 若是请求出现错误,为了友好化,可以这样设定! <default-action-ref name="actionError"></default-action-ref> <action name="actionError"> <result>/jsp/AllErros.jsp</result> </action> 2 全局结果,无论什么方法,只要返回结果一致,都会转向指定的页面! <global-results> <result name="error">/jsp/error.jsp</result> </global-results> 若是<action >...</action>中也出现error 那么他的优先级大于全局的!!!!! ------------------------------------------ 总结下简单的体系: 前端控制 : FilterDispatcher .接受请求,调用组建--->通过ActionProxyFactory(action代理工厂)获得代理,然后-->interceptor(拦截器)-->分解请求,封装到指定对象上~! | execute()--->interceptor--->转发重定向,或者直接响应 ------------------------------------------------------------------------------------------------- struts2 action的验证: //validate方法 @Override public void validate() { if(userName == null || "".equals(userName)) this.addFieldError("userName", "用户名不能为空"); if(userPassword == null || "".equals(userPassword)) this.addFieldError("userPassword", "密码必须填写"); } this.addFieldError("username","用户名不能为空"); this.addActionMessage("欢迎登陆论坛"); this.addActionError("用户名或密码错误!请重新尝试!!"); 一般来说验证信息就是以上3种形式! s标签的导入 :<%@taglib uri="/struts-tags" prefix="s"%> <s:fielderror><s:param>userName</s:param></s:fielderror> <s:actionmessage/> <s:actionerror/> ----------------------------------------------------------------- ajax,json的返回结构在struts2中的应用 action类没有任何变化,还是将数据保存在list中,在struts.xml中可以将list转换成json格式! <package name="testAjax" extends="json-default">//引用json默认包 <action name="json" class="cn.com.csuinfosoft.action.JsonAction"> <result type="json"></result>//返回类型装换成json类型 </action> </package> 在jsp页面中,这是通过jQuery得到json对象 <script type="text/JavaScript" src="http://www.mamicode.com/js/jquery-1.2.6.js"></script> <script> function testAjax() { $.ajax({ type: "POST", url:"json.action", dataType:"json", success:function(msg) { alert(‘msg === ‘ + msg.cityList); var selectObj = $("#city"); selectObj.empty(); for(i = 0; i < msg.cityList.length; i++) { selectObj.append("<option value=http://www.mamicode.com/‘"+msg.cityList[i].id+"‘>"+msg.cityList[i].name+"</option>"); } } }); } </script> ------------------------------------------------------------ session,request,application等拦截器,通过 implements struts2自带的它们接口,获得它们的map形式 public class LoginAction extends ActionSupport implements RequestAware, SessionAware ,ApplicationAware{ private Map<String,Object> request = null; private Map<String,Object> session = null; private Map<String,Object> application = null; public void setRequest(Map request) { this.request = request; } public void setSession(Map session) { this.session = session; } public void setApplication(Map application) { this.application = application; } public String execute() throws Exception { session.put("userInfo","获取了对象");//另外两种略,这样无论在其他action类中还是jsp页面中都可以通过session得到数据 } } 当然也可以通过ServletActionContext引用它们的API,得到session,request,application对象 import org.apache.struts2.ServletActionContext; ServletActionContext.getRequest().getSession(); ServletActionContext.getRequest() ----------------------------------------------------------------------------------------------------------------------------------------------- Struts2的类型转换器 Struts2的类型转换器:(开发的实际意义不大,但是可以让你理解和更好的使用Struts2的类型转换机制 转换器--在struts2的框架内部,实现请求参数--》Action属性的自动封装和类型转换。 都是来自ognl.TypeConverter 请求通过struts2的组件,转发到action之前, struts会获取该action的所用属性的信息,然后检测该属性是否有对应的类型转换器,如果有,则会进行类型转换。若没有,则会调用默认的类型转换器。 1 局部转换器:针对某一个Action的属性值转换提供实现。(Action类名-conversion.properties放在与action同一个包下) 例如:RegAction-conversion.properties里 user=cn.com.csuinfosoft.converter.MyConverter 页面上属性名都用user: 2 全局转换器:对当前所有的工程下,所有指定类型的属性进行转换。(xwork-conversion.properties放在classes目录) 例如:xwork-conversion.properties cn.com.csuinfosoft.vo.User=cn.com.csuinfosoft.converter.MyConverter 以上两个转换器,转换类基本写法一样,只是配置文档不同,这就导致了一个局部,一个全局。 转换类 实现 ognl.TypeConverter接口 public Object convertValue(Map map,Object arg1,Member arg2,String arg3,Object arg4,Class arg5){ } map--ognlContext---OGML上下文 arg1---所对应的action实例 arg2---Member成员类型,所需调用的属性设置方法(反射对象) arg3---对应的请求参数或者属性名 arg4---参数值 arg5---需要转换的属性类型 代码如下: public class MyConverter implements TypeConverter { public Object convertValue(Map map, Object arg1, Member arg2, String arg3, Object arg4, Class arg5) { if(arg5 == User.class) { User user = new User(); String[] param = (String[])arg4; user.setUserName(param[0]); user.setUserAge(Integer.parseInt(param[1])); user.setUserTel(param[2]); return user; } return null; } } 还是很容易理解的。。。。 ---------------------------------------------------------------------------------------------------------------------------------------------- Struts2的拦截器和文件上传 Struts2的拦截器: 拦截器---在struts调用Action执行过程中,提供辅助的请求处理操作。 Struts2的包中有大量的拦截器。 Interceptor -intercept(ActionInvocation invocation) --Action的执行引用 拦截器类 实现 Interceptor接口 public void destory(){ } public void init(){ } public String intercept(ActionInvocation actionInvocation) throws Exception { System.out.println("intercept----begin----"); String result = actionInvocation.invoke(); System.out.println("result === " + result); System.out.println("intercept----end----"); return result; } 启用拦截器要在struts.xml中加入配置: <package> <interceptors> <interceptor class="cn.com.interceptor.MyInterceptor" name="myInterceptor"></interceptor>//拦截器的单独定义,如果不用栈的话,那么这个拦截器用了,其他的拦截器就失效 <!--拦截器栈--> <interceptor-stack name="mydefault"> <interceptor-ref name="myInterceptor"/>//拦截器 name属性可以是已有的拦截器名称,也可以是拦截器栈的名称 <interceptor-ref name="defaultStack"/>//拦截器默认栈 ,如果不加上这个,很多默认的拦截器就不会再实现了。 </interceptor-stack> </interceptors> <action ......> <interceptor-ref name="myInterceptor"/> </action> </package> 例子代码: <struts> <package name="shushine" extends="struts-default"> <interceptors> <interceptor class="cn.com.csuinfosoft.interceptor.MyInterceptor" name="myInterceptor"></interceptor> <interceptor-stack name="myInterceptorStack"> <interceptor-ref name="myInterceptor"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </interceptor-stack> </interceptors> <action name="regAction" class="cn.com.csuinfosoft.action.RegAction"> <interceptor-ref name="myInterceptorStack"></interceptor-ref> <result name="success">reg.html</result> </action> </package> </struts> 自定义拦截器中,在一个action中有些方法需要拦截,有些方法不需要,可以用includeMethods和excludeMethods 这两个参数来设置 1 首先在拦截器类中extends MethodFilterInterceptor 2 includeMethods 优先级高于 excludeMethods <interceptor-ref name="test"> <param name="excludeMethods">method1,method2</param> <param name="includeMethods">method1,method2</param> </interceptor-ref> 对于较长时间需要等待的,可以给出execAndWait拦截器,这样可以给用户一个友好的等待提示,当然也可以自己设计友好的提示内容! <result name="wait">/jsp/wait.jsp</result> <interceptor-ref name="execAndWait"> <param name="excludeMethods">execute</param> </interceptor-ref> 避免重复提交用到的拦截器 1 TokenInterceptor 这个拦截器会查出是否重复提交,若是则可以转向错误页面! <result name="invalid.token">/jsp/error.jsp</result> <interceptor-ref name="token"></interceptor-ref> 除了在struts.xml中设定外,还要在请求jsp页面标记该拦截器 <s:form action="login" method="post"> <s:token></s:token> 这里标记该form <s:textfield name="username" label="用户名"></s:textfield> <s:textfield name="password" label="密 码"></s:textfield> <s:submit value="http://www.mamicode.com/Submit"></s:submit> <s:reset value="http://www.mamicode.com/Reset"></s:reset> </s:form> 2 TokenSession 这个拦截器会查出是否重复提交,若是则转向第一次正确登录的 页面,无需设定错误页面! <interceptor-ref name="tokenSession"></interceptor-ref> 除了在struts.xml中设定外,还要在请求jsp页面标记该拦截器 <s:form action="login" method="post"> <s:token></s:token> 这里标记该form <s:textfield name="username" label="用户名"></s:textfield> <s:textfield name="password" label="密 码"></s:textfield> <s:submit value="http://www.mamicode.com/Submit"></s:submit> <s:reset value="http://www.mamicode.com/Reset"></s:reset> </s:form> ----------------------------------------------------------------------------------------------- Struts2的文件上传功能: Struts2的文件上传是基于拦截器来实现的。 还有要加入两个文件上传的包! 页面: <form action="uploadAction.action" method="POST" enctype="multipart/form-data"> <table align="center" border="1"> <tr> <td> 文件:<input type="text" name="title"/> </td> <td> <input type="file" name="photo"/> </td> </tr> <tr> <td> 文件:<input type="text" name="title"/> </td> <td> <input type="file" name="photo"/> </td> </tr> <tr> <td> 文件:<input type="text" name="title"/> </td> <td> <input type="file" name="photo"/> </td> </tr> <tr> <td align="center" colspan="2"><input type="submit" name="s1" value="http://www.mamicode.com/上传"/> </td> </tr> </table> </form> Action类: ----------------------------------------------------- public class UploadAction implements Action { /** * 封装上传文件信息 */ private File[] photo = null; /*FileUpload拦截器会根据上传文件的信息,自动填充一下两个属性 * * photoContentType,photoFileName * */ private String[] photoContentType = null; private String[] photoFileName = null; private String[] title = null; public String execute() throws Exception { File file = null; for(int i = 0; i < photo.length; i++) { file = photo[i]; System.out.println("title === " + title[i]); System.out.println("file.name === " + photoFileName[i]); System.out.println("file.type === " + photoContentType[i]); System.out.println("file === " + file); System.out.println("######################################"); } return this.SUCCESS; } public void setPhoto(File[] photo) { this.photo = photo; } public void setPhotoContentType(String[] photoContentType) { this.photoContentType = photoContentType; } public void setPhotoFileName(String[] photoFileName) { this.photoFileName = photoFileName; } public void setTitle(String[] title) { this.title = title; } } ---------------------------------------------------------------- struts.xml中配置文件上传的拦截器: <interceptors> <interceptor-stack name="MyfileUploadStack"> <interceptor-ref name="defaultStack"></interceptor-ref> <interceptor-ref name="fileUpload"> <param name="allowedTypes">image/jpeg,image/gif</param> //这个是用来判断文件类型是否符合要求 </interceptor-ref> <interceptor-ref name="myInterceptor"></interceptor-ref> </interceptor-stack> </interceptors> <action name="uploadAction" class="cn.com.csuinfosoft.action.UploadAction"> <interceptor-ref name="MyfileUploadStack"> </interceptor-ref> <result name="success">upload.jsp</result> </action> --------------------------------------------------------------------- 文字脏话过滤~! 1 写好interceptor类 public String intercept(ActionInvocation arg0) throws Exception { Object o=arg0.getAction(); if (o instanceof charAction){ charAction action=(charAction) o; System.out.println(action); if (action!=null){ String content=action.getContent(); System.out.println(content+"-----------------"); String[] str={"TMD","tmd","GM","gm","cao"}; for(int i=0;i<str.length;i++){ if (content.contains(str[i])){ content=content.replaceAll(str[i],"***"); } } System.out.println(content+"====================="); action.setContent(content); return arg0.invoke(); }else{ return "input"; } } return "input"; } 2 在struts.xml配置对应的文件 3 特别注意: <interceptors> <interceptor name="contentInterceptor" class="cn.com.interceptor.ContentInterceptor"></interceptor> <interceptor-stack name="contentstack"> <interceptor-ref name="defaultStack"></interceptor-ref> <interceptor-ref name="contentInterceptor"></interceptor-ref> </interceptor-stack> defaultStack要写在我们拦截器前面,因为是顺序加载,先加载defaultStack ,这样action中才能得到请求页面的值~ 否贼,先我们的拦截器类,那么在方法中的action得到对应的属性值为null~! 切记:defaultStack" 写在 我们的定义拦截器类前面 ---------------------------------------------- 拦截器在action中可以设定哪些方法拦截,哪些方法不被拦截 1 首先需要拦截器类 extends MethodFilterInterceptor 2 配置中写: <interceptor-ref name="contentInterceptor"> <param name="excludeMethods">execute1,execute2</param> 设定哪些方法不被拦截 <param name="includeMethods">execute</param> 设定哪些方法被拦截 </interceptor-ref> ----------------------------------------- 拦截器拦截顺序 假设在一个action中有3个拦截器,配置顺序分别为拦截器1,拦截器2,拦截器3 则执行顺序为: 拦截器1 执行 拦截器2 执行 拦截器3 执行 execute方法实现 拦截器3 执行完毕 拦截器2 执行完毕 拦截器1 执行完毕 这类似一个递归的顺序! ---------------------------------------- 拦截器结果监听器 拦截器监听类实现 implements PreResultListener{ public void beforeResult(ActionInvocation ai,String result){ 这里对执行的结果进行监听 } } 在interceptor类中,ai.addPreResultListener(new 我们定义监听类); --------------------------------------- 拦截器也包括参数的覆盖,这个不难,不懂得网上可以查到的 struts2.0中大量使用了内置拦截器和内置拦截器栈,有些还是需要了解的 如:<interceptor-ref name="timer"/> 查看运行耗时的拦截器 ------------------------------------- 权限,判断是否登陆,通过session的到用户对象 public String interceptor(ActionInvocation ai) throws Exception{ ActionContext ac=ai.getInvocationContext(); Map session=ac.getSession(); String username=(String)session.get("username"); if (username!=null && username.length()>0){ return ai.invoke(); } else{ return Action.LOGIN; } } ================================================================================================= ------------------------------------------------------------Struts2 效验器-------------------------------------------------- 1 普通的效验代码 基于正则表达式(相对全面的注册页面) 3步! 该效验代码出现在validate方法中 1 首先 jsp页面! <%@ page language="Java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <s:head theme="ajax"/> <!--在以前的struts2版本中s:datetimepicker只需要在head标签处设置 <s:head theme="ajax"/>, 就可以直接使用s:datetimepicker的标签了。 而在2.1.6版本中不能直接这样使用了,将datetimepicker移除了。 原因是此标签调用了dojo的datetimepicker的库。 所以现在使用的时候首先要导入一个库。 struts2-dojo-plugin-2.1.6.jar。 然后还要设置dojo的taglib 详见http://blog.csdn.net/javakeikei/archive/2009/10/19/4700352.aspx#1262867 --> <style type="text/css"> body { background-color: #CCCCCC; } </style> <title>My JSP ‘regist.jsp‘ starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="http://www.mamicode.com/styles.css"> --> </head> <body> <center> <h2> 注册新用户(带*项为必填信息) </h2> <table> <hr> <s:form action="validate1"> <s:textfield name="username" label="用户名" required="true"></s:textfield> <s:textfield name="password1" label="输入密码" required="true"></s:textfield> <s:textfield name="password2" label="重复密码" required="true"></s:textfield> <s:textfield name="email" label="邮箱" required="true"></s:textfield> <tr> <td> <hr color="red"> </td> </tr> <s:textfield name="age" label="年龄"></s:textfield> <s:radio list="#{‘男‘:‘男‘,‘女‘:‘女‘}" name="sex" label="性别" /> <s:datetimepicker id="dateDemo" name="dateValue" value="http://www.mamicode.com/today" toggleType="explode" label="出生日期"></s:datetimepicker> <s:submit value="http://www.mamicode.com/提交" align="center"></s:submit><s:reset value="http://www.mamicode.com/重置" align="center"></s:reset> </s:form> </table> </center> </body> </html> 2 struts.xml 中 <action name="validate1" class="cn.com.action.registAction"> <result name="success">/jsp/registSuccess.jsp</result> <result name="input">/jsp/regist.jsp</result> </action> 3 action类中 package cn.com.action; import java.util.regex.Pattern; import com.opensymphony.xwork2.ActionSupport; public class registAction extends ActionSupport { private String username; private String password1; private String password2; private String email; private int age; private String sex; private String dateValue; // set/get 方法略! @Override public String execute() throws Exception { System.out.println(username); System.out.println(password1); System.out.println(password2); System.out.println(email); System.out.println(sex); System.out.println(dateValue); System.out.println(age); if (hasErrors()) { return INPUT; } return SUCCESS; } /** * Pattern.matches正则表达式的方法 import java.util.regex.Pattern; /w表示字母和数字或下划线的组合 * 4,15 表示长度范围 更多表达式自己查 */ @Override public void validate() { if (username.equals("")) { addFieldError("username", "必须输入用户名"); } else if (!Pattern.matches("//w{4,15}", username)) { addFieldError("username", "用户名必须是字母和数字或下划线的组合且长度在(4-15)范围内"); } if (username.equals("")) { addFieldError("password1", "必须输入密码"); } else if (!Pattern.matches("//w{6,15}", password1)) { addFieldError("password1", "密码必须是字母和数字或下划线的组合且长度在(6-15)范围内"); } if (username.equals("")) { addFieldError("password2", "必须重复输入密码"); } else if (!password2.equals(password1)) { addFieldError("password2", "重复输入密码必须与第一次输入密码一致"); } if (username.equals("")) { addFieldError("email", "必须输入邮编"); } else if (!Pattern.matches( "^//w+(//.|//w+)*//w+(//.//w+)*@//w+//w+//.//w+$", email)) { addFieldError("email", "邮编的格式不正确或者输入的邮编不存在"); } if (age < 1 || age > 99) { addFieldError("age", "年龄必须为整数且在(1-99)范围内"); } } } ------------------------------------------------- validate*(validate方法名)的存在 它可以针对指定的方法进行效验! 例如我们的action中有多个方法!如Test1 和Test2 当请求通过struts.xml中调用Test1 时,该action中的validateTest1() 效验方法会被调用! 当请求通过struts.xml中调用Test2 时,该action中的validateTest2() 效验方法会被调用! 各求所需,合理致用~! ----------------------------------------------------------- 在struts2内部有许多内置的效验器,我们也可以通过默认的Struts2默认效验框架来实现对程序的效验工作!!! 由于struts-default 默认拦截器,则效验的拦截器自然被包括,所以无需对效验器再进行拦截了 1, action 中只是很简单的! package cn.com.action; import com.opensymphony.xwork2.ActionSupport; public class registAction extends ActionSupport { private String username; private String password1; private String password2; private String email; private int age; private String sex; private String dateValue; // set/get 方法略! @Override public String execute() throws Exception { System.out.println(username); System.out.println(password1); System.out.println(password2); System.out.println(email); System.out.println(sex); System.out.println(dateValue); System.out.println(age); if (hasErrors()) { return INPUT; } return SUCCESS; } } 2 jsp页面,struts.xml保持不变 ~! 类似于前面的~! 3 编写效验action类名-validation.xml文件 该文件与action类文件必需放在同一目录下 例如:registAction-validation.xml <?xml version="1.0" encoding="GBK"?> <!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd"> <validators> <!-- 效验用户名区域 --> <field name="username"> <!-- 效验用户名不能为空 --> <field-validator type="requiredstring"> <message>必需输入用户名</message> </field-validator> <!-- 效验用户名格式问题 --> <field-validator type="regex"> <param name="expression"><![CDATA[(/w{4,15})]]></param> <message>用户名必须是字母和数字或下划线的组合且长度在(4-15)范围内</message> </field-validator> </field> <!-- 效验密码区域 --> <field name="password1"> <!-- 效验密码不能为空 --> <field-validator type="requiredstring"> <message>必需输入密码</message> </field-validator> <!-- 效验用户名格式问题 --> <field-validator type="regex"> <param name="expression"><![CDATA[(/w{6,15})]]></param> <message>密码必须是字母和数字或下划线的组合且长度在(6-15)范围内</message> </field-validator> </field> <!-- 效验重复密码区域 --> <field name="password2"> <!-- 效验重复密码不能为空 --> <field-validator type="requiredstring"> <message>必需重复输入密码</message> </field-validator> <!-- 效验重复密码一致性问题 --> <field-validator type="fieldexpression"> <param name="expression"><![CDATA[(password2.equals(password1))]]></param> <message>两次输入的密码不一致</message> </field-validator> </field> <!-- 效验邮箱区域 --> <field name="email"> <!-- 效验邮箱不能为空 --> <field-validator type="requiredstring"> <message>必需输入邮箱</message> </field-validator> <!-- 效验邮箱格式问题 --> <field-validator type="email"> <message>邮编的格式不正确或者输入的邮编不存在</message> </field-validator> </field> <!-- 效验年龄区域 --> <field name="age"> <!-- 效验年龄格式问题 --> <field-validator type="int"> <param name="min">1</param> <param name="max">99</param> <message>年龄必须是在(1-99)范围内</message> </field-validator> </field> </validators> (封装完成!) ------------------------------------------------------------------------------ 补充(<s:form action="validate1" validate="true">中的validate="true" 默认为false 若是true 先在客户端进行校验,然后在服务端再进行校验 客户端所支持的效验器不够全面,没有服务器的多,有些校验不出结果!) 若为false 只在服务器端进行校验 ------------------------------------------------------------------- 自定义校验框架也是不错的,但是基本上默认的已经比较全面够用了. -------------------------------------------------------------------- visitor 效验器在校验中的作用 例如 登录需要用户名和密码的校验 注册也需要用户名和密码的校验 这些可以用同一个校验文件 ,通过visitor就可以互相访问! 这样的会,虽然代码少了,但是程序的可读性变差了, 阅读程序时较为复杂! ----------------------------------------------------------------- 校验框架的短路现象理解就好了~! 其实际作用一般! ========================================================================================================================================== Struts2 标签: 导入struts标签库 <%@taglib uri="/struts-tags" prefix="s"%> _____________________________________________________ 1 迭代标签+ognl表达式 <s:iterator value="http://www.mamicode.com/list"> <tr> <td><s:property value="http://www.mamicode.com/name"/></td> <td><s:property value="http://www.mamicode.com/record"/></td> <td><s:property value="http://www.mamicode.com/date"/></td> </tr> </s:iterator> value="http://www.mamicode.com/……" 就是ognl表达式(对象导航语言,提供了一组数据结构和表达式,通过表达式可以访问该数据结构上的任意对象或者对象属性) ognl上下文--用于存放一次请求处理过程,所对应各级会话内容和值栈内容的map结构对象(OgnlContext) 可以访问:request,session,application,值栈,param ognl表达式--"#对象名.属性 " #application #session #request #this --"对象名.{?#this.属性==‘值‘}" <s:iterator value="http://www.mamicode.com/list.{?#this.age>20 && #this.sal>1000}"> 顺序是:值栈,request,session.application... <s:proprety value="http://www.mamicode.com/#session.userInfo"/> <s:if test="sal>1500">如果怎么样</s:if><s:else>否则怎么样</s:else> ____________________________________________________ Js效果标签(Js+Ajax+htm) <head> <s:head theme="ajax"/> //导入 ajax 模式 </head> <s:div>-->生成div元素 <s:head> -theme="ajax"--在页面导入struts2的Ajax环境(Dojo--Js框架),启用 ajax 功能 -href:通过功能访问的资源路径 -loadingText:等待加载时的提示信息 -实时的访问: -autoStart:boolean 是否循环加载 -updateFreq:int类型 循环访问的间隔时间 -delay:integer 设置延迟多长时间开始加载div标签内容 Ajax模式:基于请求对象的响应结果生成div内容 -------------------- <s:autocompleter>可以实现搜索引擎,打1个字,就可以动态生成下拉菜单显示相关内容(如google,百度) <div align="center"> 动态列表生成技术</br> 1 这个是静态list: <s:autocompleter id="select" list="{‘PengPeng‘,‘penpen‘,‘Peijing‘,‘PangPang‘}" showDownArrow="false" loadOnTextChange="true" loadMinimumCount="1"></s:autocompleter> 2 json生成的list..配置中可以设置不包含那些属性 <s:autocompleter id="input" name="selectParam" theme="ajax" href="http://www.mamicode.com/completerAction.action" showDownArrow="false" loadOnTextChange="true" loadMinimumCount="1"></s:autocompleter> </div> loadOnTextChange是否在文本内容改变时进行匹配内容的加载 showDownArrow 是否采用select下拉菜单功能 loadMinimumCount 文本框内有几位字符时才进行这种内容匹配的操作。 ---------------------------------------------------------------------------------------- --tab <s:tabbedPanel id="mytab" theme="ajax" labelposition="top" selectedTab="d2" closeButton="true" > <s:div id="d1" label="魏" theme="ajax"> 曹操</br>司马懿</br>张辽</br> </s:div> <s:div id="d2" label="蜀" theme="ajax"> 春哥</br>曾哥</br>飞哥</br> </s:div> <s:div id="d3" label="吴" theme="ajax"> 曹操</br>司马懿</br>张辽</br> </s:div> </s:tabbedPanel> ------------------------------------------------------------- ------------------------------------------------------日期 struts2上提供自带的时间组件-------------------------------------------------- <s:datetimepicker id="dateDemo" name="dateValue" value="http://www.mamicode.com/today" toggleType="explode"></s:datetimepicker> 在以前的struts2版本中s:datetimepicker只需要在head标签处设置 <s:head theme="ajax"/>, 就可以直接使用s:datetimepicker的标签了。 而在2.1.6版本中不能直接这样使用了,将datetimepicker移除了。 原因是此标签调用了dojo的datetimepicker的库。 所以现在使用的时候首先要导入一个库。 struts2-dojo-plugin-2.1.6.jar。 然后还要设置dojo的taglib
然后还要设置dojo的taglib
<%@ taglib prefix="sd" uri="/struts-dojo-tags" %>
同样也需要对theme进行设置
<s:head theme="xhtml"/> <sd:head parseContent="true"/>
上面的设置在head标签中。
然后使用sd:datetimepocker就可以实现了。
设置formatLength为long的datetimepicker标签
<s:datetimepicker toggleType="explode" value="http://www.mamicode.com/today" formatLength="long" />
设置displayFormat参数为“yyyy年MM月dd日”
displayWeeks参数为2的datetimepicker标签
<s:datetimepicker displayFormat="yyyy年MM月dd日" displayWeeks="2" />
设置weekStartsOn参数为1,toggleType参数为fade的datetimepicker标签
<s:datetimepicker weekStartsOn="1" toggleType="fade" />
设置显示时间datetimepicker标签
<s:datetimepicker type="time" value="http://www.mamicode.com/8:30" />
另外
displayFormat这个参数好像不能格式化yyyy-MM-dd hh:mm:ss 有待解决
<s:datetimepicker name="date" toggleType="explode" toggleDuration="400" displayFormat="yyyy-MM-dd hh:mm:ss" id="object_createdate" value="http://www.mamicode.com/today">
</s:datetimepicker>
--树 action类+ js上的组件 <s:tree id="myTree" theme="ajax" rootNode="rootNode" nodeTitleProperty="nodeName" nodeIdProperty="nodeId" childCollectionProperty="nodes"> </s:tree> action类上: public String execute() throws Exception { rootNode = new Nodes();//创建根元素 rootNode.setNodeId(1); rootNode.setNodeName("中信软件教育"); Nodes[] rootChild = new Nodes[2]; Nodes node = null; //二级节点 node = new Nodes(); node.setNodeId(2); node.setNodeName("教学部"); Nodes[] childNodes = new Nodes[2]; //三级节点 Nodes child = new Nodes(); child.setNodeId(4); child.setNodeName("马凯"); childNodes[0] = child; child = new Nodes(); child.setNodeId(5); child.setNodeName("DragLong"); childNodes[1] = child; node.setNodes(childNodes); rootChild[0] = node; node = new Nodes(); node.setNodeId(3); node.setNodeName("教务部"); childNodes = new Nodes[2]; //三级节点 child = new Nodes(); child.setNodeId(6); child.setNodeName("刘姥姥"); childNodes[0] = child; child = new Nodes(); child.setNodeId(7); child.setNodeName("邓艾接"); childNodes[1] = child; node.setNodes(childNodes); rootChild[1] = node; rootNode.setNodes(rootChild); return this.SUCCESS; } ------------------------------------------------------------------ JS获取s标签的值: JS获取s:autocompleter的值 使用了s:autocompleter标签,然后用js的方式获取它的值 普通获取值的方法 有些是 document.getElementById("name").value//输入框 或者 document.getElementById("name").innerText //文本 或者 document.getElementById("name").text //下拉框 s:autocomplete为DOJO对象 所以用 dojo.widget.byId(‘name‘); var autoCompleter = dojo.widget.byId("name"); 得到值:dojo.widget.byId("name").getValue(); 设置值:dojo.widget.byId("name").setValue("值"); =============================================================== struts2 配置中文 1:在web.xml中 <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class> //这以下是加入<init-param>: <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> 2:在struts.xml中 <constant name="struts.local" value="http://www.mamicode.com/zh_CN"></constant> <constant name="struts.i18n.encoding" value="http://www.mamicode.com/UTF-8"></constant> ------------------------------------------------------------------------------------------------------------------------------------------------ Struts 2.0+spring 整合还需要一个扩展包:struts2-spring-plugin-2.0.14.jar 在web.xml中 <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/action-spring.xml</param-value>//当然也可以写在applicationContext.xml </context-param> 在action-spring.xml中 <bean id="loginAction" class="cn.com.csuinfosoft.action.LoginAction" scope="prototype"> </bean>//scope="prototype"一定要配置成多例 ---------------------------------------------------------- 如果没有配置scope=prototype则操作的时候不会新建一个action,他任然会保留上次访问的过记录的信息。以前错的,它同样会报错 ,它会一直停留在上次的访问记录不变 ---------------------------------------------------------- struts.xml中的配置 <constant name="objectFactory" value="http://www.mamicode.com/spring"></constant>//全局的参数,告诉struts框架对象的创建由 spring创建 <action name="login" class="loginAction"> class对应action-spring.xml <bean id="loginAction"... <result name="success">index.jsp</result> <result name="input">login.jsp</result> </action> ---------------------------------------------------------- 错误情况: 配置时,出现的错误: Unable to load bean: type: class:com.opensymphony.xwork2.ObjectFactory - bean - jar:file:/。。。。 出现这种错误时,就要注意了,是否是struts2-core-2.0.14.jar 包的冲突~! 可能tomcat lib中有struts2-core-2.0.14.jar 和webapps项目中的 ib中的此包冲突。 或者是tomcat webapps 目录下,有多个项目,可能有项目中的lib中包含有相同的struts2-core-2.0.14.jar,这样也会报冲突的~! 去掉其他,只剩下你的项目lib中含有struts2-core-2.0.14.jar 即可~! ---------------------------------------------------------------------------------------------------------------------- 错误情况: 我们都知道~Spring中实现dao方法都是要,在action中提供set方法。有时我们也会带上get方法,因为有时它的出现无所谓,不会影响什么。。 可是,当你在改action中通过struts2的json方法返回时,会发现报: java.sql.SQLException: 访问层需要具体实施: getConnectionPoolInfo …… 原因是:该json返回是视action的里的get方法的。。getdao类的方法也会被视为返回数据,造成错误的产生!
-----------------------------------------------------------------------------------------------------------------------------------【转】
Struts 2.0全面分析
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。