欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring?Web?MVC基礎(chǔ)理論概念

 更新時(shí)間:2024年08月07日 11:31:44   作者:LileSily  
Spring?Web?MVC是基于Servlet?API構(gòu)建的原始Web框架,從?開(kāi)始就包在Spring框架中,Spring?Web?MVC是一個(gè)Web框,本文給大家介紹Spring?Web?MVC基礎(chǔ)理論,感興趣的朋友一起看看吧

1. 什么是Spring Web MVC

Spring Web MVC是基于Servlet API構(gòu)建的原始Web框架,從?開(kāi)始就包在Spring框架中。它的正式名稱“Spring Web MVC”來(lái)自其源模塊的名稱(Spring-webmvc),但它通常被稱為"Spring MVC".
總結(jié)來(lái)說(shuō),Spring Web MVC是一個(gè)Web框架.
想要理解什么是Spring MVC我們首先先要理解什么是MVC

1.1 什么是MVC

MVC是Model View Controller的縮寫(xiě),是軟件工程中共的一種軟件架構(gòu)的設(shè)計(jì)模式.把軟件系統(tǒng)分為模型,控制器,視圖三個(gè)部分.

  • view(視圖): 指的是在應(yīng)用中專門(mén)用來(lái)與瀏覽器交互,展示數(shù)據(jù)的資源.
  • model(模型): 只應(yīng)用程序的主題部分,用來(lái)處理程序中數(shù)據(jù)邏輯的部分.
  • controller(控制器): 可以理解為一個(gè)分發(fā)器,用來(lái)決定對(duì)于視圖發(fā)來(lái)的請(qǐng)求,需要哪一個(gè)模型來(lái)處理,以及處理之后需要跳回哪個(gè)視圖.即用來(lái)連接視圖和模型.

比如我們?nèi)ワ埖瓿燥?
顧客進(jìn)店之后,服務(wù)員來(lái)接待客戶點(diǎn)餐,客戶點(diǎn)完餐之后,把客戶菜單交給前廳,前廳根據(jù)客戶菜單給后廚下達(dá)命令.后廚負(fù)責(zé)做飯,做完之后,再根據(jù)菜單告訴服務(wù)員,這是X號(hào)餐桌客人的飯.
在這個(gè)過(guò)程中:

服務(wù)員就是view(視圖):負(fù)責(zé)接待顧客,給顧客點(diǎn)餐,給顧客端飯.前廳就是controller(控制器):用來(lái)給后廚下達(dá)做菜的命令.后廚就是model(模型):根據(jù)前廳發(fā)來(lái)的要求來(lái)做菜.

1.2 什么是Spring MVC

MVC是一種架構(gòu)模式,也是一種思想.而Spring MVC是對(duì)MVC思想的具體實(shí)現(xiàn).除此之外,Spring MVC還是一個(gè)Web框架.
總結(jié):Spring MVC是一個(gè)實(shí)現(xiàn)了MVC軟件設(shè)計(jì)模式的Web框架.
其實(shí)Spring MVC在前面我們就使用過(guò)了.在我們創(chuàng)建Spring Boot項(xiàng)目的時(shí)候,選擇Spring Web的時(shí)候,其實(shí)就是Spring MVC框架.也就是在創(chuàng)建的Spring Boot項(xiàng)目中添加了Spring Web MVC 的相關(guān)依賴,使得該項(xiàng)目具有了網(wǎng)絡(luò)通信的功能.

那么這時(shí)候問(wèn)題又來(lái)了,Spring Boot和Spring MVC究竟有什么關(guān)系?
Spring Boot只是實(shí)現(xiàn)Spring MVC的一種方式而已.Spring Boot中可以添加很多依賴,我們?cè)?strong>Spring Boot項(xiàng)目中添加了Spring MVC的框架,那么這個(gè)Spring Boot項(xiàng)目就可以實(shí)現(xiàn)Web的功能.

不過(guò)Spring MVC在實(shí)現(xiàn)MVC模式的時(shí)候,也結(jié)合了自身的一些特點(diǎn),下面這個(gè)圖更加適合描述Spring MVC.

通過(guò)瀏覽器來(lái)向后端發(fā)送請(qǐng)求的時(shí)候,沒(méi)有經(jīng)過(guò)view,而是直接把請(qǐng)求傳遞給了controller,之后controller選擇合適的模型,傳遞給model,model處理數(shù)據(jù)之后,把響應(yīng)返回給controller,之后controller再把響應(yīng)返回給view,之后view把響應(yīng)返回給瀏覽器.

就比如我們?nèi)ス久嬖?我們(瀏覽器)想要面試的時(shí)候,我們可以直接找到公司某部門(mén)的負(fù)責(zé)人(controller),說(shuō)我要面試(請(qǐng)求),之后部門(mén)負(fù)責(zé)人會(huì)找到面試你的那個(gè)人(model),面試之后,加入你通過(guò)了面試,面試你的那個(gè)人會(huì)把面試結(jié)果傳遞給部門(mén)負(fù)責(zé)人,之后部門(mén)負(fù)責(zé)人把消息通知給HR(view),之后HR會(huì)給你發(fā)offer.

2. Spring MVC深入學(xué)習(xí)

學(xué)習(xí)Spring MVC,重點(diǎn)也就是學(xué)習(xí)用戶通過(guò)瀏覽器與服務(wù)端交互的過(guò)程.
主要分為一下三個(gè)點(diǎn):

  • 建立連接:將用戶(瀏覽器)和Java程序連接起來(lái),也就是Java程序打開(kāi)了大門(mén),允許外界訪問(wèn).此時(shí)訪問(wèn)的地址能夠調(diào)用我們的Spring程序.
  • 傳遞參數(shù):用戶請(qǐng)求的時(shí)候會(huì)帶一些參數(shù).這些參數(shù)會(huì)傳遞到后端,在后端程序中要想辦法獲取到參數(shù).
  • 返回結(jié)果:執(zhí)行了業(yè)務(wù)邏輯之后,需要把執(zhí)行的結(jié)果返回給用戶,也就是響應(yīng).

比如去銀行存款:

  • 建立連接:去柜臺(tái)
  • 傳遞參數(shù):拿著身份證,銀行卡去存款
  • 返回結(jié)果:銀行返回一張存折.

掌握了上面的三個(gè)功能就相當(dāng)于掌握了Spring MVC.

2.1 建立連接

在Spring MVC中使用@RequestMapping來(lái)實(shí)現(xiàn)URL的路由映射,也就是通過(guò)這個(gè)注解來(lái)使得Spring項(xiàng)目與瀏覽器建立連接.代碼如下:

package com.example.demo;
import org.springframework.web.bind.annotation.*;
@RestController
public class DemoController {
    @RequestMapping("/hello")//可以理解為資源路徑
    public String hello() {
        return "Hello World";
    }
}

接下來(lái)訪問(wèn)http://127.0.0.1:8080/hello就可以看到返回的程序了.

2.1.1 @RequsetMapping注解介紹

@RequestMapping是Spring Web MVC應(yīng)用程序最常被用到的注解之一.它用來(lái)注冊(cè)接口的路由映射.表示的是,服務(wù)器在接收到請(qǐng)求的時(shí)候,路徑為/hello的請(qǐng)求就會(huì)調(diào)用hello這個(gè)方法的代碼.

何為路由映射?
當(dāng)用戶訪問(wèn)?個(gè)URL時(shí),將用戶的請(qǐng)求對(duì)應(yīng)到程序中某個(gè)類的某個(gè)方法的過(guò)程就叫路由映射.

  • 問(wèn)題:既然@RequestMapping已經(jīng)達(dá)到了我們的目的,我們?yōu)槭裁催€要加@RestController呢?

@RestController在資源訪問(wèn)的過(guò)程中起著相當(dāng)重要的作用,在Spring項(xiàng)目接收到一個(gè)請(qǐng)求之后,Spring會(huì)對(duì)所有的類進(jìn)行掃描,如果家里注解@RestController,Spring才會(huì)去看這個(gè)類里面有沒(méi)有加@RequestMapping這個(gè)注解,才可以通過(guò)瀏覽器中輸入的URL對(duì)應(yīng)到這個(gè)類中注冊(cè)的路由映射.
如果我們把@RestController去掉,就訪問(wèn)不到了.

package com.example.demo;
import org.springframework.web.bind.annotation.*;
@RequestMapping("/demo")
public class DemoController {
    @RequestMapping("/hello")//可以理解為資源路徑
    public String hello() {
        return "Hello World";
    }
}

2.1.2 @RequsetMapping的使用

不僅僅方法前面可以加上@RequestMapping注解,類的前面也可以加該注解,即@RequestMapping不僅僅可以修飾方法,還可以修飾類.當(dāng)修飾類和方法的時(shí)候,訪問(wèn)的地址是類路徑+方法路徑

package com.example.demo;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/demo")
public class DemoController {
    @RequestMapping("/hello")//可以理解為資源路徑
    public String hello() {
        return "Hello World";
    }
}

那么在訪問(wèn)hello這個(gè)方法的時(shí)候,路徑就會(huì)變?yōu)?code>/demo/hello.

注: 注解中的/hello"demo"雖然不加/也可以正確響應(yīng),但是為了編程的規(guī)范,還是建議加上.

2.1.3 @RequsetMapping支持哪些方法類型的請(qǐng)求

首先給出結(jié)論,@RequsetMapping支持所有方法類型的請(qǐng)求.下面我們來(lái)通過(guò)Postman構(gòu)造請(qǐng)求來(lái)實(shí)驗(yàn)一下.

GET方法支持

POST方法支持
剩下的方法都是同樣的道理,顯示的結(jié)果都是Hello World,這里不再一一展示.

  • 那么如何使@RequsetMapping只接受指定的幾種方法的請(qǐng)求呢?

我們就需要再注解中加上另外的一個(gè)參數(shù),method鍵值對(duì)

@RequestMapping(value = "/hello1",method = RequestMethod.GET)
public String hello1() {
    return "Hello World 1";
}

我們看到/hello1對(duì)應(yīng)的路由映射只支持GET方法.
現(xiàn)在我們?nèi)タ纯磎ethod鍵值對(duì)截取的部分源碼

public @interface RequestMapping {
    String name() default "";
    @AliasFor("path")
    String[] value() default {};
    @AliasFor("value")
    String[] path() default {};
    RequestMethod[] method() default {};//method返回的是一個(gè)RequestMethod類型的數(shù)組
    String[] params() default {};
    String[] headers() default {};
    String[] consumes() default {};
    String[] produces() default {};
}

在源碼中,我們可以看到,method返回的是一個(gè)RequestMethod類型的數(shù)組.那么這個(gè)RequestMethod中都有什么,我們?cè)偃ゲ榭唇厝〉牟糠衷创a.

public enum RequestMethod {
    GET,
    HEAD,
    POST,
    PUT,
    PATCH,
    DELETE,
    OPTIONS,
    TRACE;
}

這里我們可以看到RequestMethod是一個(gè)枚舉類型,這里面存放的都是請(qǐng)求中的方法.
由于method那里接收的是一個(gè)關(guān)于RequestMethod枚舉類型的數(shù)組,所以我們?cè)谧⒔夂蟮逆I值對(duì)的值上傳入的也是枚舉類型的數(shù)組,比如我們想支持GET和POST兩種方法:

@RequestMapping(value = "/hello1",method = {RequestMethod.GET, RequestMethod.POST})
public String hello1() {
    return "Hello World 1";
}

當(dāng)然當(dāng)元素只有一個(gè)的時(shí)候,大括號(hào)是可以省略的.就比如上面那個(gè)只有GET方法的例子.

如果指定的方法只有一種,我們也可以采用其他注解來(lái)解決
比如只支持GET方法,我們就可以使用@GetMapping注解來(lái)解決.

@GetMapping("/hello3")
public String hello3() {
    return "Hello World 3";
}

在比如只支持POST方法,可以使用@PostMapping來(lái)解決

@PostMapping("/hello4")
public String hello4() {
    return "Hello World 4";
}

2.2 請(qǐng)求

訪問(wèn)不同的路徑,就是發(fā)送不同的請(qǐng)求.在發(fā)送請(qǐng)求時(shí),可能會(huì)帶?些參數(shù),所以學(xué)習(xí)Spring的請(qǐng)求,主要是學(xué)習(xí)如何傳遞參數(shù)到后端以及后端如何接收.
傳遞參數(shù),主要是以瀏覽器和Postman來(lái)模擬.

2.2.1 傳遞單個(gè)參數(shù)

在前面,我們的方法都是沒(méi)有參數(shù)存在的,如果給我們的方法加上參數(shù)之后會(huì)怎么樣呢?

@RequestMapping("/name1")
public String name1(String name) {
    System.out.println("接收到了" + name);
    return "接收到了" + name;
}

