用户注册



邮箱:

密码:

用户登录


邮箱:

密码:
记住登录一个月忘记密码?

发表随想


还能输入:200字

jun    -  云代码空间

—— 相信 ,梦

strut2(3)

2014-08-12|1791阅||

摘要:1.国际化(了解) 2.拦截器(重点) 3.文件上传与下载(次重点) 4.ognl与valueStack(重点)



==========================================================
1.国际化
1、 国际化原理 ? 什么是国际化 ? 
同一款软件 可以为不同用户,提供不同语言界面  ---- 国际化软件
需要一个语言资源包(很多properties文件,每个properties文件 针对一个国家或者语言 ,通过java程序根据来访者国家语言,自动读取不同properties文件 )

2、 资源包编写 
properties文件命名 :  基本名称_语言(小写)_国家(大写).properties
例如 :
messages_zh_CN.properties 中国中文
messages_en_US.properties 美国英文
3、 ResourceBundle 根据不同Locale(地域信息),读取不同国家 properties文件
ResourceBundle bundle = ResourceBundle.getBundle("messages", Locale.US);

4.国际化可以对日期,货币,动态文本进行操作.
DateFormat
NumberFormat
MessageFormat

5.struts2中的国际化
1.struts2中的国际化properties文件怎样定义(定义的位置)?

1.全局---将资源包放置在src下.
* properties文件可以在任何包中
* 需要在struts.xml 中配置全局信息文件位置 

struts.xml
<constant name="struts.custom.i18n.resources" value="messages"></constant>   messages.properties 在src根目录
<constant name="struts.custom.i18n.resources" value="cn.itcast.resources.messages"></constant>   messages.properties 在 cn.itcast.resources 包




2.针对于包下的Action使用
在所在的包下创建一个package.properties文件.
3.针对于某个Action
在Action类所在的包下创建一个 ActionName.properties
4.针对于某个jsp页面中使用.
引入一个指定的国际化配置文件.需要使用struts2标签
<s:i18n name="cn.itcast.resource.text">
<s:text name="login.message"></s:text>
</s:i18n>


2.struts2中的国际化在哪些位置使用,怎样使用?

1.Action中使用
让Action类继承自ActionSupport类,可以使用它的 getText(String name)
2.视图使用(jsp)
<s:text name=""> 可以直接使用全局的国际化配置文件
3.配置文件(校验的xml文件)
<message key=""/>

问题:怎样控制动态文本
1.Action中操作
this.getText("login.message",new String[]{"用户名"})
2.视图中操作
<s:text name="login.message">
<s:param>username</s:param>
</s:text>

============================================================================================
struts2拦截器(interceptor)

在struts-default.xml文件中有一个<package> 叫struts-default
它里面定义了所有的拦截器。
  <interceptor-stack name="defaultStack">是我们使用的默认的18个拦截器.
  
  关于<interceptor>  <interceptor-stack>标签的作用
<interceptor name=""  class="">它用于声明一个拦截器

<interceptor-stack name=""> 拦截器栈
name属性是代表拦截器栈的名称
它有子元素
<interceptor-ref name="exception"/> 它用于引用一个拦截器.

拦截器作用?
拦截器是在访问Action之间或之后,可以进行一些处理.
它是可插拔式的,采用了AOP思想

AOP---面向切面的编程-----核心思想动态代理.
struts2的拦截器采用了责任链设计模式.

自定义拦截器

1.在struts2框架中所有的拦截器根接口com.opensymphony.xwork2.interceptor.Interceptor.
2.想要让拦截器向下访问通过 String intercept(ActionInvocation invocation) throws Exception;
的参数invocation.invoke()才能向下执行.

案例:权限控制,如果用户没有登录,不能访问操作.
用户登录成功后,将用户存储到session中.

如果用户没有登录,不能访问BookAction中的操作.

可以通过一个自定义的interceptor完成拦截操作.
1.创建一个PrivilegeInterceptor类继承 AbstractInterceptor(这个类是Interceptor接口的实现类)
2.重定方法
public String intercept(ActionInvocation invocation) throws Exception {

//session中存在用户,也就是说,用记登录了。
User user=(User) ServletActionContext.getRequest().getSession().getAttribute("user");

if(user==null){
//没有登录.
return Action.LOGIN;

}

return invocation.invoke();
}
3.将自己的interceptor注入到Action中.

1.声明拦截器---在<package>下
<interceptors>
<interceptor name="privilege" class="cn.itcast.utils.PrivilegeInterceptor" />
</interceptors>
2.在Action中引入拦截器
在<action>标签下
<interceptor-ref name="privilege" /> <!-- 引入一个拦截器 -->

