strut2-学习笔记(二)

时间:2022-02-02 09:54:48


Struts2学习笔记(二)

1. 自定义结果视图的类型(结果视图类型的应用)

CAPTCHA图像(随机验证码图像)

实现步骤:

(1)编写一个类实现com.opensymphony.xwork2.Result, 或者继承org.apache.struts2.dispatcher.StrutsResultSupport

package com.itheima.results;

import java.awt.Color;

import java.awt.Font;

import java.awt.Graphics;

import java.awt.image.BufferedImage;

import java.io.OutputStream;

import java.util.Random;

import javax.imageio.ImageIO;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionInvocation;

import com.opensymphony.xwork2.Result;

public class CaptchaResult implements Result {

private int width = 100;

private int height = 25;

public void setWidth(int width) {

this.width = width;

}

public void setHeight(int height) {

this.height = height;

}

public void execute(ActionInvocation invocation) throws Exception {

//BufferedImage:代表内存图片

BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

//Graphics:画笔

Graphics g = image.getGraphics();

//画边线

g.setColor(Color.GREEN);

g.drawRect(0, 0, width, height);

//填充背景色

g.setColor(Color.YELLOW);

g.fillRect(1, 1, width-2, height-2);

//干扰线

Random r = new Random();

g.setColor(Color.GRAY);

for(int i=0;i<15;i++)

g.drawLine(r.nextInt(width), r.nextInt(height), r.nextInt(width), r.nextInt(height));

//验证码

g.setColor(Color.RED);

g.setFont(new Font("宋体",Font.BOLD|Font.ITALIC, 18));

int x = 19;

for(int i=0;i<4;i++){

g.drawString(r.nextInt(10)+"",x, 20);

x+=20;

}

//ImageIO:输出图片给指定的流

OutputStream out = ServletActionContext.getResponse().getOutputStream();

ImageIO.write(image, "jpg", out);

}

}

. (2)在struts.xml 文件中声明定义的结果视图类型

<struts>

<constant name="struts.devMode" value="true" />

<package name="default" extends="struts-default">

<result-types>

<result-type name="captcha" class="com.itheima.results.CaptchaResult"></result-type>

</result-types>

<action name="genCaptcha">

<result name="success" type="captcha">

<param name="width">200</param>----//这里可以动态改变验证码视图的长宽比例

<param name="height">50</param>

</result>

</action>

</package>

</struts>

(3). Jsp视图显示内容

<form action = "">

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

验证码:<input type = "text" name = "code"><img src="${pageContext.request.contextPath}/genCaptcha.action"/>

</form>

(4). 效果截图如下

strut2-学习笔记(二)

2. 封装参数到JavaBean或action中(重点)

(1)Action或JavaBean中接收请求参数

两种方式:

(1)在动作类中成员变量给予初始值,即动作类中的字段有默认值

(2)在配置文件中注入动作类的参数值(静态参数设置)

步骤如下:

1)定义一个PersonAction类

public class PersonAction extends ActionSupport {

private String name = "刘小晨";

private String password;

private int age;

public String getName() {

return name;

}

public void setName(String name) {

System.out.println("调用了setName方法");

this.name = name;

}

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public String execute() throws Exception {

System.out.println(name+":"+password+":"+age);

return SUCCESS;

}

}

这里要为个成员变量设置相应的getter和setter方法

2)struts.xml文件的配置

<action name = "action1" class ="com.itheima.actions.PersonAction">

<param name ="name">崔召金</param>

<param name ="age">24</param>

<param name ="password">201026</param>

<result>/result.jsp</result>

</action>

访问:http://localhost:8080/day27_01_struts2Params/action1

网页返回结果如下

崔召金:201026:24

另外控制台打印出如下内容:

调用了setName方法

调用了setName方法

崔召金:201026:24

这里说明了,action自己给初始化name调用setName方法执行一次,另外一次是编码人员自己在sturts.xml中给name赋值时,又执行一次。

实际上是由一个叫做staticParams的拦截器做的(具体里面干了什么事,我真心搞不懂)

(3)表单请求参数,动态参数的注入(params)

方式一:用动作类作为模型action

Jsp页面内容:

<form action="${pageContext.request.contextPath}/action2" method="post">

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

<input type ="submit" value="保存"/>

</form>

Struts.xml文件中的配置如下:

<action name = "action2" class ="com.itheima.actions.PersonAction1">

