国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Java EE 突擊 11 - Spring MVC 程序開發(fā) (2)

這篇具有很好參考價值的文章主要介紹了Java EE 突擊 11 - Spring MVC 程序開發(fā) (2)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

這個專欄給大家介紹一下 Java 家族的核心產(chǎn)品 - SSM 框架
JavaEE 進階專欄

Java 語言能走到現(xiàn)在 , 仍然屹立不衰的原因 , 有一部分就是因為 SSM 框架的存在

接下來 , 博主會帶大家了解一下 Spring、Spring Boot、Spring MVC、MyBatis 相關(guān)知識點

并且?guī)ьI(lǐng)大家進行環(huán)境的配置 , 讓大家真正用好框架、學懂框架

來上一篇文章復習一下吧
點擊即可跳轉(zhuǎn)到前置文章
Java EE 突擊 11 - Spring MVC 程序開發(fā) (2),JavaEE 進階,java-ee,spring,mvc

三 . 獲取參數(shù)

3.1 傳遞單個參數(shù)

獲取方法1 : 通過 Servlet 中的 request 方式獲取

我們之前在 Servlet 的時候 , 獲取參數(shù)里面的信息使用的方法是 : request.getParameter(“xxx”) , 因為我們的 Spring MVC 是構(gòu)建在 Servlet 上面的 , 所以我們 Servlet 的方法在 Spring MVC 里面仍然可以使用

package com.example.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Controller
@ResponseBody
public class WebController {
    @GetMapping("/hi") //使用"/hi"可以訪問到當前方法,該方法只支持 GET 請求
    // 默認其實是把 HttpServletRequest request, HttpServletResponse response 隱藏起來了,需要用的時候再寫出來
    public Object sayHi(HttpServletRequest request, HttpServletResponse response) {
        return "Hi," + request.getParameter("name");
    }
}

image.png
接下來我們啟動項目 , 在瀏覽器的地址欄輸入 :

http://127.0.0.1:8080/hi?name=zhangsan

然后看一下頁面能否顯示出我們的名字
image.png
改成李四也是可以的
image.png
但是這種方式存在一些問題 :
image.png
image.png
這就存在一個問題 , 假如我們返回的數(shù)據(jù)是 int 類型 , 我們還能進行強轉(zhuǎn) , 但是假如我們這次沒傳數(shù)據(jù)呢 , 那進行強轉(zhuǎn)的話不就是把 null 進行強轉(zhuǎn)了嗎 , 這可不太行

獲取方法2 : Spring MVC(Spring Web) 主要獲取參數(shù)的方式

package com.example.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Controller
@ResponseBody
public class WebController {
    /**
     * 獲取單個參數(shù)
     * 代表我們從前端拿到 name 參數(shù)
     * @param name
     * @return
     */
    @GetMapping("/get1")
    public String getParam1(String name) {
        return "value=" + name;
    }
}

運行一下
image.png
那么這種情況 , 不傳參數(shù)會不會有問題呢
沒有問題 , 打印出來 null
image.png
那么我們還可以傳遞整型類型的參數(shù)

package com.example.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Controller
@ResponseBody
public class WebController {
    /**
     * 獲取單個參數(shù)
     * 代表我們從前端拿到 name 參數(shù)
     * @param name
     * @return
     */
    @GetMapping("/get1")
    public String getParam1(int age) {
        return "value=" + age;
    }
}

image.png
那么我們不更改代碼 , 接下來傳遞一個字符串呢
當然會報錯了 , 這不是自己找不自在呢嗎 , 我們目前參數(shù)列表里面寫的是 int age , 那你傳一個 String 類型的數(shù)據(jù)肯定會報錯
image.png
參數(shù)里面使用 int 的話 , 我們不傳參數(shù)的時候 , int 類型的參數(shù)就會報錯
image.png
因為基本數(shù)據(jù)類型里面并不存在 null , 只有包裝類才有 null , 所以我們這里使用包裝類即可 , 那么 int 對應的包裝類就是 Integer

package com.example.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Controller
@ResponseBody
public class WebController {
    /**
     * 獲取單個參數(shù)
     * 代表我們從前端拿到 name 參數(shù)
     * @return
     */
    @GetMapping("/get1")
    public String getParam1(Integer age) {
        return "value=" + age;
    }
}

這次就不會再報錯了 , 因為 Integer 默認就是 null
image.png
最后要注意的就是輸入框里面的參數(shù)要跟代碼里面的參數(shù)的名稱要相同
image.png

3.2 獲取多個參數(shù)

方法還是跟之前的一樣

package com.example.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Controller
@ResponseBody
public class WebController {
    /**
     * 獲取兩個參數(shù)
     * @param name
     * @param age
     * @return
     */
    @GetMapping("/get2")
    public String getParm2(String name,Integer age) {
        return "name=" + name + ",age=" + age;
    }
}

我們在瀏覽器試驗一下
image.png
那么我們的參數(shù)順序要是顛倒了 , 還能正常識別嗎 ?
image.png
Spring MVC 中傳遞多個參數(shù)的時候 , 傳遞參數(shù)的順序是不影響程序執(zhí)行的 , 獲取參數(shù)的結(jié)果和參數(shù)的名稱有關(guān) , 和順序無關(guān)
目前我們的參數(shù)只有兩個 , 但是假如我們的參數(shù)有很多 , 怎么解決呢 ?
我們當然可以寫許多個參數(shù) , 但是這樣并不是利于維護的 , 那我們其實可以把這多個參數(shù)封裝成一個對象 , 接收的時候接收一個對象即可
所以接下來 , 我們教大家怎么獲取對象

3.3 獲取對象

既然是獲取對象 , 我們首先就要有一個對象
我們在 demo 包底下新建一個 model 包 , 然后新建一個類 ,叫做 Student

package com.example.demo.model;

import lombok.Data;

// 這個類就是一個普通的實體類,不需要加五大類注解
// 使用 @Data 注解就可以不用寫 getter 和 setter 方法了
@Data
public class Student {
    // 注意: 這里的屬性名一定要和前端傳遞過來的名字相一致
    private Integer id;// 如果我們要是害怕前端不傳遞過來參數(shù)的話導致報錯的話,我們就可以把 int 提升成 Integer
    private String name;
    private Integer age;
    private String sex;
    // ...
}

