Struts2学习笔记

  • Struts2框架引言
    • 什么是框架(FrameWork)
    • Struts2框架的概念
      • MVC设计思想的优点
      • 现有的MVC控制层所存在的问题
      • Struts2的实战开发思路
  • 第一个Struts2程序的开发
    • 搭建开发环境
      • 引入核心jar包
      • 引入第三方jar包
      • 引入Struts.xml配置文件
      • 配置Struts2核心过滤器
    • 开发步骤
      • 实现Action接口
      • 配置文件配置
      • ServletActionContext类的使用
      • Strtus2的另一种访问方式
  • Struts2的跳转(4种|重点)
    • Action跳转JSP
      • 默认Forward跳转
      • Redirect跳转
    • Action跳Action
      • Forward跳转
      • Redirect跳转
    • 包 < PACKAGE >
    • 命名空间 < NAMESPACE >
    • 跨包间的跳转
    • 全局跳转
      • 注意事项
  • STRUTS2接收CLIENT的参数(重点)
    • 收集客户端的零散数据
    • 通过对象收集客户端的数据
    • 通过数组或集合的形式收集客户端的数据
  • STRUTS2中ACTION的第二种开发方式
  • DMI(DYNAMIC METHOD INVOKE 动态方法调用)(实战)
    • 编码
    • 配置
      • 第一种配置
      • 第二种配置
  • STRUTS2中的数据处理机制
    • OGNL表达式
      • 从Root区取数据
        • 从Root去中取所存对象的属性值语法:直接属性名的方式
        • 从root区中取某一个对象中的关联对象的属性值:关联引用名.属性
        • 从root区中取某一个对象当中的List集合中的元素:List集合引用名[下标]
        • 从root区中取某一个对象当中的Map集合中的某一个元素:map集合的引用名[键]
        • ognl表达式中的运算
        • OGNL表达式可以调用某种数据类型的方法
      • 从ContextMap区取数据
    • VALUESTACK
      • 作用:管理(存储)一次请求有效的数据
      • 好处
      • 获取值栈
      • 值栈的生命周期(request作用域)
      • 值栈的内存结构
      • 值栈的注意事项
    • STRUTS中的标签(上)
      • 显示数据
        • 显示单个数据
        • 显示多个数据
          • 从数组或集合中显示数据(对象类型)
          • 从数组或集合中显示数据(String类型和8种基本类型)
          • 遍历状态
    • STRUTS2数据处理机制的补充
      • Action中的成员变量替换request作用域
      • 简化值栈操作session作用域,application作用域的开发
      • 为什么叫值栈?值栈体现在哪个区呢?
      • DEBUG使用
      • 总结:现有STRUTS2的开发步骤
    • STRUTS标签(续)
      • s标签中与html相关的UI标签
      • 针对于前台视图
  • STRUTS2中的拦截器
    • 拦截器的作用:把多个ACTION中的冗余代码,抽取到拦截器中,解决代码冗余问题
    • 使用
      • 编码implements Interceptor接口
      • 配置
    • 注意:
      • 拦截响应
      • 中断请求
      • 拦截器只在本包中有效
      • 简化拦截器开发 继承AbstractInterceptor类
    • 拦截器栈
      • 默认拦截器栈
      • Struts2中的拦截器体系
        • 自定义拦截器
        • 默认拦截器(系统拦截器)了解
        • 默认拦截器放置的位置
        • 方法拦截器
    • 拦截器的应用
      • 强制登陆
      • 防止用户重复提交(令牌环)
      • Struts2令牌环解决思路
        • 客户端生成随机数
        • 配置token拦截器
        • 提供跳转目标页面
  • STRUTS2中的高级部分
    • 上传
      • 文件上传核心思路
      • 文件上传开发步骤
        • 客户端的处理
        • 服务器端创建一个文件夹,用于保存用户上传的文件
        • 处理客户端上传的文件
        • 文件上传(重构)
          • IO操作过于频繁,希望简化IO的处理
          • 文件名
          • 文件路径
          • 维护性差
          • Struts2中上传的文件默认大小为2M
    • 下载
      • 文件下载的核心思路
      • Struts2下载的步骤
        • extends ActionSupport
        • 文件下载重构(优化)
          • 完成路径的修改
          • 下载中如何处理用户需要下载的文件名字
          • 解决用户下载之后的文件名

