天天看點

JAVAEE架構技術之5-springMVC參數綁定和異步互動

資料綁定

springmvc作為web層技術,要接受頁面傳遞過來的參數值,以下幾種方式都是擷取參數值

綁定servlet内置對象

@RequestMapping("show1")
@ResponseStatus(HttpStatus.OK) //傳回void  沒有頁面傳回,給出響應狀态為200
public void test1(HttpServletRequest request , HttpServletResponse response , HttpSession session){
        //有了這些對象,之前怎麼用,這裡怎麼用
        System.out.println(request);
        System.out.println(response);
        System.out.println(session);
    }      

@PathVariable

@RequestMapping(“show2/{id}/{name}”)

@PathVariable(“id”) 指定擷取請求路徑中的參數值

@RequestMapping("show2/{id}/{name}")//@PathVariable("xx")參數可以省略,建議指定擷取
    public String test2(@PathVariable int id ,@PathVariable String name){
        System.out.println("id:"+id);
        System.out.println("name:"+name);
        //傳回String
        return "hello";//可以直接跳到視圖解析器下找hello.jsp
    }      

@RequestParam

屬性名 屬性值
value 參數名
required true(預設) false
defaultValue 預設值,如果不給參數值,就走預設值
  • 普通serlvet擷取參數值
//通過綁定servlet對象,擷取請求參數
    @RequestMapping("show3")
    @ResponseStatus(HttpStatus.OK)
    public void test3(HttpServletRequest request){

        System.out.println(request.getParameter("id"));
        System.out.println(request.getParameter("name"));

    }      
  • @RequestParam擷取參數值
/**
     * 擷取請求攜帶的參數  show4.do?id=33&name=jack
     *  1、@RequestParam 擷取請求指定參數
     *  2、value  參資料
     *  3、required 參數是否必須,預設true
     *      true: 必須
     *      false:可以不寫
     *  4、 defaultValue 如果沒有傳值,預設給出一個值 defaultValue = "jack"
     */
    @RequestMapping("show4")
    @ResponseStatus(HttpStatus.OK)
    public void test4(
            @RequestParam(value = "id",required = true) int id,
            @RequestParam(value = "name",required = false, defaultValue = "jack") String name ){

        System.out.println("id:"+id);
        System.out.println("name:"+name);

    }      

@CookieValue

/**
     * 通過背景跳轉到cookie視圖
     * @return
     */
    @RequestMapping("toCookie")
    public ModelAndView toCookie(){
        ModelAndView mv = new ModelAndView();
        mv.setViewName("cookie");
        return mv;
    }

    /**
     * 擷取cookie的值
     * @param name
     */
    @RequestMapping("show5")
    @ResponseStatus(HttpStatus.OK)
    public void test5(@CookieValue(value = "name",required = false) String name){
        System.out.println("cookie的值為:"+name);
    }      
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <a href="/hello/show5.do">測試cookie</a>
    <script>
        document.cookie = "name=jack";
    </script>
</body>
</html>      

POJO對象綁定參數

<dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.16.18</version>
    </dependency>      
@Data
public class User {
    private Integer id;
    private String name;
    private Integer age;
}      
/**
     * 接收綁定的pojo對象
     * @param user
     * @return
     */
    @RequestMapping("show6")
    public ModelAndView test6(User user){
        System.out.println(user);
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg",user);
        mv.setViewName("hello");
        return mv;
    }      
JAVAEE架構技術之5-springMVC參數綁定和異步互動

基本資料類型綁定

/**
     * 通過背景跳轉到user視圖
     * @return
     */
    @RequestMapping("toUser")
    public ModelAndView toUser(){
        ModelAndView mv = new ModelAndView();
        mv.setViewName("user");
        return mv;
    }      
