4/26day42_文件上傳綜合案例

回顧

1. listener監(jiān)聽器
    監(jiān)聽三大域?qū)ο蟮膭?chuàng)建和銷毀,request九秀、session玄捕、servletContext
    快速入門
        1.普通類烟阐,實(shí)現(xiàn)listener接口
        2.重寫抽象方法墓卦,創(chuàng)建和銷毀
        3.配置
          web.xml
          注解
    統(tǒng)計(jì)在線人數(shù)
        

2. 綜合案例
    使用mvc和三層架構(gòu)的思想實(shí)現(xiàn)用戶模塊的增刪改查
        程序入口(瀏覽器)---servlet(轉(zhuǎn)發(fā)、重定向)---service---dao

AJAX&文件上傳

今日目標(biāo)

1. json
    java和json數(shù)據(jù)相互轉(zhuǎn)換
    
2. 校驗(yàn)用戶名是否存在

3. 文件上傳【可以照著抄一遍...】

4. 安裝mysql5.7版本(如果mysql5.6以上可以繼續(xù)使用....)

一 JSON

1.1 回顧

最早是JavaScript對象表示形式睛榄,現(xiàn)在主要用于互聯(lián)網(wǎng)傳輸數(shù)據(jù)載體

* java
        User user =new User();
            user.setUsername("jack");
            user.setAge(18);
            
* javaScript
        let user = {"username":"jack","age":18};
        
        let array = [{},{},{}]
        
        name:都是字符串
        value:支持各種類型

JSON 比 XML 更小荣茫、更快,更易解析

1587864032897.png

1.2 JSON數(shù)據(jù)與java對象轉(zhuǎn)換

常見的解析器

工具名稱 介紹
Jsonlib Java 類庫场靴,需要導(dǎo)入的jar包較多
Gson google提供的一個(gè)簡單的json轉(zhuǎn)換工具
Fastjson alibaba技術(shù)團(tuán)隊(duì)提供的一個(gè)高性能的json轉(zhuǎn)換工具
Jackson 開源免費(fèi)的json轉(zhuǎn)換工具啡莉,springmvc轉(zhuǎn)換默認(rèn)使用jackson
1587864344057.png

使用jackson,需要導(dǎo)入jar包

1587864541216.png

提供了一個(gè)核心轉(zhuǎn)換器對象

ObjectMapper  om = new ObjectMapper();

1.2.1 java對象轉(zhuǎn)為json(字符串)【重點(diǎn)】

String writeValueAsString(Object object);
    // 將user對象轉(zhuǎn)為json字符串
    @Test
    public void UserToJson() throws Exception {
        User user = new User("1", "lucy", "女", 15, "德克薩斯", "123", "123@qq.com");

        // 創(chuàng)建jackson轉(zhuǎn)換器對象
        ObjectMapper om = new ObjectMapper();

        // 將任意對象轉(zhuǎn)為json字符串
        String json = om.writeValueAsString(user);
        System.out.println(json); // 在java中name必須使用雙引號包裹起來
    }

    // 將map集合轉(zhuǎn)為json字符串
    @Test
    public void MapToJson() throws Exception {
        Map<String, Object> map = new HashMap<>();
        map.put("name", "張三");
        map.put("age", 18);

        // 創(chuàng)建jackson轉(zhuǎn)換器對象
        ObjectMapper om = new ObjectMapper();

        // toJson
        String json = om.writeValueAsString(map);
        System.out.println(json); //  {"name":"張三","age":18}
    }

    // 將list集合轉(zhuǎn)為json數(shù)組字符串
    @Test
    public void ListToJson() throws Exception {
        List<User> list = new ArrayList<>();
        list.add(new User("1", "lucy", "女", 15, "德克薩斯", "123", "123@qq.com"));
        list.add(new User("2", "jack", "男", 15, "德克薩斯", "123", "123@qq.com"));

        // 創(chuàng)建jackson轉(zhuǎn)換器對象
        ObjectMapper om = new ObjectMapper();

        // toJson
        String json = om.writeValueAsString(list);
        System.out.println(json); // [{},{}]
    }

1.2.2 將json(字符串)轉(zhuǎn)為java對象【了解】