Struts2框架引言

什么是框架(FrameWork)

软件开发过程中的半成品,解决软件开发中的通用问题,从而提高开发效率。
eg

  • 字符集编码
  • 收集数据
  • 手工类型转化
  • JDBC访问

Struts2框架的概念

典型的MVC框架,人为的把一个软件分为3个层次从而提高开发效率。
M(Model | 模型层)Service + DAO + Entity
V(View | 视图层) JSP(freemarker velocity)
C(Controller | 控制层) (Servlet)

MVC设计思想的优点

  • 解耦合,利于代码维护
  • 有利于分工,提高代码开发效率

现有的MVC控制层所存在的问题

Servlet {
    //收集数据
    //出现问题1:设置字符集编码的代码问题
    String age = request.getParamter("age");
    request.getParamter("password");

    //问题2:手工进行类型转换
    Interger.parseInt();

    //调用业务
    Service

    //跳转页面
    request.getRequestDispatcher("/a.jsp").forward(request, response);

    redirect;

    //问题3:把跳转路径写死在程序中,不利于代码的维护
    response.sendredirect("/b.jsp");

Struts2的实战开发思路

Struts2代码:

Struts2 {
    MyStruts2 implements Action {
        public String execute() throws Exception {
            //调用业务
            //调用业务
            //跳转页面
            return "hibiscidai" 
        }
    }
}

对于WEBAPPLICATION的配置文件web.xml要声明映射

<servlet>
    <servlet-name>Aservlet-name>
    <servlet-class>xxx.servletservlet-class>
servlet>

<servlet-mapping>
    <servlet-name>Aservlet-name>
    <url-pattern>/Aurl-pattern>
servlet-mapping>

对于Struts.xml的配置

name="A" class="xxx.action">
    <result name="hibiscidai">
    result>

第一个Struts2程序的开发

搭建开发环境

引入核心jar包

struts2-core-2.3.15.1.jar

引入第三方jar包

引入Struts.xml配置文件

配置Struts2核心过滤器

在web.xml中声明

<filter>
    <filter-name>struts2filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilterfilter-class>
filter>
<filter-mapping>
    <filter-name>struts2filter-name>
    /*
filter-mapping>  

对于不同版本会有兼容问题,注意 filter-class 标签映射类

开发步骤

实现Action接口

配置文件配置

Struts2学习笔记_第1张图片

ServletActionContext类的使用

servlet-api.jar 包中

HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response =ServletActionContext.getResponse();
HttpSession session = request.getSession();

Strtus2的另一种访问方式

直接在项目路径下输入action名字或者 xxx.action
eg:
http://localhost:8080/ProjectName/MyAction
http://localhost:8080/ProjectName/MyAction.action

Struts2的跳转(4种|重点)

Action跳转JSP

默认Forward跳转

name="FirstStruts" class="fancylab.hibiscidai.action.MyAction">
    <result name="success" type="dispatcher">
        /ok.jsp
    result>

Redirect跳转

name="FirstStruts" class="fancylab.hibiscidai.action.MyAction">
    <result name="success" type="redirect">
        /ok.jsp
    result>

Action跳Action

Forward跳转

name="A" class="fancylab.hibiscidai.action.AAction">
    <result name="B" type="chain">
        B
    result>

name="B" class="fancylab.hibiscidai.action.BAction">
    <result name="success">
        /ok.jsp
    result>

Redirect跳转

name="A" class="fancylab.hibiscidai.action.AAction">
    <result name="B" type="redirectAction">
        B
    result>

name="B" class="fancylab.hibiscidai.action.BAction">
    <result name="success">
        /ok.jsp
    result>

包 < PACKAGE >

使配置文件当中的配置信息模块化,便于配置信息的管理。

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

命名空间 < NAMESPACE >

使用户的请求模块化,便于随后过滤器的使用。

web.xml配置

<servlet>
    <servlet-name>Aservlet-name>
    <servlet-class>fancylab.hibiscidai.action.AActionservlet-class>
servlet>
<servlet-mapping>
    <servlet-name>Aservlet-name>
    <url-pattern>/User/Aurl-pattern>
servlet-mapping>
<servlet>
    <servlet-name>Aservlet-name>
    <servlet-class>fancylab.hibiscidai.action.AActionservlet-class>
servlet>
<servlet-mapping>
    <servlet-name>Aservlet-name>
    <url-pattern>/User/Burl-pattern>
servlet-mapping>
<filter>
/User/*
filter>

访问方式:localhost:[port]/ProjectName/A

Struts2 包空间加入后
struts.xml配置

<package name="user" extends="strust-default" namespace="/First">
    "A" class="fancylab.hibiscidai.action.AAction">
package>
<package name="Admin" extends="strust-default"> 
    "A" class="fancylab.hibiscidai.action.AAction">
package>

访问方式:localhost:[port]/ProjectName/namespace/A

跨包间的跳转

<result name="D" type="chain">
    <param name="namespace">/secondparam>
    <param name="actionName">Dparam>
result>

全局跳转

当许多Action跳转到相同路径时,可以定义全局跳转,减少配置文件当中的配置信息冗余。

<global-results>
    <result  name="success">
        /ok.jsp
    result>
global-results>

注意事项

  • 只在本包内有效
  • 局部配置优先

STRUTS2接收CLIENT的参数(重点)

收集客户端的零散数据

login.jsp

type="text" name="username">
type="password" name="password">
type="submit" value="login">
xxxAction implements Action {
    private String username;
    private String password;

    //setget方法

    public String execute() {
        UserService.login(username, password);
    }
}

好处
- 简化了收集client数据的方式。

HttpServletRequest request = ServletActionContext.getRequest();
String username = request.getParameter("username
");
  • 对于通用数据进行自动类型转换。
  • 针对于post提交数据的方式,自动解决字符集编码问题。

通过对象收集客户端的数据

register.jsp

用户名type="text" name="user.username">
密码type="password" name="user.password">
年龄type="text" name="user.age">
日期type="date" name="user.birthdate">
type="submit">

User.java

class User {
    private String username;
    private String password;
    private int age;
    private Date birthdate;

    //setter和getter方法
}

RegisterAction.java

RegisterAction implements Action {
    private User user;
    //setter和getter方法
    public String execute() {
        UserService.register(user);
    }
}

通过数组或集合的形式收集客户端的数据

  • 批量删除
  • 用户勾选多个选项时
type="checkbox" value="1" name="a">
type="checkbox" value="2" name="a">
type="checkbox" value="3" name="a">

private List a;//以数组的形式接收数据

STRUTS2中ACTION的第二种开发方式

MyAction extends ActionSupport

DMI(DYNAMIC METHOD INVOKE 动态方法调用)(实战)

在一个Action中提供多个方法应对用户不同需求

编码

extends ActionSupport(建议)
语法要求:DMI中Action中的方法,方法名随便写
修饰符 返回值 参数列表 与execute中方法保持一致

配置

第一种配置

method 标签中设置方法
优点:可读性好
缺点:配置信息冗余

<action name="addUser" class="fancylab.hibiscidai.action.UserAction" method="add">action>

第二种配置

采用通配符进行
优点:配置信息不再冗余
缺点:可读性极差

<action name="user_" class="fancylab.hibiscidai.action.UserAction" method="{1}">action>

STRUTS2中的数据处理机制

数据处理机制:数据在网站中的流转
Struts2学习笔记_第2张图片

OGNL表达式

OGNL表达式:是一种独立的表达式语言,不依赖于任何的框架
OGNL表达式特点: 从root区,ContextMap区取数据

从Root区取数据

从Root区中取所存对象的属性值

从Root去中取所存对象的属性值语法:直接属性名的方式

@Test
public   void   test1() throws  Exception{
    Person person = new  Person();
    person.setUsername("laowang");
    person.setPassword("12345");
    person.setAge(30);

    System.out.println(Ognl.getValue("username",person));
    System.out.println(Ognl.getValue("password",person));
    System.out.println(Ognl.getValue("age",person));     
}

从root区中取某一个对象中的关联对象的属性值:关联引用名.属性

@Test
public  void   test2()  throws Exception{
    Person person = new  Person();
    person.setUsername("laowang");
    person.setPassword("12345");
    person.setAge(30);    
    Address address = new  Address();

    address.setStreet("文化路");
    person.setAddress(address); 

    System.out.println(Ognl.getValue("address.addressname",person));
    System.out.println(Ognl.getValue("address.street",person)); 
}

从root区中取某一个对象当中的List集合中的元素:List集合引用名[下标]

@Test
public  void   test3()  throws  Exception{  
    Person person = new  Person();
    person.setUsername("laowang");
    person.setPassword("12345");
    person.setAge(30);

    List tels = person.getTels();
    tels.add("xjr");
    tels.add("whp");

    System.out.println(Ognl.getValue("tels[0]",person));
    System.out.println(Ognl.getValue("tels[1]",person));    
}

从root区中取某一个对象当中的Map集合中的某一个元素:map集合的引用名[键]

@Test
public  void  test4() throws  Exception{
    Person person = new  Person();
    person.setUsername("laowang");
    person.setPassword("12345");
    person.setAge(30);
    Map qqs = person.getQqs();
    qqs.put("kuaige","562471794");
    qqs.put("zpf","7654321");
    System.out.println(Ognl.getValue("qqs['kuaige']",person));
    System.out.println(Ognl.getValue("qqs['zpf']",person));
}

ognl表达式中的运算

  • 算数运算 + - * / %
  • 比较运算 > < >= <= !=
  • 逻辑运算 && || !
@Test
public  void  test5()  throws Exception{
    Person person = new  Person();
    person.setUsername("laowang");
    person.setPassword("12345");
    person.setAge(30);

    System.out.println(Ognl.getValue("age<10",person));
    System.out.println(Ognl.getValue("username=='laowang'",person));    
}

OGNL表达式可以调用某种数据类型的方法

@Test
public   void  test6()  throws  Exception{
    Person person = new  Person();
    person.setUsername("laowang");
    person.setPassword("12345");
    person.setAge(30);
    System.out.println(Ognl.getValue("username.toUpperCase()",person));
    System.out.println(Ognl.getValue("username.equals('laowang')",person));
}

从ContextMap区取数据

contextmap本身是个map,在单独测试ognl时需要提供一个map集合
语法:#key的方式取值

//ContextMap区取值的方式
@Test
public void  test1() throws Exception{
    Map contextmap = new HashMap();  
    Person person = new Person();
    person.setUsername("laowang");
    person.setPassword("12345");
    person.setAge(30);
    contextmap.put("A", person);
    System.out.println(Ognl.getValue("#A.age+10", contextmap,new Object()));
}

VALUESTACK

作用:管理(存储)一次请求有效的数据

1.客户端传来的数据
2.作用域中的数据
- request
- session
- application

好处

与视图层(view层)解耦合

获取值栈

ActionContext ac = ActionContext.getContext();
ValueStack vs = ac.getValueStack();

值栈的生命周期(request作用域)

一次请求有效,请求变化则值栈变化

值栈的内存结构

请求格式

request.setAttribute("name", "laowang");
request.getAttribute("name");
request.setAttribute("n", "feige");

user类

class User {
    private String username;
    //setter和getter方法
}

request作用域底层

class request {
    private Map attribute;

    public void setAttribute(String name, String object) {
        attribute.put(name, object);
    }

    public Object getAttribute(String name) {
        Object = attrbute.get("name");
        return object;
    }
}

对于作用域
request–map
session–map
application–map

值栈的内存结构
Struts2学习笔记_第3张图片

值栈的注意事项

问题:值栈是一次请求有效,为什么可以管理session application作用域?
Struts2学习笔记_第4张图片

STRUTS中的标签(上)

作用:配合值栈在视图层显示数据
引用:
JSTL标签:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

Strtus标签:

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

显示数据

显示单个数据

value="OGNL表达式" />
  • 单一流程
if test="OGNL表达式" />
if>
else>
else>
  • 非单一流程
if test="OGNL表达式">
if>
elseif test="OGNL表达式" />
elseif>
else>
else>

显示多个数据

语法:

<s:iterator value="OGNL表达式">
s:iterator>
从数组或集合中显示数据(对象类型)

List或Set数组

<s:iterator value="#request.users">
    <h1><s:property value="username"/>h1>
    <h1><s:property value="password"/>h1>
    <h1><s:property value="age"/>h1>
s:iterator>

Map

<s:iterator value="#request.users">
    
    <h1><s:property value="key"/>h1>
    <h1>==========h1>
    
    <h1><s:property value="value"/>h1>
s:iterator>
从数组或集合中显示数据(String类型和8种基本类型)
<s:iterator value="#request.s">
    <s:property/>
s:iterator>
遍历状态
value="OGNL" status="s">
    #s.count      遍历次数
    #s.index      遍历的下标
    #s.odd       是否是奇数遍历
    #s.even      是否是偶次遍历

value="OGNL" begin="" end="" Step="">

begin:从某一个下标开始遍历
end:以某一个下标结束
step:步幅

查询所有的思路:
Struts2学习笔记_第5张图片

STRUTS2数据处理机制的补充

Action中的成员变量替换request作用域

Struts2学习笔记_第6张图片
Action中成员变量的作用:
- 收集客户端的参数(零散变量,对象,数组或集合)
- 替换request作用域

简化值栈操作session作用域,application作用域的开发

Struts2ScopeUtil工具类的开发

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.util.ValueStack;

//简化值栈操作session作用域及application作用域的使用
public class Struts2ScopeUtil {

    // 向session作用域中存值
    public static void setSessionAttribute(String OGNL, Object value) {
        ActionContext context = ActionContext.getContext();
        ValueStack valueStack = context.getValueStack();
        valueStack.setValue("#session." + OGNL, value);
    }

    // 从Session作用域中取值
    public static Object getSessionAttribute(String OGNL) {
        ActionContext context = ActionContext.getContext();
        ValueStack valueStack = context.getValueStack();
        return valueStack.findValue("#session." + OGNL);
    }

    // 向application作用域中存值
    public static void setApplicationAttribute(String OGNL, Object value) {
        ActionContext context = ActionContext.getContext();
        ValueStack valueStack = context.getValueStack();
        valueStack.setValue("#application." + OGNL, value);
    }

    // 从application作用域中取值
    public static Object getApplicationAttribute(String OGNL) {
        ActionContext context = ActionContext.getContext();
        ValueStack valueStack = context.getValueStack();
        return valueStack.findValue("#application." + OGNL);
    }
}

为什么叫值栈?值栈体现在哪个区呢?

栈:先进后出

DEBUG使用

  • 打断点
  • tomcat以debug模式启动
  • F5进入方法内部/F6不进入方法内部,只显示程序流程/F8推出debug模式/类似于ArrayList的内存结构
    Struts2学习笔记_第7张图片

总结:现有STRUTS2的开发步骤

Struts2学习笔记_第8张图片

STRUTS标签(续)

语法:
作用:自定义日期的格式

date name="#request.date" format="yyyy-MM-dd hh:mm:ss" />

语法:
作用:防止用户禁用Cookie,自动进行url重写。加载第三方资源。
注意:传值?id=41

s标签中与html相关的UI标签

———->


———->
———->
———->

语法:
作用:把多个Action的处理结果作整合

针对于前台视图

传统思路
Struts2学习笔记_第9张图片
Struts解决方案
Struts2学习笔记_第10张图片

STRUTS2中的拦截器

拦截器的作用:把多个ACTION中的冗余代码,抽取到拦截器中,解决代码冗余问题

使用

编码implements Interceptor接口

  • 方法作用:
    把多个Action中的冗余代码,写入次方法中,解决代码冗余问题
  • 参数的作用:
    ai.getAction();//获取目标的Action
    ai.getStack();//获取值栈
    ai.invoke();//控制请求的流程走向
  • 返回值的作用:
    中断用户请求时,指向跳转的目标JSP页面
public class checkloginInterceptor extends AbstractInterceptor {
    @Override
    public String intercept(ActionInvocation ai) throws Exception {
        // 获取登陆或注册的标志位
        String flag = (String) Struts2ScopeUtil.getSessionAttribute("flag");
        if (flag == null) {
            return "login";
        } else {
            ai.invoke();
        }
        return null;
    }
}

配置

<interceptors>
    <interceptor name="myInterceptor" class="fancylab.hibiscidai.interceptor.MyInterceptor">
interceptors>
<action name="A" class="fancylab.hibiscidai.action.AAction" method="A">
    <interceptor-ref name=myinterceptor">interceptor-ref>
action>

注意:

拦截响应

Struts2学习笔记_第11张图片

中断请求

Struts2学习笔记_第12张图片

拦截器只在本包中有效

简化拦截器开发 继承AbstractInterceptor类

拦截器栈

作用:管理多个拦截器
使用:不编码,只需配置


<interceptor-stack name="my">
    <interceptor-ref name="myInterceptor">interceptor-ref>
    <interceptor-ref name="myInterceptor2">interceptor-ref>
interceptor-stack>

默认拦截器栈

作用:可以指定一个拦截器栈为默认拦截器栈,可以拦截所有的目标Action

<default-interceptor-ref name="my">default-interceptor-ref>

注意:默认拦截器栈放置的位置必须在全局跳转的前边,每个包中只能配置一个默认拦截器,局部配置优先。

Struts2中的拦截器体系

自定义拦截器

默认拦截器(系统拦截器)了解

  • params
    目的:接收客户端的请求参数
    Struts2学习笔记_第13张图片
  • fileupload
  • Exception
  • workflow

默认拦截器放置的位置

Struts2-core.jar —->Struts-default.xml
Struts2学习笔记_第14张图片
注意:如果自定义了默认拦截器栈,Struts2中的系统拦截器栈将失效

<interceptors>
<interceptor-stack name="my">
    <interceptor-ref name="defalutStack">interceptor-ref>
    <interceptor-ref name="myInterceptor">interceptor-ref>
    <interceptor-ref name="myInterceptor2">interceptor-ref>
interceptor-stack>
interceptors>

注意:如果自定义拦截器,系统拦截器将失效

方法拦截器

  • 作用
    在DMI中,如果使用者采用的是通配符的配置方式,可以通过方法拦截器,拦截对应的方法。
  • 编码
    extends MethodFilterInterceptor
public class MethodInterceptor extends MethodFilterInterceptor  {
    @Override
    public String doIntercept(ActionInvocation ai) throws Exception {
        System.out.println("我是方法拦截器");
        ai.invoke();
        return null;
    }
}
  • 配置
    拦截排除某些方法
<param name="includeMethod">
拦截器拦截哪些方法
param>
 <interceptors>
    <interceptor name="methodinterceptor" class="fancylab.hibiscidai.interceptor.MethodInterceptor">
        <param name="excludeMethods">
            m4
        param>
    interceptor>
    <interceptor-stack name="my">
        <interceptor-ref name="defaultStack">interceptor-ref>
        <interceptor-ref name="methodinterceptor">interceptor-ref>
    interceptor-stack>
  interceptors>
  <defalut-interceptor-ref name="my">
  defalut-interceptor-ref>
  • 注意
    Struts2学习笔记_第15张图片
  • 总结
    拦截器的开发步骤
    Struts2学习笔记_第16张图片

拦截器的应用

强制登陆

Struts2学习笔记_第17张图片

防止用户重复提交(令牌环)

  • 发生场景
    在用户进行表单提交时,因为网络通信等问题,产生重复的表单提交
  • 解决方案
    令牌环
  • 令牌环实现原理
    Struts2学习笔记_第18张图片

Struts2令牌环解决思路

客户端生成随机数

<s:token>s:token>

配置token拦截器

引入Struts2提供的token拦截器

name="my1">
    ref name="token">ref>
    ref name="defaultStack">ref>

提供跳转目标页面

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

STRUTS2中的高级部分

上传

文件上传核心思路

  • client问题
  • 服务器端如何获得文件上传的内容
  • 服务器端如何存储文件上传的内容
    Struts2学习笔记_第19张图片

文件上传开发步骤

客户端的处理

enctype="application/x-www-form-urlencoded" 把表单中的文本中的内容,提交到服务器中

method="post" action="" enctype="application/x-www-form-urlencoded"> form>

enctype="multipart/form-data" 告知服务器端识别客户端传入的文件内容

method="post" action="" enctype="multipart/form-data">
    type="file" name="upload" />
    type="submit" value="上传" />

服务器端创建一个文件夹,用于保存用户上传的文件

处理客户端上传的文件

public class uploadAction extends ActionSupport {
    private File upload;
    // 获取客户端传入的文件名和后缀
    private String uploadFileName;
    // 获取客户端传入的文件类型
    private String uploadContentType;

    // 文件存放的目录
    private String directory;

    public String getDirectory() {
        return directory;
    }

    public void setDirectory(String directory) {
        this.directory = directory;
    }

    public String getUploadContentType() {
        return uploadContentType;
    }

    public void setUploadContentType(String uploadContentType) {
        this.uploadContentType = uploadContentType;
    }

    public String getUploadFileName() {
        return uploadFileName;
    }

    public void setUploadFileName(String uploadFileName) {
        this.uploadFileName = uploadFileName;
    }

    public File getUpload() {
        return upload;
    }

    public void setUpload(File upload) {
        this.upload = upload;
    }

    public String upload() {
        /*InputStream is = null;
        OutputStream os = null;
        // 把文件读入IO流
        try {
            is = new FileInputStream(upload);
            // 把文件写出到文件系统中
            os = new FileOutputStream("D:\\Class3\\apache-tomcat-7.0.67\\webapps\\Strutspratice\\upload\\zkf.txt");
            byte[] buffer = new byte[1024];
            int len = 0;
            while (true) {
                // 读操作
                len = is.read(buffer, 0, buffer.length);
                if (len == -1)
                    break;
                // 写操作
                os.write(buffer, 0, len);
            }
            return "uploadOK";
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return "uploadError";
        } finally {
            try {
                // 关闭流
                is.close();
                os.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }*/
        try {
            System.out.println(uploadContentType);
            System.out.println(directory);
            FileUtils.copyFile(upload, new File(getRealPath(directory) + "\\" + uploadFileName));
            return "uploadOK";
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return "uploadError";
        }
    }

    public String getRealPath(String path) {
        ServletContext servletContext = ServletActionContext.getServletContext();
        // 获取绝对路径
        String realPath = servletContext.getRealPath(path);
        return realPath;

    }
}

