springMVC(二)——處理返回值、常用註解、檔案上傳下載、異常處理、過濾器、攔截器

Today_He發表於2020-11-08

零、注意

一、maven web專案中,不能直接訪問靜態資源(html、css、js等)。
1、為什麼不能直接訪問靜態資源?
因為攔截的是//*.jsp所以路徑為/*.html也會被攔截,但是dispatcherServlet不能處理這些html,需要交給tomcat預設的servlet去處理。

2、如何交給tomcat預設的servlet處理?
✳①交給預設servlet<mvc:defalut-servlet-handler></mvc:defalut-servlet-handler>
略②指定靜態資源路徑<mvc:resources mapping="對映路徑(瀏覽器地址)" location="具體路徑(webapp下的哪個資料夾下面的哪個靜態資源)"></mvc:resources>(沒新增一個靜態資源都需要指定,複雜了)

二、返回資料型別(response)
1、重定向返回資料,需要加RedirectAttributes屬性,獲取時需要使用@RedirectAttributes註解
2、返回任意型別的資料,需要加@ResponseBody返回值轉為json格式;
自定義類,還需要開啟自定義轉換,才能生效,?<mvc:annotation-driven></mvc:annotation-driven>

三、攔截器與過濾器?
過濾器:tomcat提供的;
攔截器:springMVC提供的;用於對處理器進行預處理和後處理

四、Controller請求轉發,json自動轉換等功能
需要在spring的xml檔案中新增<mvc:annotation-driven></mvc:annotation-driven>主要就是為了Spring MVC來用的,提供Controller請求轉發,json自動轉換等功能

五、檔案上傳下載需要匯入jar包、例項化檔案上傳下載工具

Ⅰ、springMVC返回值的處理

【待補充】

Ⅱ、springMVC常用註解 0

一、@RequestParam
位置:用在方法的入參位置
作用:用於前端傳入的引數與方法形參匹配(前端傳入的引數名與方法形參名不一致才使用,否則沒必要)
屬性:

1)value:預設屬性,用於指定前端傳入的引數名稱;
2)required:用於指定此引數是否必傳(boolean),預設為true,此時前端不傳資料就會報錯;
3)defaultValue:當引數為必傳引數且前端沒有傳入引數時,必須指定一個預設值。
@RequestMapping("test1")
 public String test1(@RequestParam(value = "user",required = true,defaultValue = "abc")String username){
     System.out.println(username);
     return "/index.jsp";
 }

解釋——前端前端將user=***,傳到控制層,控制層使用username接收;因為required = true,此時如果前端沒有將引數傳過來,使用預設值,則username=abc

二、@RequestHeader
位置:用在方法入參位置
作用:用於從請求頭中獲取引數
屬性:同@RequestParam

@RequestMapping("test2")
    public String test2(@RequestHeader("cookie") String cookie){
        System.out.println(cookie);//JSESSIONID=2D7************
        return "/index.jsp";
    }

請求頭——
在這裡插入圖片描述

三、@CookieValue
位置:用在方法入參位置
作用:用於從cookie中獲取引數

 @RequestMapping("test3")
    public String test3(@CookieValue("JSESSIONID") String jsessionid){
        System.out.println(jsessionid);//2D7F453*********
        return "/index.jsp";
    }

在這裡插入圖片描述

四、@SessionAttributes(value={"…","…","…",……})
位置:放在類上
作用:將請求域的引數,放到session域中

AnnotationController.java

package com.hbw.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

@Controller
@RequestMapping("annotation")
@SessionAttributes(value = {"a","b","c","d","e"})
public class AnnotationController {
    @RequestMapping("test4")
    public ModelAndView test4(Map map, Model model, ModelAndView modelAndView, ModelMap modelMap, HttpServletRequest request){
        map.put("a","1");
        model.addAttribute("b","2");
        modelAndView.setViewName("/index.jsp");
        modelMap.addAttribute("d","4");
        request.setAttribute("e","5");

        return modelAndView;
    }
}

因為使用了request——tomcat內建物件之一,需要匯入servlet-api的jar包
但是,新匯入的jar包會與啟動tomcat外掛衝突,給jar包加個作用範圍(scope=provided)

pom.xml

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
    <scope>provided</scope>
</dependency>

index.jsp

