作者: hzboy192@192.com
Blog: http://my.csdn.net/peng_hao1988
版本总览:http://blog.csdn.net/peng_hao1988/article/details/9026897

实现步骤:

一、国际化
在Struts 2.0中,通过ActionContext.getContext().setLocale(Locale arg)可以设置用户的默认语言。不过,由于这是一个比较普遍的应用场景(Scenario),所以Struts 2.0为您提供了一个名i18n的拦截器(Interceptor),并在默认情况下将其注册到拦截器链(Interceptor chain)中。它的原理为在执行Action方法前,i18n拦截器查找请求中的一个名为"request_locale"的参数。如果其存在,拦截器就将其作为参数实例化Locale对象,并将其设为用户默认的区域(Locale),最后,将此Locale对象保存在session的名为“WW_TRANS_I18N_LOCALE”的属性中。

<!-- 使用HTML标签
<a href="${path }/userManagerAct.action?request_locale=<%=Locale.US%>">English</a>   
<a href="${path }/userManagerAct.action?request_locale=<%=Locale.CHINA%>">中文</a>
-->
<!-- 使用struts2标签  -->
<s:url id="url_en" action="userManagerAct">
	<s:param name="request_locale"><%=Locale.US%></s:param>
</s:url>
<s:a href="%{url_en}">English</s:a>
<s:url id="url_zh" action="userManagerAct">
	<s:param name="request_locale"><%=Locale.CHINA%></s:param>
</s:url>
<s:a href="%{url_zh}">中文</s:a>

如代码所示,在页面定义中英文切换链接,定位到后台任意action,只要满足url的参数中携带request_locale参数及其相应的语言或国家就可实现动态国际,不过还需在struts配置文件中添加struts的国际化配置:

<!-- 资源文件名称的前缀 -->
<constant name="struts.custom.i18n.resources" value="message"></constant>

在classpath下定义国际化资源文件,如 message_en_US.properties,message_zh_CN.properties。这样就可以实现struts2的国际化了。如果想在开发阶段快速对国际化文件修改,可以在配置文件中添加

<!-- 启用不重启载入国际化资源 -->
<constant name="struts.i18n.reload" value="true"/>

二、文件上传
在struts的配置文件中添加如下代码:

<!--
  上传文件的最大值全局参数,指定struts2默认上传文件的最大值 ,此参数值将优先于action中的值执行,所以一边
  这里的值应该大于所有action中配置的值,否则action中大于该值的配置将无意义
-->
<constant name="struts.multipart.maxSize" value="102400000"/>

注意上述配置是配置struts对文件上传的大小限制,这个是全局的,属于框架的一个属性,对于不同的文件上传请求,可以在对应的action中出配置:

<action name="resUpd" class="resumeAct" method="resUpd">
	<!--文件的保存路径,name中的值savePath为action中的一个属性 -->
	<param name="savePath">/upload</param>
	<!-- 默认拦截器中包含了文件上传的拦截器fileUpload拦截器,因此可以修改其默认参数的值 -->
	<interceptor-ref name="MyInterceptors">
		<param name="fileUpload.allowedTypes">
		image/bmp,image/png,image/gif,image/jpg,image/pjpeg,image/jpeg,application/msword
		</param>
		<!-- 此处的参数值作用于当前的action类,单位byte -->
		<param name="fileUpload.maximumSize">4096000</param>
	</interceptor-ref>
	<result name="input">/WEB-INF/jsp/upload_resume.jsp</result>
	<result name="resList" type="redirectAction">resume.action</result>
</action>

jsp页面可以通过<s:file name="intrd"/>定义一个或多个文件上传控件,对应的action中需要定义对应的属性并提供setter方法,就以实例代码为例后台action中需要定义与前提name值intrd一致的属性File intrd,String intrdContentType,String intrdFileName。如果前台定义了多个文件上传控件,将这些属性全部修改为数组即可。如上传多个文件的代码:

public class ResumeManagerAct extends BaseAction {

	private static final long serialVersionUID = 1L;

	private final Logger logger = Logger.getLogger(getClass());

	private ResumeManagerService resService;

	private List<ResumeInfo> resumeList;

	protected final int BUFFER_SIZE = 1024000 * 10;

	private String savePath;

	private File[] intrd;

	private String[] intrdContentType;

	private String[] intrdFileName;

	public String queryResume(){
		resumeList = resService.queryResumes();
		return Global.RESULT_RESUME_LIST;
	}

