[手把手教程][JavaWeb]優(yōu)雅的SpringMvc+Mybatis應(yīng)用(四)

優(yōu)雅的SpringMvc+Mybatis應(yīng)用(四)

轉(zhuǎn)眼間文章已經(jīng)到了第四期了胡嘿。堅(jiān)持做一件事,確實(shí)是很難的拓瞪。特別是要不斷的轉(zhuǎn)換思維祭埂,一個(gè)習(xí)慣前端開(kāi)發(fā)的人蛆橡,做什么還是前端的考慮的多一點(diǎn)泰演,后端的架構(gòu)設(shè)計(jì)之類的粥血,現(xiàn)在還談不上,一切穩(wěn)穩(wěn)的前進(jìn)就行了缭嫡。

關(guān)于上一期妇蛀,本來(lái)是投了首頁(yè)的评架,后來(lái)不知道什么原因沒(méi)上纵诞,檢查了一下浙芙,也就是推薦了下自己的博客和github嗡呼,有點(diǎn)惆悵南窗。

工具

  • IDE為idea15
  • JDK環(huán)境為1.8
  • maven版本為maven3
  • Mysql版本為5.5.27
  • Tomcat版本為7.0.52
  • 流程圖繪制(xmind)

本期目標(biāo)

  • 登錄注冊(cè)的簡(jiǎn)單體驗(yàn)優(yōu)化
  • 完整的后臺(tái)主頁(yè)
  • 前端使用json數(shù)據(jù)
  • 列表數(shù)據(jù)分頁(yè)

注冊(cè)登錄的簡(jiǎn)單體驗(yàn)優(yōu)化

上一期我們注冊(cè)登錄都成功了万伤,但是后臺(tái)主頁(yè)顯示很丑陋壕翩,所以這里我換了個(gè)主頁(yè)放妈,但是前面沒(méi)有注意到的細(xì)節(jié)又看到了芜抒。如下圖:

ssm應(yīng)用四-注冊(cè)成功-地址欄錯(cuò)誤
ssm應(yīng)用四-注冊(cè)成功-地址欄錯(cuò)誤

在上面的圖中攘宙,地址欄顯示的地址是前面注冊(cè)接口的地址蹭劈,并不是我們常規(guī)看到的xxx/home這種主頁(yè)地址铺韧。所以我們需要進(jìn)行優(yōu)化處理哈打。

同時(shí)料仗,我們可以看到我們的Form表單提交的提示信息是在新產(chǎn)生的ModelAndView界面里面addObject("字段名",數(shù)據(jù))立轧,這樣我們的數(shù)據(jù)都顯示到新的界面去了肺孵。也就是說(shuō)前面的設(shè)計(jì)不合符現(xiàn)在主流的開(kāi)發(fā)思路平窘,用戶體驗(yàn)也相對(duì)糟糕瑰艘。我們需要做到在登錄界面前端效驗(yàn)數(shù)據(jù)紫新,同時(shí)登錄注冊(cè)的提示信息也是在對(duì)應(yīng)的界面完成的芒率。如下:

ssm應(yīng)用四-前端form錯(cuò)誤-提示示例
ssm應(yīng)用四-前端form錯(cuò)誤-提示示例

值得注意的是:為了程序執(zhí)行效率偶芍、數(shù)據(jù)完整性和程序健壯性椎麦,我們的前端必須做對(duì)應(yīng)的基礎(chǔ)數(shù)據(jù)效驗(yàn)观挎,后端的控制器必須做所有需要的數(shù)據(jù)的效驗(yàn)嘁捷。

  • 前端數(shù)據(jù)效驗(yàn)我們使用js完成
  • 前端界面樣式是由CSS完成
  • 網(wǎng)絡(luò)請(qǐng)求采用異步請(qǐng)求雄嚣,具體的實(shí)現(xiàn)是使用的ajax完成
  • js獲取web頁(yè)面數(shù)據(jù)統(tǒng)一使用標(biāo)簽的ID,格式為:$("#標(biāo)簽ID")
  • web頁(yè)面標(biāo)簽最好一個(gè)標(biāo)簽一行履肃,這樣代碼看起來(lái)更加舒服