我們?cè)谡?qǐng)求的URL中加上查詢字符串,即參數(shù):http://127.0.0.1:8080/demo/name1?name=zhangsan(?后面的是參數(shù))
在URL中加上的參數(shù)傳入到后端之后,Spring MVC會(huì)根據(jù)方法的參數(shù)名,找到對(duì)應(yīng)的參數(shù),賦值給方法.之后拿到傳入的參數(shù)在方法中進(jìn)行一系列操作之后返回給前端.比如我們將這個(gè)請(qǐng)求通過(guò)Postman發(fā)送給Spring項(xiàng)目.

我們發(fā)現(xiàn)成功返回了響應(yīng),并且返回了正確的響應(yīng).
如果參數(shù)不一致,則獲取不到參數(shù).

注意事項(xiàng):參數(shù)類型是包裝類型和基本類型的區(qū)別

當(dāng)參數(shù)類型是包裝類型和基本類型的時(shí)候,傳入的參數(shù)Spring進(jìn)行隱式轉(zhuǎn)換之后發(fā)現(xiàn)參數(shù)類型不一致均會(huì)報(bào)400錯(cuò)誤.

@RequestMapping("/age1")
public String age1(int age) {
    System.out.println("接收到了" + age);
    return "接收到了" + age;
}
@RequestMapping("/age2")
public String age2(Integer age) {
    return "接收到了" + age;
}

但是如果我們不傳遞任何參數(shù)的時(shí)候,這時(shí)候基本類型和包裝類型就會(huì)有所區(qū)別,基本類型會(huì)直接拋出500錯(cuò)誤,而包裝類型會(huì)輸出默認(rèn)的空值null.

所以,我們?cè)谄髽I(yè)開(kāi)發(fā)中,對(duì)于參數(shù)可能為空的數(shù)據(jù),我們建議使用包裝類型.

2.2.2 傳遞多個(gè)參數(shù)

和接收單個(gè)參數(shù)?樣,直接使用方法的參數(shù)接收即可.使用多個(gè)形參.

@RequestMapping("/person1")
public String person1(String name,Integer age) {
    return "接收到了name" + name + "接收到了age" + age;
}

注:

  • 也可以通過(guò)構(gòu)造form表單來(lái)發(fā)送請(qǐng)求,這時(shí)候在URL中就沒(méi)有了參數(shù)的存在,參數(shù)跑到了請(qǐng)求中的正文內(nèi)容.
  • 如果在項(xiàng)目運(yùn)行的過(guò)程中,我們要對(duì)方法的參數(shù)進(jìn)行修改,我們不建議在原來(lái)的方法上直接進(jìn)行修改,而是另起一個(gè)方法重新寫(xiě).

2.2.3 傳遞對(duì)象

如果需要傳遞的參數(shù)比較多的時(shí)候,我們不妨把這些參數(shù)封裝成一個(gè)對(duì)象.

@RequestMapping("/person3")
public String person3(Person person) {
    return person.getName()+person.getAge()+person.getSex();
}
package com.example.demo;
public class Person {
    public String name;
    public int age;
    public String sex;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
}

之后我們使用Postman進(jìn)行請(qǐng)求發(fā)送.http://127.0.0.1:8080/demo/person3?name=zhangsan&age=20&sex=男

注意:

如果某個(gè)基本類型的參數(shù)未傳遞,如果這個(gè)基本類型參數(shù)是一個(gè)類中的成員變量,如果這個(gè)參數(shù)未傳遞,那么這個(gè)參數(shù)會(huì)有默認(rèn)的初始值,這一點(diǎn)是和上面直接把基本參數(shù)類型的參數(shù)寫(xiě)在方法的參數(shù)列表中是不一樣的.比如我沒(méi)有傳入age參數(shù).

我們可以看到age的初始值被默認(rèn)賦值為了0.如果我們針對(duì)參數(shù)是對(duì)象的使用form表單進(jìn)行參數(shù)傳遞,在GET和POST兩種方法中,只有POST方法會(huì)返回正確的結(jié)果,而GET方法會(huì)返回默認(rèn)的空值.

2.2.4 后端參數(shù)重命名

在一些特殊的情況下,前端傳遞的參數(shù)key和我們后端接收的key可能不?致,比如我們傳遞了一個(gè)Name給后端,但是后端需要接收的參數(shù)是name,這時(shí)候就需要用到@RequestParam(翻譯:請(qǐng)求參數(shù))來(lái)對(duì)后端的參數(shù)進(jìn)行重命名.

@RequestMapping("/person2")
public String person2(@RequestParam("Name") String name,Integer age) {
    return "接收到name" + name + "接收到age" + age;
}

上面這段代碼,其中Name就是前端要傳遞的參數(shù),而name是后端使用的參數(shù),此時(shí)Spring可以正確的把請(qǐng)求傳遞的參數(shù)Name綁定到后端參數(shù)name參數(shù)上.
我們使用http://127.0.0.1:8080/demo/person2?Name=zhangsan&age=20來(lái)進(jìn)行請(qǐng)求傳遞

如果我們把Name改成name,就無(wú)法進(jìn)行正確的參數(shù)傳遞了.

[注意事項(xiàng)]
在使用@RequestParam對(duì)參數(shù)進(jìn)行重命名的時(shí)候,參數(shù)就變成了必傳參數(shù).

那么造成上面這種情況的原因是什么呢,又該如何讓他變成一個(gè)非必傳參數(shù)呢?現(xiàn)在我們來(lái)查看@RequestParam的源碼:

public @interface RequestParam {
    @AliasFor("name")
    String value() default "";
    @AliasFor("value")
    String name() default "";
    boolean required() default true;
    String defaultValue() default "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";
}

我們可以看到,required那一欄默認(rèn)的值是true,表示的含義就是,該注解修飾的參數(shù)是必傳參數(shù).既然如此,我們可以通過(guò)設(shè)置@RequestParam的required參數(shù)=false來(lái)實(shí)現(xiàn)讓這個(gè)參數(shù)成為非必傳參數(shù).

@RequestMapping("/person2")
public String person2(@RequestParam(value = "Name",required = false) String name,Integer age) {
    return "接收到name" + name + "接收到age" + age;
}

此時(shí)Name為傳遞的時(shí)候,會(huì)有默認(rèn)的初始值null來(lái)返回.

2.2.5 傳遞數(shù)組

Spring MVC可以自動(dòng)綁定數(shù)組參數(shù)的賦值.

@RequestMapping("/param1")
public String param1(String[] arrayParam) {
    return Arrays.toString(arrayParam);
}

使用Postman進(jìn)行傳參:

請(qǐng)求參數(shù)名與形參數(shù)組名稱相同且請(qǐng)求參數(shù)為多個(gè),后端的方法形式參數(shù)中即可自動(dòng)接收傳輸過(guò)來(lái)的參數(shù).

