Struts2學習筆記

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>A</servlet-name>
    <servlet-class>xxx.servlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>A</servlet-name>
    <url-pattern>/A</url-pattern>
</servlet-mapping>

對於Struts.xml的配置

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

第一個Struts2程序的開發

搭建開發環境

引入核心jar包

struts2-core-2.3.15.1.jar

引入第三方jar包

引入Struts.xml配置文件

配置Struts2核心過濾器

在web.xml中聲明

<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>  

對於不同版本會有兼容問題,注意 filter-class 標籤映射類

開發步驟

實現Action接口

配置文件配置

Struts2配置文件配置

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跳轉

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

Redirect跳轉

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

Action跳Action

Forward跳轉

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

Redirect跳轉

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

包 < PACKAGE >

使配置文件當中的配置信息模塊化,便於配置信息的管理。

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

命名空間 < NAMESPACE >

使用戶的請求模塊化,便於隨後過濾器的使用。

web.xml配置

<servlet>
    <servlet-name>A</servlet-name>
    <servlet-class>fancylab.hibiscidai.action.AAction</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>A</servlet-name>
    <url-pattern>/User/A</url-pattern>
</servlet-mapping>
<servlet>
    <servlet-name>A</servlet-name>
    <servlet-class>fancylab.hibiscidai.action.AAction</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>A</servlet-name>
    <url-pattern>/User/B</url-pattern>