我們先重構(gòu)登錄頁(yè)面:
首先尺棋,我不擅長(zhǎng)寫web頁(yè)面,我能做的也就是少量的修改荆残,CSS和js本身不是我的強(qiáng)項(xiàng)内斯,需要大量的時(shí)間來(lái)磨合俘闯。

所以真朗,我選擇了在網(wǎng)上找web界面遮婶,然后自己做少量的修改蹭睡,同時(shí)一些簡(jiǎn)單的小控件我也從網(wǎng)絡(luò)獲取資源來(lái)解決需要肩豁,合理的查找資源是最快的學(xué)習(xí)方法琼锋。

登錄頁(yè)面重構(gòu)目標(biāo):

  • web前端完成基本的數(shù)據(jù)效驗(yàn)
  • 數(shù)據(jù)效驗(yàn)完成后缕坎,有基本的對(duì)應(yīng)提示谜叹。如上面登錄界面的小標(biāo)簽荷腊。
  • 異步登錄
  • 后端接口返回?cái)?shù)據(jù)為json
  • 前端頁(yè)面解析json控制程序流轉(zhuǎn)

首先女仰,按照上面的提示疾忍,我們可以知道的是前端頁(yè)面上面的基本數(shù)據(jù)效驗(yàn)是要使用js完成的,同時(shí)js中獲取web頁(yè)面標(biāo)簽的數(shù)據(jù)是需要使用標(biāo)簽的ID完成擒抛,簡(jiǎn)單的示例如下:

<script type="text/javascript">
    function webLogin() {   //定義一個(gè)名為webLogin的js函數(shù)(在java中我們稱呼函數(shù)為方法)
        var loginname = $("#u").val();  
        //var是申明一個(gè)變量的關(guān)鍵字歧沪,loginname為變量名诊胞,
        //$("#u")是找到一個(gè)標(biāo)簽ID為"u"的標(biāo)簽暖夭,.val() 是獲取對(duì)應(yīng)ID標(biāo)簽的值
        if ("" == loginname) {  //u標(biāo)簽的值為空
            //只有通過(guò) $("#u") 的形式才能獲取一個(gè)標(biāo)簽。
            $("#u").tips({  // .tips 是js提示標(biāo)簽的調(diào)用方法撵孤,具體的輪廓如上面的登陸頁(yè)面的提示標(biāo)簽
                side: 2,    
                msg: '用戶名不得為空',  //提示的信息
                bg: '#AE81FF',  //背景色
                time: 3 //呈現(xiàn)的時(shí)間
            });
            $("#u").focus();    //讓u標(biāo)簽獲取輸入焦點(diǎn)
            return false;   //返回false迈着,打斷js的執(zhí)行
        }
        
        var loginpwd = $("#p").val();  
        if (loginpwd == "") {
            $("#p").tips({
                side: 2,
                msg: '密碼不得為空',
                bg: '#AE81FF',
                time: 3
            });
            $("#p").focus();
            return false;
        }
        
        $.ajax({    //使用jquery下面的ajax開(kāi)啟網(wǎng)絡(luò)請(qǐng)求
                type: "POST",   //http請(qǐng)求方式為POST
                url: '<%=request.getContextPath()%>/userAction/login',  //請(qǐng)求接口的地址
                data: {loginId: loginname, pwd: loginpwd},  //存放的數(shù)據(jù),服務(wù)器接口字段為loginId和pwd邪码,分別對(duì)應(yīng)用戶登錄名和密碼
                dataType: 'json',   //當(dāng)這里指定為json的時(shí)候裕菠,獲取到了數(shù)據(jù)后會(huì)自動(dòng)解析的,只需要 返回值.字段名稱 就能使用了
                cache: false,   //不用緩存
                success: function (data) {  //請(qǐng)求成功闭专,http狀態(tài)碼為200。返回的數(shù)據(jù)已經(jīng)打包在data中了影钉。
                    if (data.code == 1) {   //獲判斷json數(shù)據(jù)中的code是否為1画髓,登錄的用戶名和密碼匹配,通過(guò)效驗(yàn)平委,登陸成功
                        window.location.href = "<%=request.getContextPath()%>/mvc/home";    //跳轉(zhuǎn)到主頁(yè)
                    } else {    //登錄不成功
                        alert(data.msg);    //彈出對(duì)話框奈虾,提示返回的錯(cuò)誤信息
                        $("#u").focus();
                    }
                }
            });
    }