接下來回到 WebController.java

package com.example.demo.controller;

import com.example.demo.model.Student;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Controller
@ResponseBody
public class WebController {
    /**
     * 獲取對象
     */
    @GetMapping("/get3")
    public String getParam3(Student student) {
        return student.toString();//雖然我們 Student 里面沒寫 toString,但是我們加了 @Data 注解,里面就包括了 toString
    }
}

那么前端怎么傳遞參數(shù)呢 ?
該怎么傳怎么傳 , 傳遞的順序也是無所謂的
image.png
注意事項 : 參數(shù)的傳遞是對大小寫敏感的 , 時而好使時而不好使的 , 推薦大家這個名字全部小寫 , 就別搞什么大駝峰啥的了
image.png
image.png

3.4 獲取表單參數(shù)

我們知道 , 參數(shù)請求的參數(shù)一共有 :

  1. URL 傳參 : 我們剛才的幾個實例都是 URL 傳參
  2. Ajax 傳參 : 一般是頁面局部跳轉(zhuǎn)(比如動態(tài)頁面部分內(nèi)容刷新,整體不刷新)
  3. Form 表單傳參 : 一般是頁面全部跳轉(zhuǎn)(跳轉(zhuǎn)到新頁面)使用 form 表單

獲取參數(shù)少的情況

如果我們是 Form 表單傳參 , 我們怎么實現(xiàn)
我們現(xiàn)在做一個小樣例 : 實現(xiàn)用戶的登陸 , 將用戶名密碼傳過來
我們先實現(xiàn)一個簡單的頁面 : login.html
在 resources 目錄底下的 static 里面新建一個 html 文件

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>用戶登錄</title>
  </head>
  <body>
    <!--  method="提交方法" action="提交地址" -->
    <form method="get" action="login">
      <div>
        <h1> 登錄 </h1>
        用戶名 : <input name="name"><br>
        密碼  : <input name="password"><br>
        <input type="submit" value="提 交">
      </div>
    </form>
  </body>
</html>

接下來 , 我們再來寫 WebController , 這次我們使用 @RequestMapping , @RequestMapping Get 請求和 Post 請求都能接收

package com.example.demo.controller;

import com.example.demo.model.Student;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Controller
@ResponseBody
public class WebController {
    /**
     * 獲取 form 表單中的參數(shù)
     */
    // 這塊要與前端的 action 的參數(shù)對應
    @RequestMapping("/login")
    public String login(String name,String password) {
        return "<h1>用戶名:" + name + "<br>密碼:" + password + "</h1>";
    }
}

image.png
image.png

獲取參數(shù)多的情況

剛才這種情況是參數(shù)比較少的情況 , 那要是參數(shù)非常多呢 ?
比如我們的注冊 : 用戶名、密碼、昵稱、郵箱、手機號、驗證碼…
當然還是可以寫許多個參數(shù) , 但是這樣代碼的維護性很差 , 我們也可以通過對象來獲取(跟剛才講的一樣)
我們依然是將傳遞過來的參數(shù)封裝成一個對象
我們在 model 包底下新建一個類 , 叫做 User
我們只需要保證 form 表單傳過來的參數(shù)和我們 User 類當中的 key 保持一致即可

package com.example.demo.model;

import lombok.Data;

// 這個類就是一個普通的實體類,不需要加五大類注解
// 使用 @Data 注解就可以不用寫 setter 方法了
@Data
public class User {
    // 注意: 這里的屬性名一定要和前端傳遞過來的名字相一致
    private Integer id;
    private String name;
    private String password;
    private Integer age;
    private String sex;
    private String classname;
    private String nickname;
    private String img;
    // ...
}

接下來寫一下我們的前端頁面 , 新建一個前端頁面吧 , 叫做 reg.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用戶注冊</title>
</head>
<body>
    <!--  method="提交方法" action="提交地址" -->
    <form method="get" action="reg">
        <div>
            <h1> 注冊 </h1>
            用戶名 : <input name="name"><br>
            密碼  : <input name="password"><br>
            性別  : <input name="sex"><br>
            <input type="submit" value="提 交">
        </div>
    </form>
</body>
</html>

(因為我對前端不是那么熟悉 , 所以簡單寫一下就好了)
那么我們后端怎樣接收呢 ?

package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Controller
@ResponseBody
public class WebController {
    /**
     * 獲取 form 表單(多個參數(shù))
     * @param user
     * @return
     */
    @RequestMapping("/reg")
    public String reg(User user) {
        return user.toString();
    }
}

來看一下效果
image.png
image.png


接下來 , 咱們再試驗一下 ajax 傳參的方式
我們在 resources.static 包底下新建一個 HTML 文件 , 叫做 login_ajax.html
我們還要使用 jQuery 第三方庫 : https://www.aliyundrive.com/s/G8h1rn3sgX7
然后在 static 包下新建一個文件夾 , 叫做 js , 然后把 jQuery 引入進來(選中 js 文件夾 , ctrl + v)
image.png
然后我們在代碼中引入 jQuery
image.png
然后編寫頁面代碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="js/jquery.min.js"></script>
</head>
<body>
    <div>
        <h1> 登錄 </h1>
        用戶 : <input id="name" name="name"><br>
        密碼 : <input id="password" name="password"><br>
        <input type="button" onclick="onsub()" value=" 提 交 ">
    </div>
    <script>
        function onsub() {
            jQuery.ajax({
                url:"login2",
                type:"GET",
                data:{"name":jQuery("#name").val(),"password":jQuery("#password").val()},
                success:function(result) {
                    alert(result);
                    console.dir(result);
                }
            });
        }
    </script>
</body>
</html>

接下來回到 WebController , 再寫一個 login2

package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;

@Controller
@ResponseBody
public class WebController {
    @RequestMapping("/login2")
    public HashMap<String,Object> login2(String name, String password) {
        HashMap<String,Object> result = new HashMap<>();
        result.put("name",name);
        result.put("password",password);
        return result;//返回 JSON 格式的對象
    }
}