<form action="http://localhost:8080/springmvc-test02/hello2/show18.do" method="post">
    <div>姓名:</div>
    <div><input name="name" value="張三"/></div>
    <div class="clear"></div>
    <div>年齡:</div>
    <div><input name="age" value="20"/></div>
    <div class="clear"></div>
    <div>收入:</div>
    <div><input name="income" value="100000"/></div>
    <div class="clear"></div>
    <div>結婚:</div>
    <div>
        <input type="radio" name="isMarried" value="true" checked="checked"/>是
        <input type="radio" name="isMarried" value="false"/>否</div>
    <div class="clear"></div>
    <div>興趣:</div>
    <div>
        <input type="checkbox" name="interests" value="聽歌" checked="checked"/>聽歌
        <input type="checkbox" name="interests" value="書法" checked="checked"/>書法
        <input type="checkbox" name="interests" value="看電影" checked="checked"/>看電影
    </div>
    <div class="clear"></div>
    <div><input type="submit" value="送出表單"/></div>
</form>      
/**
     * 接收基本資料類型
     */
    @PostMapping("show8")
    @ResponseStatus(HttpStatus.OK)
    public void test7(
            @RequestParam("name") String name,
            @RequestParam("age") Integer age,
            @RequestParam("income") Double income,
            @RequestParam("isMarried") Boolean isMarried,
            @RequestParam("interests") String[] interests){

        System.out.println("name: "+name);
        System.out.println("age: "+age);
        System.out.println("income: "+income);
        System.out.println("isMarried: "+isMarried);

        for(String str : interests){
            System.out.println("interests: "+str);
        }

    }      

解決亂碼問題

springmvc提供了編碼過濾器

隻解post中文亂碼問題,注意解析源碼

配置位置 web.xml

<!--編碼過濾器-->
<filter>
  <!--注意這裡是filter,不要配置成servlet-->
  <filter-name>encodingFilter</filter-name>    <!--過濾器名稱-->
  <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>  <!--過濾器的完整類名-->
  <init-param>   <!--初始化參數-->
    <param-name>encoding</param-name>  <!--參數名稱-->
    <param-value>utf-8</param-value>   <!--參數值-->
  </init-param>
</filter>
<filter-mapping> <!--過濾器映射-->
  <filter-name>encodingFilter</filter-name><!--過濾器名稱-->
  <url-pattern>/*</url-pattern><!--URL映射,給所有頁面處理亂碼-->
</filter-mapping>      

通用頁面跳轉

我們發現上面我們寫了很多次頁面跳轉的方法,其實我們可以抽取統一
@RequestMapping("to")
@Controller
public class Topage {
    /**
     * 通用頁面跳轉---視圖解析器
       http://localhost:8080/rest/to/hello
     */  
    @RequestMapping("{page}")
    public String toPage1(@PathVariable("page") String page){
        return page;
    }

    /**
     * 通用頁面跳轉---webapp下視圖--寫着玩
     */
    @RequestMapping("wp/{page}")
    public String toPage2(@PathVariable("page") String page){
        return "forward:/"+page+".html";
    }

}      
<servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/rest/*</url-pattern>
</servlet-mapping>      

數組類型

<form action="/hello/show9.do" method="post">
        <input type="checkbox" name="addr" value="鄭州"> 鄭州   <br>
        <input type="checkbox" name="addr" value="上海"> 上海   <br>
        <input type="checkbox" name="addr" value="杭州"> 杭州   <br>
        <input type="checkbox" name="addr" value="北京"> 北京   <br>
        <input type="checkbox" name="addr" value="曹縣"> 曹縣 <br>
        <input type="submit" value="數組類型">
    </form>      
/**
     * 接收數組
     * @param addr
     */
    @PostMapping("show9")
    @ResponseStatus(HttpStatus.OK)
    public void show9(String[] addr){
        for (String str :  addr){
            System.out.println(str);
        }
    }      

綁定複雜類型