把所要傳遞的參數(shù)合并在一起傳遞,中間用逗號(hào)隔開(kāi).

可以看到以上兩種方法均返回了正確的響應(yīng).我們?nèi)绻褂胒rom表單進(jìn)行發(fā)送的話,這時(shí)候請(qǐng)求GET和POST就只有POST返回的是正確的結(jié)果,而GET返回的是null.

2.2.6 傳遞集合

集合參數(shù): 和數(shù)組傳遞參數(shù)的方法類似,可以是相同的參數(shù)名多個(gè)參數(shù),也可以把參數(shù)寫(xiě)到一起,但是在后端那里,需要加上@RequestParam來(lái)綁定參數(shù)關(guān)系.
默認(rèn)的情況下,請(qǐng)求中的參數(shù)名相同的多個(gè)值,封裝的時(shí)候是一個(gè)數(shù)組,而如果要封裝集合的話,就需要在參數(shù)前面加上@RequestParam來(lái)綁定參數(shù)關(guān)系,表示傳過(guò)來(lái)的是一個(gè)數(shù)組,需要轉(zhuǎn)換成集合.

@RequestMapping("/param2")
public String param2(@RequestParam("ArrayParam") List<String> arrayParam) {
    return Arrays.toString(arrayParam.toArray());
}

如果不加注解后面的參數(shù)的話,在前端傳遞參數(shù)的時(shí)候默認(rèn)就和后端的方法參數(shù)是一樣的.

2.2.7 傳遞json數(shù)據(jù) 什么是json

  • 什么是json

JSON就是?種數(shù)據(jù)格式,有自己的格式和語(yǔ)法,使用文本表示一個(gè)對(duì)象或數(shù)組的信息,因此JSON本質(zhì)是字符串.主要負(fù)責(zé)在不同的語(yǔ)言中數(shù)據(jù)傳遞和交換.

  • json的語(yǔ)法

json是一個(gè)字符串,其格式非常類似于python中的字典和JavaScript對(duì)象字面量的格式.

  • 數(shù)據(jù)存儲(chǔ)在鍵值對(duì)(key/value)中,key和value之間用:分割.
  • 鍵值對(duì)之間由,分割.
  • 對(duì)象用{ }表示
  • 數(shù)組用[ ]表示
  • 值可以為對(duì)象,數(shù)組,字符串等等.
  • json的兩種結(jié)構(gòu)
  • 對(duì)象: 大括號(hào){}保存的對(duì)象是?個(gè)無(wú)序的鍵值對(duì)集合.?個(gè)對(duì)象以左括號(hào){ 開(kāi)始,右括號(hào)}結(jié)束。每個(gè)"鍵"后跟?個(gè)冒號(hào): ,鍵值對(duì)使用逗號(hào),分隔
  • 數(shù)組: 中括號(hào)[]保存的數(shù)組是值(value)的有序集合.?個(gè)數(shù)組以左中括號(hào)[開(kāi)始,右中括號(hào)]結(jié)束,值之間使用逗號(hào), 分隔,數(shù)組中可以存放多個(gè)對(duì)象,對(duì)象和對(duì)象之間用,分割.

下面我們展示一段json字符串:

