Struts2第四天

Struts2第四天 html

昨天:前端

  1. 自定義的攔截器:繼續methodFilterInterceptor,能夠指定哪些方法須要攔截或者不攔截。

    Intercepters(配置攔截器),intercepter(自定義攔截器),配置自定義攔截器棧,把自定義的攔截器和默認的攔截器棧,放入自定義攔截器棧 java

    覆蓋默認的攔截器棧 mysql

  2. 值棧:root(list):通常都是操做棧頂數據,push方法,set方法(將數據存入到map中,最後將map壓入棧頂),map(map):put方法存入到map棧,特色是—key和value。Action的屬性能夠存入到值棧

    取值:[0].top s:property s:property value="key"(從root棧棧頂開始搜索,直到map棧,搜索到的第一個key返回),s:property value="#key":直接從map棧獲取數據。 jquery

  3. Ognl的用法:#--能夠從map棧獲取數據,包括servlet API中的數據。%--強制解析或者強制不解析。$--配置文件中獲取值棧數據
  4. Struts的標籤: 通用標籤(value是一個ognl表達式),表單標籤(name是一個ognl表達式)

 

 

今天的安排:web

 

  1. Struts2的文件上傳(fileUpload攔截器)
  2. Struts2的文件下載(stream結果集類型)
  3. 系統環境的準備:系統靜態頁面的導入、功能分析
  4. 數據庫的建立,原始數據的導入。(單表)
  5. 員工登陸功能。(更改struts標籤、表單驗證、國際化)
  6. 員工添加功能。(ajax請求+struts2的json插件,值棧的使用,文件(簡歷)上傳)
  7. 員工列表查詢功能。(查詢全部s:iterator標籤)

 

目標:ajax

  1. 業務功能:登陸、添加、列表查詢
  2. 技術點:struts2的基礎技術(表單驗證、國際化、標籤),json插件,文件上傳

     

     

    1. Struts2的文件的上傳

      1. 回顧文件的上傳

  • 客戶端:三個必須

    <form> 設置enctype編碼類型(MIME類型) multipart/form-data sql

    <form> 設置 method 提交方式 post 數據庫

    <input type="file"> 元素,必須提供name屬性 apache

  • 服務器

    apache commons-fileupload 組件

    jsp-smartupload 組件

    Servlet3.0 之後 API內置文件上傳API

    COS 文件上傳組件

 

  1. Struts2的文件上傳機制

Struts2 內部文件上傳,默認採用 apache commons-fileupload

    Struts2 默認導入文件上傳jar包

    

文件上傳不少代碼都是同樣的,那麼還須要咱們本身去寫嗎,有一個攔截器已經幫咱們封裝了大部分代碼

defaultStack 默認攔截器棧,提供 fileUpload的攔截器,用於實現文件上傳

 

  1. Struts2的文件上傳的實現

步驟一:建立工程環境

建立工廠、導包、配置前端控制器

 

步驟二:編寫upload.jsp 上傳文件表單

建立頁面

 

注意:編碼類型必定要寫好

Upload.jsp

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

    文件上傳: <input type="file" name="upload">

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

</form>

提示:也可使用struts標籤

<s:form action="uploadAction" namespace="/" enctype="multipart/form-data" method="post" theme="simple">

    文件上傳:<s:file name="upload"></s:file>

    <s:submit value="上傳"/>

</s:form>

 

Success.jsp:

<body>

<h1>文件上傳成功!</h1>

</body>

 

 

 

步驟二:編寫action

建立action

內容以下:

public class UploadAction extends ActionSupport{

    private File upload;//上傳的文件資源,必須和form表單中的上傳標籤中的name屬性一致

    private String uploadContentType;//文件類型

    private String uploadFileName;//文件名稱

    

    public void setUpload(File upload) {

        this.upload = upload;

    }

 

    public void setUploadContentType(String uploadContentType) {

        this.uploadContentType = uploadContentType;

    }

 

    public void setUploadFileName(String uploadFileName) {

        this.uploadFileName = uploadFileName;

    }

 

    @Override

    public String execute() throws Exception {

        FileUtils.copyFile(upload, new File("f:/upload/uploadFileName"));

        

        return super.execute();

    }

}

 

步驟三:Struts.xml:

<struts>

    <!-- 配置常量 -->

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

    <!-- 開啓國際化資源文件 -->

    <constant name="struts.custom.i18n.resources" value="message"></constant>

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

        <action name="uploadAction" class="cn.itcast.struts.upload.UploadAction">

            <result>/upload/success.jsp</result>

        </action>

    

    </package>

</struts>

 

步驟四:測試

上傳文件成功

 

 

  1. 文件上傳的參數設置

問題:上傳文件是否是什麼都能上傳,無論文件類型和文件大小都能上傳?

     顯然能夠設置文件上傳的限制

 

在struts2 文件上傳,存在一些限制參數,當違背參數,跳轉 input 視圖

 

 

找到上傳的攔截器:經過攔截器中的setter方法獲取參數

 

 

  1. 【知識點1】文件大小限制

經過在action中配置攔截器棧中的fileUpload攔截器的參數, 注意:該配置隻影響當前的action的文件上傳。

 

【示例】

 

步驟一:修改struts.xml:設置上傳文件的大小爲1m,只在當前action中生效