如果送出的是一個集合的資料,SpringMVC的方法形參是無法接收的,我們必須通過實體類進行包裝才行
@Data
public class UserVO {
    private String name;
    private Integer age;
    private User user;
    private List<User> list;
    private Map<String,User> map;
    private String[] addr;
}      
<form action="/hello/show10.do" method="post">
    姓名: <input type="text" name="name">
    年齡: <input type="text" name="age">  <br/>
    user屬性中的姓名:<input type="text" name="user.name"><br/>
    user屬性中的年齡:<input type="text" name="user.age">     <br/>
    list中第一個user對象的年齡:<input type="text" name="list[0].age">  <br/>
    list中第一個user對象的姓名:<input type="text" name="list[0].name"> <br/>
    list中第二個user對象的年齡: <input type="text" name="list[1].age"> <br/>
    list中第二個user對象的姓名: <input type="text" name="list[1].name"> <br/>
    map中第一個鍵值對中值user對象的年齡: <input type="text" name="map['one'].age">  <br/>
    map中第一個鍵值對中值user對象的姓名: <input type="text" name="map['one'].name"> <br/>
    map中第二個鍵值對中值user對象的年齡: <input type="text" name="map['two'].age"> <br/>
    map中第二個鍵值對中值user對象的姓名: <input type="text" name="map['two'].name"><br/>

    請選擇喜歡的城市:
    <input type="checkbox" name="addr" value="鄭州"> 鄭州   <br>
    <input type="checkbox" name="addr" value="上海"> 上海   <br>
    <input type="checkbox" name="addr" value="杭州"> 杭州   <br>
    <input type="checkbox" name="addr" value="北京"> 北京   <br>
    <input type="checkbox" name="addr" value="曹縣"> 曹縣 <br>

    <input type="submit" value="複雜類型">
</form>      
/**
     * 接受複雜類型
     * @param userVO
     */
    @PostMapping("show10")
    @ResponseStatus(HttpStatus.OK)
    public void show10(UserVO userVO){
        System.out.println(userVO);
    }      

日期類型

@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birth;      

jsp和jstl視圖解析器

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>      
/**
 * 把資料轉發到jsp頁面中進行顯示
 */
@GetMapping("show20")
public ModelAndView test20(){

    ModelAndView mv = new ModelAndView();

    Person person = new Person();
    person.setId(11);
    person.setName("戈爾丹");
    person.setAge(22);

    Person person2 = new Person();
    person2.setId(11);
    person2.setName("趙日天");
    person2.setAge(33);

    Person person3 = new Person();
    person3.setId(11);
    person3.setName("葉良晨");
    person3.setAge(44);

    List<Person> list = new ArrayList<>();
    list.add(person);
    list.add(person2);
    list.add(person3);

    mv.addObject("list",list);
    mv.setViewName("list");

    return mv;
}      
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

    <table border="1px" cellpadding="8px" cellspacing="0px" width="80%">
        <thead>
            <tr>
                <th>ID</th>
                <th>Name</th>
                <th>Age</th>
            </tr>
        </thead>
        <tbody>
            <c:forEach items="${list}" var="person">
                <tr>
                    <td>${person.id}</td>
                    <td>${person.name}</td>
                    <td>${person.age}</td>
                </tr>
            </c:forEach>
        </tbody>
    </table>
</body>
</html>      

SpringMVC異步互動

在之前我們講的請求響應都是同步的,但是在實際開發中我們都是使用異步請求,是以下面我們使用ajax發送異步請求!

在異步請求中資料傳輸的格式我們都是使用josn來進行傳輸,速度快,小巧,使用友善!!

在響應的同時,我們也是響應json字元串,在前端解析json字元串即可!

回顧ajax

  • 發送ajax請求:$.ajax() / $.get() / $.post()
  • 響應json資料:new ObjectMapper().writeValueAsString()

我們學習完SpringMVC之後,就不用像之前那麼麻煩了,還要建立ObjectMapper對象來轉換成josn資料進行響應。

SpringMVC已經幫我們做這些事情了。SpringMVC提供了兩個注解@RequestBody和@ResponseBody實作josn資料的轉換

@ResponseBody

用于将controller方法傳回的對象通過轉換器轉換為指定的格式(通常為json)之後,寫入到response對象的響應體中。

添加依賴

<!-- Jackson Json處理工具包 -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.5</version>
</dependency>      

引入jq檔案

<script src="js/jquery-3.4.1.js"></script>      