</script>

上面的注釋已經(jīng)能很明顯的看出我們的 前端效驗(yàn)、網(wǎng)絡(luò)請(qǐng)求和js解析json廉赔,下面我們?cè)谇岸隧?yè)面中調(diào)用這個(gè)js肉微,如下:

<form action=""     //此處必須刪掉form表單的地址
    name="loginform"
    accept-charset="utf-8" 
    id="login_form" 
    class="loginForm"
    method="post">
        <input type="hidden" name="did" value="0"/>
        <input type="hidden" name="to" value="log"/>
        
        <div class="uinArea" id="uinArea">
            <label class="input-tips" for="u">帳號(hào):</label>
            <div class="inputOuter" id="uArea">
                <input type="text" id="u" name="loginId" class="inputstyle"/>
            </div>
        </div>
        
        <div class="pwdArea" id="pwdArea">
            <label class="input-tips" for="p">密碼:</label>
            <div class="inputOuter" id="pArea">
                <input type="password" id="p" name="pwd" class="inputstyle"/>
            </div>
        </div>
        
        <div style="padding-left:50px;margin-top:20px;">
            <input type="button"
               id="btn_login"
               value="登 錄"
               onclick="webLogin();"    //此處調(diào)用我們上面寫的js的登錄方法
               style="width:150px;"
               class="button_blue"/>
        </div>
</form>

上面就是web中調(diào)用js的簡(jiǎn)單實(shí)現(xiàn),注意的是蜡塌,FORM表單必須刪除action的值碉纳,在點(diǎn)擊后需要觸發(fā)對(duì)應(yīng)事件的地方調(diào)用js

當(dāng)然岗照,我們的前端頁(yè)面完成后村象,我們必須在后端接口處笆环,做出對(duì)應(yīng)的修改攒至,讓他符合我們前端的調(diào)用規(guī)則。后端修改如下:

/**
 * 用戶請(qǐng)求相關(guān)控制器
 * <br/>Created by acheng on 2016/9/26.
 */
@Controller //標(biāo)明本類是控制器
@RequestMapping("/userAction")  //外層地址
public class UserController {

    @Autowired
    private UserServiceImpl userService;    //自動(dòng)載入Service對(duì)象
    private ResponseObj responseObj;    //返回json數(shù)據(jù)的實(shí)體
    