注意:顯示上傳單個文件大小校驗錯誤的信息使用<s:fielderror/>,由於struts默認超過單個上傳文件大小限制的錯誤屬於字段錯誤。

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

      

        <action name="uploadAction" class="cn.itcast.struts.upload.UploadAction">

        <interceptor-ref name="defaultStack">

                <param name="fileUpload.maximumSize">1097152</param>

        </interceptor-ref>

            <result>/upload/success.jsp</result>

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

        </action>

    

    </package>

 

 

步驟二:Jsp頁面:顯示錯誤信息

<body>

<!-- 顯示邏輯錯誤的信息 -->

<s:fielderror/>

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

    文件上傳: <input type="file" name="upload">

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

</form>

<hr>

<s:form action="uploadAction" namespace="/" enctype="multipart/form-data" method="post" theme="simple">

    文件上傳:<s:file name="upload"></s:file>

    <s:submit value="上傳"/>

</s:form>

 

</body>

 

步驟三:測試

上傳一個超過2m的文件

點擊上傳後結果:報錯,證實限制起做用了。

 

步驟四:修改錯誤信息提示

英文的錯誤若是看不懂能夠經過覆蓋配置文件常量來自行修改爲中文

更改默認的英文提示:

內置國際化:

找到默認的錯誤信息:

建立一個國際化文件,將默認的錯誤信息覆蓋:

 

 

步驟五:再次測試上傳錯誤類型的文件:錯誤信息已修改

 

步驟六:設置文件上傳的總大小

<!-- 設置文件上傳的總大小爲20m-->

    <constant name="struts.multipart.maxSize" value="209715200" />

 

步驟七:測試上傳超過總大小的文件,好比上傳30M的文件

在頁面顯示錯誤信息必須使用<s:actionerror/>,由於struts2默認爲這是一個邏輯錯誤,因此要使用<s:actionerror/>標籤

使用<s:actionerror/>標籤後錯誤信息顯示以下:

 

步驟八:將英文的錯誤信息修改爲中文的

仍是找到默認信息的配置文件:

經過錯誤信息的前面幾個英文進行查找,能夠找到錯誤信息的key

在message.properties中自定義錯誤信息:

再次測試上傳一個超過總大小限制的文件,好比30m的文件,錯誤信息顯示以下

 

  1. 【知識點2】文件類型設定

步驟一:在xml中配置文件類型的限制:

注意:顯示文件擴展名校驗錯誤的信息使用<s:fielderror>

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

      

        <action name="upload" class="cn.itcast.struts.upload.UploadAction">

        <interceptor-ref name="defaultStack">

            <param name="fileUpload.allowedExtensions">.jpg</param>

            <param name="fileUpload.maximumSize">2097152</param>

        </interceptor-ref>

            <result>/upload/success.jsp</result>

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

        </action>

    

    </package>

 

步驟二:修改頁面提示信息:

 

步驟三:測試

上傳一個.docx的文件

點擊上傳後結果:顯示文件後綴名錯誤

 

步驟四:修改錯誤信息提示

若是須要改爲中文的錯誤提示:能夠再次到內置國際化信息文件中找到對應的key並在自定義的messages.properties配置文件中配置

配置以下:

 

步驟五:再次測試

錯誤提示已改爲中文

 

  1. Struts2的文件的下載

 

  1. 回顧文件的下載

要點:一個流, 兩個頭信息

  • 使用輸入流,讀取須要下載的資源文件
  • 設置Content-Type頭信息:下載文件對應MIME協議的文件類型,經過servletContext.getMimeType(文件名) 獲取
  • 設置Content-Disposition 頭信息:控制下載文件的方式,好比瀏覽器內部打開或者以附件形式打開,attachment;filename=文件名

 

  1. Struts2的文件下載機制

 

Struts2 文件的下載,能夠經過結果集類型stream來實現。

所以注意:文件下載的action必須返回一個結果集視圖,而且該結果集視圖的類型必須是stream

 

 

download在struts中是個關鍵字,所以在使用struts.xml配置名稱的時候最好不要用,好比:

不然會報錯以下:

 

Stream結果集類型:

內容以下:

  1. 簡單示例

步驟一:action

注意:必定要返回結果集視圖

public class DownloadAction extends ActionSupport{

    

    @Override

    public String execute() throws Exception {

        InputStream inputStream = new FileInputStream(new File("f:/a.txt"));

        ActionContext.getContext().put("inputStream", inputStream);

        System.out.println("nihao");

        return SUCCESS;

    }

}

 

步驟二:struts.xml

<!-- 文件下載 -->

        <action name="downloadAction" class="cn.itcast.struts.download.DownloadAction">

            <result type="stream"></result>

        </action>

 

步驟三:測試

 

如上這種寫法,其文件的MIME類型以及下載方式已經被固定了,在stream中有默認的方式:

這顯然不符合咱們實際開發的需求,實際開發中,須要按照下載文件的類型來改變MIME類型,並且通常都是經過附件形式進行下載,見下方複雜示例

 

 

  1. 複雜示例

步驟一:Jsp頁面

建立頁面

內容以下:

<body>

<a href="${pageContext.request.contextPath }/downloadAction?filename=holiday.jpg">下載圖片</a>

<a href="${pageContext.request.contextPath }/downloadAction?filename=.mp3">下載mp3</a>

<a href="${pageContext.request.contextPath }/downloadAction?filename=a.txt">下載txt</a>