<param name ="name">崔召金a</param>

<result>/result.jsp</result>

</action>

PersonAction1

public class PersonAction1 extends ActionSupport {

private String name = "刘小晨";

public String getName() {

return name;

}

public void setName(String name) {

System.out.println("调用了setName方法");

this.name = name;

}

public String execute() throws Exception {

System.out.println(name);

return super.execute();

}

}

总结:表单的字段输入域的name取值要和动作类的写属性名称一致。

结果如下:

调用了setName方法

调用了setName方法

Java编程经典

方式二:动作类和模型分开

Student类

package com.itheima.domain;

import java.io.Serializable;

public class Student implements Serializable {

private String name;

private int age;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

@Override

public String toString() {

return "Student [name=" + name + ", age=" + age + "]";

}

}

StudentAction动作类

package com.itheima.actions;

import com.itheima.domain.Student;

import com.opensymphony.xwork2.ActionSupport;

public class StudentAction extends ActionSupport {

private Student student = new Student();

public Student getStudent() {

System.out.println("调用了getStudent方法");

return student;

}

public void setStudent(Student student) {

System.out.println("调用了setStudent方法");

this.student = student;

}

public String execute() throws Exception {

System.out.println(student);

return NONE;

}

Jsp页面如下配置

<form action="${pageContext.request.contextPath}/saveStudent" method="post">

用户名:   <input type="text" name="student.name"/><br/>崔召金

年龄:     <input type="text" name="student.age"/><br/>23

<input type="submit" value="保存"/>

</form>

Sturts.xml文件配置代码如下:

<action name="saveStudent" class="com.itheima.actions.StudentAction"/>

控制台打印代码如下:

调用了getStudent方法

调用了getStudent方法

Student [name=崔召金, age=23]

执行的过程:

框架再调用StudentAction的getStudent(),方法,得到刚刚创建的对象

紧着着,调用student实例的setName和setAge方法,设置值。

方式三:模型驱动(ModelDriven)与valueStack有关

(1)使用模型驱动,关键是动作类的编写

package com.itheima.actions;

import com.itheima.domain.Customer;

import com.opensymphony.xwork2.ActionSupport;

import com.opensymphony.xwork2.ModelDriven;

//使用模型驱动:实现modeldrivern接口

public class CustomerAction extends ActionSupport implements ModelDriven<Customer>{

private Customer customer = new Customer();

public Customer getCustomer() {

return customer;

}

public void setCustomer(Customer customer) {

this.customer = customer;

}

@Override

public String execute() throws Exception {

System.out.println(customer);

return NONE;

}

public Customer getModel() {

return customer;

}

}

Customer类的编写

package com.itheima.domain;

import java.io.Serializable;

public class Customer implements Serializable {

private String name;

private String city;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getCity() {

return city;

}

public void setCity(String city) {

this.city = city;

}

@Override

public String toString() {

return "Customer [name=" + name + ", city=" + city + "]";

}

}

Jsp页面代码编写

<form action="${pageContext.request.contextPath}/saveCustomer.action" method="post">

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

城市:<input type="text" name="city"/><br/>

<input type="submit" value="保存"/>

</form>

Sturts.xml中的配置

<action name="saveCustomer" class="com.itheima.actions.CustomerAction"/>

原理:实际上由一个拦截器来完成的modelDriven

该拦截器会在执行动作方法前,把模型对象压到ValueStack值栈的栈顶。

控制台输出如下内容:

Customer [name=崔召金, city=上海]

3. 封装数据到Collection中

JSP页面代码

<body>

<form action="${pageContext.request.contextPath}/collectionAction1" method="post">

爱好:

<input type="checkbox" name="hobby" value="吃饭"/>吃饭

<input type="checkbox" name="hobby" value="睡觉"/>睡觉

<input type="checkbox" name="hobby" value="学java"/>学java

<input type="submit" value="保存"/>

</form>

<hr/>

<h2>批量添加员工信息</h2>

<form action="${pageContext.request.contextPath}/collectionAction2" method="post">

员工1:姓名:<input type="text" name="employees[0].name"/>薪水:<input type="text" name="employees[0].salary"/><br/>

员工2:姓名:<input type="text" name="employees[1].name"/>薪水:<input type="text" name="employees[1].salary"/><br/>

员工3:姓名:<input type="text" name="employees[2].name"/>薪水:<input type="text" name="employees[2].salary"/><br/>

<input type="submit" value="保存"/>

</form>

<h2>向Map中添加内容</h2>

<form action="${pageContext.request.contextPath}/collectionAction3" method="post">

员工1:姓名:<input type="text" name="emps['e1'].name"/>薪水:<input type="text" name="emps['e1'].salary"/><br/>

员工2:姓名:<input type="text" name="emps.e2.name"/>薪水:<input type="text" name="emps.e2.salary"/><br/>

员工3:姓名:<input type="text" name="emps.e3.name"/>薪水:<input type="text" name="emps.e3.salary"/><br/>

<input type="submit" value="保存"/>

</form>

</body>

Struts.xml文件的配置

<action name="collectionAction1" class="com.itheima.actions.CollectionAction"/>

<action name="collectionAction2" class="com.itheima.actions.CollectionAction"/>

<action name="collectionAction3" class="com.itheima.actions.CollectionAction"/>

Employee类的编写

package com.itheima.domain;

import java.io.Serializable;

public class Employee implements Serializable {

private String name;

private float salary;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public float getSalary() {

return salary;

}

public void setSalary(float salary) {

this.salary = salary;

}

@Override

public String toString() {

return "Employee [name=" + name + ", salary=" + salary + "]";

}

}

4. 自定义类型转换器:

对于大部分常用类型,开发者根本无需创建自己的转换器,Struts2内置了常见数据类型多种转换器

boolean 和 Boolean

char和 Character

int 和 Integer

long 和 Long

float 和 Float

double 和 Double

Date 可以接收 yyyy-MM-dd格式字符串

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

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

java.util.Date类型的属性可以接收格式为2009-07-20的请求参数值。但如果我们需要接收格式为20091221的请求参数,我们必须定义类型转换器,否则struts2无法自动完成类型转换。

自定义类型转换器的编写:

1、编写一个类,继承StrutsTypeConverter

package com.itheima.convertor;

import java.text.DateFormat;

import java.text.ParseException;

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.Map;

import org.apache.struts2.util.StrutsTypeConverter;

//日期转换器:

/*

* String :12/31/2001 ---->Date

* Date---------->String:12/31/2001

*/

public class MyDateConvertor extends StrutsTypeConverter {

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

//从字符串转换成日期

public Object convertFromString(Map context, String[] values, Class toClass) {

if(toClass==Date.class){

String value = values[0];//获取用户输入的参数值12/31/2001

try {

return df.parse(value);

} catch (ParseException e) {

e.printStackTrace();

}

}

return null;

}

//日期转换成字符串

public String convertToString(Map context, Object o) {

if(o instanceof Date){

Date d = (Date)o;

return df.format(d);

}

return null;

}

}

注册类型转换器

1.局部类型转换器

在action动作类所在的包中,新建一个名字为actionName-conversion.properties的文件

内容如下:

birthday=com.itheima.convertor.MyDateConverter(局部类型转换器)

2.全局类型转换器:

在web-inf/classes目录下新建一个名为:xwork-convesion.properties;

内容 如下:

java.util.Date =com.itheima.convertor.MyDateconverter

3.类型转换中的类型提示:

出现转换失败时的错误提示(conversionError拦截器完成的)

Struts.xml文件中的内容如下:

<struts>

<constant name="struts.devMode" value="true" />

<package name="default" extends="struts-default">

<action name ="addUser" class = "com.itheima.actions.UserAction" method = "add">

<result>/success.jsp</result>

<result name="error">/error.jsp</result>

<result name="input">/regist.jsp</result>

</action>

</package>

</struts>

Jsp页面中需要改动的地方:

<%@ taglib uri="/struts-tags" prefix="s"%>

。。。。。。。

<body>

<s:fielderror></s:fielderror>

。。。。。。。。。

出现转换失败,会被转向一个叫input的视图,并把错误信息提示封装到fieldError中。

在动作类所在的包中建立一个名称为“动作类名.properties”的配置文件,

内容如下:

invalid.fieldvalue.字段=你的提示信息

效果如下:

strut2-学习笔记(二)

5.struts里的输入校验:

1. 输入校验

客户端校验  过滤正常用户的误操作,通过JS代码完成

服务器端校验,整个应用阻止非法数据的最后防线

2. 验证的途径:

1.编程式验证

userAction中覆盖方法

@Override

public void validate() {

//用户名不能为null或“”

if(StringUtils.isEmpty(username)){

addFieldError("username", "用户名不能为空");//   Map<String,String>key:字段名,value错误提示

}

}

如上一个方法的作用范围为所有的action动作。如果想只约束某个动作可以这么做。

<action name ="addUser" class = "com.itheima.actions.UserAction" method = "add">

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

<result name="error">/error.jsp</result>

<result name="input">/regist.jsp</result>

</action>

<action name="UserEdit" class="com.itheima.actions.UserAction" method="edit">

<result>/success.jsp</result>

<result name="error">/error.jsp</result>

<result name="input">/edit.jsp</result>

</action>

方式一:对指定的动作让其或略验证:

@SkipValidation

public String edit()

{

return SUCCESS;

}

方式二:只针对edit方法进行验证!

public String edit()

{

return SUCCESS;

}

public void validateEdit()

{

if(StringUtils.isEmpty(username)){

addFieldError("username", "用户名不能为空哦哦");

}

}

如上所示 :

只会对edit()方法做出验证:

验证不通过时,框架会给你转向一个叫做input的视图,使用struts2的<s:fieldError/>显示错误消息提示。

2. 声明式验证

针对所有方法进行验证:

在动作类所在的包中,建立一个名称为”动作类名-validation.xml”

内容如下:

strut2-学习笔记(二)

针对某个动作进行验证:

在动作类所在的包中,建立一个名称为”动作类名-动作名称-validation.xml”

或者使用@SkipValidation

6 Struts2框架中声明式验证的内置验证器

他们都在xwork-core-*.jar包的

com.opensymphony.xwork2.validator.validators.default.xml中进行了定义。

常用的验证器:

requiredstring:字符串不能为null或空字符串。默认情况下会对数据进行trim后进行判断。

<!-- 写法形式一:可以给一个字段添加好多的验证规则 -->

<!-- 写法形式一:可以给一个字段添加好多的验证规则 -->

<field name = "username"><!-- 验证的字段名称 -->

<field-validator type="requiredstring"><!-- 不能为空 -->

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

<message>用户名不能为空,你找骂</message>

</field-validator>

<field-validator type="stringlength"><!-- 验证字符串长度的 -->

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

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

<message>用户名必须介于${minLength}~${maxLength}之间哦</message>

</field-validator>

</field>

<!-- 写法形式二:用于非字段性的验证

<validator type="requiredstring">

<param name="fieldName">username</param>

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

</validator>

7 自定义声明式验证器

1.编写一个类,继承com.opensymphony.xwork2.validator.validators.FieldValidatorSupport

StrongPasswordValidator类

package com.itheima.actions;

import com.opensymphony.xwork2.validator.ValidationException;

import com.opensymphony.xwork2.validator.validators.FieldValidatorSupport;

public class StrongPasswordValidator extends FieldValidatorSupport {

private int minLength  = -1;

public int getMinLength() {

return minLength;

}

public void setMinLength(int minLength) {

this.minLength = minLength;

}

//验证方法:针对不符合要求的内容进行判断,向Map中添加信息即可

//参数:object就是当前的动作对象

public void validate(Object object) throws ValidationException {

//获取要验证的字段名称

String fieldName = getFieldName();

Object fieldValue = getFieldValue(fieldName, object);

if(fieldValue==null)

return;

if(!isStrong((String)fieldValue)){

addFieldError(fieldName, object);

}

if((minLength>-1)&&((String)fieldValue).length()<minLength){

// 添加一个消息

addFieldError(fieldName, object);

}

}

//判断s是否强大

private static final String GROUP1 = "abcdefghijklmnopqrstuvwxyz";

private static final String GROUP2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

private static final String GROUP3 = "0123456789";

//判断密码是否强壮:至少一个大写字母、一个小写字母、一个数字

private boolean isStrong(String s) {

boolean ok1 = false;

boolean ok2 = false;

boolean ok3 = false;

int length = s.length();

for(int i=0;i<length;i++){

if(ok1&&ok2&&ok3)

break;

String character = s.substring(i,i+1);

if(GROUP1.contains(character)){

ok1 = true;

continue;

}

if(GROUP2.contains(character)){

ok2 = true;

continue;

}

if(GROUP3.contains(character)){

ok3 = true;

continue;

}

}

return ok1&&ok2&&ok3;

}

}

2.在WEB-INF\classes目录下建立一个固定名称validators.xml的配置文件,

strut2-学习笔记(二)

3.UserAction-UserEdit-validation.xml中写如下代码:

<field name ="password">

<field-validator type ="strongpassword">

<message>您的密码不够强壮</message>

</field-validator>

</field>

验证两次密码是否一致

1.jsp中如下代码:

<s:actionerror>

2.UserAction-UserEdit-validation.xml中写如下代码:

<validator type="expression">

<param name="expression">

password==repassword

</param>

<message>两次密码必须一致</message>

</validator>

8. Struts2的国际化

1、配置全局国际化消息资源包

a.配置全局消息资源包

strut2-学习笔记(二)

b、如何访问

l 在动作类中:

前提,动作类继承ActionSupport

strut2-学习笔记(二)

l 在页面中:

strut2-学习笔记(二)

或者

<s:text name="hello"></s:text>

l *指定消息资源包,借助struts2的有关国际化的标签:

strut2-学习笔记(二)

如果消息资源包在com.itheima.resources.msg_zh_CN.properties

strut2-学习笔记(二)

2. 配置局部消息资源包

一定要经过Action才行:

书写规范:在动作类所在包中,建立名字”动作类名-zh-CN.properties”的配置文件。动作类中访问,发现局部的比全局的优先级高。

strut2-学习笔记(二)

3、包范围的消息资源包

也得经过action访问

书写有规范的,名称为package_zh_CN.properties,放在类的包中。可以被包中及子包的所有动作类来访问。

总结:

strut2-学习笔记(二)

day27_00_struts2Result

day27_01_struts2Params

day27_02_struts2regist

day27_03_struts2i18n

strut2-学习笔记(二)

9. struts2中的拦截器(框架功能核心)

1.过滤器与拦截器的对比

功能是一回事。

过滤器是Servlet规范中的技术,可以对请求和响应进行过滤。

拦截器是Struts2框架中的技术,实现AOP(面向切面)的编程思想,可以对请求动作进行拦截。

2. 自定义拦截器

步骤:

A. 编写一个类,直接或间接实现Interceptor接口。(拦截器会驻留内存),一般都选择继承AbstractInterceptor

public class MyInterceptor extends AbstractInterceptor {

public String intercept(ActionInvocation invocation) throws Exception {

System.out.println("拦截器执行前");

String result = invocation.invoke();

System.out.println("拦截器执行后"+result);

return result;

}

}

B. 需要在struts.xml中进行定义

strut2-学习笔记(二)

C. 在动作配置中就可以使用了

strut2-学习笔记(二)

知识点:除了要使用自定义的拦截器之外,还要使用defaultStack,可以这么办

方法一:(自己使用)

strut2-学习笔记(二)

方法二:(大家都用的时候)

strut2-学习笔记(二)

<package name="mydefault" extends="struts-default">

<interceptors>

<interceptor name="myinterceptor" class="com.itheima.interceptor.MyInterceptor"></interceptor>

<interceptor-stack name="mydefaultStack">

<interceptor-ref name="defaultStack"></interceptor-ref>

<interceptor-ref name="myinterceptor"></interceptor-ref>

</interceptor-stack>

</interceptors>

<default-interceptor-ref name="myinterceptor"></default-interceptor-ref>

</package>

<package name="p1" extends="mydefault">

<action name="action1" class = "com.itheima.action.MyInterceptorAction" method="add">

<result>/success.jsp</result>

</action>

</package>

3. 能够指定拦截的方法或不拦截的方法(自定义拦截器)

自定义拦截指定的方法是指对拦截器进行限制,对需要拦截的动作action进行拦截,具体步骤如下:

1.写一个action类CustomerAction类

package com.itheima.action;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

public class CustomerAction extends ActionSupport {

public String add()

{

System.out.println("调用add的service方法");

return SUCCESS;

}

public String edit()

{

System.out.println("调用edit的service方法");

return  SUCCESS;

}

public String login()

{

System.out.println("登录了哦");

ServletActionContext.getRequest().getSession().setAttribute("user","ppp" );

return SUCCESS;

}

}

2.编写一个拦截器类MyInterceptor1

public class MyInterceptor1 extends MethodFilterInterceptor {

protected String doIntercept(ActionInvocation invocation) throws Exception {

System.out.println("拦截了,嘿嘿");

return invocation.invoke();

}

}

3. struts.xml文件中这样编写:

<package name="p1" extends="struts-default">

<interceptors>

<!-- 自定义一个拦截器 -->

<interceptor name="myinterceptor" class="com.itheima.interceptor.MyInterceptor"></interceptor>

<interceptor name="myinterceptor1" class="com.itheima.interceptor.MyInterceptor1"></interceptor>

</interceptors>

<action name="action1" class = "com.itheima.action.MyInterceptorAction" method="add">

<interceptor-ref name="defaultStack"></interceptor-ref>       将默认的拦截器个补进来

<interceptor-ref name="myinterceptor"></interceptor-ref>      自定义拦截器类

<result>/success.jsp</result>

</action>

<action name="*" class ="com.itheima.action.CustomerAction" method="{1}">

<interceptor-ref name="myinterceptor1">

<param name="excludeMethods">edit</param>          将剑代码,在拦截器中俄一个参数excludedMethods=需要排除的动作

</interceptor-ref>

<result>/success.jsp</result>

</action>

</package>

10. 文件啊文件上传与下载

1、前提:

form表单的method必须是post

form表单的enctype必须是multipart/form-data

提供type=”file”的上传输入域.

2.单文件上传

JSP页面代码:

<body>

<s:actionerror/>

<hr/>

<s:fielderror></s:fielderror>

<form action="${pageContext.request.contextPath}/upload1.action" method="post" enctype="multipart/form-data">

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

靓照:<input type="file" name="photo"/><br/>

<input type="submit" value="上传"/>

</form>

</body>

Struts.xml文件代码如下:

<struts>

<constant name="struts.devMode" value="true" />

<constant name="struts.custom.i18n.resources" value="globa"></constant>配置全局的资源信息。(为信息回显做翻译)

<package name="p1" extends="struts-default" >

<action name="upload1" class="com.itheima.action.UploadAction1" method="upload">

<interceptor-ref name="defaultStack">

<param name="fileUpload.allowedTypes">image/jpeg,image/png</param>允许上传的类型

<param name="fileUpload.allowedExtensionsSet">jpg,jpeg,png</param>允许上传文件的后缀名字

</interceptor-ref>

<result>/success.jsp</result>

<result name="error">/error.jsp</result>

<result name="input">/index.jsp</result>

</action>

</package>

</struts>

核心action类编写如下:

package com.itheima.action;

import java.io.File;

import java.io.IOException;

import org.apache.commons.io.FileUtils;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

//文件上传:fileUpload拦截器完成的

public class UploadAction1 extends ActionSupport {

private String username;         //text文本域中的名称保持一致

private File photo;     //和表单的上传字段名保持一致。类型是File类型的

private String photoFileName;     //上传的文件名

private String photoContentType;  //上传文件的MIME类型(这里contentType和上传字段photo合作通过拦截器得到类型)

public String getUsername() {

return username;

}

public void setUsername(String username) {

this.username = username;

}

public File getPhoto() {

return photo;

}

public void setPhoto(File photo) {

this.photo = photo;

}

public String getPhotoFileName() {

return photoFileName;

}

public void setPhotoFileName(String photoFileName) {

this.photoFileName = photoFileName;

}

public String getPhotoContentType() {

return photoContentType;

}

public void setPhotoContentType(String photoContentType) {

//System.out.println("调用getPhotoContentType方法"+photoContentType);

this.photoContentType = photoContentType;

}

@Override

public String toString() {

return "UploadAction1 [username=" + username + ", photo=" + photo + ", photoFileName=" + photoFileName + ", photoContentType=" + photoContentType + "]";

}

public String upload()

{

System.out.println(photoFileName+"(上传文件的名)"+photoContentType+"(上传文件的MIME类型)");

System.out.println(username);

//上传字段:上传到某个文件夹。存到应用的images目录下

String realPath = ServletActionContext.getServletContext().getRealPath("/files");

File file = new File(realPath);

if(!file.exists())

{

file.mkdirs();

}

try {

FileUtils.copyFile(photo, new File(file, photoFileName));

System.out.println(this.toString());

return SUCCESS;

} catch (IOException e) {

e.printStackTrace();

return ERROR;

}

}

}

3. 多文件上传于单文件上传的关系区别不是太大,关键是action类的编写:

uploadAction2.java文件的编写如下所示:

package com.itheima.action;

import java.io.File;

import java.io.IOException;

import org.apache.commons.io.FileUtils;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

//文件上传:fileUpload拦截器完成的

public class UploadAction2 extends ActionSupport {

private String username;

private File[] photo;//和表单的上传字段名保持一致。类型是File类型的 .数组或List

private String[] photoFileName;//上传的文件名

private String[] photoContentType;//上传文件的MIME类型

public String getUsername() {

return username;

}

public void setUsername(String username) {

this.username = username;

}

public File[] getPhoto() {

return photo;

}

public void setPhoto(File[] photo) {

this.photo = photo;

}

public String[] getPhotoFileName() {

return photoFileName;

}

public void setPhotoFileName(String[] photoFileName) {

this.photoFileName = photoFileName;

}

public String[] getPhotoContentType() {

return photoContentType;

}

public void setPhotoContentType(String[] photoContentType) {

this.photoContentType = photoContentType;

}

public String upload(){

//上传字段:上传到某个文件夹。存到应用的images目录下

String realPath = ServletActionContext.getServletContext().getRealPath("/images");

File directory = new File(realPath);

if(!directory.exists()){

directory.mkdirs();

}

try {

for(int i=0;i<photo.length;i++){

FileUtils.copyFile(photo[i], new File(directory, photoFileName[i]));

}

return SUCCESS;

} catch (IOException e) {

e.printStackTrace();

return ERROR;

}

}

}

文件的下载

如下所示:下在一张指定位置的图片文件名为“女神张泓洋(22).jpg”

strut2-学习笔记(二)

A.编写指定的Action类

package com.itheima.action;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.InputStream;

import java.net.URLEncoder;

import org.apache.commons.io.FilenameUtils;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

public class DownloadAction extends ActionSupport {

private InputStream image;//用in有问题的

private String filename;//文件名

private long filesize;

public InputStream getImage() {

return image;

}

public void setImage(InputStream image) {

this.image = image;

}

public String getFilename() {

return filename;

}

public long getFilesize() {

return filesize;

}

public String download() throws Exception{

//给image字节流赋值

String fileRealPath = ServletActionContext.getServletContext().getRealPath("/WEB-INF/classes/女神张泓洋 (22).jpg");

filename = FilenameUtils.getName(fileRealPath);

//方式一:中文文件要进行URL编码

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

filesize = new File(fileRealPath).length();

System.out.println(filename);

image = new FileInputStream(fileRealPath);

return SUCCESS;

}

}

Struts.xml文件中的配置如下:

<constant name="struts.ognl.allowStaticMethodAccess" value="true" />

。。。。。。。。。ajijiiiaoj

<action name="download" class="com.itheima.actions.DownloadAction" method="download">

<result type="stream">

<param name="inputName">image</param>

<param name="contentType">application/octet-stream</param>

<!-- 在struts.xml中使用OGNL表达式获取动作类中属性的值。 调用动作类中的 getFilename()-->

<!-- 中文文件名编码:方式二.使用OGNL表达式,调用URLEncode的静态方法 -->

<!-- 默认OGNL调用静态方法是不行的,需要开启一个常量开关.struts.ognl.allowStaticMethodAccess=true -->

<param name="contentDisposition">attachment;filename=${@java.net.URLEncoder@encode(filename,'UTF-8')}</param>

<param name="contentLength">${filesize}</param>

</result>

</action>

strut2-学习笔记(二)的更多相关文章

