Struts2.1.x、Hibernate3.5.X实战总结

  作者:隔壁老王(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">&lt;?xml version="1.0" encoding="UTF-8" ?&gt;</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" />

你可能感兴趣的:(Ajax,bean,json,xml,struts)