Map:${requestScope.get("a")}<br/>
Model:${requestScope.get("b")}<br/>
ModelMap:${requestScope.get("d")}<br/>
request:${requestScope.get("e")}

✳五、RequestBody
位置:用在方法入參位置
作用:用於接收前端傳入的訊息體,可將json格式轉為物件格式。注意:只有post請求才有訊息體。

注意:需要在spring的xml檔案中新增<mvc:annotation-driven></mvc:annotation-driven>主要就是為了Spring MVC來用的,提供Controller請求轉發,json自動轉換等功能

1)前端

<script>
    $(function($) {
        $.ajax({
            type: "POST",
            url: "/annotation/test5",
            contentType:"application/json",
            data: '{"bid":"123","bname":"語文"}',
            success: function(msg){
                alert( "Data Saved: " + msg );
            }
        });
    });
</script>

2)後端

 @RequestMapping("test5")
    public String test5(@RequestBody Book book){
        System.out.println(book);
        return "/index.jsp";
    }

3)控制檯
Book{bid=123, bname=‘語文’}

✳六、ResopnseBody
位置:方法上
作用:將我們的返回值非同步響應為json資料

?引用——
詳細來說,就是將controller的方法返回的物件通過適當的轉換器轉換為指定的格式之後,寫入到response物件的body區,通常用來返回JSON資料或者是XML資料。

注意
在使用此註解之後不會再走檢視處理器,而是直接將資料寫入到輸入流中,他的效果等同於通過response物件輸出指定格式的資料。在使用 @RequestMapping後,返回值通常解析為跳轉路徑,但是加上 @ResponseBody 後返回結果不會被解析為跳轉路徑,而是直接寫入 HTTP response body 中。 比如非同步獲取 json 資料,加上 @ResponseBody 後,會直接返回 json 資料。@RequestBody 將 HTTP 請求正文插入方法中,使用適合的 HttpMessageConverter 將請求體寫入某個物件。

1)前端呼叫

<body>
<a href="/annotation/test6" >點選</a>
</body>

2)後端

 @RequestMapping("test6")
    @ResponseBody
    public Book test6(){
        Book book = new Book();
        book.setBid(1);
        book.setBname("數學");
        return book;
    }

3)響應給頁面
頁面顯示——

{"bid":1,"bname":"數學"}

七、@ModelAttribute
作用:向請求域物件(request)中新增資訊
位置:

1、放在方法入參位置上
	1)從表單中獲取普通的資料,同時將這個資料以表單控制元件的名稱為key放入請求域中;
	2)表單的資料被封裝成一個自己定義的實體類物件,註解中的key可以任意取名。??????這點還沒遇見,後面在補充吧
	3)肯定也能獲取下面這類方法中的返回引數
	
2、放在方法上
	1)為當前的controller中所有可以直接訪問的方法提供公共資料

1)前端
比如輸入,Tom

<body>
<%--測試ModelAttribute--%>
<form action="/annotation/test7" method="post">
    使用者名稱:<input type="text" name="user">
    <input type="submit">
</form>

</body>

2)後端

@RequestMapping("test7")
    public String test71(@ModelAttribute("user")String user,@ModelAttribute("ceshi")String aa){
    	//獲取表單提交過來的普通引數
        System.out.println(user);
        //獲取公共方法提供的公共引數
        System.out.println(aa);
        return "/index.jsp";
    }

    @ModelAttribute("ceshi")
    public String test72(){
        System.out.println("我是公共方法,為其他共有方法提供引數");
        return "公共引數";
    }

3)控制檯

我是公共方法,為其他共有方法提供引數
Tom
公共引數

八、@RequestMapping
位置:類上、方法上
作用:設定訪問控制層的路徑
method屬性的第一個值表示只處理get請求;第二個值表示RESTFUL風格(見下一個標籤)

@RequestMapping(value = "test8",method = {RequestMethod.GET,RequestMethod.PUT})

九、@PathVariable
位置:用在方法入參位置
作用:獲取請求路徑變數,通常用於restful風格編碼。?
在這裡插入圖片描述
1、為什麼要使用RESTful風格?
因為http協議中的url本身不具有表示狀態的功能,是一個無狀態請求協議。
2、那麼如何表示操作狀態呢?
我們通過請求方式指定狀態:

新增:POST
刪除:DELETE
修改:PUT
查詢:GET

