首页 > 代码库 > Struts2龙之总结

Struts2龙之总结

 一、Struts2执行流程: 

  1.客户端初始化一个指向servlet容器(tomcat)的请求;

  2.这个请求经过一系列过滤器(Filter);

  3.接着StrutsPrepareAndExecuteFilter被调用,StrutsPrepareAndExecuteFilter询问ActionMapper来决定这个请求是否需要调用某个Action;

  4.如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy;

  5.ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类;

  6.ActionProxy调用invoke方法创建一个ActionInvocation的实例。

  7.递归调用,判断是否还有下一个拦截器,当没有了下一个拦截器,就执行Action的业务方法。

  8.一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可能是另外的一个Action链;

  9.返回结果的时候依旧经过一系列拦截器。

   请求 ---- StrutsPrepareAndExecuteFilter 核心控制器 ----- Interceptors 拦截器(实现代码功能,只访问action时执行 ) ----- Action execuute --- 结果页面 Result 

 二、在web.xml 配置struts2 前端控制器 (Filter

  <filter>

   <filter-name>struts2</filter-name>

   <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>

  </filter>

  <filter-mapping>

   <filter-name>struts2</filter-name>

   <url-pattern>/*</url-pattern>

  </filter-mapping>

 三、struts2 常量配置 (键值对 properties

  struts2 默认常量 在 default.properties 中配置

  常用常量

  <constant name="struts.i18n.encoding" value="http://www.mamicode.com/UTF-8"/>  ----- 相当于request.setCharacterEncoding("UTF-8"); 解决post请求乱码

   <constant name="struts.action.extension" value="http://www.mamicode.com/action,,"/>  --- 访问struts2框架Action访问路径 扩展名 (要求)

  * struts.action.extension=action,, 默认以.action结尾扩展名 和 不写扩展名 都会分发给 Action

   <constant name="struts.serve.static.browserCache" value="http://www.mamicode.com/false"/> false不缓存,true浏览器会缓存静态内容,产品环境设置true、开发环境设置false

  <constant name="struts.devMode" value="http://www.mamicode.com/true" />  提供详细报错页面,修改struts.xml后不需要重启服务器 (要求)

   <action>name <package>namespace属性 共同决定 Action的访问路径 !!!!!!!!

   例如

   <package name="usermanager" namespace="/user" extends="struts-default">

     <action name="hello" class="cn.itcast.struts2.demo1.HelloAction">

   访问路径 /user/hello.action

   3) <action> 元素配置默认值

    <package> namespace 默认值 /

  <action> class 默认值 ActionSupport

  <result> name 默认值 success

  <action> method默认值execute

 4struts2 配置文件分离

通过 <include file="struts-part1.xml"/> struts2 配置文件 拆分

分离配置文件的原则:按模块进行分离,再统一组装到struts.xml  (<include>标签)

 

五、 Action的访问

 

HTTP请求 提交 Struts2 StrutsPrepareAndExecuteFilter 核心控制器 ------ 请求分发给不同Action

 

 

 

1、 让请求能够访问Action  ----- Action书写方式 三种

 

第一种 Action可以是 POJO  ((PlainOldJavaObjects)简单的Java对象) ---- 不需要继承任何父类,实现任何接口

 

* struts2框架 读取struts.xml 获得 完整Action类名

 

* obj = Class.forName("完整类名").newInstance();

 

    * Method m = Class.forName("完整类名").getMethod("execute");  m.invoke(obj); 通过反射 执行 execute方法

 

 

 

第二种 编写Action 实现Action接口

 

Action接口中,定义默认五种 逻辑视图名称

 

public static final String SUCCESS = "success";  // 数据处理成功 (成功页面)

 

public static final String NONE = "none";  // 页面不跳转  return null; 效果一样

 

public static final String ERROR = "error";  // 数据处理发送错误 (错误页面)

 

public static final String INPUT = "input"; // 用户输入数据有误,通常用于表单数据校验 (输入页面)

 

public static final String LOGIN = "login"; // 主要权限认证 (登陆页面)

 

 

 

* 五种逻辑视图,解决Action处理数据后,跳转页面

 

 

 

第三种 编写Action  继承ActionSupport  (推荐)

 

   Action中使用 表单校验、错误信息设置、读取国际化信息 三个功能

 

 

 

 

 

  

 

2Action中方法调用

 

    1) 在配置 <action> 元素时,没有指定method属性, 默认执行 Action类中 execute方法

 

   <action name="request1" class="baoming.demo3.RequestAction1" />

 

    2) 在<action> 元素内部 添加 method属性,指定执行Action中哪个方法

 

<action name="regist" class="baoming.demo4.RegistAction" method="regist"/> 执行 RegistAction regist方法

 

  

 

3) 使用通配符* ,简化struts.xml配置

 

<a href="http://www.mamicode.com/${pageContext.request.contextPath }/user/customer_add.action">添加客户</a>

 

<a href="http://www.mamicode.com/${pageContext.request.contextPath }/user/customer_del.action">删除客户</a>

 

 

 

struts.xml

 

<action name="customer_*" class="baoming.struts2.demo4.CustomerAction" method="{1}"></action>   ---  {1}就是第一个* 匹配内容

 

 

Action 构造方法调用几次?是否为单例

 

        Action的生命周期?

 

因为每次请求都会调用构造方法,说明它是多实例的,不存在线程并发访问时的冲突问题

 

Struts1会不会存在线程安全问题?Struts1是单例的,会存在线程并发访问时的安全问题

 

 

 

 

 

3、 动态方法调用 (零配置路线)

 

   访问Action中指定方法,不进行配置

 

   1) 在工程中使用 动态方法调用 ,必须保证 struts.enable.DynamicMethodInvocation = true 常量值为true

 

   2) 在action的访问路径 中 使用 "!方法名"

 

页面

 

<a href="http://www.mamicode.com/${pageContext.request.contextPath }/user/product!add.action">添加商品</a>

 

配置

 

<action name="product" class="bao.struts2.demo4.ProductAction"></action>

 

执行 ProductAction 中的 add方法

 

 

 

 

 

 

 

六、在Action中使用Servlet API

 

1、 在Action 中解耦合方式 间接访问 Servlet API  --------- 使用 ActionContext 对象

 

struts2 Action API 已经与 Servlet API 解耦合 (没有依赖关系 )

 

* Servlet API 常见操作 : 表单提交请求参数获取,向requestsessionapplication三个范围存取数据

 

 

 

actionContext = ActionContext.getContext();

 

 actionContext.getParameters(); 获得所有请求参数Map集合

 

    

 

actionContext.put("company", "数据"); / actionContext.get("company") request范围存取数据

 

3) actionContext.getSession(); 获得session数据Map,对Session范围存取数据

 

  actionContext.getSession().put("key","value");

 

4) actionContext.getApplication(); 获得ServletContext数据Map,对应用访问存取数据

 

  actionContext.getApplication().put("key","value");

 

    *本质分析是否存在线程安全问题? 不会有 答案原码:ActionContext  (使用ThreadLocal存储相关的值)

 

 

 

3、 在Action中直接通过 ServletActionContext 获得Servlet API

 

ServletActionContext.getRequest() : 获得request对象 (session

 

ServletActionContext.getResponse() : 获得response 对象

 

ServletActionContext.getServletContext() : 获得ServletContext对象

 

* 静态方法没有线程问题,ThreadLocal

 

 

 

 

 

七、 结果页面的配置

 

Action处理请求后, 返回字符串(逻辑视图名), 需要在struts.xml 提供 <result>元素定义结果页面

 

1、 局部结果页面 和 全局结果页面

 

<action name="result" class="bao.struts2.demo6.ResultAction">

 

<!-- 局部结果  当前Action使用 -->

 

<result name="success">/demo6/result.jsp</result>

 

</action>

 

 

 

<global-results>

 

<!-- 全局结果 当前包中 所有Action都可以用-->

 

<result name="success">/demo6/result.jsp</result>

 

</global-results>

 

 

 

2、 结果页面跳转类型

 

* struts-default.xml 定义了 一些结果页面类型

 

* 使用默认type dispatcher 转发 (request.getRequestDispatcher.forward

 

 

 

1)  dispatcher Action 转发给 JSP

 

2)  chain Action调用另一个Action (同一次请求)

 

<result name="success" type="chain">hello</result>  hello是一个Actionname

 

3redirect Action重定向到 JSP

 

     <result name="success" type="redirect">hello.action</result>  hello是一个Actionname

 

4redirectAction Action重定向到另一个Action

 

<result name="success" type="redirectAction">hello</result>

 

 

 

Action : 可以作为模型,也可以是控制器 

属性驱动 模型驱动

第一种 Action 本身作为model对象,通过成员setter封装 (属性驱动 )

页面:

用户名  <input type="text" name="username" /> <br/>

Action

public class RegistAction1 extends ActionSupport {

private String username;

public void setUsername(String username) {

this.username = username;

}

}

  * struts2  Action 是多实例

 struts1 Action 是单例的

  

 

第二种 :创建独立model对象,页面通过ognl表达式封装 (属性驱动)

页面:

用户名  <input type="text" name="user.username" /> <br/>  ----- 基于OGNL表达式的写法

Action

public class RegistAction2 extends ActionSupport {

private User user;

public void setUser(User user) {

this.user = user;

}

 

public User getUser() {

return user;

}

}

 

问题: 谁来完成的参数封装

<interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>

 

第三种 :使用ModelDriven接口,对请求数据进行封装 (模型驱动 ) ----- 主流

页面:

用户名  <input type="text" name="username" /> <br/>  

Action

public class RegistAction3 extends ActionSupport implements ModelDriven<User> {

private User user = new User(); // 必须手动实例化

public User getModel() {

return user;

}

}

* struts2 有很多围绕模型驱动的特性

* <interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/> 为模型驱动提供了更多特性

 

对比第二种、第三种 第三种只能在Action中指定一个model对象,第二种可以在Action中定义多个model对象

<input type="text" name="user.username" />

<input type="text" name="product.info" />

 

属性驱动和模型驱动都是框架的拦截器来帮助实现的。

 

 

 数据类型转换问题

1struts2 内部提供大量类型转换器,用来完成数据类型转换问题

boolean Boolean

charCharacter

int Integer

long Long

float Float

double Double

Date 可以接收 yyyy-MM-dd格式字符串  (yyyy/MM/dd不能转)

数组  可以将多个同名参数,转换到数组中

集合  支持将数据保存到 List 或者 Map 集合

 

案例: 输入合法年龄和生日可以自动转换

当输入abc 转换为 int类型 age

Caused by: java.lang.NoSuchMethodException: bao.struts2.demo3.CustomerAction.setAge([Ljava.lang.String;

分析: 输入20 ,转换 int类型20  --- setAge(int)

      输入abc,转换int 出错 ---- setAge(String) ----- 报错方法不存在异常

 

2、 自定义类型转换器 (了解

1) 自定义类型转换器

第一种 实现TypeConverter接口

convertValue(java.util.Map<java.lang.String,java.lang.Object> context, java.lang.Object target, java.lang.reflect.Member member, java.lang.String propertyName, java.lang.Object value, java.lang.Class toType)

第二种 继承 DefaultTypeConverter

convertValue(java.util.Map<java.lang.String,java.lang.Object> context, java.lang.Object value, java.lang.Class toType)

第三种 继承 StrutsTypeConverter

convertFromString(java.util.Map context, java.lang.String[] values, java.lang.Class toClass)  --- 请求封装

convertToString(java.util.Map context, java.lang.Object o)   --- 数据回显

 

 类型转换器 一直都是双向转换

页面提交请求参数,封装到model --- 需要转换

model数据 需要在页面 回显  ---- 需要转换

 

2) 以 1990/10/10 为例,自定义日期转换器,完成转换  第二种方法

public Object convertValue(Map<String, Object> context, Object value,

Class toType) {

// 根据toType判断 是请求封装 还是 数据回显

DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");

if (toType == Date.class) {

// 请求参数封装 (value是字符串)

String[] params = (String[]) value;

String strVal = params[0]; // 转换为 日期类型

try {

return dateFormat.parse(strVal);

} catch (ParseException e) {

e.printStackTrace();

}

} else {

// 回显(valueDate)

Date date = (Date) value;

return dateFormat.format(date);

}

 

return null;

}

 

3) 注册类型转换器

局部注册 只对当前Action有效 (针对属性)

全局注册 针对所有Action的日期类型有效 (针对类型 )

 

局部注册 Action类所在包 创建 Action类名-conversion.properties , 格式 : 属性名称=类型转换器的全类名

全局注册 src下创建 xwork-conversion.properties ,格式 : 待转换的类型=类型转换器的全类名

 

3、 类型转换中错误处理

通过分析拦截器作用,得知当类型转换出错时,自动跳转input视图 ,在input视图页面中 <s:fieldError/> 显示错误信息

* Action所在包中,创建 ActionName.properties,在局部资源文件中配置提示信息 : invalid.fieldvalue.属性名= 错误信息

 

校验器

1、 校验的分类 : 客户端数据校验 和 服务器端数据校验

客户端数据校验 ,通过JavaScript 完成校验 (改善用户体验,使用户减少出错 )

服务器数据校验 ,使用框架内置校验功能 struts2 内置校验功能 ) ----- 必须的

 

2struts2 支持校验方式

代码校验 :在服务器端通过编写java代码,完成数据校验

配置校验 XML配置校验(主流) 和 注解配置校验

 

 

4XML配置方式 数据校验 (企业主流校验)

代码校验 不适用于大型项目, 流程数据复杂时,开发量和维护量 都会很大

 

xml配置校验原理 : 将很多校验规则代码已经写好,只需要在xml中定义数据所使用校验规则就可以了

 

步骤一 :编写jsp

步骤二 :编写Action 继承ActionSupport 或者 实现 Validateable 接口

步骤三 :封装请求参数

* 使用xml校验 必须提供get方法

步骤四 :编写校验规则xml文件

Action所在包 编写 Action类名-validation.xml Action所有业务方法进行校验

引入DTD

------ xwork-core-2.3.7.jar xwork-validator-1.0.3.dtd

<!DOCTYPE validators PUBLIC

   "-//Apache Struts//XWork Validator 1.0.3//EN"

   "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">

内置校验器定义文件

xwork-core-2.3.7.jar /com/opensymphony/xwork2/validator/validators/default.xml

 

内建校验器

* required (必填校验器,要求被校验的属性值不能为null)

* requiredstring (必填字符串校验器,要求被校验的属性值不能为null,并且长度大于0,默认情况下会对字符串去前后空格)

* stringlength (字符串长度校验器,要求被校验的属性值必须在指定的范围内,否则校验失败,minLength参数指定最小长度,maxLength参数指定最大长度,trim参数指定校验field之前是否去除字符串前后的空格)

* regex (正则表达式校验器,检查被校验的属性值是否匹配一个正则表达式,expression参数指定正则表达式,caseSensitive参数指定进行正则表达式匹配时,是否区分大小写,默认值为true)

* int(整数校验器,要求field的整数值必须在指定范围内,min指定最小值,max指定最大值)

* double(双精度浮点数校验器,要求field的双精度浮点数必须在指定范围内,min指定最小值,max指定最大值)

* fieldexpression (字段OGNL表达式校验器,要求field满足一个ognl表达式,expression参数指定ognl表达式,该逻辑表达式基于ValueStack进行求值,返回true时校验通过,否则不通过)

* email(邮件地址校验器,要求如果被校验的属性值非空,则必须是合法的邮件地址)

* url(网址校验器,要求如果被校验的属性值非空,则必须是合法的url地址)

* date(日期校验器,要求field的日期值必须在指定范围内,min指定最小值,max指定最大值)

 

案例

required  必填校验器

<field-validator type="required">

       <message>性别不能为空!</message>

</field-validator>

 

requiredstring  必填字符串校验器

<field-validator type="requiredstring">

       <param name="trim">true</param>

       <message>用户名不能为空!</message>

</field-validator>

 

stringlength:字符串长度校验器

<field-validator type="stringlength">

<param name="maxLength">10</param>

<param name="minLength">2</param>

<param name="trim">true</param>

<message><![CDATA[产品名称应在2-10个字符之间]]></message>

</field-validator>

 

int:整数校验器

<field-validator type="int">

<param name="min">1</param>

<param name="max">150</param>

<message>年龄必须在1-150之间</message>

</field-validator>

 

date: 日期校验器

<field-validator type="date">

<param name="min">1900-01-01</param>

<param name="max">2050-02-21</param>

<-- OGNL表达式在配置文件中的写法-->

<message>生日必须在${min}${max}之间</message>

</field-validator>

 

url:  网络路径校验器

<field-validator type="url">

<message>数据的主页地址必须是一个有效网址</message>

</field-validator>

 

email:邮件地址校验器

<field-validator type="email">

<message>电子邮件地址无效</message>

</field-validator>

 

regex:正则表达式校验器

<field-validator type="regex">

     <param name="expression"><![CDATA[^13\d{9}$]]></param>

     <message>手机号格式不正确!</message>

</field-validator>

 

fieldexpression : 字段表达式校验

<field-validator type="fieldexpression">

       <param name="expression"><![CDATA[(password==repassword)]]></param>

       <message>两次密码输入不一致</message>

</field-validator>

 

如何对指定的方法校验 ??? 格式  Action类名-ActionName(<action>元素name属性)-validation.xml

例如 校验AddCustomerActionexecute方法  配置 <action name="addcustomer" ...method="regist"/>

        校验文件名字: AddCusotmerAction-addcustomer-validation.xml

 

 国际化信息显示

1、 国际化原理 ? 什么是国际化 ?

同一款软件 可以为不同用户,提供不同语言界面  ---- 国际化软件   internationalization  --i18n    本地化localization  l10n

需要一个语言资源包(很多properties文件,每个properties文件 针对一个国家或者语言 ,通过java程序根据来访者国家语言,自动读取不同properties文件 )

 

2、 资源包编写

properties文件命名 :  基本名称_语言(小写)_国家(大写).properties

例如

messages_zh_CN.properties 中文中国

messages_en_US.properties 英文美国

 

 

4struts2 框架国际化配置

第一种 全局国际化信息文件 (所有Action都可以使用 ) ------- 最常用

* properties文件可以在任何包中

* 需要在struts.xml 中配置全局信息文件位置

 

struts.xml

<constant name="struts.custom.i18n.resources" value="http://www.mamicode.com/messages"></constant>   messages.properties src根目录

<constant name="struts.custom.i18n.resources" value="http://www.mamicode.com/bao.resources.messages"></constant>   messages.properties bao.resources

 

国际化信息

Action中使用  : this.getText("msg");

jsp中使用  :<s:text name="msg" />

在配置文件中(校验xml) : <message key="agemsg"></message>

 

 自定义拦截器

拦截器 的使用 ,源自Spring AOP(面向切面编程)思想

拦截器 采用 责任链 模式

*  在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。

    *  责任链每一个节点,都可以继续调用下一个节点,也可以阻止流程继续执行

 

struts2 中可以定义很多个拦截器,将多个拦截器按照特定顺序 组成拦截器栈 (顺序调用 栈中的每一个拦截器 )

 

 

拦截器与拦截器栈的区别?

  拦截器:<interceptor>   拦截器栈:<interceptor-stack>

  从功能上看,拦截器栈本身就是一个功能更加强大的拦截器

  从结构上看,拦截器栈是由多个拦截器有序组织在一起

 

 

配置一个拦截器:<interceptor>

拦截器栈:<interceptor-stack>

    在栈中引入一个定义好的拦截器<interceptor-ref name=""/>

定义默认的拦截器栈:<default-interceptor-ref name=""/>

 

类的写法

  1struts2 所有拦截器 都必须实现 Interceptor 接口

  2AbstractInterceptor 类实现了 Interceptor 接口. 并为 init, destroy 提供了一个空白的实现

所有实际开发中,自定义拦截器 只需要 继承 AbstractInterceptor类, 提供 intercept 方法实现

 

 

 

3、 常用struts2 拦截器

<interceptor-ref name="modelDriven"/> 模型驱动

<interceptor-ref name="fileUpload"/> 文件上传

<interceptor-ref name="params"> 参数解析封装

<interceptor-ref name="conversionError"/> 类型转换错误

<interceptor-ref name="validation"> 请求参数校验

<interceptor-ref name="workflow"> 拦截跳转 input 视图

 

 

OracleMySQL 作为应用数据库区别

mysql存在数据库概念,在企业开发中,针对一个项目创建一个单独数据库,创建单独用户, 为用户授予数据库权限 ,

oracle 一个数据库就是一个服务,在这个库中可以存在很多用户,每个用户有单独表空间 ,针对一个项目,只需要创建一个用户

 

 

Struts2 框架 上传与下载

 

文件上传

 

1) 企业常用文件上传技术 : jspSmartUpload(主要应用 JSP model1 时代) 、 fileupload Apache commons项目中一个组件)、 Servlet3.0 集成文件上传 Part

 

2) 文件上传  enctype="multipart/form-data"  MIME协议定义多部分请求体 (消息体)

 

 

 

3) 上传页面编写

 

存在 <input type="file" name="upload"/> 上传项,必须提供name属性

 

表单提交方式 必须 post 提交

 

表单编码类型 enctype="multipart/form-data"  

 

 

 

4Struts2 对文件上传的支持

 

提供 FileUpload 拦截器,用于解析 multipart/form-data 编码格式请求,解析上传文件的内容

 

fileUpload拦截器 默认在 defaultStack 栈中, 默认会执行的

 

 

 

Action需要对上传文件内容进行接收

 

页面:

 

<input type="file" name="upload" />

 

Action :

 

public class UploadAction extends ActionSupport {

 

// 接收上传内容

 

// <input type="file" name="upload" />

 

private File upload; // 这里变量名 和 页面表单元素 name 属性一致

 

private String uploadContentType;//MIME类型   image/jpeg  text/html

 

private String uploadFileName;

 

}

 

* 格式 : 上传表单项name属性 + ContentType 、 上传表单项name属性 + FileName

 

* 为三个对象 提供 setter 方法

 

 

 

通过FileUtils 提供 copyFile 进行文件复制,将上传文件 保存到服务器端

 

 

 

5) Struts2 上传文件过程中错误处理

 

   配置 input 视图 ,作为上传出错后 跳转页面

 

   在文件上传时,如果发生错误 fileUpload拦截器 会设置错误信息,workflow拦截器 跳转到 input 视图

 

 

 

   通过 struts.multipart.maxSize 常量设置文件上传总大小限制

 

      * struts.multipart.maxSize=2097152 默认上传文件总大小 2MB

 

      * 超过文件总大小,跳转input 视图, 通过 <s:actionError /> 回显错误信息

 

   struts.xml 设置上传总大小

 

       <constant name="struts.multipart.maxSize" value="http://www.mamicode.com/20000000"></constant>

 

 

 

   设置上传文件总大小,对所有上传form有效,只想对当前form进行设置,可以设置fileUpload拦截器属性

 

     FileUpload 拦截器有 3 个属性可以设置.

 

* maximumSize: 上传文件的最大长度(以字节为单位), 默认值为 2 MB

 

* allowedTypes: 允许上传文件的类型, 各类型之间以逗号分隔  image/jpeg,text/html

 

* allowedExtensions: 允许上传文件扩展名, 各扩展名之间以逗号分隔

 

   如果针对fileUpload 进行参数设置,当出错时,在页面通过 <s:fieldError /> 回显错误信息

 

 

 

   

 

 文件下载

 

文件下载原理:

 

  1.一个流  输出流

 

  2.两个头  response.setHeader("Content-Type","application/octet-stream");

 

            response.setHeader("Content-Disposition","attachment;filename=1.jpg");

 

 

 

1struts2 完成文件下载,通过 结果集类型 (Result Typestream 来完成的

 

 struts-default.xml 定义 <result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>

 

2) 使用Stream结果集 完成文件下载

 

文件下载原理: 服务器读取下载文件内容,通过Response响应流写回, 设置 ContentTypeContentDisposition 头信息

 

 

 

public class StreamResult extends StrutsResultSupport {

 

protected String contentType = "text/plain"; // contentType头信息  (下载文件对应 MIME协议规定类型 )

 

* html --- text/html . txt--- text/plain

 

protected String contentDisposition = "inline"; // ContentDisposition头信息 (下载文件打开方式 inline浏览器内部打开, attachment 以附件形式打开)

 

 

 

protected String inputName = "inputStream";  // 需要Action中 提供 getInputStream 方法 返回 InputStream 提供下载文件 内容

 

}

 

 

 

Action 提供 InputStream  返回值 getInputStream 方法 ------- 指定下载文件流

 

配置 stream 结果集 参数 <param name="contentType">${contentType}</param> ---- Action 中提供 getContentType

 

*  ServletActionContext.getServletContext().getMimeType(filename);

 

配置 stream 结果集 参数 <param name="contentDisposition">attachment;filename=${filename}</param> ---- Action 提供 getFilename

 

* 下载附件名乱码问题 , IE和火狐 解决不同

 

public String encodeDownloadFilename(String filename, String agent)

 

throws IOException {

 

if (agent.contains("Firefox")) { // 火狐浏览器

 

filename = "=?UTF-8?B?"

 

+ new BASE64Encoder().encode(filename.getBytes("utf-8"))

 

+ "?=";

 

} else { // IE及其他浏览器

 

filename = URLEncoder.encode(filename, "utf-8");

 

}

 

return filename;

 

}

 

Struts2龙之总结