運行查看效果 , 我們可以把 谷歌瀏覽器自帶的抓包工具打開 (Fiddler 一樣)
image.png
有可能是你的 jQuery 沒有正常工作
但是咱們的代碼目前是沒有問題的 , 那就有可能是你的 IDEA 搞的鬼 …
image.png
image.png
image.png
image.png
image.png
我們只需要把 target 目錄刪掉重新運行即可
image.png
然后這次就有了
image.png
回到瀏覽器我們重新看一眼
image.png
這回就有數(shù)據(jù)了
image.png
接下來輸入數(shù)據(jù) , 我們就抓到了包 , 他的類型是 application/json , 這就因為我們的 HashMap 也是 key-value 模型的 , 會轉(zhuǎn)換成 JSON 數(shù)據(jù)格式
image.png
點擊彈窗的確定之后 , 我們再來看一下控制臺
image.png
這就說明前端傳過來的數(shù)據(jù) , 我們后端已經(jīng)接收到了

3.5 接收 JSON 對象

package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;

@Controller
@ResponseBody
public class WebController {
    @RequestMapping("/login2")
    public HashMap<String,Object> login2(String name, String password) {
        HashMap<String,Object> result = new HashMap<>();
        result.put("name",name);
        result.put("password",password);
        return result;//返回 JSON 格式的對象
    }
}

我們可以通過 Postman 構(gòu)造 JSON 對象
image.png
點擊 Send , 然后去 Fiddler 抓包
image.png
那么有的同學說 : 我們傳遞的是 JSON 對象過去的啊 ,你用一個普通的參數(shù)能接收到嗎 ?
那么我們再來寫一個 login3 , 就做一件事 : 拿對象

package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;

@Controller
@ResponseBody
public class WebController {
    @RequestMapping("/login3")
    public HashMap<String,Object> login3(User user) {
        HashMap<String,Object> result = new HashMap<>();
        result.put("name",user.getName());
        result.put("password",user.getPassword());
        return result;//返回 JSON 格式的對象
    }
}

如果說 , 我通過這幾句代碼 , 通過一個 User 對象能夠拿到前端傳過來的對象的相關(guān)信息 , 并且把 name 值和 password 值進行 set 了 , 那么我們代碼指定是沒有問題的 , 那么我們返回的時候就不會是 null 了
那么我們再來試一下
image.png
image.png

我們剛剛講過的通過 Ajax , 跟這個有很大區(qū)別 , 大家不要搞混
image.png
我們現(xiàn)在是通過傳輸 JSON 的這種方式 , 所以這兩個是完全不一樣的
image.png
最剛開始是在 url 里面搞事情 , 現(xiàn)在是在 body 里面搞事情 , 是不一樣的 .

所以接收一個 JSON 對象 , 是跟以前都不一樣的 , 我們需要加一個注解 : @RequestBody
image.png
這個注解的作用就是告訴這個對象 , 我接收的時候 , 不是從 url 里面去獲取的 , 是從 body 里面獲取的

package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;

@Controller
@ResponseBody
public class WebController {
    /**
     * 得到用戶傳遞的 JSON 對象
     * @param user
     * @return
     */
    @RequestMapping("/login3")
    public HashMap<String,Object> login3(@RequestBody User user) {
        HashMap<String,Object> result = new HashMap<>();
        result.put("name",user.getName());
        result.put("password",user.getPassword());
        return result;//返回 JSON 格式的對象
    }
}

@RequestBody 注解只能搭配對象使用 ,不能搭配單個屬性使用


最后 , 大家要清楚 :
image.png
圈出來的部分 , 其實他不是在 body 里面?zhèn)髦档?/p>

有的同學會說 , 我們之前都是 GET 啊 , GET 的情況下不就是通過 URL 去傳的嗎 ?
那改成 POST 就傳到 Body 里面了啊

那我們就試一下 , 把這里改成 POST
image.png
然后重新運行
image.png
image.png
而且我們的請求當中也并未設(shè)置 content-type 為 JSON 格式 , 而是 application/x-www-form-urlencoded 的形式 (也就是 form 表單的形式) , 并不是 JSON 格式
image.png
那么我們通過 Postman 構(gòu)造 JSON 格式再看一下呢
image.png
然后查看抓包結(jié)果
image.png

通過 ajax 傳遞 JSON 對象給后端(后續(xù)繼續(xù)講解)

我們需要設(shè)置兩個位置 :

  1. 設(shè)置請求的格式 content-type 為 JSON
$.ajax({
  url: '/your/api/endpoint',
  type: 'POST',
  data: JSON.stringify({ key: value }), // 將數(shù)據(jù)轉(zhuǎn)換成 JSON 字符串
  contentType: 'application/json', // 設(shè)置請求的格式為 JSON
  dataType: 'json', // 指定服務器返回的數(shù)據(jù)類型為 JSON
  success: function(data) {
    // 請求成功后的處理邏輯
  },
  error: function(code, status, error) {
    // 請求失敗后的處理邏輯
  }
});
  1. data 里面的寫法就需要是一個 JSON 對象了(把圈出來的部分轉(zhuǎn)換成一個 JSON 對象)

image.png
在 JS 中 , 轉(zhuǎn)換 JSON 對象可以使用 JSON 對應的庫

JSON.parse :JSON 轉(zhuǎn)化成 字符串
JSON.stringify :JS 對象轉(zhuǎn)化成 JSON

3.6 上傳文件

使用注解 : @RequestPart(“文件名”) , 使用 MultpartFile 類型去接收
拿到文件之后還需要去存儲 , 我們的 Spring MVC 也給大家提供了一種方法 : transferTo(), 在括號內(nèi)新 new 一個文件對象 , 名字就是要上傳的文件名
口說無憑上實例

package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;