  1. WPF的Binding学习笔记&lpar;二&rpar;

    原文: http://www.cnblogs.com/pasoraku/archive/2012/10/25/2738428.htmlWPF的Binding学习笔记(二) 上次学了点点Binding的 ...

  2. AJax 学习笔记二&lpar;onreadystatechange的作用&rpar;

    AJax 学习笔记二(onreadystatechange的作用) 当发送一个请求后,客户端无法确定什么时候会完成这个请求,所以需要用事件机制来捕获请求的状态XMLHttpRequest对象提供了on ...

  3. &lbrack;Firefly引擎&rsqb;&lbrack;学习笔记二&rsqb;&lbrack;已完结&rsqb;卡牌游戏开发模型的设计

    源地址:http://bbs.9miao.com/thread-44603-1-1.html 在此补充一下Socket的验证机制:socket登陆验证.会采用session会话超时的机制做心跳接口验证 ...

  4. JMX学习笔记&lpar;二&rpar;-Notification

    Notification通知,也可理解为消息,有通知,必然有发送通知的广播,JMX这里采用了一种订阅的方式,类似于观察者模式,注册一个观察者到广播里,当有通知时,广播通过调用观察者,逐一通知. 这里写 ...

  5. java之jvm学习笔记二&lpar;类装载器的体系结构&rpar;