T readValue(String json,Class<T> classType);
    // 將json字符串轉(zhuǎn)為user對象
    @Test
    public void JsonToUser() throws Exception {
        String json = "{\"id\":\"1\",\"name\":\"lucy\",\"sex\":\"女\",\"age\":15,\"address\":\"德克薩斯\",\"qq\":\"123\",\"email\":\"123@qq.com\"}";

        // 創(chuàng)建jackson轉(zhuǎn)換器對象
        ObjectMapper om = new ObjectMapper();

        // toUser
        User user = om.readValue(json, User.class);
        System.out.println(user);
    }

    // 將json字符串轉(zhuǎn)為map集合(如果你獲取的json格式?jīng)]有對應(yīng)的java實(shí)體對象憎乙,就可以拿map接收)
    @Test
    public void JsonToMap() throws Exception {
        String json = "{\"name\":\"lucy\",\"age\":18}";

        // 創(chuàng)建jackson轉(zhuǎn)換器對象
        ObjectMapper om = new ObjectMapper();

        // toMap
        Map<String, Object> map = om.readValue(json, Map.class);
        System.out.println(map);
    }

    // 將json數(shù)組字符串轉(zhuǎn)為list集合
    @Test
    public void JsonToList() throws Exception {
        String json = "[{\"id\":\"1\",\"name\":\"lucy\",\"sex\":\"女\",\"age\":15,\"address\":\"德克薩斯\",\"qq\":\"123\",\"email\":\"123@qq.com\"},{\"id\":\"2\",\"name\":\"jack\",\"sex\":\"男\(zhòng)",\"age\":15,\"address\":\"德克薩斯\",\"qq\":\"123\",\"email\":\"123@qq.com\"}]";

        // 創(chuàng)建jackson轉(zhuǎn)換器對象
        ObjectMapper om = new ObjectMapper();

        // toList
        List list = om.readValue(json, List.class);
        System.out.println(list);
    }

1.3 自定義模板

1587866270735.png

二 案例:檢查用戶名是否可用

需求

? 在用戶注冊頁面票罐,輸入用戶名,當(dāng)用戶名輸入框失去焦點(diǎn)時(shí)泞边,發(fā)送異步請求该押,將輸入框的用戶名傳遞給服務(wù)器進(jìn)行是否存在的校驗(yàn)。

2.1 技術(shù)分析

此需求使用了ajax技術(shù):通過==異步提交==阵谚,實(shí)現(xiàn)頁面的==局部刷新==蚕礼,提高用戶的體驗(yàn)

JQuery提供的ajax函數(shù)

* ajax
        $.ajax({
            type:"請求方式,get|post",
            url:"請求服務(wù)器地址",
            data:"請求參數(shù)",
            success:function(resp){
                resp就是服務(wù)器返回的結(jié)果...
            }
        });

* get
        $.get(url(地址?參數(shù)),function(resp){
            
        });


* post
        $.post(url,data,function(resp){
            
        })

2.2 需求分析

1587868403078.png

2.3 代碼實(shí)現(xiàn)

① index.jsp

1587868753719.png
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>${NAME}</title>
    <script src="${pageContext.request.contextPath}/js/jquery-3.2.1.js"></script>
</head>
<body>
<h3>用戶注冊</h3>
<form action="#" method="post">
    用戶名:<input type="text" name="username" id="username"> <span id="userwarn"></span> <br>
</form>

<script>
    // 給用戶文本框綁定失去焦點(diǎn)事件
    $('#username').blur(function () {
        // 獲取用戶輸入的值
        console.log(this.value);
        let data = "username=" + this.value;
        // 發(fā)送ajax請求
        $.ajax({
            type:"post",
            url:'${pageContext.request.contextPath}/CheckServlet',
            data:data,
            success:function (resp) {
                console.log(resp);
                // 判斷結(jié)果并實(shí)現(xiàn)局部刷新
                if(resp.flag){
                    $('#userwarn').text(resp.msg).css('color','green');
                }else{
                    $('#userwarn').text(resp.msg).css('color','red');
                }
            }
        })
    })
</script>
</body>
</html>

② CheckServlet

@WebServlet("/CheckServlet")
public class CheckServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        // 1.接收請求參數(shù)
        String username = request.getParameter("username");

        // 2.聲明map集合
        Map<String, Object> map = new HashMap<>();

        // 3.判斷用戶是否存在
        if(username.equals("jack")){
            map.put("flag",false);
            map.put("msg", "× 此用戶已注冊");
        }else{
            map.put("flag",true);
            map.put("msg", "√ 此用戶可以注冊");
        }

        // 4.將map集合轉(zhuǎn)為json字符串
        ObjectMapper om = new ObjectMapper();
        String json = om.writeValueAsString(map);
        System.out.println(json);

        // 5.設(shè)置json的MIME類型
        response.setContentType("application/json;charset=utf-8");

        // 6.response響應(yīng)json到客戶端
        response.getWriter().write(json);
    }

}

三 案例:文件上傳

需求

? 在用戶注冊頁面梢什,我們可以輸入用戶名奠蹬,還可以選擇要上傳的文件;點(diǎn)擊提交按鈕嗡午,就可以將用戶輸入的內(nèi)容和選擇的文件保存到服務(wù)器上

3.1 技術(shù)分析

1587870989239.png

3.1.1 客戶端如何將文件轉(zhuǎn)為文本

1. 表單提交方式必須為post
        action="post"
        
2. 表單的enctype屬性值必須為multipart/form-data 多組件表單數(shù)據(jù)
        enctype="multipart/form-data"
        
3. 在表單中提供文件上傳項(xiàng)
    <input type="file" name="pic">
1587871962157.png

3.1.2 服務(wù)器將文本轉(zhuǎn)為字節(jié)流

  1. 使用apache提供工具類 commons-fileupload(今天講囤躁,最麻煩的....)
  2. 使用servlet3.0版本,通過注解實(shí)現(xiàn)(黑馬旅游網(wǎng))
  3. 使用springMVC框架(最簡單荔睹,底層使用commons-fileupload)