編寫ajax代碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/jquery-3.4.1.js"></script>
</head>
<body>
    <table border="1">
        <tr>
            <td>name</td>
            <td>age</td>
        </tr>
    </table>
    <script>
        $.ajax({
            url: 'UserController/ajaxResponse.do',
            type: 'POST',
            dataType:"json",
            success: function (data) {
                var str = '';
                $(data).each(function (i) {
                    str += `
                        <tr>
                            <td>${data.name}</td>
                            <td>${data.age}</td>
                            <td></td>
                        </tr>
                    `;
                });
                $("table").append(str);
            }
        });
    </script>
</body>
</html>      

編寫Controller

@Controller
@RequestMapping("UserController")
public class UserController {

    /**
     * 響應json串   
     * @return
     */
    @PostMapping("ajaxResponse")
    @ResponseBody //傳回的對象以json的形式響應  {"name":"jack","age":99}
    public User getUser(){
        User user = new User();
        user.setName("jack");
        user.setAge(99);
        return user;
    }
}      

@RestController用法

@RequestMapping("UserController")
@RestController   //@RestController  == @Controller 和 @ResponseBody
public class UserController {

    /**
     * 響應json串
     * @return
     */
    @PostMapping("ajaxResponse")
    public User getUser(){
        User user = new User();
        user.setName("jack");
        user.setAge(99);
        return user;
    }
}      

@RequestBody

用于接收前端請求體中的json資料,使用@RequestBody注解就可以自動的封裝指定的對象中

引入jq檔案

<script src="js/jquery-3.4.1.js"></script>      

編寫ajax代碼

  • 使用: $.ajax() 函數
  • 規則:
  • ajax送出的資料必須是一個标準的json字元串
  • ajax送出的方式必須為post,資料必須在請求體中
  • ajax送出的MIME類型必須為:application/json;charset=utf-8
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/jquery-3.4.1.js"></script>
</head>
<body>
    <script>$(function () {
            $.ajax({
                url: '/UserController/ajaxRequest.do',
                type: 'POST',
                data: '{"name":"jack","age":99}',
                contentType:'application/json;charset=utf-8',
                success: function (data) {

                }
            });
        });</script>
</body>
</html>      

編寫Controller

/**
     * 接受json串
     * @param user
     */
    @PostMapping("ajaxRequest")
    public void test(@RequestBody User user){
        //User(name=jack, age=99)
        System.out.println(user);
    }      

小結

​@RequestBody​

​:将請求體中的json字元串,轉為指定類型的java對象

​@ResponseBody​

​:将java對象轉為json字元串,再設定到響應體中,傳回到浏覽器(用戶端)

處理靜态資源

測試前端代碼

當點選按鈕時,發現沒有任何反應,這是因為SpringMVC在預設情況下,所有的靜态資源都會被攔截(js,css。html,圖檔、視訊、音頻),在web.xml檔案中,我們配置的攔截路徑是​

​/​

​ 這種形式除了jsp都會被攔截

<servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <!--攔截webapp下所有靜态資源,除了jsp-->
    <url-pattern>/</url-pattern>
</servlet-mapping>      

把攔截路徑設定為 / 時,會發現連html靜态頁面都無法通路

三種方式解決

  • web.xml配置方式一
<servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <!--攔截webapp下所有資源,除了jsp-->
    <url-pattern>/</url-pattern>
</servlet-mapping>

<!-- 處理靜态資源攔截-->
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.jpg</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.css</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.html</url-pattern>
</servlet-mapping>      
  • springmvc-servlet.xml 配置檔案
<!--
    靜态資源手動映射
        mapping="/img/**" 浏覽器發送請求
        location="/img/" 靜态資源的路徑
-->
<mvc:resources mapping="/html/**" location="/html/"/>
<mvc:resources mapping="/img/**" location="/img/" />
<mvc:resources mapping="/js/**" location="/js/" />  
<mvc:resources mapping="/css/**" location="/css/"/>      
  • springmvc-servlet.xml 配置檔案【簡化方式】
<!-- 處理靜态資源攔截-->
<!--配置tomcat預設的靜态資源處理-->
<mvc:default-servlet-handler/>      

繼續閱讀