注意:如果在某一个action中显示的声明了一个拦截器,那么默认的18个拦截器失效了。

问题:现在不想对BookAction中的select拦截。
可以通过继承一个MethodFilterInterceptor,它可以控制针对于哪些方法进行拦截.

可以在struts.xml文件中声明拦截器时指定参数来控制哪些方法被拦截,哪些不被拦截
<interceptor name="privilege" class="cn.itcast.utils.PrivilegeInterceptor">
<param name="excludeMethods">select,update</param>
<param name="includeMethods">add,del</param>
</interceptor> <!-- 声明一个拦截器 -->

------------------------------------------------------------------------------
struts2文件上传与下载
1.上传
struts2内置了commons-fileupload插件.
在它默认的18个拦截器中有一个叫fileupload拦截器

在页面上
1.method=post
2.enctype="multipart/form-data"
3.组件要有名称 <input type="file" name="upload">

在Action中
在Action中声明三个属性
private File upload;
private String uploadContentType;
private String uploadFileName;

提供get/set方法。
在execute方法中通过  FileUtils.copyFile(File src,File dest)完成文件复制.

问题:
1.配置input视图来控制上传失败时跳转的页面.

2.在default.properties
# struts.multipart.parser=cos
# struts.multipart.parser=pell
struts.multipart.parser=jakarta  使用的是commons-fileupload插件
用于设置当前上传时所使用的插件.

如果使用cos或pell必须导入相应的插件包

3.限定上传文件大小
通过 struts.multipart.maxSize 常量设置文件上传总大小限制 
* struts.multipart.maxSize=2097152 默认上传文件总大小 2MB 
* 超过文件总大小,跳转input 视图, 通过 <s:actionError /> 回显错误信息 
在struts.xml 设置上传总大小
<constant name="struts.multipart.maxSize" value="20000000"></constant>

4.针对fileupload拦截器进行配置,也可以限定文件上传操作

在FileUploadInterceptor中有三个属性
protected Long maximumSize;  限定每一个上传文件大小
protected Set<String> allowedTypesSet = Collections.emptySet();  限定上传文件的MimeType类型
protected Set<String> allowedExtensionsSet = Collections.emptySet();  限定上传文件的后缀名


怎样设置这些属性?
<interceptor-ref name="defaultStack">
<param name="fileUpload.maximumSize">20971520</param>
<param name="fileUpload.allowedExtensions">txt,jpg</param>
</interceptor-ref>

5.对错误信息进行国际化操作
1.针对于Action创建一个properties文件.
2.错误信息模板
配置如下:
struts.messages.error.uploading=Error uploading: {0}
struts.messages.error.file.too.large=File too large: {0} "{1}" "{2}" {3}
struts.messages.error.content.type.not.allowed=Content-Type not allowed: {0} "{1}" "{2}" {3}
struts.messages.error.file.extension.not.allowed=File extension not allowed: {0} "{1}" "{2}" {3}
{0}:<input type=“file” name=“uploadImage”>中name属性的值
{1}:上传文件的真实名称
{2}:上传文件保存到临时目录的名称
{3}:上传文件的类型(对struts.messages.error.file.too.large是上传文件的大小)


3.在自己的properties文件中修改配置
修改为
struts.messages.error.uploading=上传错误: {0}
struts.messages.error.file.too.large=上传文件太大: {0} "{1}" "{2}" {3}
struts.messages.error.content.type.not.allowed=上传文件的类型不允许: {0} "{1}" "{2}" {3}
struts.messages.error.file.extension.not.allowed=上传文件的后缀名不允许: {0} "{1}" "{2}" {3}


多文件上传
第一步:在WEB-INF/lib下加入commons-fileupload-1.2.1.jar、commons-io-1.3.2.jar。这两个文件可以从http://commons.apache.org/下载。
第二步:把form表的enctype设置为:“multipart/form-data“,如下:
<form enctype="multipart/form-data" action="${pageContext.request.contextPath}/xxx.action" method="post">
 <input  type="file" name="uploadImages">
 <input  type="file" name="uploadImages">
</form>
第三步:在Action类中添加以下属性,属性红色部分对应于表单中文件字段的名称:
public class uploadAction{
 private File[] uploadImages;//得到上传的文件
 private String[] uploadImagesContentType;//得到文件的类型
 private String[] uploadImagesFileName;//得到文件的名称
 //这里略省了属性的getter/setter方法
 public String saveFiles() throws Exception{
ServletContext sc = ServletActionContext.getServletContext();
String realpath = sc.getRealPath("/uploadfile");
try {
if(uploadImages!=null&&uploadImages.length>0){
for(int i=0;i<uploadImages.length;i++){
File destFile = new File(realpath,uploadImageFileNames[i]);
FileUtils.copyFile(uploadImages[i], destFile);
 }
}
} catch (IOException e) {
 e.printStackTrace();}return "success";}}