3.1.2 代碼實(shí)現(xiàn)【課下抄一遍即可】

① 導(dǎo)入文件上傳相關(guān)jar包

1587872397979.png
1587872441280.png

② index.jsp

1587872494757.png

③ 指定服務(wù)器保存文件路徑

1587872548319.png

④ 編寫servlet接收文件并保存

步驟分析

1. 創(chuàng)建磁盤文件項(xiàng)工廠

2. 創(chuàng)建核心解析對象(依賴工廠對象)

3. 解析request對象狸演,返回上傳項(xiàng)list集合

4. 遍歷list,獲取每一個(gè)上傳項(xiàng)

5. 判斷
      普通上傳項(xiàng)
        name和value
      文件上傳項(xiàng)
        文件名
        字節(jié)輸入流
        保存服務(wù)器端
@WebServlet("/UploadServlet")
public class UploadServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            // 1.創(chuàng)建磁盤文件項(xiàng)工廠
            DiskFileItemFactory factory = new DiskFileItemFactory();
            // 2.創(chuàng)建上傳解析器對象(依賴工廠對象)
            ServletFileUpload fileUpload = new ServletFileUpload(factory);
            // 3.解析request請求僻他,返回上傳項(xiàng)list集合
            List<FileItem> fileItems = fileUpload.parseRequest(request);
            // 4.遍歷list
            for (FileItem fileItem : fileItems) {
                // 5.判斷是文件項(xiàng)還是普通項(xiàng)
                if (fileItem.isFormField()) {// 普通上傳項(xiàng)
                    // 獲取name屬性名
                    String name = fileItem.getFieldName();
                    // 獲取value屬性值
                    String value = fileItem.getString();
                    System.out.println("普通上傳項(xiàng):" + name + "=" + value);
                } else {// 文件上傳項(xiàng)
                    // a.獲取文件名   demo.txt
                    String fileName = fileItem.getName();
                    // b.獲取文件字節(jié)輸入流
                    InputStream in = fileItem.getInputStream();
                    // c.獲取文件擴(kuò)展名
                    String extName = FileUtil.extName(fileName);
                    // d.生成隨機(jī)文件名
                    fileName = IdUtil.simpleUUID() + "." + extName;

                    // 此文件名會保存數(shù)據(jù)庫一份宵距,給用戶查詢使用...

                    // 獲取upload目錄在服務(wù)器真實(shí)路徑
                    String realPath = request.getServletContext().getRealPath("/upload/");

                    // 判斷此目錄是否存在
                    File dirFile = new File(realPath);
                    if (!dirFile.exists()) {
                        dirFile.mkdirs(); // 如果不存在自己創(chuàng)建
                    }

                    // 設(shè)置文件字節(jié)輸出流
                    FileOutputStream out = new FileOutputStream(realPath + fileName);

                    // 流的拷貝
                    IoUtil.copy(in, out);

                    // 關(guān)流
                    out.close();
                    in.close();

                    response.getWriter().write("success");
                }
            }
        } catch (FileUploadException e) {
            e.printStackTrace();
        }
    }

}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市吨拗,隨后出現(xiàn)的幾起案子满哪,更是在濱河造成了極大的恐慌,老刑警劉巖劝篷,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哨鸭,死亡現(xiàn)場離奇詭異,居然都是意外死亡携龟,警方通過查閱死者的電腦和手機(jī)兔跌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來峡蟋,“玉大人坟桅,你說我怎么就攤上這事∪锘龋” “怎么了仅乓?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蓬戚。 經(jīng)常有香客問我夸楣,道長,這世上最難降的妖魔是什么子漩? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任豫喧,我火速辦了婚禮,結(jié)果婚禮上幢泼,老公的妹妹穿的比我還像新娘紧显。我一直安慰自己,他們只是感情好缕棵,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布孵班。 她就那樣靜靜地躺著,像睡著了一般招驴。 火紅的嫁衣襯著肌膚如雪篙程。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天别厘,我揣著相機(jī)與錄音虱饿,去河邊找鬼。 笑死触趴,一個(gè)胖子當(dāng)著我的面吹牛氮发,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播雕蔽,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼折柠,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了批狐?” 一聲冷哼從身側(cè)響起扇售,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎嚣艇,沒想到半個(gè)月后承冰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡食零,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年困乒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贰谣。...
    茶點(diǎn)故事閱讀 39,965評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡娜搂,死狀恐怖迁霎,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情百宇,我是刑警寧澤考廉,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站携御,受9級特大地震影響昌粤,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜啄刹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一涮坐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧誓军,春花似錦袱讹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至债查,卻和暖如春非区,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背盹廷。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工征绸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人俄占。 一個(gè)月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓管怠,卻偏偏與公主長得像,于是被迫代替她去往敵國和親缸榄。 傳聞我的和親對象是個(gè)殘疾皇子渤弛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評論 2 355