    java的class只在需要的时候才内转载入内存,并由java虚拟机的执行引擎来执行,而执行引擎从总的来说主要的执行方式分为四种, 第一种,一次性解释代码,也就是当字节码转载到内存后,每次需要都会重新 ...

  6. Java IO学习笔记二

    Java IO学习笔记二 流的概念 在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成. 程序中的输入输 ...

  7. 《SQL必知必会》学习笔记二&rpar;

    <SQL必知必会>学习笔记(二) 咱们接着上一篇的内容继续.这一篇主要回顾子查询,联合查询,复制表这三类内容. 上一部分基本上都是简单的Select查询,即从单个数据库表中检索数据的单条语 ...

  8. NumPy学习笔记 二

    NumPy学习笔记 二 <NumPy学习笔记>系列将记录学习NumPy过程中的动手笔记,前期的参考书是<Python数据分析基础教程 NumPy学习指南>第二版.<数学分 ...

  9. Learning ROS for Robotics Programming Second Edition学习笔记&lpar;二&rpar; indigo tools

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...

  10. Redis学习笔记二 (BitMap算法分析与BitCount语法)

    Redis学习笔记二 一.BitMap是什么 就是通过一个bit位来表示某个元素对应的值或者状态,其中的key就是对应元素本身.我们知道8个bit可以组成一个Byte,所以bitmap本身会极大的节省 ...

随机推荐