    /**
     * 登錄接口躁劣,因?yàn)閖son數(shù)據(jù)外層一般都是Object類型迫吐,所以返回值必須是Object<br/>
     *  這里的地址是: 域名/userAction/login
     *
     * @param req
     * @param user
     * @return
     */
    @RequestMapping(value = "/login"    //內(nèi)層地址
            , method = RequestMethod.POST   //限定請(qǐng)求方式
            , produces = "application/json; charset=utf-8") //設(shè)置返回值是json數(shù)據(jù)類型
    @ResponseBody
    public Object login(HttpServletRequest req, User user) {
        Object result;
        if (null == user) {
            responseObj = new ResponseObj<User>();
            responseObj.setCode(ResponseObj.EMPUTY);
            responseObj.setMsg("登錄信息不能為空");
            result = new GsonUtils().toJson(responseObj);   //通過(guò)gson把java bean轉(zhuǎn)換為json
            return result; //返回json
        }
        if (StringUtils.isEmpty(user.getLoginId()) || StringUtils.isEmpty(user.getPwd())) {
            responseObj = new ResponseObj<User>();
            responseObj.setCode(ResponseObj.FAILED);
            responseObj.setMsg("用戶名或密碼不能為空");
            result = new GsonUtils().toJson(responseObj);
            return result;
        }
        //查找用戶
        User user1 = userService.findUser(user);
        if (null == user1) {
            responseObj = new ResponseObj<User>();
            responseObj.setCode(ResponseObj.EMPUTY);
            responseObj.setMsg("未找到該用戶");
            result = new GsonUtils().toJson(responseObj);
        } else {
            if (user.getPwd().equals(user1.getPwd())) {
                responseObj = new ResponseObj<User>();
                responseObj.setCode(ResponseObj.OK);    //登錄成功,狀態(tài)為1
                responseObj.setMsg(ResponseObj.OK_STR);
                responseObj.setData(user1); //登陸成功后返回用戶信息
                result = new GsonUtils().toJson(responseObj);
            } else {
                responseObj = new ResponseObj<User>();
                responseObj.setCode(ResponseObj.FAILED);
                responseObj.setMsg("用戶密碼錯(cuò)誤");
                result = new GsonUtils().toJson(responseObj);
            }
        }
        return result;
    }
}

注意:如果為了返回?cái)?shù)據(jù)為json账忘,那么我們需要設(shè)定某個(gè)方法對(duì)應(yīng)的注解為:@ResponseBody 志膀。 否則會(huì)產(chǎn)生404錯(cuò)誤熙宇!

我們通過(guò)上面的重構(gòu)可以明白以下幾點(diǎn):

  • 前端
    • js實(shí)現(xiàn)基本的數(shù)據(jù)效驗(yàn)
    • js發(fā)起網(wǎng)絡(luò)請(qǐng)求
    • ajax發(fā)起網(wǎng)絡(luò)請(qǐng)求,返回類型設(shè)置json能自動(dòng)解析
    • js獲取頁(yè)面控件
    • 頁(yè)面控件調(diào)用js
    • js獲取解析后的json數(shù)據(jù)的值溉浙,進(jìn)行程序流轉(zhuǎn)控制
  • 后端:
    • 后端控制器必須申明
    • 后端的地址必須配置
    • 每個(gè)地址返回的數(shù)據(jù)類型要匹配
    • 返回json數(shù)據(jù)烫止,方法上面必須配置:@ResponseBody
    • 可以使用工具類來(lái)方便開(kāi)發(fā)

后臺(tái)主頁(yè)→個(gè)人信息修改

上期我們可以看到,我們的登錄和注冊(cè)都是已經(jīng)OK了〈粱現(xiàn)在我們登錄和注冊(cè)成功后馆蠕,我們都讓他跳轉(zhuǎn)到主頁(yè)去。同時(shí)完善登錄和注冊(cè)的錯(cuò)誤提示頁(yè)面惊奇。

一般來(lái)說(shuō)互躬,大家更喜歡看到登錄成功后的主頁(yè)界面,畢竟大多數(shù)人都是有喜新厭舊之嫌颂郎。我也是一樣的吼渡。哈哈。

為了程序的執(zhí)行邏輯乓序,考慮后端需求都不是那么單一寺酪,我們先做一些公共的建設(shè)。比如說(shuō)用戶信息修改現(xiàn)實(shí)之類的竭缝。如下圖:

ssm應(yīng)用四-后臺(tái)主頁(yè)-修改個(gè)人信息
ssm應(yīng)用四-后臺(tái)主頁(yè)-修改個(gè)人信息

如上圖所示房维,我們需要一個(gè)可以彈出的對(duì)話框,我去百度了一下抬纸,那個(gè)“妹子UI”還是很受人歡迎咙俩,所以就集成進(jìn)來(lái)了。