@Controller
@ResponseBody
public class WebController {
    /**
     * 上傳文件
     */
    @RequestMapping("/reg2")
    // 第一個參數(shù):name
    // 第二個參數(shù):文件,獲取文件需要加注解@RequestPart,注解需要設(shè)置參數(shù)
        // 括號內(nèi)起一個名字,保證這個名字和前端部分保持一致
    public String reg2(String name, @RequestPart("myfile") MultipartFile file) throws IOException {
        // 已經(jīng)拿到頭像了,接下來要保存頭像
        // 使用絕對路徑,不能使用相對路徑
        file.transferTo(new File("D:\\study\\dogTest.jpg"));//目錄+圖片名,這里的文件名起什么名存到目錄里的就是什么名
        return "success";
    }
}

那么后端代碼已經(jīng)實現(xiàn) , 可是我們怎樣去上傳圖片呢 ?
還是要使用我們的 Postman (良心工具)
image.png
然后填寫 key
image.png
之后上傳文件
image.png
再把第一個參數(shù) name 給填上
image.png
之后點擊 Send 發(fā)射 , 去 Fiddler 抓包看看
image.png
image.png
接下來我們?nèi)タ纯磮D片上沒上傳成功
image.png

3.7 獲取 Cookie/Session/Header

獲取 Cookie

傳統(tǒng)獲取 header / cookie
package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;

@Controller
@ResponseBody
public class WebController {
    /**
     * 傳統(tǒng)方法獲取 header/cookie
     */
    @RequestMapping("/cookie1")
    @ResponseBody
    public String cookie1(HttpServletRequest request,HttpServletResponse response) {
        String name = request.getParameter("name");
        // 獲取所有 cookie 信息
        Cookie[] cookies = request.getCookies();
        return name;
    }
}
簡單地獲取 Cookie : 使用注解 @CookieValue

@CookieValue(“Cookie 名稱” String 賦值給誰)
這個注解需要一個參數(shù) , 這個參數(shù)跟 @RequestPart 的參數(shù)是一樣的 , 需要拿到前端傳遞過來的 key 值
比如 : @CookieValue(“haha” String xixi)
從前端傳遞過來的請求里面 , 去找一叫做 haha 的 cookie ,把 cookie 的 value 值交給當前程序的 xixi 變量 , 然后在程序里面我們就可以使用 xixi 變量了

package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;

@Controller
@ResponseBody
public class WebController {
    /**
     * Spring MVC 獲取 cookie 的值
     */
    @RequestMapping("/getck")
    public String getCookie(@CookieValue("haha") String xixi) {
        return "haha:" + xixi;// cookie名 + 要把haha賦值給誰
    }

}

image.png
接下來我們使用開發(fā)者工具進行模擬 cookie 環(huán)境
添加 key value 數(shù)據(jù)
image.png
然后刷新頁面
image.png
抓個包看看
image.png

那么為什么瀏覽器會默認將當前網(wǎng)站的所有 cookie 發(fā)送給后端呢 ?
原因就是 : http 協(xié)議無狀態(tài)(我在訪問你的時候 , 我不會記錄你是誰)
那這樣的話就會存在問題 : 如果你做的是教務管理系統(tǒng) , 是需要進行登錄的 , 然后你在進行發(fā)送每一次請求的時候 , 后端都不認識你啊 , 這就意味著我們每一次操作都需要進行登錄 , 那這肯定是不行
所以我們有兩種方案 :

  1. 每一次在 URL 上面動手腳 , 在 URL 上面加一個標識 , 每一次加了這個標識之后 , 后端在拿前端的參數(shù)時候 ,先拿這個標識 , 看看這個標識有沒有問題 .

但是這樣還是存在問題 :

  1. 標識加到了 URL 里面 , 還是有暴露的風險
  2. 驗證的時候 , 通過 URL 去驗證 , 但是 URL 很好偽造的 .

所以這種方法不太靠譜

  1. 把用戶的身份標識存在客戶端(瀏覽器) , 那我們?yōu)g覽器唯一能操作的東西只有 cookie , 所以他就設(shè)計了一個機制 : 把身份標識加到了 cookie 里面

其實第二種方法也不是那么安全 , 在客戶端的所有的東西都是不安全的 , 我們都可以通過特殊手段去偽造 , 但是使用 cookie 的這種偽造成本是比直接在 URL 里面添加參數(shù)要高的 , 雖然不能保證絕對的安全 , 但是能夠保證相對的安全

而且使用 cookie 這種形式 , 我們存儲的是秘鑰 , 存的并不是一個固定的值 , 而且這個秘鑰 , 同一個用戶登錄多次是不一樣的 , 即使你拿到秘鑰了 , 但是過一陣子重新登陸之后秘鑰就過期了 ,你破解了也沒有用
那么我們就選擇第二種方式 : 把身份標識存儲到 cookie 里面 , 把身份標識存儲到 cookie 里面也有問題啊 , 即使我的身份信息已經(jīng)存到 cookie 里面了 , 那瀏覽器也不知道你什么時候需要這個身份信息 , 所以瀏覽器就只好每次都返回 ,管你用不用呢 , 有 cookie 我就給你

那么接下來 , 假如說我想打印兩組 cookie 呢 ?
我們只需要在代碼里面函數(shù)參數(shù)部分再寫一份注解
image.png

package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;

@Controller
@ResponseBody
public class WebController {
    /**
     * Spring MVC 獲取 cookie 的值
     */
    @RequestMapping("/getck")
    public String getCookie(@CookieValue("haha") String xixi,
                            @CookieValue("aima") String aiba) {
        return "haha:" + xixi + " aima:" + aiba;
    }

}

刷新一下
image.png
這個 cookie 是沒有進行持久化的 , 我們把瀏覽器關(guān)掉重新打開訪問 ,就會報錯
image.png
因為 cookie 相對來說不太安全 , 我們又出現(xiàn)了 session , 我們不能把所有的安全機制放在外人手里 , 所以放到服務器端會安全一點 , 而 session 完全是在服務器端的 , 現(xiàn)在我的程序就是服務器端 , 正常情況下不能讓客戶端去記錄所有的登錄信息 , 那我們要把控制權(quán)攥在自己手里 , 就使用 session . 因為 session 是放在服務器端的 , 但是又有一個問題 : 服務器端的東西要在服務器端生效 , 但是用戶操作是在客戶端操作啊 , 那為了解決這個問題 , session 里面就會有個東西 , 叫做 sessionId , 這就相當于我有一個會話表 , 會話表里面有兩部分數(shù)據(jù) : 一個是 sessionId , 一個是存儲的對應信息 , 這個 sessionId 是隨機生成的 , 同一個用戶每次登陸生成的 sessionId 是不同的 , 這樣就可以保證安全性以及時效性
image.png