{
	 "squadName": "Super hero squad",
	 "homeTown": "Metro City",
	 "formed": 2016,
	 "secretBase": "Super tower",
	 "active": true,
	 //數(shù)據(jù)保存在鍵值對(duì)中
	 //鍵和值之間使用:分割,鍵值對(duì)之間使用,分割
	 "members": [{
	 "name": "Molecule Man",
	 "age": 29,
	 "secretIdentity": "Dan Jukes",
	 "powers": ["Radiation resistance", "Turning tiny", "Radiation 
	blast"]//數(shù)組中可以包含多個(gè)元素
	 }, {//這個(gè)元素也可以是對(duì)象
	 "name": "Madame Uppercut",
	 "age": 39,
	 "secretIdentity": "Jane Wilson",
	 "powers": ["Million tonne punch", "Damage resistance", "Superhuman 
	reflexes"]
	 }, {
	 "name": "Eternal Flame",
	 "age": 1000000,
	 "secretIdentity": "Unknown",
	 "powers": ["Immortality", "Heat Immunity", "Inferno", 
	"Teleportation", "Interdimensional travel"]
	 }]
}

也可以壓縮表示為:

{"squadName":"Super hero squad","homeTown":"Metro 
City","formed":2016,"secretBase":"Super tower","active":true,"members":
[{"name":"Molecule Man","age":29,"secretIdentity":"Dan Jukes","powers":
["Radiation resistance","Turning tiny","Radiation blast"]},{"name":"Madame 
Uppercut","age":39,"secretIdentity":"Jane Wilson","powers":["Million tonne 
punch","Damage resistance","Superhuman reflexes"]},{"name":"Eternal 
Flame","age":1000000,"secretIdentity":"Unknown","powers":["Immortality","Heat 
Immunity","Inferno","Teleportation","Interdimensional travel"]}]}

可以使用json在線工具來(lái)校驗(yàn)json的書(shū)寫(xiě),如https://www.json.cn/.

  • json字符串和Java對(duì)象的互轉(zhuǎn)

Spring MVC框架集成了json的轉(zhuǎn)換工具,我們可以直接拿來(lái)使用.我們可以使用ObjectMapper中的一系列方法來(lái)對(duì)json和Java對(duì)象兩者之間進(jìn)行轉(zhuǎn)換.

package com.example.demo;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class json {
    private static ObjectMapper objectMapper = new ObjectMapper();
    public static void main(String[] args) throws JsonProcessingException {
        Person person = new Person();
        person.setName("zhangsan");
        person.setAge(18);
        person.setSex("男");
        String json = objectMapper.writeValueAsString(person);
        System.out.println(json);
        Person person2 = objectMapper.readValue(json, Person.class);//傳入一個(gè)json字符串和一個(gè)類的類對(duì)象
        System.out.println(person2.toString());
    }
}
package com.example.demo;
public class Person {
    public String name;
    public int age;
    public String sex;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                '}';
    }
}

  • 如何傳遞json對(duì)象

接收json對(duì)象,需要使用@RequestBody注解,這個(gè)注解翻譯過(guò)來(lái)就是請(qǐng)求正文的意思,意思是這個(gè)注解起到的作用是從請(qǐng)求中的正文部分獲取數(shù)據(jù).請(qǐng)求的參數(shù)必須寫(xiě)在正文中.而我們的json字符串就寫(xiě)在請(qǐng)求的正文中.
后端是這樣實(shí)現(xiàn)的:

@RequestMapping("/param3")
public String param3(@RequestBody Person person) {
    return person.toString();
}

接下來(lái)我們使用Postman構(gòu)造請(qǐng)求,把json字符串寫(xiě)入請(qǐng)求的正文中:

{
    "name":"zhangsan",
    "age":18,
    "sex":"male"
}

響應(yīng)結(jié)果如下:

如果去掉注解@RequestBody,那么后端就無(wú)法正確接收json數(shù)據(jù),前端返回的響應(yīng)也不正確.

由于后端沒(méi)有接收到關(guān)于person對(duì)象傳遞的任何信息,所以都默認(rèn)都賦值為了初始值.

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

PathVariable翻譯過(guò)來(lái)之后,是"路徑可變"的意思,意思是我們要通過(guò)URL獲取路徑作為傳遞過(guò)來(lái)的參數(shù),而這個(gè)路徑是不固定的.
這個(gè)注解主要的作用就是在請(qǐng)求URL路徑上的數(shù)據(jù)綁定.之前我們通過(guò)http請(qǐng)求傳遞參數(shù)都是在?后面的查詢字符串中.而現(xiàn)在我們要通過(guò)URL中的資源路徑來(lái)傳遞參數(shù).
后端代碼實(shí)現(xiàn)如下:
@RequestMapping的參數(shù)中在加上一些路徑的標(biāo)識(shí),每個(gè)參數(shù)外面使用{ }括起來(lái).

@RequestMapping("/param4/{name}/{age}")
public String param4(@PathVariable String name,@PathVariable Integer age){
    return name+age;
}

我們通過(guò)Postman來(lái)構(gòu)造請(qǐng)求http://127.0.0.1:8080/demo/param4/zhangsan/18

我們看到前端返回了正確的響應(yīng).
[注意事項(xiàng)]
如果方法參數(shù)名稱和需要綁定的URL中的變量名稱不?致時(shí),需要@PathVariable的屬性value賦值.

@RequestMapping("/param4/{Name}/{Age}")
public String param4(@PathVariable("Name") String name,@PathVariable("Age") Integer age){
    return name+age;
}

前端還是會(huì)返回正確的響應(yīng).

2.2.9 上傳文件@RequestPart

后端代碼實(shí)現(xiàn):

@RequestMapping("/param5")
public String param5(@RequestPart("file") MultipartFile file) throws IOException {
    file.transferTo(new File("D:/personal/" + file.getOriginalFilename()));
    //上傳文件,前面寫(xiě)的是存儲(chǔ)文件的路徑,后面加上原文件的名字
    return "已經(jīng)獲取到" + file.getOriginalFilename();
}

使用Postman向指定位置發(fā)送文件.

指定位置接收到了文件.

2.2.10 獲取Cookie/Session

  • 回顧C(jī)ookie和Session

Cookie中的內(nèi)容和URL中的query string內(nèi)容類似,都是鍵值對(duì)內(nèi)容,它們都是程序員自定義的.每個(gè)鍵值對(duì)之間用";“隔開(kāi),鍵和值之間用”="隔開(kāi).

  • Cookie是瀏覽器本地存儲(chǔ)的一種機(jī)制,Cookie本質(zhì)上可以在客戶端的硬盤(pán)上持久化保存的.是瀏覽器給網(wǎng)頁(yè)的一種能夠持久化存儲(chǔ)數(shù)據(jù)的機(jī)制.
  • 有的網(wǎng)站,需要在客戶端這邊存儲(chǔ)一些必要的信息,希望可以持久化存儲(chǔ),于是瀏覽器就給網(wǎng)頁(yè)提供了Cookie,是瀏覽器對(duì)于硬盤(pán)的操作做了一些特殊的封裝,相當(dāng)于提供了一個(gè)或者一組特殊的文件,并且內(nèi)容只能是鍵值對(duì).
  • 那么Cookie是具體如何保存的呢?
  • 瀏覽器會(huì)針對(duì)不同的域名,每個(gè)網(wǎng)站都有自己的Cookie文件保存在硬盤(pán)中.
  • Cookie從哪里來(lái)?
  • Cookie中的數(shù)據(jù),來(lái)自于服務(wù)器(服務(wù)器返回給瀏覽器的數(shù)據(jù)),訪問(wèn)網(wǎng)站的時(shí)候,網(wǎng)站的服務(wù)器會(huì)返回http響應(yīng),在http響應(yīng)中,會(huì)包含Set-Cookie這樣的header,它就會(huì)把一些鍵值對(duì)保存到瀏覽器的Cookie中.Cookie保存到瀏覽器之后,后續(xù)瀏覽器訪問(wèn)該網(wǎng)站的時(shí)候,就會(huì)在請(qǐng)求的header中,把之前保存的鍵值對(duì)都帶入進(jìn)去,在返回給服務(wù)器.
  • 那么問(wèn)題又來(lái)了,為什么還要返回給服務(wù)器?
  • 這是因?yàn)镃ookie可以使客戶端存儲(chǔ)一些必要的"配置信息",從而讓服務(wù)器對(duì)于用戶提供的服務(wù)更加"個(gè)性化".

舉例說(shuō)明:剪頭發(fā)
A去了一家理發(fā)店之后,理發(fā)師就問(wèn)他:“你想怎么剪?” 但是這時(shí)候A就會(huì)反問(wèn)理發(fā)師:“你能怎么剪”?于是理發(fā)師就說(shuō):“可以剪平頭,毛寸…”,于是A就說(shuō):"給我剪個(gè)平頭."在A下次去了之后,就可以直接告訴理發(fā)師,剪個(gè)平頭.同理,B也經(jīng)歷了上述過(guò)程,他最終選擇了毛寸.

和上面剪頭發(fā)是相同的道理,客戶端也不止有一個(gè),每個(gè)客戶端都會(huì)有自己的偏好,此時(shí)就需要讓每個(gè)客戶端保存這樣的數(shù)據(jù),之后就可以通過(guò)Cookie隨時(shí)把這樣的信息返回給服務(wù)器.例如:瀏覽器的夜間模式和白日模式,一次設(shè)置好了之后,下次再打開(kāi)服務(wù)器的時(shí)候,瀏覽器的顏色模式不會(huì)改變.

  • Cookie自動(dòng)登錄

Cookie中雖然有很多的鍵值對(duì)都是程序員自定義的,但是往往會(huì)有一個(gè)特殊的鍵值對(duì),用來(lái)標(biāo)識(shí)用戶的身份信息.

  • 首先在獲取登錄頁(yè)面與返回登錄登錄頁(yè)面的html的過(guò)程中不包含任何的Cookie.
  • 在用戶輸入用戶名和密碼之后,這時(shí)候用戶名和密碼就會(huì)交給服務(wù)器,驗(yàn)證它們的正確性,在確認(rèn)正確之后,就會(huì)創(chuàng)建會(huì)話(session),(會(huì)話可以理解為一個(gè)類,其中類中具體包含什么,要看業(yè)務(wù)邏輯,但是其中一定有sessionId,也就是令牌)并把sessionId返回給瀏覽器,這個(gè)sessionId存在于響應(yīng)報(bào)文header中的Set-Cookie中,我們也可以把他叫做"令牌",令牌中存儲(chǔ)的是一個(gè)字符串,類似于"身份標(biāo)識(shí)",不會(huì)存儲(chǔ)太多的信息,在瀏覽器收到sessionId之后,就會(huì)把Id存儲(chǔ)在硬盤(pán)中,即創(chuàng)建了Cookie.
  • 在之后客戶端要訪問(wèn)該域名下的其他頁(yè)面的時(shí)候,就可以把sessionId交給服務(wù)器,服務(wù)器獲取到sessionId之后,就可以根據(jù)這個(gè)值,知道用戶的詳細(xì)信息.也就是直接通過(guò)之前創(chuàng)建的sessionId的Cookie就可以訪問(wèn)到,無(wú)需再次登錄.

舉例說(shuō)明:去醫(yī)院看病

  • 到了醫(yī)院先掛號(hào).掛號(hào)時(shí)候需要提供?份證,同時(shí)得到了?張"就診卡",這個(gè)就診卡存儲(chǔ)著關(guān)于患者身份信息的sessionId,就相當(dāng)于患者的"令牌".
  • 后續(xù)去各個(gè)科室進(jìn)行檢查,診斷,開(kāi)藥等操作,都不必再出示?份證了,只要憑就診卡即可識(shí)別出當(dāng)前患者的?份.在就診室的刷卡機(jī)上刷一下就診卡,醫(yī)生就會(huì)知道你的所有信息.
  • 看完病了之后,不想要就診卡了,就可以注銷這個(gè)卡.此時(shí)患者的?份和就診卡的關(guān)聯(lián)就銷毀了.(類似于?站的注銷操作)
  • ?來(lái)看病,可以辦?張新的就診卡,此時(shí)就得到了?個(gè)新的"令牌"
  • 使用Spring獲取Cookie
    • 傳統(tǒng)獲取Cookie
@RequestMapping("/param6")
public String param6(HttpServletRequest request, HttpServletResponse response) throws IOException  {
    Cookie[] cookies = request.getCookies();
    for (Cookie cookie : cookies) {
        System.out.print(cookie.getName()+":"+cookie.getValue());
    }
    return "已經(jīng)獲取到Cookie";
}

之后我們通過(guò)瀏覽器偽造Cookie,來(lái)向后端傳遞請(qǐng)求.http://127.0.0.1:8080/demo/param6

我們看到了后端已經(jīng)成功拿到了Cookie中的數(shù)據(jù).

Spring MVC是Spring基于Servlet實(shí)現(xiàn)的.其中上面一段代碼中的HttpServletRequestHttpServletResponse是Servlet提供的兩個(gè)類.這兩個(gè)類在每一個(gè)接口中均默認(rèn)存在,需要的時(shí)候?qū)懗鰜?lái)就可以.
HttpServletRequest 對(duì)象代表客戶端的請(qǐng)求.請(qǐng)求中的所有信息均可以通過(guò)這個(gè)類拿到.
HttpServletResponse對(duì)象代表服務(wù)器的響應(yīng).響應(yīng)中的所有信息均可以通過(guò)這個(gè)類拿到.

  • 獲取Cookie中的某一個(gè)鍵值對(duì)

方法一: 使用equals()方法

@RequestMapping("/param7")
public String param7(HttpServletRequest request) {
    Cookie[] cookies = request.getCookies();
    for (Cookie cookie : cookies) {
        if ("bite".equals(cookie.getName())) {
            return cookie.getValue();
        }
    }
    return "為獲取到指定的Cookie";
}

通過(guò)瀏覽器構(gòu)造Cookie,我們看到了前端返回了正確的響應(yīng).

后端打印了相應(yīng)的日志:

方法二:通過(guò)@CookieValue注解獲取.

    @RequestMapping("/param8")
    public String param8(@CookieValue("bite") String bite) {
        System.out.println("獲取到了" + bite);
        return bite;
    }

前端與后端響應(yīng)均正確:

Session的存儲(chǔ)和獲取
Session是服務(wù)器端的機(jī)制,它需要先存儲(chǔ),才能獲取到.

Session的存儲(chǔ)

@RequestMapping("/param9")
public String param9(HttpServletRequest request){
    //獲取Session對(duì)象,如果不存在Session對(duì)象,getSession之后不加或參數(shù)為true會(huì)自動(dòng)創(chuàng)建
    HttpSession session = request.getSession();
    if (session != null) {//確保Session成功創(chuàng)建
        session.setAttribute("bite", "888");
    }
    return "Session存儲(chǔ)成功";
}

方法解釋:
getSession(boolean create): 如果參數(shù)為true的時(shí)候,就會(huì)在Session不存在的時(shí)候,自動(dòng)創(chuàng)建Session,如果參數(shù)為false,就不會(huì)創(chuàng)建.
getSession():和上一種方法參數(shù)為true的時(shí)候效果相同.
setAttribute(String s,String o):設(shè)置Session中的參數(shù).

Session的讀取
讀取Session依然使用HttpServletRequest

@RequestMapping("/param10")
public String param10(HttpServletRequest request){
    HttpSession session = request.getSession(false);
    if (session != null){
        String s = (String) session.getAttribute("bite");
        System.out.println("獲取到了Session");
        return s;
    }
    return "未獲取到Session";
}

運(yùn)行
[注意事項(xiàng)] 在重啟服務(wù)器之后,上一次存在內(nèi)存中的Session數(shù)據(jù)會(huì)被清空,需要重新設(shè)置Session之后才可以獲取到.

我們可以看到,存儲(chǔ)了Session之后,瀏覽器把SessionID存儲(chǔ)在了Cookie中.

之后我們可以使用瀏覽器存儲(chǔ)的令牌獲取Session.

簡(jiǎn)潔獲取Session
上面獲取Session的方法比較傳統(tǒng),我們下面展示兩種簡(jiǎn)潔的方法.
方法一:使用@SessionAttribute注解

@RequestMapping("/param11")
public String param11(@SessionAttribute(value = "bite",required = false)
                      String bite){
    return bite;
}

運(yùn)行結(jié)果如下:

@SessionAttribute的后面兩個(gè)注解表示的意思和前面@RequestParam注解后面的兩個(gè)參數(shù)的作用非常像.第一個(gè)作用是參數(shù)綁定的作用,第二個(gè)參數(shù)如果為true或者不寫(xiě),表示這個(gè)參數(shù)是必傳參數(shù),如果為false,就是非必傳參數(shù),如果Session傳遞未成功,就返回null.
方法二:直接使用HttpSession作為參數(shù)

@RequestMapping("/param12")
public String param12(HttpSession session){
    String string = (String) session.getAttribute("bite");
    System.out.println("成功獲取到了Session");
    return string;
}

HttpSession作為參數(shù)的時(shí)候,效果和getSession()方法一樣,在沒(méi)有Session的時(shí)候,會(huì)自動(dòng)創(chuàng)建Session.
運(yùn)行結(jié)果如下:

2.2.11 獲取Header 傳統(tǒng)獲取方法

傳統(tǒng)的方法

依然是從HttpServletRequst中獲取.

@RequestMapping("/param13")
public String param13(HttpServletRequest request){
    return request.getHeader("User-Agent");
}

我們使用getHeader方法來(lái)獲取Header.在后面的參數(shù)是Header中的"key".
運(yùn)行測(cè)試:

下面是我們通過(guò)抓包軟件抓取的網(wǎng)絡(luò)通行信息.我們發(fā)現(xiàn)Header中的User-Agent一欄與瀏覽器上的一致.

簡(jiǎn)潔獲取方法
通過(guò)@RequestHeader注解來(lái)獲取,在注解后面加上需要獲取Header中的"key".

@RequestMapping("/param14")
public String param14(@RequestHeader("sec-ch-ua-platform") String string){
    return string;
}

運(yùn)行結(jié)果:

與抓包工具中的結(jié)果一致:

2.3 響應(yīng)

在我們前面代碼的例子中,每次瀏覽器都會(huì)返回響應(yīng)的響應(yīng),而前面的響應(yīng)都是數(shù)據(jù)響應(yīng),響應(yīng)還可以是頁(yè)面,狀態(tài)碼,Header等.

2.3.1 返回靜態(tài)頁(yè)面

首先我們需要穿件一個(gè)前端頁(yè)面index.html.創(chuàng)建的文件放在static目錄下.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>我是index文件</h1>
</body>
</html>

[注意] 在寫(xiě)完前端文件之后,不要通過(guò)idea右上角的瀏覽器小圖標(biāo)的方式打開(kāi),我們需要通過(guò)后端返回頁(yè)面的方式打開(kāi).

下面我們展示一種后端代碼的寫(xiě)法:

@RequestMapping("/demo2")
@RestController
public class DemoController2 {
    @RequestMapping("/param1")
    public Object param1(){
        return "/index.html";
    }
}

我們看到,瀏覽器并沒(méi)有返回對(duì)應(yīng)的html頁(yè)面,而是直接返回了一串字符串?dāng)?shù)據(jù).那么怎么解決呢.我們需要把@RestController注解變成@Controller注解.

