Struts2

Struts2 Architects Guide-Big Picture 简要处理流程 HttpRequest-->ActionContextCleanUp(如果使用到sitemesh)->FilterDispatcher.doFilter(调用ActionMapper)->ActionMapper.getMapping(是否需要调用action处理页面请求)-->Dispatcher.serviceAction(调用ActionProxy包装的Action代理执行action)-->ActionInvocation.invoke(调用所有的before拦截器然后调用action本身的执行方法)-->如果有preresultlistener那么执行beforeResult方法-->ActionInvocation.invoke(执行完action方法本身后会根据action方法返回的resultcode去查找对应的result)-->Render Views(JSP,ftl,etc)-->执行after拦截器-->返回response给浏览器-->如果存在AutoActionContextCleanUp,那么ActionContext推迟到AutoActionContextCleanUp清除,否则有FilterDispatcher自己清除. 系统中的所有对象的创建都是利用ObjectFactory实现的,该接口可以针对不同IOC实现提供不同的实现. 文档中有提到说ActionInvocation中实现了command模式,这点有点看不太懂,难道是迭代那些interceptor的intercept方法就是所谓的命令模式的实现,这个无非就是面向接口编程,难道命令模式本身就没什么内容? 该内容后续将画一个流程图或者时序图,顺便研习一下struts2和xwork的源码. 16:53 浏览 (224) 评论 (0) 分类: struts2学习 2008-03-27 缩略显示Struts2 Core Developers Guide-Cookbook 1.Handling File Uploads 采用FileUploadInterceptor实现文件上传操作. 定义struts.properties文件中的如下属性来实现一下参数的配置 struts.multipart.parser定义解析用户上传文件的库. struts.multipart.saveDir定义用户上传文件保存的路径. struts.multipart.maxSize指定上传文件的最大值设置. 2.HibernateAndSpringEnabledExecuteAndWaitInterceptor 该例子是对ExecuteAndWaitInterceptor的一个扩展 目的是为了让后台线程运行的时候可以获取到hibernate的session中的对象,感觉上和opensessioninview类似. 具体的实现类是OpenSessionExecuteAndWaitInterceptor 重新新的OpenSessionBackgroundProcess类以确保在后台线程执行的过程中,session始终不被关闭,以保证事务. 3.How to validate field formats, such as a phone number 可以利用正则表达式实现 /([/d][/d][/d]/) [/d][/d][/d]-[/d][/d][/d][/d] Phone number must be in the format (XXX) XXX-XXXX 4.如何在jsp页面上访问session,request等对象中的属性 如下 struts2中所有的ognl的对象都默认暴露给jsp或者jstl标记库. 5.Value Stack Internals(值堆栈的内部实现机制) Value本质上就是一个list 在value stack上调用[1]返回是的是从index 1开始的一个子列表,只有调用stack上的peek或者pop等方法才能返回实际stack中的实际对象. 举例如下,假设有一个列表包含了[model,action] [0]返回CompoundRoot对象包含[model,action] [1]返回CompoundRoot对象包含[action] [0].toString()调用value stack上第一个存在toString()方法的对象. [1].foo从调用从action stack上的第一个对象的getFoo()方法, 不会正常工作因为sturts2会把该方法翻译为从堆栈头部开始查找有peek()方法的第一个对象. 在struts2中栈中的对象有 * req - the current HttpServletRequest * res - the current HttpServletResponse * stack - the current OgnlValueStack * ognl - an instance of OgnlTool * ui - a (now deprecated) instance of a ui tag renderer 6.OGNL OGNL规则 假设堆栈中有两个对象foo,bar,foo是堆栈root元素,要获取堆栈中的值可以用如下语法 #foo.blash #bar.blash blash-->foo.bash(由于foo是root元素所以foo和#前缀可以省略. OGNL栈在struts的实现中处于是的栈的root元素 value stack上存储了很多对象,但是对与ognl来说它们看起来就像只有一个对象. 在root元素之外struts2还存储了其他的对象例如session,request等等的对象. 他们之中数值的访问必须加上#session,#request等等前缀. 实际的树状图如下 | |--application | |--session context map---| |--value stack(root) | |--request | |--parameters | |--attr (searches page, request, session, then application scopes) | value stack中的对象有 action对象. 7.Collections (Maps, Lists, Sets)的创建和处理 list: {e1,e2,e3} map: #{key1:value1,key2:value2} 判断集合中是否有某个元素 muhahaha boo muhahaha boo 获取集合的子集 * ? - All elements matching the selection logic * ^ - Only the first element matching the selection logic * $ - Only the last element matching the selection logic person.relatives.{? #this.gender == 'male'} Lambda Expressions 上列语句中[]以内的部分为lambda表达式,#this表示函数的参数 8.在页面上显示action中的bean的值 如果需要显示多个bean的值 The name is: 如果只需要显示单个的值 9.Tabular inputs(批量输入) 如果后台list中item的个数不确定的话可以使用XworkList来代替ArrayList.Xwork中get方法的源码如下 while (index >= this.size()) { try { //todo this.add(objectFactory.buildBean(clazz, null)); //ActionContext.getContext().getContextMap())); } catch (Exception e) { throw new XWorkException(e); } } return super.get(index); 10.HTML form buttons HOWTO [list] Determine Which Button Was Pressed(一个form多个button多个方法) cookbook中列举的例子是利用每个button的name对应一个boolean的属性来解决. 但是在spring+struts的例子中看好像也可以通过如下方式实现 Dynamic Set of Buttons(列表中存在多个submit按钮每个按钮提交到对应的需要修改的对象) 前端