</body>

 

 

 

步驟二:Action

public class DownloadAction extends ActionSupport{

    

    private String filename;

    

    public void setFilename(String filename) throws Exception {

        filename=new String(filename.getBytes("iso8859-1"),"utf-8");

        this.filename = filename;

    }

 

    @Override

    public String execute() throws Exception {

        InputStream inputStream = new FileInputStream(new File("f:/"+filename));

        //經過文件名稱獲取mime類型

        String contentType = ServletActionContext.getServletContext().getMimeType(filename);

        

        //獲取瀏覽器的類型

        String agent = ServletActionContext.getRequest().getHeader("User-Agent");

        

        //附件名稱的編碼

        String encodeDownloadFilename = encodingFileNameUtil.encodeDownloadFilename(filename, agent);

        //將文件類型存入值棧

        ActionContext.getContext().put("contentType", contentType);

        //將輸入流存入值棧

        ActionContext.getContext().put("inputStream", inputStream);

        //以附件形式進行下載

        String contentDisposition="attachment;filename="+encodeDownloadFilename;

        //將下載類型存入到值棧

        ActionContext.getContext().put("contentDisposition", contentDisposition);

        return SUCCESS;

    }

}

 

步驟三:Struts.xml:

<!-- 配置文件下載 -->

        <action name="downloadAction" class="cn.itcast.struts.download.DownloadAction">

            <result type="stream">

                <param name="contentType">${#contentType}</param>

                <param name="contentDisposition">${#contentDisposition}</param>

            </result>

        </action>

 

步驟四:測試

執行結果

 

 

步驟五:分析

一個流和兩個頭,最終其實仍是從值棧中經過固定的key查詢出來的,所以咱們能夠直接將數據經過對應的key存入值棧就能夠了,而不須要去到struts.xml中配置參數。

Stream代碼:

 

  1. 項目開發環境的搭建

開發軟件:

考慮系統的架構:你要用什麼技術、要怎麼分層、要用什麼組件 。。。

咱們的架構:struts2+mysql+jquery+dbutil

 

  1. 構建strut2的環境

步驟一:建立工程並導入頁面

導入靜態頁面

效果以下:

 

 

步驟二:導入lib,共計16個

建立工具包,導入工具類和配置文件:

 

struts的lib+dbutil+數據驅動+c3p0

更改數據源配置:將數據源修改爲本身的數據庫配置

 

步驟三:配置文件

兩個配置文件(web.xml前端控制器-過濾器,核心配置文件struts2.xml)

前端控制器:

Struts.xml

 

  1. 環境測試

測試環境

請求地址:

顯示以下:

 

 

  1. 開發功能的分析

 

經過分析頁面效果, 要開發功能 :

一、 員工登錄

二、 員工添加 (上傳簡歷 )

三、 員工列表查詢 (多條件 組合查詢 )

四、 員工編輯(回顯,更新)

五、 員工詳細信息查看 (簡歷下載 )

六、 員工刪除 (阻止默認事件發生)

七、自定義攔截器

 

 

詳細功能:

* 要完成的功能:

* 把普通的html標籤替換爲struts2標籤

* 登陸

* 用戶名和密碼用struts2驗證框架進行驗證

 

* 首頁完善

* 顯示當前的用戶名

 

* 用戶的添加

包含文件上傳,配置參數(臨時路徑總開關 3三個配置 struts2驗證框架表單重複提交)

 

* 用戶的條件查詢

 

* 用戶的編輯(文件上傳)

 

* 用戶的修改

包含文件上傳,表單重複提交

 

* 用戶的刪除

 

* 查看

包含文件下載)

 

* 自定義攔截器(驗證用戶登陸)

 

 

 

  1. 數據庫的建立和數據的導入。

準備工具:mysql

 

  1. 創建數據庫,創建用戶,受權

通常企業開發的時候,不會用root用戶。root主要用來管理用。

通常咱們都創建新的用戶和數據,而後對應一個項目。

1.創建數據庫usermanage---root先登陸

編碼是跟你數據庫配置有關係。默認值在my.ini的文件中配置的,若是沒有配置默認編碼,那麼建議你手動選擇,不然會出現編碼問題。

[mysqld]

#服務端編碼配置

character-set-server=utf8

 

手動選擇:

 

2.創建用戶,而且受權

 

主機:%表明其餘任何的機器能夠訪問,localhost:本機能夠訪問

 

將剛纔創建的表受權給新建的用戶:

 

命令腳本:

grant all on struts2_em17.* to struts2_em17;

從新用新建的用戶登陸:

  1. 導入原始數據(表結構+基本數據)

#用戶表

CREATE TABLE S_User(

    userID INT NOT NULL AUTO_INCREMENT, #主鍵ID

    userName VARCHAR(50) NULL, #用戶姓名

    logonName VARCHAR(50) NULL, #登陸名

    logonPwd VARCHAR(50) NULL, #密碼#

    sex VARCHAR(10) NULL, #性別(例如:男,女)

    birthday VARCHAR(50) NULL, #出生日期

    education VARCHAR(20) NULL, #學歷(例如:研究生、本科、專科、高中)

    telephone VARCHAR(50) NULL, #電話

    interest VARCHAR(20) NULL, #興趣愛好(例如:體育、旅遊、逛街)

    path VARCHAR(500) NULL, #上傳路徑(path路徑)

    filename VARCHAR(100) NULL, #上傳文件名稱(文件名)

    remark VARCHAR(500) NULL, #備註

    PRIMARY KEY (userID)

) ;

 

#初始化數據:默認用戶名和密碼是admin

INSERT INTO s_user (userID,userName,logonName,logonPwd) VALUES (1,'超級管理員','admin','admin');

 

運行腳本:先選中數據庫,而後將腳本粘貼進窗口,而後運行:

刷新用F5

 

  1. 建立包層次

 

  1. 員工登陸功能。

  1. 需求功能分析

業務流程:當用戶輸入用戶名密碼後,若是經過,則跳到首頁,若是不經過,則跳回來。

分析:表單校驗。好比:不能不輸入。要求:用戶名和密碼必須都輸入。

後臺邏輯:當登陸成功了,將用戶放入session。

 

  1. 頁面標籤改爲struts標籤

目標:要將普通的表單,改形成struts2的表單。

爲何?struts表單,用起來比較方便,簡單,並且你用struts開發,用s標籤,能夠表單回顯。

 

運行發現樣式發生變化:

緣由是struts2有內置樣式,解決方案:將內置的樣式去掉。

struts.xml:

 

 

  1. 編寫登陸功能

 

  1. action

    public String login(){

        UserService userService = new UserService();

        User queryUser=userService.findUser(user);

        if (queryUser==null) {

            //添加錯誤提示信息

            this.addActionError("用戶名或者密碼錯誤!");

            return LOGIN;

        }else{    

            //登陸成功將信息存入到session

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

            return SUCCESS;

        }

  1. service層

public class UserService {

 

    public User findUser(User user) {

        UserDao userDao = new UserDao();

        return userDao.findUser(user);

    }

}

  1. dao層

public class UserDao {

 

    public User findUser(User user) {

 

        QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());

        String sql = "select * from s_user where logonName=? and logonPwd=?";

        try {

            return queryRunner.query(sql, new BeanHandler<User>(User.class),

                    user.getLogonName(), user.getLogonPwd());

        } catch (SQLException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

            throw new RuntimeException("根據用戶名和密碼查詢用戶失敗!");

        }

    }

}

  1. Struts.xml

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

        <!-- 用戶管理 -->

        <action name="user_*" class="cn.itcast.usermanage.web.UserAction" method="{1}">

            <result type="redirect">/login/home.jsp</result>

            <!-- 登陸校驗錯誤跳轉視圖 -->

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

        </action>

</package>

  1. 頁面添加錯誤提示

  1. 測試

登陸錯誤提示:

  1. 表單校驗

配置Xml校驗文件:

配置校驗文件:通常用局部校驗。(一個功能表單對應一個校驗,每一個表單的提示錯誤信息可能都不同。):格式:在action類的包中創建一個文件:action類名-action的名字-validation.xml

 

步驟一:建立校驗文件

校驗內容:

<validators>

    <field name="logonName">

        <field-validator type="requiredstring">

            <message key="LogonName.required"></message>

        </field-validator>

    </field>

    <field name="logonPwd">

        <field-validator type="requiredstring">

            <message key="LogonPwd.required"></message>

        </field-validator>

    </field>

</validators>

 

 

步驟二:配置國際化信息

內容:

 

步驟三:Action

登陸錯誤的信息提示從國際化信息文件中獲取

    public String login(){

        UserService userService = new UserService();

        User queryUser=userService.login(user);

        if (queryUser==null) {

            //添加錯誤提示信息

            this.addActionError(this.getText("LoginError"));

            return LOGIN;

        }else{    

            //登陸成功將信息存入到session

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

            return SUCCESS;

        }

    }

 

步驟四:Struts.xml

開啓國際化信息機制

具體配置內容:配置校驗失敗跳轉的結果集視圖

<struts>

    <!-- 配置一個開發者模式 -->

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

    <!-- 修改strute標籤樣式爲簡單樣式 -->

    <constant name="struts.ui.theme" value="simple"></constant>

    <!-- 開啓國際化信息機制 -->

    <constant name="struts.custom.i18n.resources" value="message"></constant>

    <!-- package: name:包名,必須保證惟一性 extends:繼承struts-default namespace:名稱空間 -->

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

        <!-- 設置action -->

        <action name="user_*" class="cn.itcast.struts.action.UserAction" method="{1}">

            <!-- 登陸失敗跳轉的結果集視圖 -->

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

            <!-- 若是登陸成功,跳轉到home.jsp -->

            <result type="redirect">/login/home.jsp</result>

            <!-- 配置字段校驗失敗跳轉的input結果集視圖 -->

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

        </action>

    </package>

</struts>

 

 

步驟五:jsp頁面

添加校驗錯誤提示

 

步驟六:測試

什麼都不寫提交表單

 

 

【擴展】

表單錯誤信息的局部顯示

 

樣式想跟在後面,須要手動更改模版。

 

 

  1. 錯誤信息補充

擴展補充:

關於struts2的這個三個:區別

  1. fieldError 用來存儲字段錯誤的信息,通常用於存放具體的字段校驗的錯誤,會和字段綁定。

  2. actionerror:用來存儲action範圍(request)內錯誤信息,這個存儲與具體字段無關的表單錯誤信息。

 

 

  1. 主頁顯示優化

優化一:

頁面顯示用戶名:並無顯示數據庫中的用戶名,顯然是寫死了。

找到所在的jsp頁面:

將原來寫死的數據改爲用EL表達式來從session中獲取。

 

優化二:

登陸成功後顯示頁面:

top.jsp頁面:

首頁重定向:

<!-- 用戶登陸 -->    

        <action name="user_*" class="cn.itcast.struts.actoin.UserAction" method="{1}">

            <!-- 配置登陸成功後須要響應的結果集視圖 -->

            <result type="redirect">/login/home.jsp</result>

            <!-- 登陸失敗後須要跳轉的結果集視圖 -->

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

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

        </action>

 

  1. 員工添加功能。

需求功能分析:將表單數據保存到數據庫

 

 

 

  1. jquery插件的使用

JQuery有不少插件,幫助咱們作一些效果或者功能。

 

jQuery官方+第三方都提供了一些插件(easyUI)。

 

官方的插件:jQuery ui

下載:

http://jqueryui.com

解壓查看全部插件效果(查看index.html便可):

集成方式:

步驟一:導入js庫和樣式:

 

步驟二:頁面引入:

參考使用:

Datepicker

 

步驟三:jqueryui.jsp

 

彈出的插件:

 

 

  1. 表單標籤修改爲struts標籤

將普通的form表單改爲struts表單

 

 

  1. 添加用戶-表單校驗

分析:

 

給登陸名、密碼、用戶姓名添加一個非空的針對方法的局部表單校驗

 

步驟一:action

新增一個add方法,須要作局部的表單校驗

public String add() throws IOException{

        System.out.println("新增用戶成功!");

        return SUCCESS;

    }

 

步驟二:添加xml局部校驗文件

 

 

步驟三:編寫的國際化信息

 

步驟四:頁面上顯示錯誤信息:

 

步驟五:測試

校驗錯誤跳轉input視圖,而此時咱們應該讓其從新跳轉到add.jsp,從新新增用戶。

錯誤緣由:struts.xml中咱們已經配置過一個登陸失敗時跳轉的input視圖,如今新增用戶校驗失敗的話也會跳轉到以前配置input視圖,但是這個input視圖配置的結果集並非咱們想要的,咱們在新增用戶校驗失敗的時候須要從新跳轉到新增用戶—add.jsp頁面。而一個action中只能配置一個input視圖,此時該怎麼辦?

分析:看workflow攔截器是否是有推薦的解決方案。

核心文件中:攔截器:負責錯誤頁面的跳轉:

進入到這個類中發現註釋中有使用標籤來修改結果集的簡介

 

 

步驟六:添加input視圖跳轉的註解

    //添加用戶

    //能夠手動更改校驗錯誤發生是跳轉的結果集視圖

    @InputConfig(resultName="addError")

    public String add(){

        System.out.println("用戶新增成功");

        return "add";

    }

Struts.xml:添加addinput視圖的跳轉

<!-- 設置action -->

        <action name="user_*" class="cn.itcast.struts.action.UserAction" method="{1}">

            <!-- 登陸失敗跳轉的結果集視圖 -->

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

            <!-- 若是登陸成功,跳轉到home.jsp -->

            <result type="redirect">/login/home.jsp</result>

            <!-- 配置字段校驗失敗跳轉的input結果集視圖 -->

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

            <!-- 配置校驗失敗的結果集視圖 -->

            <result name="addError">/user/add.jsp</result>

        </action>

 

步驟七:再次測試

結果:校驗錯誤後仍是返回add.jsp頁面,無誤。

 

  1. 編寫保存數據的代碼

保存的時候要注意兩個操做:

  1. 用戶信息的保存。
  2. 上傳簡歷文件的保存。

 

 

  1. 保存用戶信息(上傳簡歷除外)

步驟一:Action

    //添加用戶

    //能夠手動更改校驗錯誤發生是跳轉的結果集視圖

    @InputConfig(resultName="addError")

    public String add(){

        UserService userService = new UserService();

        userService.add(user);

        return "add";

    }

 

步驟二:Service

public void add(User user) {

        new UserDao().add(user);

    }

 

步驟三:Dao

    public void add(User user) {

        QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());

        String sql = "insert into s_user values(null,?,?,?,?,?,?,?,?,?,?,?)";

        try {

            queryRunner.update(sql, user.getUserName(), user.getLogonName(),

                    user.getLogonPwd(), user.getSex(), user.getBirthday(),

                    user.getEducation(), user.getTelephone(),

                    user.getInterest(), user.getPath(), user.getFilename(),

                    user.getRemark());

        } catch (SQLException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

            throw new RuntimeException("新增用戶失敗!");

        }

 

    }