</servlet-mapping>
<filter>
/User/*
</filter>

訪問方式:localhost:[port]/ProjectName/A

Struts2 包空間加入後
struts.xml配置

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

訪問方式:localhost:[port]/ProjectName/namespace/A

跨包間的跳轉

<result name="D" type="chain">
    <param name="namespace">/second</param><!--目標包的namespace-->
    <param name="actionName">D</param><!--目標包下的目標Action-->
</result>

全局跳轉

當許多Action跳轉到相同路徑時,可以定義全局跳轉,減少配置文件當中的配置信息冗餘。

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

注意事項

  • 只在本包內有效
  • 局部配置優先

STRUTS2接收CLIENT的參數(重點)

收集客戶端的零散數據

login.jsp

<input type="text" name="username">
<input type="password" name="password">
<input 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

用戶名<input type="text" name="user.username">
密碼<input type="password" name="user.password">
年齡<input type="text" name="user.age">
日期<input type="date" name="user.birthdate">
<input 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);
    }
}

通過數組或集合的形式收集客戶端的數據

  • 批量刪除
  • 用戶勾選多個選項時
<input type="checkbox" value="1" name="a">
<input type="checkbox" value="2" name="a">
<input 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中的數據處理機制

數據處理機制:數據在網站中的流轉
數據處理機制-servlet-struts2

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<String> 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<String, String> 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<String,Person> contextmap = new HashMap<String,Person>();  
    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

值棧的內存結構
值棧的內存結構

值棧的注意事項

問題:值棧是一次請求有效,爲什麼可以管理session application作用域?
值棧注意事項

STRUTS中的標籤(上)

作用:配合值棧在視圖層顯示數據
引用:
JSTL標籤:

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

Strtus標籤:

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

顯示數據

顯示單個數據

<s:property value="OGNL表達式" />
  • 單一流程
<s:if test="OGNL表達式" />
</s:if>
<s:else>
</s:else>
  • 非單一流程
<s:if test="OGNL表達式">
</s:if>
<s:elseif test="OGNL表達式" />
</s:elseif>
<s:else>
</s: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">
    <!--取map的鍵-->
    <h1><s:property value="key"/></h1>
    <h1>==========</h1>
    <!--取map的值-->
    <h1><s:property value="value"/></h1>
</s:iterator>
從數組或集合中顯示數據(String類型和8種基本類型)
<s:iterator value="#request.s">
    <s:property/>
</s:iterator>
遍歷狀態
<s:iterator value="OGNL" status="s">
    #s.count      遍歷次數
    #s.index      遍歷的下標
    #s.odd       是否是奇數遍歷
    #s.even      是否是偶次遍歷
</s:iterator>
<s:iterator value="OGNL" begin="" end="" Step="">
</s:iterator>

begin:從某一個下標開始遍歷
end:以某一個下標結束
step:步幅

查詢所有的思路:
查詢所有的思路

STRUTS2數據處理機制的補充

Action中的成員變量替換request作用域

Action中的成員變量替換request作用域
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的內存結構
    debug使用

總結:現有STRUTS2的開發步驟

debug開發步驟

STRUTS標籤(續)

<s:date/>

語法:<s:date name="OGNL" format="自定義日期類型" />
作用:自定義日期的格式

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

<s:url/>

語法:<s:url action="" namespace=""/><s:url value=""/>
作用:防止用戶禁用Cookie,自動進行url重寫。加載第三方資源。
注意:傳值<s:url action="" namespace=""/>?id=41

s標籤中與html相關的UI標籤

<s:form></s:form>———-><form></form>
<s:head/> ———-><head></head>
<s:text name=""></s:text>———-><input type="text"/>
<s:date name=""/>———-><input type="date"/>

<s:action />

語法:<s:action name="" namespace="" executeResult="" />
作用:把多個Action的處理結果作整合

針對於前臺視圖

傳統思路
傳統首頁顯示方式
Struts解決方案
Struts解決前臺首頁

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攔截響應

中斷請求

Struts2中斷請求

攔截器只在本包中有效

簡化攔截器開發 繼承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
    目的:接收客戶端的請求參數
    param攔截器
  • fileupload
  • Exception
  • workflow

默認攔截器放置的位置

Struts2-core.jar —->Struts-default.xml
Struts-default.xml
注意:如果自定義了默認攔截器棧,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強制登錄

防止用戶重複提交(令牌環)

  • 發生場景
    在用戶進行表單提交時,因爲網絡通信等問題,產生重複的表單提交
  • 解決方案
    令牌環
  • 令牌環實現原理
    令牌環實現原理

Struts2令牌環解決思路

客戶端生成隨機數

<s:token></s:token>

配置token攔截器

引入Struts2提供的token攔截器

<interceptor-stack name="my1">
    <interceptor-ref name="token"></interceptor-ref>
    <interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>

提供跳轉目標頁面

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

STRUTS2中的高級部分

上傳

文件上傳核心思路

  • client問題
  • 服務器端如何獲得文件上傳的內容
  • 服務器端如何存儲文件上傳的內容
    文件上傳核心思路

文件上傳開發步驟

客戶端的處理

enctype="application/x-www-form-urlencoded" 把表單中的文本中的內容,提交到服務器中

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

enctype="multipart/form-data" 告知服務器端識別客戶端傳入的文件內容

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

服務器端創建一個文件夾,用於保存用戶上傳的文件

處理客戶端上傳的文件

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”);
維護性差

文件目錄轉移到配置文件中進行配置

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

Action中聲明成員變量即可

private String directory;
Struts2中上傳的文件默認大小爲2M

Struts2中上傳的文件默認大小

<!--指定Struts2中 文件上傳大小的上限-->
<constant name="struts.multipart.maxSize" value="2097152000"></constant>

下載

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

文件下載的核心思路

Struts2文件下載核心思路

Struts2下載的步驟

extends ActionSupport

//目的告知Struts2將要下載的文件
public InputStream getInputStream() throws Exception {
    return new FileInputStream(getRealPath(directory) + "\\" + filename);
}
<result type="stream">
    <!-- 指定文件下載類型 -->
    <param name="contentType">text/plain</param>
    <!-- inline代表瀏覽器下載之後直接打開 attachment以附件的形式進行下載 filename下載之後的文件名 -->
    <param name="contentDisposition">attachment;filename=${filename}</param>
</result>

文件下載重構(優化)

完成路徑的修改

通過getRealPath()方法與Action中爲成員變量賦值的方式,完成路徑的修改。

下載中如何處理用戶需要下載的文件名字

客戶通過傳遞參數的形式,向Action中傳遞數據,Action中通過成員變量接收數據。

<ul>
    <li>
        <a href="<s:url action='download' namespace='/user' />?filename=z.txt">
            z.txt
        </a>
    </li>
    <li>
        <a href="<s:url action='download' namespace='/user' />?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">/upload</param>
    <result type="stream">
        <!-- 指定文件下載類型 -->
        <param name="contentType">text/plain</param>
        <!-- inline代表瀏覽器下載之後直接打開 attachment以附件的形式進行下載 filename下載之後的文件名 -->
        <param name="contentDisposition"> attachment;filename=${filename}</param>
    </result>
</action>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章