后台 private Map delete = new HashMap(); 提交到id将被提交到后台页面上作为key保留. 该技术可以用于提供批量保存的功能. [/list] 16:12 浏览 (686) 评论 (0) 分类: struts2学习 2008-03-27 缩略显示Struts2 Core Developers Guide-FAQ 1.What are the fundamental differences between Struts and JSF Specifically, JSF is a "component" framework whereas Struts is an "action" framework. 总的来说,JSF,asp.net这种框架采用的是一种,类似于cs架构中的组件式,基于组建事件的编程风格. 而struts事基于action的框架,这里的action对于http来说应该可以理解为url,或者说是REST中的资源路径. 2.如何在页面上直接从流中显示图片. faq中居然自己写了一个MyActionResult类实现,一看日期居然是2006-7-22,好像在struts2中可以直接通过streamresult指定contenttype为image/jpeg,image/gif来实现了. 3.How can we return a text string as the response faq中描述可以利用streamresult在stream中加入text信息来解决.但是这个给人感觉比较奇怪./ 4.How can we test applications? 原则,尽量把一些业务逻辑代码移到facade层中,保持action类中的代码量尽量少这样就可以通过测试,facade来覆盖大部分的系统功能. 另外faq中推荐了一种Selenium工具来进行UI测试. 5.How can we test Actions 直接创建并且调用action对象的方法. 通过ActionProxyFactory包装后调用,这样可以调用测试拦截器和result的运行结果是否正确. 6.如何处理文件上传的请求. 建议的方式是采用fileuploadinterceptor,可以实现多文件上传功能 代码如下
public void setMyDoc(File[] myDocs) public void setMyDocContentType(String[] contentTypes) public void setMyDocFileName(String[] fileNames) 7.How can we force the Action Mappings (struts.xml) to reload devMode=true或者struts.configuration.xml.reload=true 8.如何分割struts配置文件 .... 可以加载单个jar文件中的struts.xml配置文件. 9.Parameters in configuration results result中的location属性支持ognl表达式,所以可以通过其实现结果的参数化. .... otherAction?id=${id} ${redirectURL} ... .... 不过需要对应的action方法中有getId和getRedirectURL方法. 10.运行时获取session Map attibutes = ActionContext.getContext().getSession(); 或者实现SessionAware并且加入servlet-config拦截器. 11.运行时获取request HttpServletRequest request = ServletActionContext.getRequest(); 或者实现ServletRequestAware并且加入servlet-config拦截器. 12.运行时获取response HttpServletResponse response = ServletActionContext.getResponse() 或者实现ServletResponseAware并且加入servlet-config拦截器. 13.获取提交的request parameters Map parameters = ActionContext.getContext().getParameters(); 实现ParameterAware并且加入servlet-config拦截器. 14.访问action配置中定义的参数 直接在action中定义对应action中参数名的settermethod,或者定义setParams(Map)来实现. 15.Can we access an Action's Result Map resultsMap = invocation.getProxy().getConfig().getResults(); 16.How do I obtain security details (JAAS) 从request中获取 HttpServletRequest request = ServletActionContext.getRequest(); String authType = request.getAuthType(); // http or https String user = request.getRemoteUser(); // the user principal (in string) Principalprincipal = request.getUserPrincipal(); // get a Principal object bool isAuth = request.isUserInRole("patrick"); 实现PrincipalAware并且加入servlet-config拦截器 通过调用PrincipalProxy的同名方法实现. 17.如何改变页面的主题(theme) 由于value支持ognl所以也可以写成 18.Why isn't our Prepare interceptor being executed Prepare 拦截器最好在validation拦截器之前,否则可能被打断. 19.Why doesn't my setter get called ? getter和setter操作的数据类型必须一直,否则ognl会忽略. 20.How do we repopulate controls when validation fails faq中提示采用preparable接口和action标记实现,但是感觉ConversionErrorInterceptor也可以实现相同的功能 21.如何测试校验信息 public class WebLoginActionTest extends TestCase { private WebLoginAction wla; protected void setUp() throws Exception { wla = new WebLoginAction(); wla.setJ_username(""); wla.setJ_password(null); super.setUp(); } public void testWebLoginActionValidation() throws ValidationException { ActionValidatorManager avm = ActionValidatorManagerFactory.getInstance(); avm.validate(wla,""); Map fieldErrors = wla.getFieldErrors(); assertTrue(wla.hasErrors()); assertEquals(2, fieldErrors.size()); assertTrue(fieldErrors.containsKey("j_username")); assertTrue(fieldErrors.containsKey("j_password")); System.out.println("[errors] : " + fieldErrors.toString()); } } 22.为什么使用CDATA时有些消息会被忽略. 确保 <#assign mm="getText('"+parameters.label?html+"')" /><#t/> ${stack.findValue(mm)}:<#t/> or ${stack.findValue("getText('"+parameters.label?html+"')")} After making the change, tags with a label attribute will use the value you set as a key. 26.Can I add I18N outside the Action's context 可以通过如下的标签来实现对应的properties文件的加载以便在为调用action的情况下使用resource bundle.

" alt=""/>

