作者: 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:ServerTomcat6.0workCatalinalocalhoststruts2_spring3_hibernate3_1.2upload__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
》》》》》》》》》》》》》》》》转载请注明出处《《《《《《《《《《《《《《《《