	/**
	 * 上传文件并保存信息
	 * @return
	 */
	public String resUpd(){
		String sPath = null;
		if(intrdFileName == null){
			this.addFieldError("intrd", getText("please.choose.file"));
			return INPUT;
		}
		try {
			for(int i = 0; i < intrdFileName.length; i++){
				sPath = copyFile(intrd[i], intrdContentType[i], intrdFileName[i]);
				ResumeInfo res = new ResumeInfo();
				res.setId(0);
				res.setTrueName(intrdFileName[i]);
				res.setDocPath(sPath);
				res.setUser((Userinfo)this.sessionGet(Global.SESSION_USER_INFO));
				resService.saveResumes(res);
			}
		} catch (IOException e) {
			logger.error(e);
			addActionError("上传文件失败!");
			return INPUT;
		}
		return Global.RESULT_RESUME_LIST;
	}

	/**
	 * 删除文件
	 * @return
	 */
	public String resDel(){
		Object id = this.requestGetParam("id");
		resService.delResumes(Integer.parseInt(id.toString()));
		return Global.RESULT_RESUME_LIST;
	}

	/**
	 * copy文件
	 * @param sFile
	 * @author porter
	 * @throws IOException
	 * @created 2013-6-14 下午11:42:02
	 */
	private String copyFile(File sFile, String cType, String fileName) throws IOException{
		if(sFile == null)
			return null;
		BufferedInputStream input = null;
		BufferedOutputStream output = null;
		StringBuilder dfPath = new StringBuilder();
		File path = new File(ServletActionContext.getServletContext().getRealPath(savePath));
		if(!path.exists())
			path.mkdirs();
		dfPath.append(path.getPath()).append("\\").append(getNewFileName(fileName));
		File dFile = new File(dfPath.toString());

		input = new BufferedInputStream(new FileInputStream(sFile), BUFFER_SIZE);
		output = new BufferedOutputStream(new FileOutputStream(dFile));
		byte[] b = new byte[BUFFER_SIZE];
		while(input.read(b) > 0){
			output.write(b);
		}
		output.close();
		input.close();
		logger.info("upload file succeed! type : "+intrdContentType+", fileName : "+intrdFileName);
		return dfPath.toString();
	}

	private String getNewFileName(String fname){
		return DateTimeUtil.getNowNoneFmtDateTime()+fname.substring(fname.lastIndexOf("."));
	}

	public ResumeManagerService getResService() {
		return resService;
	}

	public void setResService(ResumeManagerService resService) {
		this.resService = resService;
	}

	public List<ResumeInfo> getResumeList() {
		return resumeList;
	}

	public String getSavePath() {
		return savePath;
	}

	public void setSavePath(String savePath) {
		this.savePath = savePath;
	}

	public void setResumeList(List<ResumeInfo> resumeList) {
		this.resumeList = resumeList;
	}

	public File[] getIntrd() {
		return intrd;
	}

	public void setIntrd(File[] intrd) {
		this.intrd = intrd;
	}

	public String[] getIntrdContentType() {
		return intrdContentType;
	}

	public void setIntrdContentType(String[] intrdContentType) {
		this.intrdContentType = intrdContentType;
	}

	public String[] getIntrdFileName() {
		return intrdFileName;
	}

	public void setIntrdFileName(String[] intrdFileName) {
		this.intrdFileName = intrdFileName;
	}
}

通过上述配置基本可以上传文件了,在上传文件是控制台会打印如下日志:

Mar 20 , 2007 4 : 08 : 43 PM org.apache.struts2.dispatcher.Dispatcher getSaveDir
INFO: Unable to find 'struts.multipart.saveDir' property setting. Defaulting to javax.servlet.context.tempdir
Mar 20 , 2007 4 : 08 : 43 PM org.apache.struts2.interceptor.FileUploadInterceptor intercept
INFO: Removing file intrd D:\Server\Tomcat6.0\work\Catalina\localhost\struts2_spring3_hibernate3_1.2\upload__c2ab6f4_13f431f0155__8000_00000013.tmp 

上述信息告诉我们,struts.multipart.saveDir没有配置。struts.multipart.saveDir用于指定存放临时文件的文件夹,该配置可写在struts.properties或struts.xml文件中。例如,如果在struts.xml文件加入如下代码:

<!-- 上传文件时临时目录的位置 -->
<constant name="struts.multipart.saveDir" value="/tmp"/>

如果上传的文件不符合条件就会异常提示,通过在全局的国际资源文件中加入:

struts.messages.error.content.type.not.allowed=The file you uploaded is not a image
struts.messages.error.file.too.large=File size exceeds the maximum range.

可以实现将异常信息转换成可识别的异常提示。

三、result type redirect与redirect-action区别
1、使用redirect需要后缀名 使用redirect-action不需要后缀名 
2、type="redirect" 的值可以转到其它命名空间下的action,而redirect-action只能转到同一命名空下的 action,因此它可以省略.action的后缀直接写action的名称。

四、文件下载

1.action中的配置