@RequestMapping("/demo2")
@Controller
public class DemoController2 {
    @RequestMapping("/param1")
    public Object param1(){
        return "/index.html";
    }
}

我們看到這次瀏覽器返回了對(duì)應(yīng)的html頁(yè)面.

那么@RestController@Controller有什么區(qū)別呢?
@RestController一般用來(lái)返回?cái)?shù)據(jù),這些數(shù)據(jù)的響應(yīng)報(bào)頭中的Content-Type都是text/html格式的,@Controller一般用來(lái)返回視圖.這個(gè)視圖一般是用前端的代碼寫(xiě)好的文件.就是前面我們?cè)贛VC設(shè)計(jì)模式中提到過(guò)的視圖(view).
@RestController == @Controller + @ResponseBody.其中@Controller表示的是我們前面我們MVC模式中的控制器.而@ResponseBody表示的是響應(yīng)正文,定義返回的數(shù)據(jù)為非視圖模式.
@RestController的源碼如下,我們也可以看到這個(gè)注解上面也標(biāo)有@Controller + @ResponseBody兩個(gè)注解:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
    @AliasFor(
        annotation = Controller.class
    )
    String value() default "";
}

2.3.2 返回?cái)?shù)據(jù)@ResponseBody

上面我們提到了@ResponseBody注解表示的是返回?cái)?shù)據(jù),也就是以text/html的格式返回
@ResponseBody即是類注解又是方法注解.給類加上該注解之后,就表示類中所有的方法返回的都是數(shù)據(jù),給方法加上之后,表示的是只有這個(gè)方法返回的是數(shù)據(jù).