步驟四:Struts.xml:

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

            <!-- 設置action -->

        <action name="user_*" class="cn.itcast.struts.action.UserAction" method="{1}">

            <!-- 登陸失敗跳轉的結果集視圖 -->

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

            <!-- 若是登陸成功,跳轉到home.jsp -->

            <result type="redirect">/login/home.jsp</result>

            <!-- 配置字段校驗失敗跳轉的input結果集視圖 -->

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

            <!-- 配置校驗失敗的結果集視圖 -->

            <result name="addError">/user/add.jsp</result>

            <!-- 配置新增用戶成功後跳轉的結果集視圖 -->

            <result name="add">/user/list.jsp</result>

        </action>

    </package>

步驟五:測試

測試保存:發現有兩個字段沒有數據,一個是路徑,一個是文件名,這兩個是和上傳簡歷有關的字段。

  1. 上傳簡歷

    1. 思路分析

思考:在簡歷上傳完成以後是否是要保存到一個指定的路徑,那麼這個路徑保存的時候要考慮會不會重複,所以須要給保存的文件設置一個隨機的不會重複的路徑。

 

 

在第四天的課前資料裏面有一個工具類,能夠自動生成一個隨機的文件名和二級目錄,能夠將該工具類複製到utils包下:

內容以下:

有了隨機的目錄和文件名,只要再指定一個盤符保存就好了,爲了使用方便,這個盤符咱們能夠設置成一個常量,而這個常量咱們也能夠建立一個類來調用它,以下:這個常量好處是節省資源,只會初始化一次。