27.How to escape special chars in resource bundles 如何在resource文件中转义特殊字符 The special chars /', { and }: escape ' with another ' '' (double-single quote) escape / with another / // (double backslash) enclose } with ' '}' enclose { with ' '{' 28.How do I change the invalid input error message for a particular field 如何修改某个字段的错误信息 invalid.fieldvalue.user.dob=Please enter Date of Birth in the correct format. 29.为jsp页面添加jsp标签的支持 在web.xml中添加如下定义 jspSupportServlet org.apache.struts2.views.JspSupportServlet 10 30.Can an action tag run another method apart from the default execute method 可以采用action别名来实现该需求. 11:13 浏览 (363) 评论 (0) 分类: struts2学习 2008-03-25 缩略显示Struts2 Core Developers Guide-Type Conversion 1.Overview 类型转化在struts2中的主要作用是把页面上符合ognl定义的控件的名字的输入值映射到action的相应字段中.以删除在servlet时代需要经常做的request.getParameter操作,并且利用ognl表达式甚至可以直接把页面上字段的值直接注入到action声明的对象中,是这个过程能够自动化,使得代码更加的简洁,更OO,可以说hibernate是处理对象到数据库的双向转化,struts2就是处理对象到html页面的双向转化. 2.Working Sample [list] Action以及字段级别的类型转化在action对应的目录下定义ActionClassName-conversion.properties point = com.acme.PointConverter 全局以及类级别的类型转化 xwork-conversion.properties在classpath com.acme.Point = com.acme.PointConverter PointConverter必须实现TypeConverter或者直接继承StrutsTypeConverter类. 并且实现如下的双向转化 public abstract Object convertFromString(Map context, String[] values, Class toClass); public abstract String convertToString(Map context, Object o); 该接口中还有个performFallbackConversion 方法,用来实现转化失败后的一些必要的操作. 当转化出现错误的时候需要抛出 XWorkException或者TypeConversionException以便struts2可以捕获该异常. [/list] 3.Built in Type Conversion Support(内建的转化) String boolean / Boolean char / Character int / Integer, float / Float, long / Long, double / Double dates arrays 数组数据可以单个转化数据 collections 如果不能确定collection中的元素的类型,默认传见一个String的ArrayList. 4.Relationship to Parameter Names 类型转化的最佳利用方式是直接在页面上定义user.name这样就能把input的数据直接注入到action.getUser().setName()方法中. Use complex OGNL expressions--struts2能够自动处理对象的创建,而不用手工的创建嵌套对象. Ognl语法支持创建带有不带参数构造函数的对象. user.name会调用getUser().setName()但是如果user为空,那么action还必须具有setUser方法. For lists and maps, use index notation, such as people[0].name or friends['patrick'].name. 对于多选框,如果定义问people.name 则系统会自动传见多个person对象并且注入name属性. 5.Creating a Type Converter 继承StrutsTypeConverter类,实现to,from双向转化操作并且通过ActionClassName-conversion.properties或者全局xwork-conversion.properties中加载改converter即可. 6.Advanced Type Conversion(高级类型转化) Null Property Handling(空指针处理)--自动对象嵌套关系创建. 实现规则 当ognl抛出空指针异常后,struts2能捕获该异常,并且自动创建相应的对象. 如果属性被声明为Collection or List,创建ArrayList并注入. 如果声明为Map,创建HashMap并且注入. 如果是javabean并且具有无参数构造函数,系统会利用ObjectFactory.buildBean方法创建该对象. 流程如下 person.name-->setUsers()-->getUsers().setName() 7.Collection and Map Support [list] 系统支持在定义list或者collection中的对象类型.通过在Class-conversion.properties 定义Element_xxx=Class(xxx表示action中对应的字段名),美来定义action中的对象类型. 可以通过annotation来支持上面的Element_xxx定义. 定义集合索引方式. 在配置文件中定义KeyProperty_xxx=yyy xxx是集合字段的名字,yyy集合中类的某个需要当作索引的属性.下列举例 MyAction.java /** * @return a Collection of Foo objects */ public Collection getFooCollection() { return foo; } foo.java /** * @return a unique identifier */ public Long getId() { return id; } 在文件MyAction-conversion.properties中定义 KeyProperty_fooCollection=id fooCollection(22)将代表fooCollection中id为22,foo对象. 通过fooCollection(22).name可以直接设置该对象的其他属性的值. fooCollection(22)如果返回空值,不会自动创建该对象,可以通过fooCollection.makeNew[0]=Phil直接创建该对象,如果该写法用于Set那么必须定义foo对象的equal和hashCode并且包含id之外的字段,以防止Set删除id字段为null的元素. 类型转化着部分处理的代码感觉和ognl结合的比较紧密,需要结合ognl来研习. [/list] 8.Type Conversion Error Handling 类型转化错误提供了一种方式以区分用户输入错误和,输入类型转化错误. 所有的类型转化错误的提示信息的格式可以通过重写xwork.default.invalid.fieldvalue来修改. 也可以修改通过在Action.properties定义invalid.fieldvalue.xxx(xxx是字段名)来修改所需要显示的类型转化错误的信息. 显示该错误信息的途径有 Globally, using the Conversion Error Interceptor 在validator文件中定义conversion validator来显示. 16:50 浏览 (434) 评论 (0) 分类: struts2学习 2008-03-25 缩略显示Struts2 Core Developers Guide-Localization 1.Overview 支持国际化的模块: 1. the UI Tags 2. Messages and Errors from the ValidationAware interface (implemented by ActionSupport and ValidationAwareSupport) 3. Within action classes that extend ActionSupport through the getText() method 2.Resource Bundle Search Order(Resouce文件搜索规则) 1. ActionClass.properties 2. BaseClass.properties (all the way to Object.properties) 3. Interface.properties (every interface and sub-interface) 4. ModelDriven's model (if implements ModelDriven), for the model object repeat from 1 5. package.properties (of the directory where class is located and every parent directory all the way to the root directory) 6. search up the i18n message key hierarchy itself 7. global resource properties 规则如下图 Package hierarchy To clarify #5, while traversing the package hierarchy, Struts 2 will look for a file package.properties: com/ acme/ package.properties actions/ package.properties FooAction.java FooAction.properties If FooAction.properties does not exist, com/acme/action/package.properties will be searched for, if not found com/acme/package.properties, if not found com/package.properties, etc. 3.Examples [list] [*] 可以嵌套在ui tags中 [*] [*] 指定显示需要查找的resource bundle的文件. [/list] 4.I18n Interceptor 该拦截器可以在运行过程中改变某个session对应的locale信息,和localization配合以实现internationlization. 5.Global Resources (struts.custom.i18n.resources) in struts.properties 6.由于struts2支持与action相关的resource的定义,导致可以造成会有多个重复的key的存在. 解决该问题的方法是,通过定义ActionSupport.properties in com/opensymphony/xwork2 and put it on your classpath.来实现所有action的key的统一定义.不过这样一来所有的action都必须继承自ActionSupport. 由以上启发,其实也可以自己写一个接口,当作标记接口,所有的action都实现该接口,并且在该接口的文件夹中加入interfacename.properties文件也可以解决该问题. 7.Formatting Dates and Numbers(日期和数字的格式化) [list] struts2其实通过i10n来实现数字和日期的格式化的. 定义日期或者数字显示的格式需要利用ognl表达式的特性. 例子 format.time = {0,time} format.number = {0,number,#0.0##} format.percent = {0,number,##0.00'%'} format.money = {0,number,/u00A4##0.00} 通过s:text标签嵌套需要转化的数字或者日期的值来实现以上数据的格式化. Localizing form data with getText代码示例如下 详细的说明请参考getText in ActionSupport代码中实际调用的方法为 textProvider.getText(String key, String[] args) [/list] 16:48 浏览 (619) 评论 (0) 分类: struts2学习 2008-03-25 缩略显示Struts2 Core Developers Guide-Validation 1.Using Annotations(利用java5的标记实现验证) [list] 该方式的验证必须在class级别上声明@Validation()属性代码如下 @Validation() public class SimpleAnnotationAction extends ActionSupport { } 在字段的setter方法上定义验证的规则 field validation的声明方式 @RequiredFieldValidator(type = ValidatorType.FIELD, message = "You must enter a value for bar.") @IntRangeFieldValidator(type = ValidatorType.FIELD, min = "6", max = "10", message = "bar must be between ${min} and ${max}, current value is ${bar}.") public void setBar(int bar) { this.bar = bar; } plain validation的声明方式 @Validations( requiredFields = {@RequiredFieldValidator(type = ValidatorType.SIMPLE, fieldName = "customfield", message = "You must enter a value for field.")}, requiredStrings = {@RequiredStringValidator(type = ValidatorType.SIMPLE, fieldName = "stringisrequired", message = "You must enter a value for string.")}, emails = { @EmailValidator(type = ValidatorType.SIMPLE, fieldName = "emailaddress", message = "You must enter a value for email.")}, urls = { @UrlValidator(type = ValidatorType.SIMPLE, fieldName = "hreflocation", message = "You must enter a value for email.")}, stringLengthFields = {@StringLengthFieldValidator(type = ValidatorType.SIMPLE, trim = true, minLength="10" , maxLength = "12", fieldName = "needstringlength", message = "You must enter a stringlength.")}, intRangeFields = { @IntRangeFieldValidator(type = ValidatorType.SIMPLE, fieldName = "intfield", min = "6", max = "10", message = "bar must be between ${min} and ${max}, current value is ${bar}.")}, dateRangeFields = {@DateRangeFieldValidator(type = ValidatorType.SIMPLE, fieldName = "datefield", min = "-1", max = "99", message = "bar must be between ${min} and ${max}, current value is ${bar}.")}, expressions = { @ExpressionValidator(expression = "foo > 1", message = "Foo must be greater than Bar 1. Foo = ${foo}, Bar = ${bar}."), @ExpressionValidator(expression = "foo > 2", message = "Foo must be greater than Bar 2. Foo = ${foo}, Bar = ${bar}."), @ExpressionValidator(expression = "foo > 3", message = "Foo must be greater than Bar 3. Foo = ${foo}, Bar = ${bar}."), @ExpressionValidator(expression = "foo > 4", message = "Foo must be greater than Bar 4. Foo = ${foo}, Bar = ${bar}."), @ExpressionValidator(expression = "foo > 5", message = "Foo must be greater than Bar 5. Foo = ${foo}, Bar = ${bar}.") } 采用该方式验证可以减少配置文件的数量但是关于验证错误信息中对localization的支持有待调查。 [/list] 2.Examples(使用用例) [list] Basic Validation 主要一点就是声明validation.xml 文件放在action类的包下,命名规则为 -validation.xml or --validation.xml Client Validation 服务器端的配置代码和Basic Validation的代码一直不同的地方在于在jsp页面上声明s:form标记的时候必须指定 validate="true"属性,并且不支持把namespace写在action上而要直接写在页面的namespace属性上。实际应用如下 not work AJAX Validation 2.0.x版本的ajax验证是和DWR结合的,文档中介绍的是和Dojo结合的版本。 服务器端配置除了Basic Validation,需要在struts.xml文件中加入如下拦截器 在页面上的form标签中加入theme="xhtml"属性并且没有validate="true"属性 在head中加入 在s:submit按钮(可以使其他控件例如bind)中加入validate="true"属性 如果需要进一步使用ajax提交,需要在s:submit,ajaxAfterValidation="true" Setting validate to true in the form tag还是可以打开JavaScript验证,不过该验证会在ajax验证前执行。 工作原理 jsonValidation必须在正常的validation拦截器之后执行。 该拦截器先检查struts.enableJSONValidation属性为true则执行ajax验证。 检查 struts.validateOnly为true并且存在validation错误的时候,把错误信息序列化为JSON 在客户端使用utils.js中StrutsUtils. Include prototype.js,utils.js and validation.js(the one for the theme being used), if you are not using the Dojo plugin. 详细的验证流程参考文档中的处理流程图. Field Validators 这种校验器需要嵌套在标签中使用。 并且可以在field标签中定义多个validator。 该校验器有两种形式还可以使用plain validator中加入fieldname属性来实现这种校验器。 Non Field Validators 该校验器的工作方式如下 Visitor Field Validator 这种vistor用于定义使用某个对象自己的校验器进行数据的校验。 该校验器可以校验对象,数组,结合等等的元素。 context属性用于指定用于验证对象所对应的xml文件名字规则。如果需要验证的对象的名字为User那么寻找的校验文件的路径为User-Context-validation.xml appendPrefix指定是否需要在属性前面添加前缀,前缀为fieldname如果filename为user那么指定appendPrefix后验证的实际字段名就为user.name [/list] 3.Bundled Validators(系统预定义的校验器) [list] conversion validator--ConversionErrorFieldValidator 用于检查所校验的字段是否存在类型转化错误。 可以定义repopulateField用于保留转化错误前的用户输入值。 实现的原理主要是把捕获页面的conversion错误并且获取该字段的错误信息,添加到对应的context中。 repopulateField的实现是定义从context的errors中获取到该字段的用户输入值,并且利用preresultlistener在用户执行完action后,result执行前,改变statck中该value的值为用户错误输入的值。 date validator--DateRangeFieldValidator 用于判断date类型的数据的大小 通过继承AbstractRangeValidator并且date类型的数据实现了Comparable接口来实现多种数据类型的比较。 详细比较代码如下 if ((getMinComparatorValue() != null) && (value.compareTo(getMinComparatorValue()) < 0)) { addFieldError(getFieldName(), object); } // only check for a maximum value if the max parameter is set if ((getMaxComparatorValue() != null) && (value.compareTo(getMaxComparatorValue()) > 0)) { addFieldError(getFieldName(), object); } double validator--DoubleRangeFieldValidator 实现了double类型数值的比较 Inclusive为min =max email validator--EmailValidator 校验email格式是否正确 该校验器其实是继承正则表达式实现的。表达式如下 "//b(^[_A-Za-z0-9-]+(//.[_A-Za-z0-9-]+)*@([A-Za-z0-9-])+(//.[A-Za-z0-9-]+)*((//.[A-Za-z0-9]{2,})|(//.[A-Za-z0-9]{2,}//.[A-Za-z0-9]{2,}))$)//b" expression validator--ExpressionValidator 利用ongl表达式校验field的值。 表达式必须能返回Boolean的值。 fieldexpression validator--FieldExpressionValidator 校验ognl表达式的值,必须指定filedname,并且错误信息是field级别的。 int validator--IntRangeFieldValidator 实现和date一致. regex validator--RegexFieldValidator 利用正则表达式校验某个字段的值。 required validator 验证某个字段非空 requiredstring validator 判断值是否是字符串,而且判断字符串长度是否大于0 stringlength validato 判断字符串的长度范围. url validator--URLValidator 判断字符串格式是否符合url的格式 实际调用TextUtils.verifyUrl方法实现. visitor validator--VisitorFieldValidator 实现上一章节已经讲到这里不在鏊述。 [/list] 4.Registering Validators 通过ValidatorFactory.parseValidators()方法解析加载所有配置文件中有定义的validator,系统只记住validator的名字和对应的实现类的包全路径。 加载过程会寻找的文件如下classpath中的validators.xml,com/opensymphony/xwork2/validator/validators/default.xml,com/opensymphony/xwork2/validator/validators中-validators.xml结尾的所有文件. 5.Turning on Validation(添加验证拦截器) 加入如下拦截器到栈中 6.Defining Validation Rules [list] 校验文件的路径的查找规则 (1)Per Action class: in a file named ActionName-validation.xml (2)Per Action alias: in a file named ActionName-alias-validation.xml (3)以上都找不到则会递归的往对象的继承类或者接口类上一直找到Object.class 代码如下 if (clazz.isInterface()) { for (Class anInterface : clazz.getInterfaces()) { validatorConfigs.addAll(buildValidatorConfigs(anInterface, context, checkFile, checked)); } } else { if (!clazz.equals(Object.class)) { validatorConfigs.addAll(buildValidatorConfigs(clazz.getSuperclass(), context, checkFile, checked)); } } [/list] 7.Localizing and Parameterizing Messages(messae信息的本地化和参数化) validator的message元素可以定义key属性,用户从resource bundle文件中获取消息体, 并且用ognl表达式获取相对应的值. 也可以直接在ognl表达式中用getText方法直接查找resource bundle中的值.例子如下 ${getText("validation.failednotice")}! ${getText("reason")}: ${getText("validation.inputrequired")} 8.Validator Flavour 当校验的信息是针对字段的时候采用field-validator会更加好理解。 9.Short-Circuiting Validator(短路) Plain validator 优先于 field-validator. 校验过程中将先校验Plain validator后校验field-validator. 只要有Plain validator短路,其余的所有validator都不会被校验。 field-validator如果定义了短路属性,只会短相同fieldname的其他校验器,而不会影响到其他field的校验器,包括Plain validator 16:20 浏览 (1105) 评论 (0) 分类: struts2学习 2008-03-25 缩略显示Struts2 Core Developers Guide-PreResultListener 1.主要功能&触发时间 该监听器主要在action的execute方法执行完以后,result.execute()方法执行前调用。 接口如下 public interface PreResultListener { void beforeResult(ActionInvocation invocation, String resultCode); } 在DefaultActionInvocation对应的调用如下 //判断是否还有拦截器未执行,如果还有则继续执行拦截器链 //这里通过把DefaultActionInvocation对象本身往后续拦截器中传递来实现interceptors这个interceptor的迭代。 if (interceptors.hasNext()) { final InterceptorMapping interceptor = (InterceptorMapping) interceptors.next(); UtilTimerStack.profile("interceptor: "+interceptor.getName(), new UtilTimerStack.ProfilingBlock () { public String doProfiling() throws Exception { resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this); return null; } }); } else { //所有拦截器执行完成调用action的执行方法。 resultCode = invokeActionOnly(); } // this is needed because the result will be executed, then control will return to the Interceptor, which will // return above and flow through again //调用preResultListeners的内容 if (!executed) { if (preResultListeners != null) { for (Iterator iterator = preResultListeners.iterator(); iterator.hasNext();) { PreResultListener listener = (PreResultListener) iterator.next(); String _profileKey="preResultListener: "; try { UtilTimerStack.push(_profileKey); listener.beforeResult(this, resultCode); } finally { UtilTimerStack.pop(_profileKey); } } } // now execute the result, if we're supposed to //调用result.execute方法. if (proxy.getExecuteResult()) { executeResult(); } executed = true; } 2.注册方法 通过调用 invocation.addPreResultListener具体代码如下(摘自struts2 docs) public class MyAction extends ActionSupport { ... public String execute() throws Exception { ActionInvocation invocation = ActionContext.getActionInvocation(); invocation.addPreResultListener(new PreResultListener() { public void beforeResult(ActionInvocation invocation, String resultCode) { // perform operation necessary before Result execution } }); } ... } 10:12 浏览 (316) 评论 (0) 分类: struts2学习 2008-03-25 缩略显示Struts2 Core Developers Guide-DispatcherListener 1.主要功能 在Dispatcher对象init或者destroy的时候执行某些代码接口如下 public void dispatcherInitialized(Dispatcher du) { // do something to Dispatcher after it is initialized eg. du.setConfigurationManager(....); } public void dispatcherDestroyed(Dispatcher du) { // do some cleanup after Dispatcher is destroyed. } } 源代码上看只有Dispatcher.init()方法中和WebLogic相关的部分有调用到DispatcherListener的dispatcherInitialized方法,所有感觉该接口不是那么重要的样子。 private void init_CheckWebLogicWorkaround(Container container) { // test whether param-access workaround needs to be enabled if (servletContext != null && servletContext.getServerInfo() != null && servletContext.getServerInfo().indexOf("WebLogic") >= 0) { LOG.info("WebLogic server detected. Enabling Struts parameter access work-around."); paramsWorkaroundEnabled = true; } else { paramsWorkaroundEnabled = "true".equals(container.getInstance(String.class, StrutsConstants.STRUTS_DISPATCHER_PARAMETERSWORKAROUND)); } synchronized(Dispatcher.class) { if (dispatcherListeners.size() > 0) { for (DispatcherListener l : dispatcherListeners) { l.dispatcherInitialized(this); } } } } 10:01 浏览 (168) 评论 (0) 分类: struts2学习 2008-03-24 缩略显示Struts2 Core Developers Guide-Result Types 1.总览 action负责applicate state,result负责view状态的管理。 2.Chain Result 实现类为ActionChainResult.java 主要和ChainInterceptor配合用于Action Chaining 特点是把action的valuestack和prameters往下传。 3.Dispatcher Result [list] 实现类ServletDispatcherResult 可选参数为location(jsp文件的路径),parse(location中的属性是否需要ognl解析,默认为true)。 location的解析通过StrutsResultSupport类的conditionalParse方法实现。 首先判断是否存在PageContext,如果存在则表示页面是跳转,而不是通过action标记include。 其次如果不存在PageContext if (!response.isCommitted() && (request.getAttribute("javax.servlet.include.servlet_path") == null)) 页面跳转,否则页面include。 详细代码需要跟踪学习。 [/list] 4.FreeMarker Result 实现类为FreemarkerResult.java 参数比上一个result多了contentType(定义返回的contentType,默认text/html; location属性可以获取的ftl的相对路径为(1)action对应资源的web路径,action对应的java路径。 writeIfCompleted默认为false,如果true只有不存在ftl解析错误的时候才写入到流中。 5.HttpHeader Result 实现类HttpHeaderResult 直接设置result的status例如404,403等。 可以设置result的headers,headers的值可以用ognl表达式解析。 error可以直接定义httpresponse的错误码. errorMessage设置了error后显示在页面上的错误信息。 6.Redirect Result 实现类ServletRedirectResult.java 主要功能是调用response.sendRedirect方法直接改变浏览器的地址栏信息,所有原先运行的action的信息都会丢失,因此在两个action之间传递值方式只有通过session或者querystring location支持ognl解析. 7.Redirect Action Result 实现类ServletActionRedirectResult继承自ServletRedirectResult 该类利用ActionMapper.getUriFromActionMapping方法解析redirecturl。 关于actonnane,method,namespace的解析和chain result一致,并且支持ognl解析。 和rediract result一样能够提供额外的parameter传递。 8.Stream Result 实现类StreamResult 主要用于向respone直接输入raw格式的数据,用于显示图片以及文件下载等场合。 inputName属性定义了action中对应的inputstream的get方法,支持ognl. contentType ,contentLength,bufferSize不言自明。 contentDispostion属性文件下载是显示另存为的文件名。 9.Velocity Result 实现类VelocityResult 功能和Freemaker类似这里不做介绍. 10.XSL Result 实现类XSLTResult 主要目的是利用xslt模板把action对象转化为xml格式的文档。 个人认为可以利用freemarker文档实现,不用那么费劲用xslt实现。节省学习的成本。 11.PlainText Result 实现类PlainTextResult 相当于把dispather输出的html页面用文本的形式输出. 个人认为可能主要应用于ajax场合。 12.Tiles Plugin 类似jsp页面模板之类的东西,和asp.net的masterpage应该类似,但是现在貌似sitemesh更流行,tiles是struts1时代遗留的东西。不想花时间去研究了。 22:14 浏览 (321) 评论 (0) 分类: struts2学习 2008-03-24 缩略显示Struts2 Core Developers Guide-Action Chaining 1.顾名思义,该功能的主要目的是执行一连串的action方法,并且执行过程中并不进行实际上的页面跳转。 定义action的result type为chain定义 可以定义属性的actionName(所要调用的acton的名字), 定义namespace属性,确定action所属的namespace,skipActions中所有的action都无条件的执行,method属性(定义所调用action对象的方法,默认调用execute). 在ActionChainResult中把前一个action的valuestack,parameter,chain_histroy拷贝到下一个action的的context中。 并且在下一个action的interceptor中加入chaininterceptor可以把上一个action中的对应的properties和parameters拷贝到下一个action中。 该chain类似与把很多action组合成一个时间,这样做不推荐的,推荐使用Redirect Action Result替代该方法。 22:07 浏览 (203) 评论 (0) 分类: struts2学习 2008-03-24 缩略显示Struts Core Developers Guide-Writing Interceptors 1.实现Interceptor interface接口 该接口有三个方法 init() destroy() intercept() 2.线程安全 由于interceptor是单例的,并不向action那样每个request都创建一个一个action对象所以不存在线程同步的问题。 3.继承AbstractInterceptor抽象类 该类实现了默认的init和destroy方法,直接实现intercept方法即可。 17:33 浏览 (154) 评论 (0) 分类: struts2学习 2008-03-24 缩略显示Struts Core Developers Guide-Framework Interceptor Alias Interceptor 用于在ActionChain中的不同action之间传递参数,把相同的参数用不同的别名来命名 #{ 'foo' : 'bar' } foo参数的值将被赋予别名bar Chaining Interceptor 该拦截器把所有value stack上的对象(除了那些实现了Unchainable接口的)拷贝到当前执行对象中(Action).可以定义includes和excludes分别指定需要或者不需要拷贝的参数,该拦截器一般和chain result结合使用.详细配置如下。 otherAction good_result.ftl Checkbox Interceptor 和hiddenfield一起解决checkbox在未选中情况下提交到服务器端时的数据丢失问题。 Cookie Interceptor 顾名思义用于把cookie的值注入到action中,从源代码中得到的规则如下 如果cookieName存在*,并且cookieValue为空或者存在*,注入所有的cookie到action. 如果cookieName为空,不获取和注入任何cookie,即使定义了CookieAware得到的cookiemap也是空的。 如果cookieName不为空其不含有*,那么只注入于cookiename对应的cookie,并且注入前还会根据定义的cookieValue判断是否需要注入该cookiename对应的值。 Conversion Error Interceptor 要想利用该interceptor,action类必须实现ValidationAware接口 把所有conversionErrors转化成对应action的fielderrors。 保存用户提交上来的原始值,通过preresultlistener的处理还原到action的value stack中. Create Session Interceptor 从源码上看除了ServletActionContext.getRequest().getSession(true);这句没有其它的功能了。 DebuggingInterceptor 显示action运行的调试信息有如下调试类型xml,console,command,browser. Execute and Wait Interceptor 用于在后台处理处理需要很长执行时间的请求,用于防止http超时问题。 拦截器必须放在最后 该拦截器实际于session实现的。 主要原理是先返回一个wait结果(如果action为定义wait结果,struts2会利用freemarker自动生成一个wait页面)给浏览器,然后启动一个后台线程单独处理action的请求,等待action请求处理完成后把结果返回给母线程。 action对象会被推入stack的最顶层,使用stack.push方法. 可以定义显示wait页面的延迟时间,如果查询请求并不需要很长时间的话,就不需要显示wait页面。 Exception Interceptor 主要的目的就是把exception转化成result,而不是大expcetion trace直接打印到页面上,一来提高系统的安全性,二来提高用户体验。 当系统捕获异常,系统会利用ExceptionHolder把exception wrap一下推入statck以便resutl页面render的时候可以获取到对应的action的信息,或者直接输入trace。 File Upload Interceptor 基于MultiPartRequestWrapper,用于处理文件上传的请求 获取所有页面上的file字段的文件,并且把这些字段转化设置到request的parameters中,并添加了contenttype和filename属性。对应的setter为fieldNameContentType,fieldNameFileName. I18n Interceptor 设置于用户session相关的locale信息,并且保存该locale信息。 处理流程为先从request_locale=en_US获取locale信息,然后从request的parameters中删除locale信息,并且保存到session中,并应用到所有的request中。 Logger Interceptor 记录action的start和stop信息,只有英文信息,不支持国际化。 Message Store Interceptor 主要功能是为了把action的message和error已经field error存储到session,以供后续的action获取这些信息。 可以定义三种operationmode STORE,RETRIEVE,NONE. RETRIEVE主要通过合并集合和map的方式实现。 Model Driven Interceptor 操作其实很简单,就是调用实现的了ModelDriven接口的Action的getModel方法,然后把getModel返回的对象压栈。 Scoped Model Driven Interceptor 实现该接口的action可以根据scope的定义,直接从objectfactory中初始化对象,对象的标示由name属性决定。 Parameters Interceptor 主要功能是把parametermaps上的param利用OGNL表达式设置到相应stack的action中。 还能设置拒绝设置某些恶意参数例如.,#=,等会影响OGNL执行的参数,已经用户通过实现ParameterNameAware接口定义acceptableParameterName中忽略的参数。 例外还需要的功能包括CreatingNullObjects,DenyMethodExecution,ReportingConversionErrors。 Prepare Interceptor action实现了Preparable接口 调用prepare开头的方法。 调用prepareDo开头的方法. 如果alwaysinvokePrepare设置为true(默认),那名总会调用prepare方法. Scope Interceptor 设计该拦截器的目的是为了利用session,application在多个action之间传递值,以实现类似wizard的导航功能。 可以利用application或session或者同时利用两者传递值。 如果利用session传递,则在传递过程中会为session加锁。 如果action定义该拦截器的属性为start,那么session中对应的property的值会被设置成该action锁对应的属性的值。(sessionReset属性具有一样的效果) 如果action定义该拦截器的属性为end,那么session中对应的properties会被移除。 如果action中为定义任何start,end或者sessionReset属性,那么表示该action处于wizard的中间,action执行前会从session中导入所需要的property的值,action执行完后会把这些值导出到session中。 该interceptor本身实现了PreResultListener接口并且在intercept之后添加自己到action执行完,result render前执行从action中到处property到session或者删除session中的property操作。 Servlet Config Interceptor 用于向实现了特定接口的action中注入和servlet有关的对象,action可以实现的对应接口如下 ServletContextAware,ServletRequestAware,ServletResponseAware,ParameterAware,RequestAware,SessionAware,ApplicationAware,PrincipalAware. Static Parameters Interceptor 把struts.xml中定义的该interceptor的params pair注入对应的action中,并且如果action实现了Parameterizable接口该interceptor也会把该paramsmap通过该接口的setParams注入到对应的action中。 Roles Interceptor 通过该拦截器调用request的isUserInRole方法实现 Timer Interceptor 放回action中的方法执行的时间。 Token Interceptor 用于判断是否重复提交表单。在页面上和token一起使用。 Token Session Interceptor 用于判断是否重复提交表单。在页面上和token一起使用,Token Interceptor的改进版本,当token验证失败的时候会返回上次成功的action的执行结果。 Validation Interceptor 处理表单验证的拦截器,该拦截器一般配置于最后或者倒数第二个action,因为在该拦截器调用前所有的actionproperty需要准备好。 该拦截器支持用户实现Validatable接口的validate方法或者validateXxx,validateDoXxx方法,规则和pareparable一致。 拦截器支持exclude和includemethod方法的配置 Workflow Interceptor 该拦截器的也是为了验证,不过该action只调用那些实现了validatable或者ValidationAware接口的validateXxx,validate,validateDoXxx方法,并且判断是否有某个action,hasErrors()如果有直接打断action chain并且返回Input作为结果。 但是实际代码感觉和文档描述的有点不一致,实际代码只检查实现了ValidationAware的action的hasError方法. Parameter Filter Interceptor 用于过滤哪些参数不需要,那些参数需要注入到action中。 defaultBlock默认为false如果设置成true只有allow列表中的开头的parameter才能注入到action, allow和block的方式都是以字符串开头为规则例如person会block,person.name等等的字段。但是如果allow中定义了person.address那么该parameter可以通过。 Profiling Interceptor 用于打开系统性能检测功能。 MethodFilterInterceptor [list] 所有继承该interceptor的拦截器都可以通过定义excludeMethods ,includeMethods来过滤拦截器需要拦截的方法,文档中解释说includeMethods比较优先,但是从代码上看感觉应该是excludeMethods比较优先,代码如下 if (((excludeMethods.contains("*") && !includeMethods.contains("*")) || excludeMethods.contains(method)) && !includeMethods.contains(method)) { return false; } return includeMethods.size() == 0 || includeMethods.contains(method) || includeMethods.contains("*"); 有空写个测试用例测试一下。 [/list] 16:50 浏览 (386) 评论 (0) 分类: struts2学习 2008-03-21 缩略显示Struts2 Core Developers-Interceptors 1.Understanding Interceptors(理解拦截器的工作原理) 拦截器主要是为了完成action执行前的有些准备工作,以及action完成的有些扫尾工作。 拦截器可以中端action的执行过程。 拦截器定义在拦截器栈中,并且按照一定的顺序执行。 struts2拦截器的调用主要通过ActionProxy所代理的action对象来实现interceptor的调用。 2.Configuring Interceptors login.jsp /secure/home 拦截器可以是包级别或者action级别。并且能够覆盖。 3.Stacking Interceptors 可以参考struts-default.xml中的配置。 4.Framework Interceptors(框架定义好的拦截器) 详细参考struts应用。 Method Filtering 方法过滤 例如validation中可以过滤那些方法需要表单验证,那些方法不需要 Interceptors that extends this capability include: TokenInterceptor TokenSessionStoreInterceptor DefaultWorkflowInterceptor ValidationInterceptor 可以定配置的参数有 excludeMethods - method names to be excluded from interceptor processing includeMethods - method names to be included in interceptor processing 如果一个方法同时存在于以上两个参数则includeMethods优先。 Interceptor Parameter Overriding 重写以上参数的形式有如下两种 myValidationExcludeMethod myWorkflowExcludeMethod myValidationExcudeMethod myWorkflowExcludeMethod 15:42 浏览 (149) 评论 (0) 分类: struts2学习 2008-03-21 缩略显示Struts2 Core Developers Guide-Configuration 1.最初也是最终的理想Zero Configuration 目前主要的原理就是通过java5提供的annotation机制把xml配置移动到实际的代码中,但是我认为这样做的好处有 便于测试,由于不存在xml文件,不需要再为了测试环境编写一分不同的xml配置文件,所有的配置已经都再代码里面了。 目前struts该功能还在测试中,主要是需要通过再web.xml中添加需要扫描的类目录,以及几个和xml文件中的element对应的annotation来实现。 2.Annotation 主要是和zero configuration配合使用。 包含了Action(namespace,parentpackeage,result,resutls) Interceptor(After,Before,BeforeResult) Validator,Type Conversion Annotations. 再xml文件中都能找到对应的映射。 3.Configuration Elements Administrative Elements Bean Configuration 定义某个接口的实现类,然后只要需要再框架内部实现用@Inject标记即可实现该接口对象的注入。 使用static实现把某些特定值注入到某个类的特定方法中,所以如果该属性为true的时候type必须为空。 Constant Configuration 代替struts.properties中的定义修改系统运行时参数。 可以配置的途径除了struts.xml,struts.properties外还有web.xml struts org.apache.struts2.dispatcher.FilterDispatcher struts.devMode true Package Configuration struts,pagckage是配置的最外层元素,我们可以再Package中定义action,interceports等元素, 其中包可以继承,可以abstract(可以不包含实际action). Namespace Configuration 顾名思义该配置主要是为了解决action名字的冲突(例如可能系统很多模块都有menu或者help)action。 默认的namespace是""空串,意味着如果再其他的namespace没有找到对应的action就回直接回到该namespace寻找action, Root Namespace ("/") 该namespace只匹配对应的context根目录的请求,如果其他namespace的action没有找到回直接回到default namespace不会回到该namespace寻找。 Include Configuration 该元素的主要目的就是模块化,把大的配置文件分割为小的配置文件,便于模块化开发。 Interceptor Configuration Interceptor标记是mixed and matched即interceptor-ref既可以ref到interceptor也可以ref到interceptor stack。 应用还可以定义默认的interceptor Action Configuration struts2的核心工作单元,配置某个http请求如何处理。 主要定义的方面如下 action的名称-->页面上请求的url中的.action前面的字符一致。 例如http://myoldman/index/Welcome.action将会对应于系统中 Package namespace 为"index" name为Welcome的action。 利用struts2的form标签可以根据页面上制定的action属性,自动生成对应带后缀的action请求。 如果action带有/则必须在struts.xml文件中加入 . action的对应的处理类 对应的exception handler 对应的interceptors ation method 如果action没有定义method属性,默认的action方法将会是execute()(in the interface Action) action不是必须实现该接口,struts2会根据类反射的方式找到对应的执行方法, 不过如果没有execute方法并且未定义action的method属性,struts2会抛出异常。 Wildcard Method(通配符方法) 通配符号可以作为前缀或后缀 通配符可以扩张到validation,typeconvesion,message file等。 如果一个action元素没有配置任何class,struts2会默认使用ActionSupport作为实现类。 该类实现了一些基本的跳转和方法,例如execute和input等 如果需要自己覆盖默认的class可以利用default-class-ref in package元素来定义。 link to action 尽量使用action跳转到特定的jsp页面而不是直接跳转到某个jsp页面,这样做的好处就是所有的jsp页面都当作view通过action管理,实现mvc2模式。 Default action 可以未package配置一个默认的action,如果struts在应用中找不到任何的action的话,就会去找默认的action,不过如果需要未整个应用定义该效果的话需要在default package上定义一个default-action-ref这样只要未实现的action都会跳转到action执行。 或者也可以使用wildcard default把如下代码放到default package中所有action的最后。 /{1}.jsp 然后往还未实现的jsp页面上加入stub page。 两种reload struts.xml配置文件的方法, struts.configuration.xml.reload=true String execute() { com.opensymphony.xwork.config.ConfigurationManager.destroyConfiguration(); return SUCCESS; } Wildcard Mappings(通配符映射) 如果有两个通配符匹配的话,系统默认选择最后一个匹配。 * Matches zero or more characters excluding the slash ('/') character. ** Matches zero or more characters including the slash ('/') character. /character The backslash character is used as an escape sequence. 其中{N}n从1-9,并且{0}匹配整个url。 Result Configuration 系统预定一的result String SUCCESS = "success"; String NONE = "none"; String ERROR = "error"; String INPUT = "input"; String LOGIN = "login"; 默认resulttype为dispatcher并且默认对应success。 全局result 该定义和package同级别,主要目的是为了所有的包能共享result,例如login失败的跳转等。 Dynamic Results result的location属性可以通过OGNL从action对象上获取 ${nextAction} 如上配置可以通过action中的如小方法获取。 private String nextAction; public String getNextAction() { return nextAction; } Exception Configuration(异常配置) struts2的异常处理通过interceptor实现。如果需要加入的异常处理的话需要加入exception的interceptor。 配置需要捕获的exception和对应需要跳转到的result。 页面上可通过如下的属性输出exception的内容。 exception The exception object itself exceptionStack The value from the stack trace 4.Configuration Files(配置文件) web.xml 定义struts2框架所必须的FilterDispatcher struts.xml Main configuration, contains result/view types, action mappings, interceptors, and so forth struts.properties yes Framework properties可以在struts.xml中通过constance元素替换。 struts-default.xml struts2 jar中自带无需关注。 struts-default.vm yes Default macros referenced by velocity.properties struts-plugin.xml yes At the root of a plugin JAR Optional configuration files for Plugins in the same format as struts.xml. velocity.properties yes /WEB-INF/classes/ Override the default Velocity configuration Static Content struts把一些css和js文件放在了包的static和tempalte目录中。 Performance tuning 关闭logging和devMode 删除不需要要的interceptor 定义正确地http头比如cache expire等 把struts2包中的static信息拷贝到webroot中。 Create a freemarker.properties file in your WEB-INF/classes directory 并且设置template_update_delay=60000 struts默认会间隔500ms检查template是否需要reload。 启用Freemarker template caching struts.freemarker.templatesCache = true; Do not create sessions unless you need them. 如果使用freemarker作为view请直接使用freemark的语法。不要使用OGNL 11:34 浏览 (443) 评论 (0) 分类: struts2学习 2008-03-21 缩略显示Struts2 Core Developers Guide-Develop with struts 1.Ajax集成 struts2集成了对Ajax处理的支持,只需要对resulttype做处如下配置 text/html inputStream 并且struts有多个开源ajax框架的plugins例如Dojo,YUI等。 2.Dependency Injection Dependency Injection是目前几乎所有开发所必须要添加的容器,IOC容器能无缝的在应用系统中把接口与实现联系起来,是的系统中的大部分组件都依赖接口而不是依赖于具体的实现,以提高系统的可维护性。 struts2有自己的IOC容器的实现,该实现于Google guice类似,另外struts2还可以通过插件的方式支持spring,guice等其他IOC容器。 3.Profiling(系统运行监视) struts2可以通过配置虚拟机参数支持监视功能。 通过在tomcat的CATALINA_OPTS中添加 -Dxwork.profile.activate=true 还能结合log4j把系统监视所得的数据以不同的形式输出。 4.Debugging 通过修改struts配置中的struts.devMode = true 打开struts的调试模式,并且通过页面上的在action后加入debug=xml或者debug=console来显示显示系统运行中的各个对象的调试信息。 5.Development Mode 打开该配置后系统会 每个请求都会重新载入resouce bundles-->可以通过struts.i18n.reload = true 单独实现。 每个请求都会重新载入struts.xml配置文件-->可以通过struts.configuration.xml.reload = true单独实现。 会使得某些debug或者可以忽略的问题抛出异常。 由于以上特点,打开该开关会严重影响系统性能,所以在实际生产环境中不要忘记可关闭该开关。 10:45 浏览 (199) 评论 (0) 分类: struts2学习 2008-03-21 缩略显示Struts2 Core Developers Guide-Nutshell(概要) Architecture in a Nutshell(架构概要) request->Servlet filter-->before interceptors->action-->preresultlistener->result->after interceptors-->response 其中核心部分是interceptors,action,result Struts Tags in a nutshell(标记库概要) 标记库存在的主要意义就是减少页面代码,已经封装多个页面html元素到一个标记库中,以求最大化复用性。 Struts Configuration in a Nutshell 主要配置文件集中在struts.xml文件中,该文件主要配置applcation运行interceptors,actions,results等信息。现在可以利用annotation来代替xml文件做配置。 Struts MVC in a Nutshell 分离mvc的职责,让taglib和model承当大部分heavy lifting,control只是承当交通警察的角色(定义处理请求,准备model,处理后跳转请求)。 10:22 浏览 (137) 评论 (0) 分类: struts2学习 2008-03-20 缩略显示Struts2 Core Developers Guide-tutorial 关键字: learning about struts2 1.Dependency of struts2 struts2最小依赖包 struts2-core.jar-->核心包。 xwork.jar-->xwork2依赖库 ognl.jar-->Object Graph Navigation Language(OGNL),el语言库。 freemarker.jar-->大名鼎鼎的模板生成器,文档解释说所有UI tag的模块都是基于该框架处理的。这点需要进一步深入解释。 commons-logging.jar-->log记录框架。 2.configuration of action in struts.xml web.xml-->定义struts映射的filter。这个是所有基于servlet的web框架的切入点。 struts.xml-->定义了struts运行所需要的action,results,拦截器,拦截器堆栈等。 3.How to use tags for render the dynamic data of response.(s:url,s:a,s:textfield,s:password and so on) 这个是所有j2eeweb框架都具有的特性,标签库,主要目的也是为了封装html的语法,简化编写,提高效率。 4.Wildcard mappings by using asterisk(*) and "{1}" grammer. 通配符映射,可以加前缀合或者后缀,该特性可用于灵活的定义action之间的关系,以实现类似与ror似的0配置管理。 5.Coding action and the processing of struts2 framework for http request. 合webwork时代的写法一致。大部分情况下继承于ActionSupport类。并且Action中不暴露任何request,respones相关的信息,完全依赖于struts2利用valuestack把表单的值映射到Action的model中。 6.Select result for after the process of the execute function in action. 这个不用解释了,就是根据action方法中返回的字符串和struts.xml中配置的result决定action处理完某个request后的跳转。success的结果可以不需要在result标记中定义name属性其他的结果都需要定义result的name属性。 7.Including missing page for pages the not yet implemented. 把name="*"的action放到action的最后,并且跳转到于Action名称相对应的页面,并且该页面上如果是一个未完成的页面需要直接include一个missing页面以提醒开发这该页面还未实现。 8.How to validate the input data in the server side. struts2利用xwork的validation库进行表单验证某个action对应的验证xml文件的格式为Actionname-validation.xml或者Actionname-alias-validation.xml其中alias为某个action类在struts配置文件中对应的别名。 9.Localized the message field. 本地化i10n和国际化i18n是目前web应用的都需要考虑的地方,其主要目的是提前考虑到应用系统如何适应多国语言的处理,把页面中所有静态的语言表示都使用使用message.properties文件映射起来。这样对于不同的语言只要相应的添加该语言的properties文件即可,从而不用为某个语言重新开发,测试应用。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值