文件上传(重构)

IO操作过于频繁,希望简化IO的处理

Commons-io.jar 提供文件操作的工具类

FileUtils.copyFile(upload, new File(getRealPath(directory) + "\\" + uploadFileName));
文件名

如何获得用户上传的文件名

private File upload;
// 获取客户端传入的文件名和后缀
private String uploadFileName;
// 获取客户端传入的文件类型
private String uploadContentType;
文件路径

如何在web开发中通过相对路径获取绝对路径

ServletContext sc = ServletActionContext.getServletContext();
String RealPath = ac.getRealPath(“相对路径”);
String RealPath = ac.getRealPath(“/upload”);
维护性差

文件目录转移到配置文件中进行配置

name="upload" class="fancylab.hibiscidai.Action.uploadAction" method="upload">
    name="directory>/upload

Action中声明成员变量即可

private String directory;
Struts2中上传的文件默认大小为2M

Struts2中上传的文件默认大小


<constant name="struts.multipart.maxSize" value="2097152000">constant>

下载

/struts-2.3.15.1/docs/WW/docs/stream-result.html stream-result

文件下载的核心思路

Struts2学习笔记_第20张图片

Struts2下载的步骤

extends ActionSupport

//目的告知Struts2将要下载的文件
public InputStream getInputStream() throws Exception {
    return new FileInputStream(getRealPath(directory) + "\\" + filename);
}
<result type="stream">
    
    <param name="contentType">text/plainparam>
    
    <param name="contentDisposition">attachment;filename=${filename}param>
result>

文件下载重构(优化)

完成路径的修改

通过getRealPath()方法与Action中为成员变量赋值的方式,完成路径的修改。

下载中如何处理用户需要下载的文件名字

客户通过传递参数的形式,向Action中传递数据,Action中通过成员变量接收数据。

<ul>
    <li>
        <a href="?filename=z.txt">
            z.txt
        a>
    li>
    <li>
        <a href="?filename=zkf.txt">
            zkf.txt
        a>
    li>
ul>
//获取客户端所要下载的文件名
private String filename;
解决用户下载之后的文件名
//获取客户端所要下载的文件名
private String filename;
<action name="download" class="com.baizhi.Action.downloadAction">
    <param name="directory">/uploadparam>
    <result type="stream">
        
        <param name="contentType">text/plainparam>
        
        <param name="contentDisposition"> attachment;filename=${filename}param>
    result>
action>

你可能感兴趣的:(前端)