內容以下:其實只是一個保存路徑的前半段而已。

 

上傳文件須要注意的要點:

一、form表單提交方式必須是post,enctype屬性必須是= multipart/form-data

二、必須有一個上傳文件的標籤

 

開始編寫上傳邏輯

 

保存分兩步進行:

第一步:先保存文件到服務器

依賴於攔截器:

 

  1. 編寫上傳簡歷業務邏輯

 

步驟一:action

添加上傳文件須要的屬性

以上這三個屬性原來咱們是直接寫在action中的,可是顯示若是分了三層以後上傳的邏輯更加適合寫在service層中,而爲了傳遞參數方便,所以咱們能夠將這個三個屬性寫到user對象中去而且提供getter和setter方法,這樣傳遞到service層進行業務邏輯處理的時候顯然方便不少。。

修改user:

在add方法中添加上傳邏輯:

//新增用戶

    @InputConfig(resultName="addError")

    public String add(){

        

        UserService userService = new UserService();

        userService.add(user);

        return "add";

    }

 

步驟二:service添加上傳邏輯

    public void add(User user) {

        try {

            //添加一個用戶是否上傳文件的判斷,避免空指針錯誤

            if (user.getUpload()!=null) {

                String uploadFileName = user.getUploadFileName();

                //生成一個uuid文件名

                String uuid = UploadUtils.generateRandonFileName(uploadFileName);

                //生成一個二級目錄

                String dir = UploadUtils.generateRandomDir(uuid);

                //生成一個指定保存簡歷的路徑

                String realPath=SystemConstant.Default_DIR+dir+"/"+uuid;

                user.setPath(realPath);

                user.setFilename(uploadFileName);

                File upload = user.getUpload();

                //保存簡歷到指定的路徑

                FileUtils.copyFile(upload, new File(realPath));

            }

            new UserDao().add(user);

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

 

步驟三:測試

上傳成功

 

 

步驟四:設置上傳簡歷的大小和後綴名

文件上傳大小的設置:

struts.xml文件中的大小與實際文件大小的關係:1048576(Bytes) = 1024*1024 = 1M實際文件大小。

struts有兩個地方來限制文件上傳大小的!

1)核心配置文件中的常量

 

2)在struts.xml中的action標籤裏配置:

局部的文件上傳參數:

<action name="user_*" class="cn.itcast.usermanage.web.UserAction"

            method="{1}">

            <!-- 設置局部上傳文件大小和擴展名 -->

            <interceptor-ref name="defaultStack">

                <param name="fileUpload.maximumSize">2097152</param>

                <param name="fileUpload.allowedExtensions">.doc,.avi,.docx,.txt,.mp3</param>

            </interceptor-ref>

<!-- 登陸失敗跳轉的結果集視圖 -->

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

 

            <result type="redirect">/login/home.jsp</result>

            <!-- 登陸校驗錯誤跳轉視圖 -->

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

            <result name="add">/user/list.jsp</result>

<!-- 新增用戶校驗錯誤跳轉視圖 -->

            <result name="addError">/user/add.jsp</result>

        </action>

或者在package設置全局的文件上傳參數:

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

        <!-- 設置全局上傳文件的大小和擴展名 -->

        <interceptors>

            <interceptor-stack name="mydefault">

                <interceptor-ref name="defaultStack">

                    <!-- 限制上傳文件大小 -->

                    <param name="fileUpload.maximumSize">2097152</param>

                    <!-- 限制上傳文件擴展名 -->

                    <param name="fileUpload.allowedExtensions">.doc,.avi,.docx,.txt,.mp3</param>

                </interceptor-ref>

            </interceptor-stack>

        </interceptors>

        <!-- 覆蓋默認攔截器棧 -->

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

        <!-- 用戶管理 -->

        <action name="user_*" class="cn.itcast.usermanage.web.UserAction"

            method="{1}">

<!-- 登陸失敗跳轉的結果集視圖 -->

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

 

            <result type="redirect">/login/home.jsp</result>

            <!-- 登陸校驗錯誤跳轉視圖 -->

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

            <result name="add">/user/list.jsp</result>

<!-- 新增用戶校驗錯誤跳轉視圖 -->

            <result name="addError">/user/add.jsp</result>

</action>

    </package>

上面局部和全局的兩選其一便可

 

步驟三:測試

上傳一個4M的文件:報錯出現內置錯誤提示

 

 

 