Session 存取和獲取

Servlet 時代的方式

獲取 session

package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;

@Controller
@ResponseBody
public class WebController {
    @RequestMapping("/setsess")
    @ResponseBody
    public String setsess(HttpServletRequest request) {
        // 獲取 HttpSession 對象
        // 參數(shù)為true:如果沒有session對象就創(chuàng)建一個session
        HttpSession session = request.getSession(true);
        if (session == null) {
            session.setAttribute("username","java");
        }
        return "success";
    }
}

讀取 session

package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;

@Controller
@ResponseBody
public class WebController {
    @RequestMapping("/sess")
    @ResponseBody
    public String sess(HttpServletRequest request) {
        // 如果session不存在,不會自動創(chuàng)建
        HttpSession session = request.getSession(false);
        String username = "none";
        if(session != null && session.getAttribute("username") != null) {
            username = (String) session.getAttribute("username");
        }
        return "username:" + username;
    }
}
獲取 session 更簡潔的方式 : @SessionAttribute
package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;

@Controller
@ResponseBody
public class WebController {

    /**
     * 設(shè)置 session
     * @param request
     * @return
     */
    @RequestMapping("/setsess")
    public String setsess(HttpServletRequest request) {
        // 獲取 HttpSession 對象
        // 參數(shù)為true:如果沒有session對象就創(chuàng)建一個session
        HttpSession session = request.getSession(true);
        if (session != null) {
            session.setAttribute("username","java");
        }
        return "success";
    }

    @RequestMapping("/getsess")
    public String getsess(@SessionAttribute("username") String username) {
        return "username:" + username;
    }
}

運行一下
image.png
會報錯的 , 這是因為我們的 session 還沒添加進去
所以我們需要先運行 setsess , 再運行 getsess
image.png
image.png我們可以在 sessionAttribute 里面加上 required = false , 此時再來看效果

package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;

@Controller
@ResponseBody
public class WebController {
    @RequestMapping("/getsess")
    public String getsess(@SessionAttribute(value = "username",required = false) String username) {
        return "username:" + username;
    }
}

我們直接來訪問他的 getsess
image.png
這回就不報錯了 , 這是因為 required = false , 直白一點就是 : session 可以為空 , 可以不為空 , 不為空的時候返回 null
之前說 , session 是依靠 cookie 的 , 那就帶大家來個花活
image.png
那我們故意把這個 sessionId 篡改了之后呢 ?
image.png

獲取 Header

Servlet 時代的方式
package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;

@Controller
@ResponseBody
public class WebController {
    @RequestMapping("/getheader")
    public String getheader(HttpServletRequest request) {
        String userAgent = request.getHeader("User-Agent");
        return userAgent;
    }
}
獲取 Header 更簡單的方式 : @RequestHeader
package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;

@Controller
@ResponseBody
public class WebController {
    /**
     * 讀取請求頭
     * @param userAgent
     * @return
     */
    @RequestMapping("/gethead")
    public String getHead(@RequestHeader("User-Agent") String userAgent) { //把請求頭里面的User-Agent信息放到userAgent里面
        return "UserAgent:" + userAgent;
    }
}

那么這里面的 User-Agent 是什么 ?
image.png
運行就會把我們的版本信息打印出來
image.png
image.png

3.8 重命名前端參數(shù) : @RequestParam

比如說前端給我們的參數(shù) ,叫做 username , 那么我們后端想要使用 name , 那前后端名稱不統(tǒng)一的話 , 程序就無法運行 , 所以 Spring MVC 給我們提供了一個注解 : @RequestParam


package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;

@Controller
@ResponseBody
public class WebController {
    /**
     * 前端參數(shù)重命名
     * 以后端程序員的視角,咱們參數(shù)應該設(shè)置成 time
     * 但是以前端程序員的視角,人家覺得設(shè)置成t之后,放在URL里面不占位置,傳輸速度快
     * 這就產(chǎn)生分歧了
     * @return
     */
    @RequestMapping("/gettime")
    // 后端程序員想要去用 time
    public String getTime(String time) {
        return "time:" + time;
    }
}

我們的參數(shù)寫的是 time , 但是前端設(shè)置的返回的 URL 里面的參數(shù)是 t , 所以我們進行測試的話就會發(fā)生錯誤
image.png
因為我們后端設(shè)置的參數(shù)叫做 time , 但是 URL 里面?zhèn)鬟^來的是 t , 所以服務器端就接收不到數(shù)據(jù)
那怎么辦呢 ?
我們就可以使用 @RequestParam

package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;

@Controller
@ResponseBody
public class WebController {
    /**
     * 前端參數(shù)重命名
     * 以后端程序員的視角,咱們參數(shù)應該設(shè)置成 time
     * 但是以前端程序員的視角,人家覺得設(shè)置成t之后,放在URL里面不占位置傳輸速度快
     * 這就產(chǎn)生分歧了
     * @return
     */
    @RequestMapping("/gettime")
    // 后端程序員想要去用 time
    public String getTime(@RequestParam("t") String time) { //接收 URL 里面的 t , 用 time 替換
        return "time:" + time;
    }
}

重命名之后 , 再次運行
image.png
那么前端程序員想要改成 time , 然后告訴后端程序員我改完了
然后后端程序員去運行
image.png好家伙 , 你竟敢耍我 …
其實這就不是前端程序員的鍋了 , 我們設(shè)置好參數(shù)重命名之后就只能使用設(shè)置好的參數(shù)名了 , 比如不能用 time 了 , 只能用 t 了
image.png
image.png
那么我們就可以設(shè)置一下 required 屬性為 false , 這樣即使沒傳過來 t 參數(shù)的話 , 也不會報錯了 , 只是顯示為 null