同樣,如果類上有@RestController注解的時(shí)候,就證明給所有的方法都加了@ResponseBody注解,所有的方法都以數(shù)據(jù)的方式返回.

如果一個(gè)類中即有頁(yè)面要返回,也有數(shù)據(jù)要返回,就在需要返回?cái)?shù)據(jù)的方法上面加上@ResponseBody.類的控制器使用@Controller.

@RequestMapping("/demo2")
@Controller
public class DemoController2 {
    @RequestMapping("/param1")
    public Object param1(){
        return "/index.html";
    }
    @RequestMapping("param2")
    @ResponseBody
    public Object param2(){
        return "String";
    }
}

瀏覽器返回的視圖與數(shù)據(jù)如下:

2.3.3 返回html代碼片段

    @RequestMapping("/param3")
    @ResponseBody
    public String param3(){
        return "<h1>我是html~</h1>";
    }

2.3.4 返回json

后端返回json的方法是使用對(duì)象返回.可以使用HashMap返回,也可以另外創(chuàng)建一個(gè)對(duì)象,按屬性返回.
方法一:創(chuàng)建HashMap

@RequestMapping("/param4")
@ResponseBody
public HashMap<String,Integer> param4(){
    HashMap<String, Integer> map = new HashMap<>();
    map.put("aa",1);
    map.put("bb",2);
    map.put("cc",3);
    return map;
}

瀏覽器返回響應(yīng),是json格式的數(shù)據(jù):

方法二:通過(guò)類中的屬性

@RequestMapping("/param5")
@ResponseBody
public Person param5(){
    Person person = new Person();
    person.setName("zhangsan");
    person.setAge(19);
    person.setSex("male");
    return person;
}