我們選取一個(gè)比較喜歡的后端主頁(yè)湿故,然后把對(duì)應(yīng)的資源放入到對(duì)應(yīng)的文件目錄(js阿趁、css、images等)坛猪,需要新加入的資源如果在以前的目錄中沒(méi)有的話脖阵,那么我們需要在里面進(jìn)行配置。比如說(shuō)這里我加入了字體文件墅茉,那么我現(xiàn)在需要先把字體文件指定目錄為:

static/font/

目錄指定后我需要在Spring的配置文件命黔,spring-web.xml中配置靜態(tài)資源的目錄如下:

<mvc:resources mapping="/fonts/**" location="/static/fonts/"/>

剩下的就是寫好jsp頁(yè)面(Copy+Pause+修改資源文件路徑)。然后我們?cè)贑ontroller中配置好路徑

/**
 * 后臺(tái)主頁(yè)
 *
 * @return
 */
@RequestMapping(value = "/home", method = RequestMethod.GET)
public String home() {
    return "home";
}

這樣子配置好了后就斤,我們就可以直接用“域名/mvc/home”來(lái)訪問(wèn)我們的主頁(yè)了悍募。同時(shí)按照上面的設(shè)置,我們登錄成功后洋机,直接解析json確認(rèn)用戶登錄成功坠宴,然后前端使用js來(lái)進(jìn)行頁(yè)面跳轉(zhuǎn),如:

window.location.href = "<%=request.getContextPath()%>/mvc/home";    //跳轉(zhuǎn)到主頁(yè)

這樣绷旗,我們就能修復(fù)上面說(shuō)道的頁(yè)面和地址顯示不匹配的問(wèn)題喜鼓。

同時(shí)副砍,通過(guò)上面的可以看出,我們?cè)趈sp頁(yè)面中,純粹沒(méi)加入任何jsva代碼,全是使用的前端+接口實(shí)現(xiàn)的功能漓摩。我們這樣做,以后維護(hù)和重構(gòu)中也能降低一部分壓力谨垃。

言歸正傳,我們這里主要是想做一個(gè)個(gè)人信息修改的功能硼控。首先我們進(jìn)行功能和業(yè)務(wù)流程分析刘陶。

功能和業(yè)務(wù)流程分析:

  • 1.web點(diǎn)擊頭像顯示修改信息對(duì)話框。
  • 2.根據(jù)后端定義的用戶信息表牢撼,得出用戶信息修改需要填寫的資料匙隔。
  • 3.用戶上傳個(gè)人資料,上傳之前前端必須先進(jìn)行基礎(chǔ)信息驗(yàn)證熏版。
  • 4.用戶個(gè)人信息驗(yàn)證通過(guò)后纷责,上傳到服務(wù)器。(重點(diǎn))
  • 5.服務(wù)器接收上傳的信息撼短,進(jìn)行存儲(chǔ)再膳,并返回修改結(jié)果。(重點(diǎn))

從上面我們可以看到我畫出兩個(gè)重點(diǎn)曲横,而且這兩個(gè)重點(diǎn)都是java web避免不了事情喂柒。為什么這樣說(shuō)呢?

  • 1.任何一個(gè)動(dòng)態(tài)的web服務(wù)器都免不了數(shù)據(jù)資料的更新禾嫉,數(shù)據(jù)資料更新一般分為兩種灾杰。
    • 有文件的信息上傳
    • 無(wú)文件的信息上傳
  • 2.可能其他童鞋看到http請(qǐng)求的方法有很多種,但是一般來(lái)說(shuō)get和post我們能做出任何的操作熙参。
  • 3.在大量數(shù)據(jù)的服務(wù)器中艳吠,考慮到很多因素(歷史記錄查詢、數(shù)據(jù)庫(kù)增量等)孽椰,一般不會(huì)進(jìn)行真正的物理數(shù)據(jù)刪除昭娩,一般都是通過(guò)控制輸出來(lái)實(shí)現(xiàn)的。(實(shí)戰(zhàn)經(jīng)驗(yàn)黍匾,血淚教訓(xùn)栏渺,切記)