<action name="download" class="com.hzboy.action.FileDownloadAction">
	<result name="success" type="stream">
		<!-- action中必须有一个getTargetFile的方法,且返回值必须是InputStream的 -->
		<param name="inputName">inputStream</param>
		<!-- downloadFileName为action中的属性 -->
		<param name="contentDisposition">attachment;fileName="${trueName}"</param>
		<param name="contentType">application/octet-stream;charset=ISO-8859-1</param>
		<param name="bufferSize">4096</param>
	</result>
	<result name="input">/WEB-INF/jsp/message.jsp</result>
</action>

当result为stream类型时,struts2会自动根据你配置好的参数下载文件。其中主要使用的参数是:
(1).contentType 指定下载文件的文件类型 —— application/octet-stream 表示无限制
(2).inputName 流对象名 —— 比如这里写inputStream,它就会自动去找Action中的getInputStream方法。
(3).contentDisposition 使用经过转码的文件名作为下载文件名 —— 默认格式是attachment;filename="${fileName}",将调用该Action中的getFileName方法。
(4).bufferSize 下载文件的缓冲大小。
2.action中的核心代码:

private String fileName;

private String trueName;

private File file;
private String result = SUCCESS;

@Override
public String execute() throws Exception {
	file = new File(fileName);
	if(!file.exists()){
		result = INPUT;
		this.addActionMessage(getText("file.not.exist"));
	}
	else
		result = SUCCESS;
	return result;
}

public InputStream getInputStream() throws FileNotFoundException{

	return new FileInputStream(file);

}

3.下载是点击取消报异常的解决办法:
http://blog.sina.com.cn/s/blog_a3bf416201014t9r.html.