3、具體什麼意思?以修改某個學生的資訊舉例
1)以往的風格:/updateStudentById?id=1
2)使用RESTful風格:/student/1

程式碼如下:
增加、查詢沒啥特別的;修改和刪除需要加<input type="hidden" name="_method" value="PUT或者DELETE"/>因為form的method屬性預設值只有get、post。這裡使用修改進行說明。
1)前端

<body>
<%--這裡只是測試說明,直接指定修改的具體學生了--%>
<form action="/annotation/student/1" method="post">
	<%--這裡的name屬性值,不要隨便寫,不然找不到--%>
    <input type="hidden" name="_method" value="PUT"/>
    <input type="submit"/>
</form>
</body>

2)後端

@RequestMapping(value = "student/{sid}",method = RequestMethod.PUT)
    public String updatePerson1(@PathVariable("sid")String sid){
        System.out.println("修改"+sid+"號學生");
        return "/index.jsp";
    }

3)web.xml中的配置

<!--用於對RESTful風格的攔截器 -->
<filter>
   <filter-name>HiddenHttpMethodFilter</filter-name>
   <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
   <filter-name>HiddenHttpMethodFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

4)結果
http://localhost:8080/annotation/student/1

Ⅲ、springMVC檔案上傳與下載

準備工作
1、引入jar包

<!--檔案上傳-->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>

2、初始化上傳工具multipartResolver
就是檔案上傳解析器,它會將上傳的檔案進行封裝
注意:id是固定的

<!--初始化檔案上傳、下載例項-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--        <property name="maxUploadSize" value="102400000"></property>-->
</bean>

一、檔案上傳

1)、提交上傳申請

<form action="/annotation/test9" method="post" enctype="multipart/form-data">
    <%--name隨便取,但是必須與處理請求的引數名相同。不然需要在入參位置使用@RequestParam("name屬性的值")註解--%>
    <input name="multipartFile" type="file">
    <input type="submit" value="檔案上傳">
</form>

2)、處理上傳請求

 /*檔案上傳*/
    @RequestMapping("test9")
    public String test9(MultipartFile multipartFile){
        //獲取上傳檔案的名字,並在前面加上32位隨機字元
        String fileName =UUID.randomUUID() + multipartFile.getOriginalFilename();
        //指定上傳路徑(客戶端上傳到伺服器,不可能沒有這個資料夾,讓使用者去建立。肯定是事先就準備有的資料夾)
        File file = new File("H:\\FileLoad\\" + fileName);
        try {
            //上傳,ovwe
            multipartFile.transferTo(file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "/index.jsp";
    }

二、批量上傳

1)前端請求

<form action="/annotation/test10" method="post" enctype="multipart/form-data">
    <%--兩個name必須一樣,才是陣列啊--%>
    <input name="files" type="file">
    <input name="files" type="file">
    <input type="submit" value="檔案批量上傳">
</form>

2)後臺處理

/*批量上傳*/
    @RequestMapping("test10")
    public String test10(MultipartFile[] files){
        for(MultipartFile file:files){
            File newFile = new File("H:\\FileLoad\\" + UUID.randomUUID()+file.getOriginalFilename());
            try {
                file.transferTo(newFile);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return "/index.jsp";
    }

三、檔案下載

1)前端請求
filePath表示該資源在伺服器上的詳細路徑、filename表示待下載的檔案的全名稱

<a href="/annotation/test11?filePath=H:\\FileLoad\\123.png&filename=123.png">123.png下載</a>

2)後臺處理

 /*檔案下載*/
    @RequestMapping("test11")
    //注意引數名與前端的引數名相同。不然需要使用@RequestParam(這是spring MVC獲取前端傳入資料自動匹配的規則)
    public ResponseEntity<byte[]> test11(String filePath,@RequestParam("filename") String fileName) throws IOException {
        File file = new File(filePath);
        //定義響應頭
        HttpHeaders httpHeaders = new HttpHeaders();
        //指定以下載的方式開啟檔案
        httpHeaders.setContentDispositionFormData("attachment",fileName);
        //指定下載檔案的資料型別
        return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),httpHeaders, HttpStatus.OK);
    }

Ⅳ、springMVC異常處理

【冷颼颼,待補充】

Ⅴ、springMVC過濾器

Ⅵ、springMVC攔截器

相關文章