現(xiàn)在我們開(kāi)始實(shí)現(xiàn)對(duì)話框:

打開(kāi)“妹子UI”的js插件頁(yè)面,我們找到模態(tài)窗口相關(guān)的文檔膀捷,在“模擬 Prompt”這里迈嘹,我們可以看到具體的對(duì)話框的實(shí)現(xiàn)和調(diào)用如下:

<!--這是html代碼-->
<button
  type="button"
  class="am-btn am-btn-success"
  id="doc-prompt-toggle">
  Prompt
</button>

<div class="am-modal am-modal-prompt" tabindex="-1" id="my-prompt">
  <div class="am-modal-dialog">
    <div class="am-modal-hd">Amaze UI</div>
    <div class="am-modal-bd">
      來(lái)來(lái)來(lái)削彬,吐槽點(diǎn)啥吧
      <input type="text" class="am-modal-prompt-input">
    </div>
    <div class="am-modal-footer">
      <span class="am-modal-btn" data-am-modal-cancel>取消</span>
      <span class="am-modal-btn" data-am-modal-confirm>提交</span>
    </div>
  </div>
</div>

<!--這是js調(diào)用-->
$(function() {
  $('#doc-prompt-toggle').on('click', function() {  //在這里設(shè)定上面的按鈕的點(diǎn)擊函數(shù)
    $('#my-prompt').modal({ //顯示ID為my-prompt的窗口
      relatedTarget: this,
      onConfirm: function(e) {  //窗口的確定按鈕的響應(yīng)事件
        alert('你輸入的是:' + e.data || '')
      },
      onCancel: function(e) {   //取消按鈕的響應(yīng)事件
        alert('不想說(shuō)!');
      }
    });
  });
});

關(guān)于上面的相關(guān)代碼全庸,我們需要引入妹子UI后才能使用P阒佟!壶笼!接下來(lái)我們需要改造成符合我們實(shí)際需求的界面神僵,如下:

<!--這里是html代碼-->
<div class="am-modal am-modal-prompt" tabindex="-1" id="my-prompt">
    <div class="am-modal-dialog">
        <div class="am-modal-hd">用戶信息修改</div>
        <div class="am-modal-bd">
            <form enctype="multipart/form-data" accept-charset="UTF-8">
                姓名:
                <input type="text" class="am-modal-prompt-input" id="changeName">

                性別:
                <input type="text" class="am-modal-prompt-input" id="changeSex">

                手機(jī)號(hào):
                <input type="text" class="am-modal-prompt-input" id="changeCell">

                年齡:
                <input type="text" class="am-modal-prompt-input" id="changeAge">

                頭像:
                <div class="am-modal-prompt-input">

                    <input type="file" name="file"
                           id="changeHeadPic" size="28"/>

                </div>
            </form>
        </div>
        <div class="am-modal-footer">
            <span class="am-modal-btn" data-am-modal-cancel>取消</span>
            <span class="am-modal-btn" data-am-modal-confirm>上傳</span>
        </div>
    </div>
</div>

<!--下面是js代碼-->
    var fileName;
    <!--文件上傳這里加入了js插件:jquery.ajaxfileupload.js-->
    function uploadFile() {
        //這里應(yīng)該加入Loading 窗口開(kāi)啟
        fileName = document.getElementById('changeHeadPic').value;
        $.ajaxFileUpload({
            url: "<%=request.getContextPath()%>/userAction/uploadHeadPic",
            secureuri: false, //是否需要安全協(xié)議,一般設(shè)置為false
            fileElementId: 'changeHeadPic', //文件上傳域的ID
            dataType: 'json', //返回值類型 一般設(shè)置為json
            contentType: "application/x-www-form-urlencoded; charset=utf-8",
            success: function (data) {
                alert(data.msg);
                //先根據(jù)返回的code確定文件是否上傳成功
                //文件上傳失敗覆劈,直接彈出錯(cuò)誤提示保礼,根據(jù)錯(cuò)誤進(jìn)行相應(yīng)的事物處理(關(guān)閉Loading窗口,彈出提示對(duì)話框)
                //文件上傳成功后责语,繼續(xù)現(xiàn)實(shí)loading窗口炮障,接著執(zhí)行上傳表單信息等事物
            }

        });
    }

    function changeUserInfo() { //顯示個(gè)人信息修改窗口
        $('#my-prompt').modal({
            relatedTarget: this,
            onConfirm: function () {
                uploadFile();   //調(diào)用上面的文件上傳函數(shù)
            },
            onCancel: function (e) {
            }
        });
    }
    