問題:文件大小在全局設置和局部設置,這兩種有什麼區別:

  • 全局常量配置的struts.multipart.maxSize掌控整個項目所上傳文件的最大的Size(默認2m),超過了這個size,後臺報錯,程序處理不了如此大的文件。fielderror裏面會有以下的提示:

the request was rejected because its size (16272982) exceeds the configured maximum (9000000)

或者以下:

又或者服務器系統就直接拋出沒有響應的錯誤。

或者

  • action中配置的,是針對一次上傳的文件大小。這個大小不能超過全局常量的配置,不然要麼超過了報錯,要麼無效。

當上傳的文件在struts.multipart.maxSize和maximumSize之間時,系統提示:

File too large: file "MSF的概念.ppt" "upload__5133e516_129ce85285f__7ffa_00000005.tmp" 6007104

 

結論:全局通常設置大一些,局部的通常根據要求設置。

 

【錯誤信息的國際化覆蓋】

找到錯誤信息提示:

覆蓋:將該錯誤提示信息寫如message.properties國際化文件中

用中文覆蓋原提示便可

再次測試:

 

 

 

 

 

  1. 添加功能優化-異步請求用戶名是否重複

需求:若是用戶名在數據庫中已經存在,那麼我將提醒用戶,而且不容許提交。

技術:ajax

開發分析:失去焦點後,登陸名後面提示,提交按鈕禁用掉。

 

修改頁面,增長ajax的前端代碼:使用異步請求接收響應的json數據。

 

問題:爲何不能直接將數據存入值棧,而後頁面獲取值棧信息進行判斷用戶是否存在呢?

緣由:異步請求,當回調函數獲取data數據的時候,響應已經結束了,而值棧的生命週期是從一個請求開始到響應結束,所以值棧的生命週期已通過了,值棧內沒有數據了。

 

struts內置了json的轉換器(可以自動將java對象轉換成json,而且能夠自動放入響應reponse中)。struts2-json-plugin插件中。

能自動將值棧中的某個對象,自動轉換成json,而且自動放入響應。

咱們就只須要將要異步請求的結果,放入值棧就能夠了。插件會自動去拿。

注意:須要修改<package name="default" namespace="/" extends="json-default">

  1. 導入json插件包

  1. 頁面代碼    

首先在登陸名標籤下面添加一個span標籤用來添加提示信息

其次能夠經過該標籤的html來添加提示信息。

 

$(document).ready(function(){

            //使用class屬性處理 'yy-mm-dd' 設置格式"yyyy/mm/dd"

            $('#birthday').datepick({dateFormat: 'yy-mm-dd'});

            

            $("#userAction_save_do_logonName").blur(function(){

                $.post("${pageContext.request.contextPath}/user_checkUserExist",{"logonName":$(this).val()},function(data){

                    

                    if(!data.isExist){

                        $("#checkUser").html("<font color='green'>能夠註冊!</font>");

                        $("#userAction_save_do_submit").removeAttr("disabled");

                    }else{

                        $("#checkUser").html("<font color='red'>登陸名已存在!</font>");

                        $("#userAction_save_do_submit").attr({"disabled":"disabled"});

                    }

                

                });

            

            });

        });

  1. 編寫異步請求Action

    /**

     * 異步請求校驗登陸名是否存在

     * @return

     */

//異步請求校驗,檢查登陸名是否存在

    public String checkUserExist(){

        UserService userService = new UserService();

        User queryUser=userService.checkUserExist(user);

        Map map = new HashMap();

        if (queryUser==null) {

            map.put("isExist", false);

        }else{

            map.put("isExist", true);

        }

        //第一種轉換成json數據的方法:壓入棧頂

        /*ActionContext.getContext().getValueStack().push(map);*/

        //第二種轉換成json數據的方法:將數據存入到值棧

        ActionContext.getContext().put("json", map);

        return "checkUserExist";

}

 

 

  1.     Struts.xml

修改package的繼承包:

配置結果集:

<!-- 用戶登陸 -->

        <action name="user_*" class="cn.itcast.struts.action.UserAction" method="{1}">

            <!-- 登陸失敗跳轉的結果集視圖 -->

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

            <!-- 若是登陸成功,跳轉到home.jsp -->

            <result type="redirect">/login/home.jsp</result>

            <!-- 配置字段校驗失敗跳轉的input結果集視圖 -->

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

            <!-- 配置校驗失敗的結果集視圖 -->

            <result name="addError">/user/add.jsp</result>

            <!-- 配置新增用戶成功後跳轉的結果集視圖 -->

            <result name="add">/user/list.jsp</result>

            <!-- 轉換成json數據必須使用json的結果集類型:第一種寫法 -->

            <!-- <result name="checkUserExist" type="json"></result> -->

            <!-- 轉換成json數據必須使用json的結果集類型:第二種寫法 -->

            <result name="checkUserExist" type="json">

                <param name="root">json</param>

            </result>

        </action>

  1. 測試

測試無誤

  1. 分析

打開json插件包下的struts-plugin.xml

原理:

怎麼進行響應數據?

響應的數據怎麼來的?

由此原理分析可見,響應json數據有兩種寫法

  • 若是root屬性存在,則將根據root屬性的值在值棧中尋找對應的值;(推薦)
  • 若是root屬性不存在,則直接將棧頂的元素拿到。

     

 

 

 

步驟三:測試

測試效果和第一種方法一致。

 

