Struts的最佳实践
Build the best performing large applications
译者:下面的实践在现在看来有些可能并不是最佳,译出来主要是供大家参考。
带动态域的屏幕(Screen with dynamic fields)
Form bean必须为在JSP中的每个域提供getter和setter方法,问题是如何为动态域写这些方法。
Struts best practice:
可能的解决方案:
ü 让JSP页面的域是指定的方式,例如field1,field2,field3等等,在form bean中提供他们的getter和setter方法,能够出现在页面的域的数量不能多于form bean中的变量的数量
ü 为在JSP页面中的所有动态域利用在form bean中的可用的被索引的getter和setter方法。
第二种方法中,在JSP中增加域的数量不需要在任何组件中进行修改;因此,这是推荐的最佳实现。实现细节如下:
1. 假设一个带在form bean中所有的动态域资源ID的字符串数组,JSP页面可以这样写:
<logic:iterate name= "FormName" property="propertyName" indexId="abc" > <html:nested property='dynaProperty(<bean:write name="abc")'/> </logic:iterate> |
2. 在form bean中声明两个方法,如下所示。这些方法会作为JSP页面中所有的动态域的getter和setter方法。在上面的JSP页面中dynaProperty在()中出现的被作为key,从form bean的getDynaproperty()或setDynaProperty()方法调用。这些值应该被存在HashMap对应的key中,以后在Action类中可以通过对应的值从HashMap取出来。
public class testVarForm extends ActionForm { private HashMap hMap = new HashMap();
public testVarForm() { } public void setDynaProperty(String key, Object value) { this.hMap.put(key, value); } public Object getDynaProperty(String key) { return this.hMap.get(key); } public HashMap getHashMap() { return this.hMap; } public void setHashMap(HashMap newHMap) { this.hMap =newHMap; } } |
保护JSP页面(Safeguarding JSP pages)
防止查看源码,直接访问JSP。
Struts最佳实践
ü 不要让用户直接访问任何JSP页面,起始页可以是HTML文档。在web.xml中增加下面的行来阻止用户直接访问JSP页面。
<web-app>
...
<security-constraint>
<web-resource-collection>
<web-resource-name>no_access</web-resource-name>
<url-pattern>*.jsp</url-pattern>
</web-resource-collection>
<auth-constraint/>
</security-constraint>
...
</web-app>
|
ü 最常见的选择是把JSP页面藏在WEB-INF文件夹的后面。这只能算一种折衷方案。例如,你不能把javascript/css文件隐藏在WEB-INF后面,并且如果你使用Struts组件,可能还会遇到一些上下文相关的问题。
第二种方法允许一些JSP页面(那些不能被放在WEB-INF后面的)直接可见。不要求描述文件,因而,最佳实践是把页面放在WEB-INF后面。
错误分类(Error categorization)
在N层应用中错误处理变得复杂。在基于浏览器的应用中,错误处理可以在客户端使用JavaScript以及在使用专用java方法的WEB层或EJB层。Struts提供了ActionMessages/ActionErrors类来维护需要被报告的错误信息堆栈,能使用<html:error>之类的tag显示给用户的错误信息。问题是用不同的风格,例如error,warning或者information,报告不同类型的错误。
1. 在合适的类别下注册错误
2. 识别这些信息,并且始终如一的显示他们。
Struts最佳实践
Struts的ActionError类方便的解决了不同类型堆栈信息的第一个问题。要显示不同类型的错误信息,在一个接口内定义这些类型,FATAL,ERROR,WARNING,INFO。然后在Action或form bean中,你可以这样使用:
errors.add("fatal", new ActionError("....")); 或 errors.add("error", new ActionError("....")); 或 errors.add("warning", new ActionError("....")); 或 errors.add("information", new ActionError("...."));
saveErrors(request,errors);
|
要根据这些分类来显示,使用下面的代码:
<logic:messagePresent property="error">
<html:messages property="error" id="errMsg" >
<bean:write name="errMsg"/>
</html:messages>
</logic:messagePresent >
或 <logic:messagePresent property="error">
<html:messages property="error" id="errMsg" >
showError('<bean:write name="errMsg"/>'); // JavaScript Function
</html:messages>
</logic:messagePresent >
|
服务请求确认(Validation of service requester)
在基于WEB的应用中,认证可以在任何类中被用到,取决于是否使用的是基于SSO或JAAS机制。这里的挑战是检查服务请求者的真实性和用户Session的有效性。
Struts最佳实践
通常的做法是在HttpSession中保存用户认证后的证书。以后调用在session上下文中的证书来检查。问题是在哪放置这些检查。要考虑性能,应用易于管理和以后的变化。
ü 在做任何操作前对Session context进行验证(在Struts-example.war的CheckLoginTag.java中就是这样做)。
ü 在Action类中进行对Session context的认证。
ü 写执行认证的servlet请求过滤。
ü 扩展RequestProcessor
头两个选择要求每个JSP页面或Action类执行对Session context的认证。接口的变化会导致所有这些JSP页面和类的变动。第三个选项是有效的,但是过度的处理了这个问题。
最佳实践是扩展RequestProcessor,在诸如processActionPerform()或processRoles()的方法中执行认证。
应用安全(Application security)
在WEB应用中的常见的安全需求有页面级、函数级、数据行级和域级。如果设计的不合适,那么引起的不仅是性能问题,还会带来维护的梦魇。
对于上面提到的所有的安全类型,首选的方法是放置安全检查代码在一个类中,而不是在每个组件(例如JSP和Action类)中到处乱放。
Struts为页面级和函数级的安全检查提供了方法processRoles(),然而为列级和域级安全类型什么也没提供,写好他们是大多数Struts使用者的最大挑战。
Struts最佳实践
ü 对于页面级和函数级的安全,继承RequestProcessor覆写processRoles()方法来执行针对保存着角色和页面ID/函数ID映射的HashMap的检查。