上面的代碼,我們完成了控制窗口顯示的函數(shù)坤候,完成了修改個(gè)人信息界面的構(gòu)建⌒灿現(xiàn)在我們需要的是找到執(zhí)行程序入口。按照我的習(xí)慣白筹,肯定是找到頭像控件智末,然后設(shè)置點(diǎn)擊事件為上面的changeUserInfo()。實(shí)現(xiàn)如下:

<!--下面是頭像的html代碼徒河,在頭像控件后面的點(diǎn)擊事件上面添加上函數(shù)就行了系馆。-->
<div class="user-img">
    <img src="/static/images/avatar-1.jpg" alt="user-img" title="Mat Helme"
         class="img-circle img-thumbnail img-responsive" onclick="changeUserInfo()">    <!--在這里添加onclick方法的值為:changeUserInfo()-->
        <div class="user-status offline">
            <i class="am-icon-dot-circle-o" aria-hidden="true"></i>
        </div>
</div>

好的,上面我們可以看到我的前端界面代碼基本上完成了顽照。接下來(lái)由蘑,我們需要在我們后端上面寫上對(duì)應(yīng)的程序接口,實(shí)現(xiàn)功能即可代兵。

本來(lái)計(jì)劃文件上傳單獨(dú)使用commons-fileupload和commons-io完成的纵穿,畢竟這是在Servelt上面的老套路,但是我發(fā)現(xiàn)Spring里面已經(jīng)考慮到這一點(diǎn)奢人,有新的東西來(lái)完成谓媒,所以就使用了Spring的實(shí)現(xiàn)方式。具體代碼如下:

    //我們?cè)赨serController這個(gè)控制器里添加這個(gè)方法
    @RequestMapping(value = "/uploadHeadPic"
            , method = RequestMethod.POST
            , produces = "application/json; charset=utf-8")
    @ResponseBody
    public Object uploadHeadPic(@RequestParam(required = false) MultipartFile file, HttpServletRequest request) {
        //在這里面文件存儲(chǔ)的方案一般是:收到文件→獲取文件名→在本地存儲(chǔ)目錄建立防重名文件→寫入文件→返回成功信息
        //如果上面的步驟中在結(jié)束前任意一步失敗何乎,那就直接失敗了句惯。
        if (null == file || file.isEmpty()) {
            responseObj = new ResponseObj();
            responseObj.setCode(ResponseObj.FAILED);
            responseObj.setMsg("文件不能為空");
            return new GsonUtils().toJson(responseObj);
        }
        responseObj = new ResponseObj();
        responseObj.setCode(ResponseObj.OK);
        responseObj.setMsg("文件長(zhǎng)度為:" + file.getSize());
        return new GsonUtils().toJson(responseObj);
    }

完成了上面的方法后,我們覺(jué)得應(yīng)該是沒(méi)問(wèn)題了支救,畢竟這樣一個(gè)接口來(lái)接受請(qǐng)求是沒(méi)問(wèn)題的嘛抢野,是的,我也是這么認(rèn)為的各墨。

但是現(xiàn)實(shí)的打臉是很嚴(yán)重的指孤,因?yàn)榘凑者@么寫后,我無(wú)論如何都收不到文件(文件一直為null),Why恃轩?我的思路是正確的啊结洼。經(jīng)過(guò)我的仔細(xì)查找,發(fā)現(xiàn)我的Spring的配置文件中叉跛,沒(méi)有添加文件的支持設(shè)置松忍,所以我們又得補(bǔ)充配置文件,spring-web.xml新增配置如下:

    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--下面設(shè)置的是上傳文件的最大大小-->
        <property name="maxUploadSize" value="10000000"/>   
    </bean>