瀏覽器返回響應(yīng),依然是json格式的數(shù)據(jù),返回的是對(duì)象中屬性的值:

2.3.5 設(shè)置狀態(tài)碼

SpringMVC也為程序員提供了自定義狀態(tài)碼的功能,可以讓程序員手動(dòng)指定狀態(tài)碼.
使用HttpServletResponse+setStatus方法訪問(wèn)到響應(yīng)中的狀態(tài)碼.

@RequestMapping("/param6")
@ResponseBody
public String param6(HttpServletResponse response){
    response.setStatus(400);
    return "設(shè)置狀態(tài)碼為400";
}

瀏覽器返回響應(yīng),需要注意的是,我們自定義的錯(cuò)誤狀態(tài)碼返回的不一定是瀏覽器報(bào)錯(cuò)的一大坨信息,狀態(tài)碼并不影響頁(yè)面的顯示.

我們通過(guò)抓包工具發(fā)現(xiàn),響應(yīng)的狀態(tài)碼被設(shè)置為了400.圖標(biāo)也變?yōu)榱思t色.

2.3.6 設(shè)置header

Http響應(yīng)報(bào)頭也會(huì)向客戶端傳遞一些附加信息,如:Content-Type,Local等.這些信息就是通過(guò)@RequestMapping來(lái)實(shí)現(xiàn)的.先來(lái)看一看@RequestMapping的源碼:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
@Reflective({ControllerMappingReflectiveProcessor.class})
public @interface RequestMapping {
    String name() default "";
    @AliasFor("path")
    String[] value() default {};
    @AliasFor("value")
    String[] path() default {};
    RequestMethod[] method() default {};
    String[] params() default {};
    String[] headers() default {};
    String[] consumes() default {};
    String[] produces() default {};
}
  • value(),path():指定映射的URL.
  • method():指定請(qǐng)求的方法.如GET,POST等.
  • consumes():指定處理的請(qǐng)求的提交內(nèi)容類型(Content-Type),例如:application/json, text/html等.
  • produces():指定返回的內(nèi)容類型,也就是瀏覽器上響應(yīng)之后顯示的內(nèi)容類型.和上面的consumes()一樣.

設(shè)置Content-Type
我們通過(guò)設(shè)置produces的值,設(shè)置響應(yīng)報(bào)頭的Content-Type.

//返回的響應(yīng)是json格式
@RequestMapping(value = "/param7",produces = "application/json")
@ResponseBody
public String param7(){
    return "{\"success\":true}";
}


我們看到瀏覽器返回的響應(yīng)數(shù)據(jù)是json格式的數(shù)據(jù).

如果不在@RequestMapping后面加上produces參數(shù)的話,返回響應(yīng)的時(shí)候,Spring還是會(huì)以默認(rèn)的text.html格式返回.

  • 設(shè)置其他的Header

設(shè)置其他Header,需要使用Spring中提供的HttpServletResponse提供的方法來(lái)設(shè)置.

@RequestMapping("/param8")
@ResponseBody
public String param8(HttpServletResponse response){
    response.setHeader("MyHeader","value");
    return "設(shè)置Header成功";
}

我們通過(guò)Fiddler抓包可以看到,報(bào)頭中自定義的header已經(jīng)被加入進(jìn)去了.

如果header的名稱已經(jīng)存在,在設(shè)置它的Value的時(shí)候會(huì)覆蓋掉原來(lái)的值.

到此這篇關(guān)于Spring Web MVC基礎(chǔ)理論的文章就介紹到這了,更多相關(guān)Spring Web MVC內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java 關(guān)鍵字 volatile 的理解與正確使用

    Java 關(guān)鍵字 volatile 的理解與正確使用

    本文主要介紹 volatile 的使用準(zhǔn)則,以及使用過(guò)程中需注意的地方,感興趣的朋友一起看看吧
    2017-06-06
  • 解決spring security中遇到的問(wèn)題

    解決spring security中遇到的問(wèn)題

    這篇文章主要介紹了解決spring security中遇到的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • java 字符串截取的實(shí)例詳解

    java 字符串截取的實(shí)例詳解

    這篇文章主要介紹了java 字符串截取的實(shí)例詳解的相關(guān)資料,希望通過(guò)本文能幫助到大家,需要的朋友可以參考下
    2017-09-09
  • Java實(shí)現(xiàn)的模糊匹配某文件夾下的文件并刪除功能示例

    Java實(shí)現(xiàn)的模糊匹配某文件夾下的文件并刪除功能示例

    這篇文章主要介紹了Java實(shí)現(xiàn)的模糊匹配某文件夾下的文件并刪除功能,涉及java針對(duì)目錄與文件的遍歷、匹配、判斷、刪除等相關(guān)操作技巧,需要的朋友可以參考下
    2018-02-02
  • Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(34)

    Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(34)

    下面小編就為大家?guī)?lái)一篇Java基礎(chǔ)的幾道練習(xí)題(分享)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧,希望可以幫到你
    2021-07-07
  • 深入淺出Java中的字節(jié)流和字符流詳解

    深入淺出Java中的字節(jié)流和字符流詳解

    Java 中的輸入輸出(I/O)流主要分為字節(jié)流和字符流,這兩類流為開(kāi)發(fā)者提供了高效的文件讀寫(xiě)方式,也解決了不同編碼格式下的字符處理問(wèn)題,本文將帶你深入了解字節(jié)流和字符流的區(qū)別、應(yīng)用場(chǎng)景以及如何使用它們處理文件操作
    2024-12-12
  • 關(guān)于接口ApplicationContext中的getBean()方法使用

    關(guān)于接口ApplicationContext中的getBean()方法使用

    這篇文章主要介紹了關(guān)于接口ApplicationContext中的getBean()方法使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • Java使用AES加密和解密的實(shí)例詳解

    Java使用AES加密和解密的實(shí)例詳解

    這篇文章主要介紹了Java使用AES加密和解密的實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-07-07
  • Spring Boot 整合單機(jī)websocket的步驟 附github源碼

    Spring Boot 整合單機(jī)websocket的步驟 附github源碼

    websocket 是一個(gè)通信協(xié)議,通過(guò)單個(gè) TCP 連接提供全雙工通信,這篇文章主要介紹了Spring Boot 整合單機(jī)websocket的步驟(附github源碼),需要的朋友可以參考下
    2021-10-10
  • IDEA 2020 2全家桶安裝激活超詳細(xì)圖文教程

    IDEA 2020 2全家桶安裝激活超詳細(xì)圖文教程

    這篇文章主要介紹了IDEA-2020-2 全家桶安裝激活超詳細(xì)教程,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08

最新評(píng)論