  1. SQL Server 2012提供的OFFSET&sol;FETCH NEXT与Row&lowbar;Number&lpar;&rpar;对比测试 &lbrack;T&rsqb;

    SQL Server 2008中SQL应用系列--目录索引 前些天看到一篇文章<SQL Server 2012 - Server side paging demo using OFFSET/FE ...

  2. FireFox下上传控件的显示问题

    Chrome正常 FireFox显示不正常 上传控件一直有个问题,就是样式问题,解决方法就是用一个大的背景层挡住,然后点大的背景层去触发上传控件的Click事件. Html: <span id= ...

  3. CSS优先级算法是如何计算?

    CSS的specificity特性或非凡性,它是一个衡量css优先级的一个标准, 既然的标准就有判定规定和计算方式,specificity用一个四位数来表示, 更像四级从左到右,左的最大级,一级大于一 ...

  4. HDU1247 Hat’s Words(Trie的动态内存版本)

    Hat’s Words Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Tota ...

  5. Oracle单个数据文件超过32G后扩容

    Oracle单个数据文件超过32G后扩容   表空间数据文件容量与DB_BLOCK_SIZE的设置有关,而这个参数在创建数据库实例的时候就已经指定.DB_BLOCK_SIZE参数可以设置为4K.8K. ...

  6. linux环境变量配置总结

    LD_LIBRARY_PATH: 动态库的查找路径设置:方法一: export  LD_LIBRARY_PATH=LD_LIBRARY_PATH:/XXX 但是登出后就失效方法二: 修改~/.bash ...

  7. HDU2138(Miller-Rabin素数检测)

    最近在看RSA,找到一个一个大素数是好多加密算法的关键一步,而大素数无法直接构造,一般情况下都是生成一个随机数然后判断是不是素数.判断是否是素数的方法有好多,有的能够准确判断,比如可以直接因式分解(R ...

  8. mssql sqlserver update delete表别名用法简介

    转自:http://www.maomao365.com/?p=6973  摘要: 在sql脚本编写中,如果需要在update delete 中使用表别名的方法,必须按照一定的规则编写,否则将会出现相应 ...

  9. 【Netty】通俗地讲,Netty 能做什么?

    作者:郭无心链接:https://www.zhihu.com/question/24322387/answer/78947405来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...

  10. Visual studio 2017 Installer 打包&period;netframework

    前几步和网上其他教程一样的.主要是把.net framework 打包进安装程序里,如果选的是“从与我的应用程序相同的位置下载系统必备组件”,会提示 ERROR: 要在“系统必备”对话框中启用“从与我 ...