經(jīng)過(guò)上面的一番折騰筷厘,我們發(fā)現(xiàn)框架這個(gè)東西鸣峭,也不是一勞永逸的,畢竟很多東西需要不斷的增加酥艳。

總結(jié):

  • 任何東西都需要根據(jù)需求不斷的變化摊溶,可增可減,張弛有度充石。
  • Spring接收文件上傳時(shí)更扁,Controller的具體方法的參數(shù)前面插入注解,同時(shí)數(shù)據(jù)類型是MultipartFile赫冬。
  • 引入第三方資源的時(shí)候浓镜,必須查看文檔,根據(jù)說(shuō)明文檔好辦事劲厌。
  • js進(jìn)行前端流程控制膛薛,后端接口隔離,前后端解耦补鼻。

前兩天刮臺(tái)風(fēng)哄啄,停電導(dǎo)致數(shù)據(jù)丟失,是個(gè)很尷尬的事情风范,拖慢了進(jìn)度咨跌。同時(shí),朋友遇到點(diǎn)問(wèn)題硼婿,我在開(kāi)導(dǎo)他锌半。文章寫到現(xiàn)在也是凌晨4點(diǎn)過(guò)了,本期計(jì)劃的列表分頁(yè)也沒(méi)做寇漫,很對(duì)不起大家對(duì)我的期待刊殉。真誠(chéng)的說(shuō)一聲:對(duì)不起。對(duì)不起你們的期待州胳。

給朋友開(kāi)導(dǎo)的時(shí)候记焊,我也總結(jié)了下做人做事:隨心、追夢(mèng)栓撞、勇敢遍膜、獨(dú)行碗硬。希望有心做事的,都用這幾句話勉勵(lì)自己吧瓢颅。

前行的路上不只是孤獨(dú)恩尾,還有滿山的鮮花,更有遠(yuǎn)方和詩(shī)惜索。


下期預(yù)告:

  • 列表分頁(yè)
  • 簡(jiǎn)易用戶角色控制
  • 攔截器的使用
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市剃浇,隨后出現(xiàn)的幾起案子巾兆,更是在濱河造成了極大的恐慌,老刑警劉巖虎囚,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件角塑,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡淘讥,警方通過(guò)查閱死者的電腦和手機(jī)圃伶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)蒲列,“玉大人窒朋,你說(shuō)我怎么就攤上這事』柔” “怎么了侥猩?”我有些...
    開(kāi)封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)抵赢。 經(jīng)常有香客問(wèn)我欺劳,道長(zhǎng),這世上最難降的妖魔是什么铅鲤? 我笑而不...
    開(kāi)封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任划提,我火速辦了婚禮,結(jié)果婚禮上邢享,老公的妹妹穿的比我還像新娘鹏往。我一直安慰自己,他們只是感情好骇塘,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布掸犬。 她就那樣靜靜地躺著,像睡著了一般绪爸。 火紅的嫁衣襯著肌膚如雪湾碎。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天奠货,我揣著相機(jī)與錄音介褥,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛柔滔,可吹牛的內(nèi)容都是我干的溢陪。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼睛廊,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼形真!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起超全,我...
    開(kāi)封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤咆霜,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后嘶朱,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體蛾坯,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年疏遏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了脉课。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡财异,死狀恐怖倘零,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情戳寸,我是刑警寧澤视事,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站庆揩,受9級(jí)特大地震影響俐东,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜订晌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一虏辫、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧锈拨,春花似錦砌庄、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至缝彬,卻和暖如春萌焰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背谷浅。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工扒俯, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留奶卓,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓撼玄,卻偏偏與公主長(zhǎng)得像夺姑,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子掌猛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容