作者:隔壁老王(wallimn.iteye.com),本人原创,欢迎转载,转载请保留此信息。2010-06-25
刚开始用struts2.1.8、Hibernate3.5.3,不断地遇到问题、解决问题。学新东西还是让人痛并快乐着。
把一些东西记录下来,希望对其它朋友有所帮助。
(一)validateXxx返回不同的input页面
多数人会采用一个类多个方法的方式,如果多个方法都需要输入验证,验证失败时应该会返回各自不同的输入页面,而struts默认会返回统一的input页面。就显然不能满足应用的要求。
解决方法:
让Action实现ValidationWorkflowAware 接口,为getInputResultName()方法设置合适的返回值。
可以通过查看com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor的源码搞清楚其原理。
也有人说可以用注释的方法:
public class DownloadController extends ActionSupport {
@InputConfig(methodName="inputIndex")
//@InputConfig(resultName="input")
public String index() {
System.out.println("-------index-----------");
return "xx";
}
public void validateIndex() {
addFieldError("hell", ".my hello.");
System.out.println("ok");
}
public string inputIndex() {
return "input";
}
}
(二)使用beanutils.populate把request中的parameter转移到bean中时,日期格式字符串的处理
beanutils.populate方法,可以把提交的表单中的内容自动装配到bean实例中,非常的方便。
最新版本的beanutils包提供了功能更强的自动转换功能。一般情况下,对于含有日期类型的bean,通过日期选择控件,可以限制用户的输入要么满足yyyy-MM-dd的形式,要么为空。但是,当用户上传的日期字符串为空串的时候,会引发异常。
这可以通过自定义转换器的方式来解决。
/**
*
*/
package com.wallimn.common.util;
import java.util.Date;
import org.apache.commons.beanutils.converters.DateTimeConverter;
/**
* <br/>
* 编码:wallimn 时间:2010-6-24 下午05:36:24<br/>
* 版本:V1.0<br/>
*/
public class MyDateConverter extends DateTimeConverter {
/* (non-Javadoc)
* @see org.apache.commons.beanutils.converters.AbstractConverter#getDefaultType()
*/
@SuppressWarnings("unchecked")
@Override
protected Class getDefaultType() {
return Date.class;
}
@SuppressWarnings("unchecked")
@Override
protected Object convertToType(Class targetType, Object value)
throws Exception {
if(value==null || "".equals(value)){
return null;
}
return super.convertToType(targetType, value);
}
public MyDateConverter(){
super();
}
public MyDateConverter(Object defaultValue){
super(defaultValue);
}
}
注册方法:
static {
MyDateConverter d = new MyDateConverter ();
String[] datePattern = { "yyyy-mm-dd", "yyyy/mm/dd", "yyyy.mm.dd" };
d.setPatterns(datePattern);
ConvertUtils.register(d, java.util.Date.class);
}
这样就可以把日期字符串取到bean对象里了,空串也不会引发异常。
public static void populate(HttpServletRequest request, Object obj) {
Map map = request.getParameterMap();
try {
BeanUtils.populate(obj, map);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
(三)xwork2.1.6的jar包、源码、文档下载地址:
http://release.opensymphony.com/xwork/2.1.6/xwork-assembly-2.1.6-all.zip
我估计:命名很规范,以后再出新版本,可以把上面的数字改一下。
(四)1Action多个方法(method)的相关问题
目前遇到这样几个问题:
每个方法各自进行输入校验,校验失败返回各自输入页面(如前所述,Action要实现接口:ValidationWorkflowAware);
token拦截器只拦截特定方法;
以上几个问题可以通过参数配置来解决,当然Action要提供相关参数的get、set方法。
<?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="com.wallimn.action.sys" namespace="/pages/sys" extends="wallimn">
<action name="User_*" method="{1}" class="com.wallimn.action.sys.UserAction">
<param name="methodName">{1}</param>
<param name="inputResultName">{1}_input</param>
<!-- 定义不同方法的输入、返回页面 -->
<param name="methodSuccessResultName">{1}_success</param>
<param name="methodErrorResultName">{1}_error</param>
<param name="methodInputResultName">{1}_input</param>
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="token">
<param name="sys_token"/>
<!-- 逗号分隔,可以对指定的多个方法进行重复提交检验 -->
<param name="includeMethods">register</param>
</interceptor-ref>
<result>/pages/sys/login.jsp</result>
<result name="login_input">/pages/sys/login.jsp</result>
<result name="login_success">/pages/sys/login_success.jsp</result>
</action>
<action name="Sys_*" class="com.wallimn.action.GeneralAction">
<result>/pages/sys/{1}.jsp</result>
</action>
</package>
</struts>
(四)自定义一个既可以返回XML结果也可以返回json结果的struts结果类型
struts2自带了一个json结果类型,没有一个直接xml结果类型,自己写一个,试验了一下,效果还不错。xml类型的结果,我主要是在dhtmlXTree控件中使用。
类定义
package com.wallimn.common.util;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.dispatcher.StrutsResultSupport;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.util.ValueStack;
/**
* 可以是XML,或者json文本<br/>
* 编码:wallimn 时间:2010-6-29 下午05:11:25<br/>
* 版本:V1.0<br/>
*/
public class AjaxResult extends StrutsResultSupport {
/**
* 说明:<br/>
* 时间:2010 下午05:11:48
*/
private static final long serialVersionUID = -1253157812823444791L;
public AjaxResult(){
super();
}
public AjaxResult(String location){
super(location);
}
private String contentType="text/xml;charset=UTF-8";
private String xmlHead=null;
private String charset="UTF-8";
private String nocache="true";
/**
* 标识内容的key
*/
public final String KEY_CONTENT="ajax.resultstring.by.wallimn";
/**
* 控制是否添加xml文件的头
*/
public final String KEY_ADDXMLHEAD="ajax.addxmlhead.by.wallimn";
/* (non-Javadoc)
* @see org.apache.struts2.dispatcher.StrutsResultSupport#doExecute(java.lang.String, com.opensymphony.xwork2.ActionInvocation)
*/
@Override
protected void doExecute(String finalLocation, ActionInvocation invocation)
throws Exception {
HttpServletResponse response = (HttpServletResponse) invocation.getInvocationContext().get(HTTP_RESPONSE);
PrintWriter pw = response.getWriter();
resolveParamsFromStack(invocation.getStack());
response.setContentType(contentType);
response.setCharacterEncoding(charset);
if(!"false".equals(nocache)){
response.setHeader("pragma", "no-cache");
response.setHeader("cache-control", "no-cache");
response.setHeader("expires", "0");
}
if(xmlHead!=null && !"".equals(xmlHead)){
Boolean bAddHead = (Boolean) invocation.getInvocationContext().get(KEY_ADDXMLHEAD);
if(bAddHead!=Boolean.FALSE){
pw.println(xmlHead);
}
}
String resultString = (String) invocation.getInvocationContext().get(KEY_CONTENT);
pw.println(resultString);
response.getWriter().flush();
}
protected void resolveParamsFromStack(ValueStack stack){
String contentType = stack.findString("contentType");
if(contentType!=null){
this.setContentType(contentType);
}
String charset = stack.findString("charset");
if(charset!=null){
this.setCharset(charset);
}
String xmlHead = stack.findString("xmlHead");
if(xmlHead!=null){
this.setXmlHead(xmlHead);
}
String nocache = stack.findString("nocache");
if(xmlHead!=null){
this.setNocache(nocache);
}
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
public String getContentType() {
return contentType;
}
public void setCharset(String charset) {
this.charset = charset;
}
public String getCharset() {
return charset;
}
public void setXmlHead(String xmlHead) {
this.xmlHead = xmlHead;
}
public String getXmlHead() {
return xmlHead;
}
public void setNocache(String nocache) {
this.nocache = nocache;
}
public String getNocache() {
return nocache;
}
}
配制文件
<package name="wpsystem" namespace="/" extends="struts-default">
<result-types>
<result-type name="ajaxResult" class="com.wallimn.common.util.AjaxResult"></result-type>
</result-types>
<global-results>
<result name="ajax.xml" type="ajaxResult">
<param name="contentType">text/xml;charset=UTF-8</param>
<param name="xmlHead"><?xml version="1.0" encoding="UTF-8" ?></param>
</result>
<result name="ajax.json" type="ajaxResult">
<param name="contentType">text/plain;charset=UTF-8</param>
</result>
</global-results>
</package>
使用方法很简单
public String unittreexml() throws Exception{
String xml = "XML字符串";
ActionContext.getContext().put(KEY_CONTENT,xml);
return "ajax.xml";
}
public String json() throws Exception{
ActionContext.getContext().put(KEY_CONTENT,"{email:'[email protected]',name:'wallimn'}");
return "ajax.json";
}
(五)获得request、response的方法
直接获取的方法:
HttpServletRequest request = ServletActionContext.getRequest ();
//或者:
ActionContext ct= ActionContext.getContext() ;
HttpServletRequest request=
(HttpServletRequest)ct.get(ServletActionContext.HTTP_REQUEST);
或者使用IOC方法:
第一步:让action实现ServletRequestAware接口
第二步:在action中声明一个HttpServletRequest类型的实例变量
第三步:在action中实现ServletRequestAware接口的setServletRequest方法,实现方式很简单,如下所示。
private HttpServletRequest request;
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
对于response处理是类似的。
(六)上传文件过大的问题:
配置struts.multipart.maxSize项为你想要的大小.
默认2097152,即2M(2097152/1024/1024);
可修改struts.xml文件,加入常量
<constant name="struts.multipart.maxSize" value="10000000" />