package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;

@Controller
@ResponseBody
public class WebController {

    /**
     * 前端參數(shù)重命名
     * @return
     */
    @RequestMapping("/gettime")
	// 在括號里面設(shè)置 required = false 就代表沒有傳過來 t 這個參數(shù) , 我也不報錯 , 顯示 null 即可
    public String getTime(@RequestParam(value = "t",required = false) String time) { //接收 URL 里面的 t , 用 time 替換
        return "time:" + time;
    }
}

image.png
但是我們使用 @RequestParam 之后只能識別 t 參數(shù) , 并將 t 參數(shù)的值 , 設(shè)置給 time 變量
此時即使使用 time 參數(shù) , 也為時已晚了 , 也是讀取不到前端的參數(shù)的 , 他只認參數(shù)名為 t 的參數(shù)

3.9 獲取 URL 中的參數(shù) : @PathVariable

有一種奇奇怪怪的 URL , 他不是用 ? 引出的 , 它是以目錄形式存在的
image.png
那么這種情況有沒有呢 ?
當然也是存在的 , 給大家舉個栗子 . 我們?nèi)ニ阉餍旒熏?br>image.png
有的詞條就是在前面的 , 有的詞條就是在后面的
那搜狗和知乎公司實力旗鼓相當 , 他們倆為啥一個在前一個在后呢 , 其實就有可能是 URL 的問題
image.png
image.png
那這樣的話 , B 公司就有可能會被搜索引擎推送到前面 , 因為他是在 URL 里面添加參數(shù)的 , 肯定要比在參數(shù)里面添加參數(shù)比重更高 .
但是在 URL 里面獲取參數(shù)更加困難 , 不過也不是沒有辦法
我們需要注意兩個位置 :

  1. 在 @RequestMapping 里面寫路由的時候 , 要加一個花括號 , 表示當前花括號里面的內(nèi)容不是一個靜態(tài)的字符 , 是一個變量
@RequestMapping("login4/{name}/{password}")
// 這就代表 name 并不是一個目錄 , 而是一個變量
  1. 要在參數(shù)里面使用一個特殊的注解 : @PathVariable
@RequestMapping("/login4/{name}/{password}")
// 在每個參數(shù)前面加上 @PathVariable 就代表從 URL 的路由中拿變量賦值給對應的變量
// 比如 : @PathVariable String name 就代表從路由中拿到 name 變量給參數(shù)中的 name 變量
public String login4(@PathVariable String name, @PathVariable String password) {
    System.out.println("name:" + name + " password:" + password);
    return "name:" + name + " password:" + password;
}

我們還可以進行指定名稱

package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;

@Controller
@ResponseBody
public class WebController {
    /**
     * 從 URL 里面獲取參數(shù)
     * @param username
     * @param password
     * @return
     */
    @RequestMapping("/login4/{name}/{password}")
    // 在路由里面拿 name 變量的路由,賦值給 username
    public String login4(@PathVariable("name") String username, @PathVariable String password) {
        System.out.println("name:" + username + " password:" + password);
        return "name:" + username + " password:" + password;
    }
}

運行一下
前端傳遞參數(shù)直接采用路徑層級來傳遞的
image.png

四 . 返回數(shù)據(jù)

其實我們之前已經(jīng)用過很多次了 , 就是最后 return 回去就好了
不過要清楚一件事 :

4.1 返回值類型是 String

如果我們代碼中返回的是 String 類型 , 那么 Spring MVC 會自動幫我們?nèi)マD(zhuǎn)換成 text/html 格式
拿剛才的例子舉例

package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;

@Controller
@ResponseBody
public class WebController {
    /**
     * 從 URL 里面獲取參數(shù)
     * @param username
     * @param password
     * @return
     */
    @RequestMapping("/login4/{name}/{password}")
    public String login4(@PathVariable("name") String username, @PathVariable String password) {
        return "username:" + username + " password:" + password;
    }
}

這個方法返回的數(shù)據(jù)類型是 String
那么我們運行之后 , 看一下抓包結(jié)果
image.png

4.2 返回值類型是 HashMap

如果返回值類型是 HashMap 的話 , 此時 Spring MVC 就會幫我們設(shè)置一個新的類型

package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;

@Controller
@ResponseBody
public class WebController {
    @RequestMapping("/login2")
    public HashMap<String, Object> login2(String name, String password) {
        HashMap<String, Object> result = new HashMap<>();
        result.put("name", name);
        result.put("password", password);
        return result;//返回 JSON 格式的對象
    }
}

image.png
image.png

4.3 返回值是 View

想要實現(xiàn)返回值是 View(頁面) 的話 , 我們只需要刪除掉 @ResponseBody 注解即可

package com.example.demo.controller;

import com.example.demo.model.Student;
import com.example.demo.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;

@Controller
public class WebController {
    @RequestMapping("/hi2") 
    public Object sayHi() {
        return "/index.html";
    }
}

image.png
image.png

4.4 請求轉(zhuǎn)發(fā) / 請求重定向

forward(請求轉(zhuǎn)發(fā)) VS redirect(請求重定向)
請求轉(zhuǎn)發(fā)就是 , 比如我們使用的學校官網(wǎng) , 有一天換網(wǎng)站了 , 之前那個網(wǎng)站不用了 , 但是大部分人記住的還是之前那個網(wǎng)站 , 而且老師和同學們記住一個新的網(wǎng)站也很麻煩 , 那就實現(xiàn)這樣的一件事情 - 輸入老網(wǎng)站的地址就轉(zhuǎn)發(fā)到新的頁面
而請求重定向 , 指的就是后端會告訴瀏覽器 , 你請求的目標網(wǎng)址不是我這里 , 你去其他人那里吧 .
或者再給大家換個例子 :
雙11 剁手節(jié) , 躺了一年 , 也挺辛苦的 , 給自己換個手機吧 . 那必然支持國貨華為啊 , 興高采烈地去買了個華為的折疊屏手機 , 但是好景不長 , 他壞掉了 . 我去咨詢客服 , 客服說我可以去全國的華為售后中心去進行維修 , 這就叫做請求轉(zhuǎn)發(fā) . 而請求重定向就是你聽說蘋果的售后貼心無比 , 你拿著華為手機去找人家維修 , 人家說 : “先生 , 請您去華為售后中心尋求幫助 , 我們這里是蘋果售后服務中心.”
請求轉(zhuǎn)發(fā)就是對內(nèi)的 , 請求重定向就是對外的 .
forward 和 redirect 具體區(qū)別如下

  1. 請求重定向(redirect)將請求重新定位到資源;請求轉(zhuǎn)發(fā)(forward)服務器端轉(zhuǎn)發(fā)。