問題:爲何不在struts.xml中使用$以下取數據?

區別:

${ognl表達式},你在xml等配置文件中,直接要獲取值棧中的某個值的時候,用這個。

而在源碼中須要的root是一個參數,這個參數是一個字符串:

  1. 員工列表查詢功能。

無條件查詢

分析功能:

將數據從數據庫查詢出來,放入值棧,頁面使用struts的循環標籤(<s:iterator>)進行打印便可。

 

  1. 頁面請求

/login/left.jsp

  1. 編寫action

    /**

     * 查找全部用戶

     * @return

     */

//查詢全部用戶

    public String list(){

        UserService userService = new UserService();

        List<User> userList=userService.queryList();

        //將查到的全部用戶存入到值棧

        ActionContext.getContext().put("userList", userList);

        return "list";

    }

 

Service:

// 查詢全部用戶

    public List<User> queryList() {

        UserDao userDao = new UserDao();

        List<User> userList = userDao.queryList();

        return userList;

    }

    

dao:

//查詢全部用戶

    public List<User> queryList() {

        QueryRunner runner = new QueryRunner(JDBCUtils.getDataSource());

        String sql = "select * from s_user";

        try {

            return runner.query(sql, new BeanListHandler<User>(User.class));

        } catch (SQLException e) {

            throw new RuntimeException("異步校驗檢查用戶是否存在失敗!");

        }

    }

  1. List.jsp頁面顯示

導入strut是標籤

將原來寫死的數據刪除後替換以下:

<s:iterator value="userList" var="user">

                                        <tr onmouseover="this.style.backgroundColor = 'white'"

                                            onmouseout="this.style.backgroundColor = '#F5FAFE';">

                                            <td style="CURSOR: hand; HEIGHT: 22px" align="center"

                                                width="18%">

                                                <s:property value="logonName"/>|<s:property value="#user.logonName"/>|${logonName }

                                            </td>

                                            <td style="CURSOR: hand; HEIGHT: 22px" align="center"

                                                width="17%">

                                                <s:property value="userName"/>|<s:property value="#user.userName"/>|${userName }

                                            </td>

                                            <td style="CURSOR: hand; HEIGHT: 22px" align="center"

                                                width="8%">

                                                <s:property value="sex"/>|<s:property value="#user.sex"/>|${user.sex }

                                            </td>

                                            <td style="CURSOR: hand; HEIGHT: 22px" align="center"

                                                width="23%">

                                                <s:property value="telephone"/>|<s:property value="#user.telephone"/>|${telephone }

                                            </td>

                                            <td style="CURSOR: hand; HEIGHT: 22px" align="center">

                                                <s:property value="education"/>|<s:property value="#user.education"/>|${education }

                                            </td>

                                            <td align="center" style="HEIGHT: 22px">

                                                <a href="${pageContext.request.contextPath}/user/edit.jsp?userID=15">

                                                    <img src="${pageContext.request.contextPath}/images/i_edit.gif" border="0" style="CURSOR: hand">

                                                </a>

                                            </td>

                                            <td align="center" style="HEIGHT: 22px">

                                                <a href="${pageContext.request.contextPath}/user/view.jsp?userID=15">

                                                    <img src="${pageContext.request.contextPath}/images/button_view.gif" border="0" style="CURSOR: hand">

                                                </a>

                                            </td>

                                            <td align="center" style="HEIGHT: 22px">

                                                <a href="${pageContext.request.contextPath}/user/list.jsp?userID=15">

                                                    <img src="${pageContext.request.contextPath}/images/i_del.gif" width="16" height="16" border="0" style="CURSOR: hand">

                                                </a>

                                            </td>

                                        </tr>

                                    </s:iterator>

 

  1. struts.xml

當新增用戶成功以後,跳轉回查詢列表頁面:

 

    <!-- 設置action -->

        <action name="user_*" class="cn.itcast.struts.action.UserAction" method="{1}">

            <!-- 登陸失敗跳轉的結果集視圖 -->

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

            <!-- 若是登陸成功,跳轉到home.jsp -->

            <result type="redirect">/login/home.jsp</result>

            <!-- 配置字段校驗失敗跳轉的input結果集視圖 -->

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

            <!-- 配置校驗失敗的結果集視圖 -->

            <result name="addError">/user/add.jsp</result>

            <!-- 配置新增用戶成功後跳轉的結果集視圖 -->

            <result name="add">/user/list.jsp</result>

            <!-- 轉換成json數據必須使用json的結果集類型:第一種寫法 -->

            <!-- <result name="checkUserExist" type="json"></result> -->

            <!-- 轉換成json數據必須使用json的結果集類型:第二種寫法 -->

            <result name="checkUserExist" type="json">

                <param name="root">json</param>

            </result>

            <!-- 查詢全部用戶成功後條件結果集視圖 -->

            <result name="list">/user/list.jsp</result>

        </action>

 

  1. 測試

新增用戶後跳轉到list.jsp,而且顯示全部用戶信息,測試無誤。

 

 

 

 

  1. 重點和小結

邏輯執行的流程圖:

小結

 

做業:

一、今天的練習。

二、上傳簡歷的添加文件大小和文件類型的限制。

三、作完以後:將條件查詢作完。。*(就是一個sql拼接,改表單-數據模型有對應的屬性)

相關文章
相關標籤/搜索