----------------------------------------------------------------------------------------------
2.下载

文件下载方式:
1.超连接
2.服务器端以流的方式向浏览器写回数据.

struts2文件下载
文件下载注意事项:
1.response.setContentType(Stirng mimeType);
2.response.setHeader("Content-Disposition","attachment;filename=xxxx");

文件下载操作
1.donwload.jsp
<a href="${pageContext.request.contextPath}/download?filename=18.jpg">下载18.jpg</a>
<br>
<a href="${pageContext.request.contextPath}/download?filename=22.jpg">下载22.jpg</a>
<br>
2.DownloadAction
private String filename;

3.完成下载
1.在struts.xml文件中对应的DownloadAction的配置信息中配置
<result type='stream'>

</result>

在stream对应的类中org.apache.struts2.dispatcher.StreamResult
有三个属性
protected String contentType = "text/plain";  设置响应的mimeType类型
protected String contentDisposition = "inline"; 设置响应content-dispostion值
protected InputStream inputStream; 设置响应数据


<action name="download" class="cn.itcast.action.DownloadAction">
<result type="stream">  <!-- 可以完成文件下载  -->
<param name="contentType">${contentType}</param> 代表在当前的Action类中去调用一个getContentType方法,这个方法的返回值就是用于赋值给contentType的.
<param name="contentDisposition">attachment;filename=${filename}</param>
<param name="inputStream">${inputStream}</param>
</result>
</action>

下载文件时乱码问题:
1.连接中文件名称包含中文处理.
解决:在setFilename方法中解决
this.filename = new String(filename.getBytes("iso8859-1"), "utf-8");

2.下载文件乱码问题
ie:utf-8码
firefox:base64编码

=======================================================================
ognl与valueStack介绍
ognl--对象导航图语言.
它比el更强大.
ognl是一个开源项目.

OGNL 提供五大类功能 
  1、支持对象方法调用,如xxx.doSomeSpecial(); 
  
<s:property value="'abc'.length()">


  2、支持类静态的方法调用和值访问
静态方法调用必须开启

调用 静态方法 : @[类全名(包括包路径)]@[方法名]  --- <s:property value="@java.lang.String@format('您好,%s','小明')"/>
* 使用 静态方法调用 必须 设置 struts.ognl.allowStaticMethodAccess=true


  3、访问OGNL上下文(OGNL context)和ActionContext; (重点 操作ValueStack值栈 )
  4、支持赋值操作和表达式串联
  5、操作集合对象。
  
 通过ognl访问上下文以及ActionContext

1.什么是值栈 ValueStack ? 

它是一个容器.本质上是一个接口 ValueStack接口.这个接口有一个实现类 OgnlValueStack,
我们使用的其实就是OgnlValueStack。

每一个Action对应一个ValueStack.
将valueStack存储到了request范围内.
将valueStack对象以 "struts.valueStack"存储到了request范围内.

valueStack中有两部分:
root-----CompoundRoot 它继承了ArrayList
context----Map

root中存储了Action相关属性
context中存储了web相关对象.


2.valueStack内部结构

ValueStack由两部分组成:
1.List     public abstract CompoundRoot getRoot();
2.Map    public abstract Map<String, Object> getContext();


Struts 会把下面这些映射压入 ContextMap 中
parameters: 该 Map 中包含当前请求的请求参数
request: 该 Map 中包含当前 request 对象中的所有属性
session: 该 Map 中包含当前 session 对象中的所有属性
application:该 Map 中包含当前 application  对象中的所有属性
attr: 该 Map 按如下顺序来检索某个属性: request, session, application

Root下存储的是Action相关的信息.

通过ognl从valueStack中获取信息时,默认是从root中获取.
从root中获取数据直接写名称就可以.
如果要从map中获取,必须使用#来操作.

context 对应Map 引入 root对象

3.获取ValueStack
1.直接从request中获取.
ValueStack vs = (ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack");

2.通过ActionContext获取

关于ActionContext与ValueStack的关系
ActionContext ctx = new ActionContext(stack.getContext());
在ActionContext中存在context引用.
ValueStack vs=ActionContext.getContext().getValueStack();

顶 0踩 0收藏
文章评论
    发表评论

    个人资料

    • 昵称: jun
    • 等级: 资深程序员
    • 积分: 1523
    • 代码: 94 个
    • 文章: 24 篇
    • 随想: 0 条
    • 访问: 7 次
    • 关注

    最新提问

      站长推荐