請求重定向是將資源重新定位 , 整個請求還是瀏覽器重新去請求的 , 請求轉(zhuǎn)發(fā)是服務器幫你去轉(zhuǎn)發(fā)的 . 他要完成的事是更多的

  1. 請求重定向地址發(fā)生變化,請求轉(zhuǎn)發(fā)地址不發(fā)生變化。

請求重定向本質(zhì)上是你訪問一個地方 , 他告訴你這個地方不對你重新去訪問另外一個地方 , 所以地址相對于之前就會發(fā)生變化 . 請求轉(zhuǎn)發(fā)是服務器幫我們?nèi)ネ瓿傻?, 我們并不知道背后的原理 , 所以他的地址是不發(fā)生變化的

  1. 請求重定向與直接訪問新地址效果一致,不存在原來的外部資源能夠訪問;請求轉(zhuǎn)發(fā)的話服務器端轉(zhuǎn)發(fā)
    有可能造成原外部資源不能訪問。

請求重定向能夠保證我們訪問新的地址的效果是一模一樣的 , 能夠保證所有的功能都是正常的 .
而使用請求轉(zhuǎn)發(fā)就保證不了 , 請求轉(zhuǎn)發(fā)可能會造成某些功能實現(xiàn)不了 , 有些文件資源訪問不了 , 原因是因為請求轉(zhuǎn)發(fā)的時候是服務器幫助我們?nèi)マD(zhuǎn)發(fā)的 , 轉(zhuǎn)發(fā)完了之后 , 他的地址就停留到了當前你訪問的地址 , 而這些外部的資源 , 就是以當前地址來作為相對地址去訪問的 , 那地址改變了 , 之前的資源就都不見了 . 那就會請求不到資源 , 這樣的話 JS 加載不上 , 從而導致 ajax 發(fā)不出去 , 就導致我們的功能不能正常使用 .

使用方法 : (其實后端已經(jīng)不實現(xiàn)跳轉(zhuǎn)的功能了 , 這應該是前端的職責)

// 請求重定向
@RequestMapping("/index")
public String index() {
    return "redirect:/index.html";
}
// 請求轉(zhuǎn)發(fā)
@RequestMapping("/index2")
public String index2() {
    return "forward:/index.html";
}

在 controller 包底下新建一個類 , 叫做 TestController

package com.example.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class TestController {
    // 請求轉(zhuǎn)發(fā)
    // 返回頁面的時候,返回值要為 Object
    // 實現(xiàn)效果:當我們訪問 hello 的時候,讓他跳轉(zhuǎn)到登錄頁面
    @RequestMapping("/hello")
    public Object hello() {
        return "forward:/login.html";
    }

    // 請求重定向
    @RequestMapping("/hello2")
    public Object hello2() {
        return "redirect:/reg.html";
    }
}

對應的 login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用戶登錄</title>
</head>
<body>
    <!--  method="提交方法" action="提交地址" -->
    <form method="get" action="login">
        <div>
            <h1> 登錄 </h1>
            用戶名 : <input name="name"><br>
            密碼  : <input name="password"><br>
            <input type="submit" value="提 交">
        </div>
    </form>
</body>
</html>

對應的 reg.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用戶注冊</title>
</head>
<body>
    <!--  method="提交方法" action="提交地址" -->
    <form method="get" action="reg">
        <div>
            <h1> 注冊 </h1>
            用戶名 : <input name="name"><br>
            密碼  : <input name="password"><br>
            性別  : <input name="sex"><br>
            <input type="submit" value="提 交">
        </div>
    </form>
</body>
</html>

運行一下 :
請求轉(zhuǎn)發(fā)的情況 : 頁面發(fā)生變化了 , 但是地址未發(fā)生變化
image.png
請求重定向的情況 : 頁面發(fā)生變化了 , 地址也發(fā)生變化了
image.png
image.png文章來源地址http://www.zghlxwxcb.cn/news/detail-644068.html

到了這里,關(guān)于Java EE 突擊 11 - Spring MVC 程序開發(fā) (2)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務器費用