五、DWR集成

  <servlet>
  	<servlet-name>dwr-invoke</servlet-name>
  	<servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
  	<init-param>
  		<!-- 配置该参数可以用来测试dwr是否配置成功,测试方法http://localhost:8080/projectName/dwr -->
  		<param-name>debug</param-name>
  		<param-value>true</param-value>
  	</init-param>
  </servlet>

  <servlet-mapping>
  	<servlet-name>dwr-invoke</servlet-name>
  	<url-pattern>/dwr/*</url-pattern>
  </servlet-mapping>

在web.xml文件中添加如下配置,如果该文件中配置的struts的url-pattern路径为"/*",就需要在将dwr的url-pattern的值从其中过滤调,否则dwr将无法工作。具体做法是在struts的properties或xml文件中配置struts.action.excludePattern,如:

<!-- 不需要struts控制器处理的URI -->
<constant name="struts.action.excludePattern" value="/dwr/*"></constant>

在WEB-INF目录下添加dwr.xml文件,并配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC
    "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN"
    "http://getahead.ltd.uk/dwr/dwr20.dtd">

<dwr>
	<allow>
		<!-- class:指定一个处理类
		<create creator="new" javascript="check" scope="page">
			<include method="checkUName"/>
            <param name="class" value="com.hzboy.action.UserManagerAct"/>
        </create>
        -->

        <!-- 指定spring容器中的bean,该方法中某些 试图层的方法不能调用,如struts2的getText(String key) -->
        <create javascript="check" creator="spring" scope="page">
        	<include method="checkUName"/>
            <param name="beanName" value="userAct"/>
        </create>

        <!-- 指定struts中的action处理
        <create javascript="check" creator="struts">
        	<include method="checkUName"/>
            <param name="formBean" value="checkName"/>
        </create>
         -->
	</allow>
</dwr>

然后在使用的jsp页面添加如下代码:

<script type="text/javascript" src="dwr/engine.js"></script>
<script type="text/javascript" src="dwr/util.js"></script>
<script type="text/javascript" src="dwr/interface/check.js"></script>

调用方法如下(详细代码请参见示例代码):

check.checkUName(uname,function(rs){
	if(rs == "0"){
		$("#chkMsg").css({"color":"green"});
		$("#chkMsg").text("该用户名可以使用。");
	}else{
		$("#chkMsg").css({"color":"red"});
		$("#chkMsg").text("用户名已存在!");
	}
});

六、异常处理

在struts.xml文件中配置如下代码:

<global-results>
	<result name="exception">/exception.jsp</result>
</global-results>
<global-exception-mappings>
	<!-- 定义异常,及处理页面 -->
	<exception-mapping result="exception" exception="java.lang.Exception"/>
</global-exception-mappings>

其中exception.jsp为自定义的异常处理页面。

示例代码:http://download.csdn.net/detail/peng_hao1988/5869541

》》》》》》》》》》》》》》》》转载请注明出处《《《《《《《《《《《《《《《《



【Struts2+Spring3+Hibernate3】SSH框架整合实现CRUD_1.2的更多相关文章

  1. 【Struts2+Spring3+Hibernate3】SSH框架整合实现CRUD_1.3

    作者: hzboy192@192.com Blog: http://my.csdn.net/peng_hao1988 版本总览:http://blog.csdn.net/peng_hao1988/ar ...

  2. Struts2.0+Spring3+Hibernate3(SSH~Demo)

    Struts2.0+Spring3+Hibernate3(SSH~Demo) 前言:整理一些集成框架,发现网上都是一些半成品,都是共享一部分出来(确实让人很纠结),这是整理了一份SSH的测试案例,完全 ...

  3. SSH框架整合

    SSH框架整合 一.原理图 action:(struts2) 1.获取表单的数据 2.表单的验证,例如非空验证,email验证等 3.调用service,并把数据传递给service Service: ...

  4. Spring+Hibernate+Struts(SSH)框架整合

    SSH框架整合 前言:有人说,现在还是流行主流框架,SSM都出来很久了,更不要说SSH.我不以为然.现在许多公司所用的老项目还是ssh,如果改成流行框架,需要成本.比如金融IT这一块,数据库dao层还 ...

  5. dwr与ssh框架整合教程

    (1)dwr与ssh框架整合教程dwr框架介绍. DWR(Direct Web Remoting)是一个用于改善web页面与Java类交互的远程服务器端Ajax开源框架,可以帮助开 发人员开发包含AJ ...

  6. ssh框架整合之登录以及增删改查

    1.首先阐述一下我用得开发工具,myeclipse2017+oracle,所以我的基本配置步骤可能不一样,下面我用几张图来详解我的开发步骤. ---1先配置structs (Target 选择apac ...

  7. J2EE进阶(十)SSH框架整合常见问题汇总(一)

    SSH框架整合常见问题汇总(一) 前言 以下所列问题具有针对性,但是遇到同类型问题时均可按照此思路进行解决. HTTP Status 404 - No result defined for actio ...

  8. SSH项目整合教学Eclipse搭建SSH(Struts2+Spring3+Hibernate3)

    这篇博文的目的 尝试搭建一个完整的SSH框架项目. 给以后的自己,也给别人一个参考. 读博文前应该注意: 本文提纲:本文通过一个用户注册的实例讲解SSH的整合.创建Struts项目,整合Hiberna ...

  9. Struts2+Spring+Hibernate实现员工管理增删改查功能(一)之ssh框架整合

    前言        转载请标明出处:http://www.cnblogs.com/smfx1314/p/7795837.html 本项目是我写的一个练习,目的是回顾ssh框架的整合以及使用.项目介绍: ...

随机推荐

  1. 【三】用Markdown写blog的常用操作

    本系列有五篇:分别是 [一]Ubuntu14.04+Jekyll+Github Pages搭建静态博客:主要是安装方面 [二]jekyll 的使用 :主要是jekyll的配置 [三]Markdown+ ...

  2. .Net组件程序设计之上下文

    .Net组件程序设计之上下文 在后续篇幅的远程调用的文章里有说到应用程序域,那是大粒度的控制程序集的逻辑存在,那么想对对象的控制又由谁来做主呢?没错了,就是上下文.CLR把应用程序域更细化了,在应用程 ...

  3. IOS开发之Bug--遇到一个类型不确定的bug

    下面的问题不大,是我在开发中遇到的问题: 然后我就google搜一下这个报错 . 下面就解决了:

  4. 关于Android中查看app安装时间等信息的问题

    PackageManager packageManager=this.getPackageManager(); try { PackageInfo packageInfo=packageManager ...

  5. Composer实现PHP中类的自动加载

    本篇博客承接上一篇,学习一下Composer实现的PHP的类的自动加载方式.首先说明一下,Composer是PHP针对PHP语言的第三方的依赖管理工具,将工程所用到的依赖文件包含在composer.j ...

  6. HTMLTestRunner修改Python3的版本

    在拜读虫师大神的Selenium2+Python2.7时,发现生成HTMLTestRunner的测试报告使用的HTMLTestRunner的模块是用的Python2的语法.而我本人比较习惯与Pytho ...

  7. WCF初探-15:WCF操作协定

    前言: 在前面的文章中,我们定义服务协定时,在它的操作方法上都会加上OperationContract特性,此特性属于OperationContractAttribute 类,将OperationCo ...

  8. 获取滚动条ScrollBar宽度

    function getScrollBarWidth () { var inner = document.createElement('p'); inner.style.width = "1 ...

  9. C Looooops(扩展欧几里得)

    C Looooops Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 20128 Accepted: 5405 Descripti ...

  10. android上让我放弃使用wstring来操作中英文字符串 转

    android上让我放弃使用wstring来操作中英文字符串 2013-08-07 16:37:24|  分类: cocos2d|举报|字号 订阅     项目需要,需要对中英文字符串进行遍历修改等, ...