相關(guān)文章

  • Spring MVC 程序開發(fā)

    Spring MVC 程序開發(fā)

    目錄 什么是 Spring MVC? MVC 定義 MVC 和 Spring MVC 的關(guān)系 為什么要學 Spring MVC? Spring MVC 項目的創(chuàng)建 學習 Spring MVC 的 三個目標 Spring MVC項目的連接(用戶 和 程序 的 映射) 方法1:@RequestMapping(“/xx”) @RequestMapping 是 post 還是 get 請求? 總結(jié) 拓展 ?方法2 和 方法 3:@GetMapping??和

    2024年02月15日
    瀏覽(25)
  • Spring MVC程序開發(fā)

    Spring MVC程序開發(fā)

    目錄 1.什么是Spring MVC? 1.1MVC定義 1.2MVC和Spring MVC的關(guān)系 2.為什么要學習Spring MVC? 3.怎么學Spring MVC? 3.1Spring MVC的創(chuàng)建和連接 3.1.1創(chuàng)建Spring MVC項目 3.1.2@RequestMapping 注解介紹 3.1.3 @RequestMapping 是 post 還是 get 請求? ?編輯?3.1.4 @GetMapping 和 PostMapping 3.2 獲取參數(shù) 3.2.1 傳遞單個參數(shù)

    2024年02月14日
    瀏覽(19)
  • Java EE 突擊 14 - Spring AOP

    Java EE 突擊 14 - Spring AOP

    這個專欄給大家介紹一下 Java 家族的核心產(chǎn)品 - SSM 框架 JavaEE 進階專欄 Java 語言能走到現(xiàn)在 , 仍然屹立不衰的原因 , 有一部分就是因為 SSM 框架的存在 接下來 , 博主會帶大家了解一下 Spring、Spring Boot、Spring MVC、MyBatis 相關(guān)知識點 并且?guī)ьI(lǐng)大家進行環(huán)境的配置 , 讓大家真正用好

    2024年02月11日
    瀏覽(25)
  • Java EE 突擊 9 - Spring Boot 日志文件

    Java EE 突擊 9 - Spring Boot 日志文件

    這個專欄給大家介紹一下 Java 家族的核心產(chǎn)品 - SSM 框架 JavaEE 進階專欄 Java 語言能走到現(xiàn)在 , 仍然屹立不衰的原因 , 有一部分就是因為 SSM 框架的存在 接下來 , 博主會帶大家了解一下 Spring、Spring Boot、Spring MVC、MyBatis 相關(guān)知識點 并且?guī)ьI(lǐng)大家進行環(huán)境的配置 , 讓大家真正用好

    2024年02月13日
    瀏覽(21)
  • 三、使用注解形式開發(fā) Spring MVC程序

    1、 創(chuàng)建 maven 項目,添加框架支持 2、 添加依賴,因為 maven 可以有一些資源過濾的問題,這里直接將資源過濾配置補全 3、 檢查項目結(jié)構(gòu)中是否有 lib 夾以及 jar 是否成功導入了,并配置 tomcat 這里配置完基本上就不用在動了,統(tǒng)一使用注解來解決 @Controller: @Controller 用于標

    2024年02月12日
    瀏覽(19)
  • SSM框架的學習與應用(Spring + Spring MVC + MyBatis)-Java EE企業(yè)級應用開發(fā)學習記錄(第五天)MyBatis的注解開發(fā)

    SSM框架的學習與應用(Spring + Spring MVC + MyBatis)-Java EE企業(yè)級應用開發(fā)學習記錄(第五天)MyBatis的注解開發(fā)

    ? 昨天我們深入學習了 MyBatis多表之間的關(guān)聯(lián)映射,了解掌握了一對一關(guān)聯(lián)映射,一對多關(guān)聯(lián)映射,嵌套查詢方式以及嵌套結(jié)果方式,掌握了緩存機制的一級緩存,二級緩存等概念,也使用了代碼進行復現(xiàn)理解 。但是都是基于XML配置文件的方式來實現(xiàn)的,現(xiàn)在我們要學習一下

    2024年02月11日
    瀏覽(58)
  • (第六天)初識Spring框架-SSM框架的學習與應用(Spring + Spring MVC + MyBatis)-Java EE企業(yè)級應用開發(fā)學習記錄

    (第六天)初識Spring框架-SSM框架的學習與應用(Spring + Spring MVC + MyBatis)-Java EE企業(yè)級應用開發(fā)學習記錄

    ? 昨天我們已經(jīng)把Mybatis框架的基本知識全部學完,內(nèi)容有Mybatis是一個半自動化的持久層ORM框架,深入學習編寫動態(tài)SQL,Mybatis的關(guān)聯(lián)映射,一對一、一對多、多對多、Mybatis的緩存機制,一二級緩存的開啟和設(shè)置,緩存命中率、如何使用idea鏈接數(shù)據(jù)庫自動生成pojo類等。我們學

    2024年02月10日
    瀏覽(29)
  • SSM框架的學習與應用(Spring + Spring MVC + MyBatis)-Java EE企業(yè)級應用開發(fā)學習記錄(第三天)動態(tài)SQL

    SSM框架的學習與應用(Spring + Spring MVC + MyBatis)-Java EE企業(yè)級應用開發(fā)學習記錄(第三天)動態(tài)SQL

    昨天我們深入學習了 Mybatis的核心對象SqlSessionFactoryBuilder , 掌握MyBatis核心配置文件以及元素的使用 ,也掌握MyBatis映射文件及其元素的使用。那么今天我們需要掌握的是更加復雜的查詢操作。 學會編寫MyBatis中動態(tài)SQL 學會MyBatis的條件查詢操作 學會MyBatis的更新操作 學會MyBati

    2024年02月11日
    瀏覽(31)
  • SSM框架的學習與應用(Spring + Spring MVC + MyBatis)-Java EE企業(yè)級應用開發(fā)學習記錄(第一天)Mybatis的學習

    SSM框架的學習與應用(Spring + Spring MVC + MyBatis)-Java EE企業(yè)級應用開發(fā)學習記錄(第一天)Mybatis的學習

    一、當前的主流框架介紹(這就是后期我會發(fā)出來的框架學習) Spring框架 ? Spring是一個開源框架,是為了解決企業(yè)應用程序開發(fā)復雜性而創(chuàng)建的 ,其主要優(yōu)勢之一就是分層架構(gòu)。 Spring提供了更完善的開發(fā)環(huán)境,可以為POJO(Plain Ordinary Java Object,普通Java對象 )對象提供企業(yè)級

    2024年02月12日
    瀏覽(58)
  • SSM框架的學習與應用(Spring + Spring MVC + MyBatis)-Java EE企業(yè)級應用開發(fā)學習記錄(第二天)Mybatis的深入學習

    SSM框架的學習與應用(Spring + Spring MVC + MyBatis)-Java EE企業(yè)級應用開發(fā)學習記錄(第二天)Mybatis的深入學習

    上一篇我們的項目搭建好了,也寫了簡答的Junit測試類進行測試,可以正確映射到數(shù)據(jù)庫中。 那么這篇文章來深入學習一下以下幾個點: 了解 MyBatis的核心對象SqlSessionFactoryBuilder 以及它的作用 掌握MyBatis核心配置文件以及元素的使用 。 掌握MyBatis映射文件及其元素的使用 。

    2024年02月11日
    瀏覽(34)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包