一篇文章帶你掌握主流服務層框架——SpringMVC

来源:https://www.cnblogs.com/qiuluoyuweiliang/archive/2022/10/06/16757184.html
-Advertisement-
Play Games

一篇文章帶你掌握主流服務層框架——SpringMVC 在之前的文章中我們已經學習了Spring的基本內容,SpringMVC隸屬於Spring的一部分內容 但由於SpringMVC完全針對於服務層使用,所以我們在介紹時常常把SpringMVC單獨當作一個大章節來學習 溫馨提醒:在學習SpringMV ...


一篇文章帶你掌握主流服務層框架——SpringMVC

在之前的文章中我們已經學習了Spring的基本內容,SpringMVC隸屬於Spring的一部分內容

但由於SpringMVC完全針對於服務層使用,所以我們在介紹時常常把SpringMVC單獨當作一個大章節來學習

溫馨提醒:在學習SpringMVC前請確保已學習Spring內容

SpringMVC簡介

首先我們先來簡單瞭解一下SpringMVC:

  • SpringMVC是一種基於Java實現MVC模型的輕量級Web框架
  • SpringMVC致力於服務層,同Servlet一樣應用於服務層,用於服務層開發
  • SpringMVC隸屬於Spring,同樣具有簡化代碼,使用簡單,開發便捷,靈活性強的優點

SpringMVC入門案例

在未學習SpringMVC之前,我們的服務端開發通常採用Servlet:

package com.itheima.web.servlet.old;

import com.alibaba.fastjson.JSON;
import com.itheima.pojo.Brand;
import com.itheima.service.BrandService;
import com.itheima.service.impl.BrandServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.List;

//@WebServlet("/addServlet")
public class AddServlet extends HttpServlet {

    private BrandService brandService = new BrandServiceImpl();

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //1. 接收品牌數據
        BufferedReader br = request.getReader();
        String params = br.readLine();//json字元串

        //轉為Brand對象
        Brand brand = JSON.parseObject(params, Brand.class);

        //2. 調用service添加
        brandService.add(brand);

        //3. 響應成功的標識
        response.getWriter().write("success");
    }

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

我們可以註意到其過程非常繁瑣,因為我們需要獲取參數併進行類型轉換,包括添加至Service等過程

但是SpringMVC秉承著簡化代碼的原則,將大部分內容轉化為Java代碼進行封裝,大大減少了繁瑣的過程

接下來我們來介紹SpringMVC版:

  1. 導入jar包
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.itheima</groupId>
  <artifactId>springmvc_01_quickstart</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <dependencies>
<!--    servlet坐標-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>
<!--    SpringMVC坐標-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.2.10.RELEASE</version>
    </dependency>
  </dependencies>
<!--Tomcat配置-->
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.tomcat.maven</groupId>
        <artifactId>tomcat7-maven-plugin</artifactId>
        <version>2.1</version>
        <configuration>
          <port>80</port>
          <path>/</path>
        </configuration>
      </plugin>
    </plugins>
  </build>


</project>
  1. 創建SpringMVC控制類(等同於Servlet類)
package com.itheima.controller;

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

//定義表現層控制器bean
@Controller
public class UserController {

    //設置映射路徑為/save,即外部訪問路徑
    @RequestMapping("/save")
    //設置當前操作返回結果為指定json數據(本質上是一個字元串信息)
    @ResponseBody
    public String save(){
        System.out.println("user save ...");
        return "{'info':'springmvc'}";
    }

    //設置映射路徑為/delete,即外部訪問路徑
    @RequestMapping("/delete")
    @ResponseBody
    public String delete(){
        System.out.println("user save ...");
        return "{'info':'springmvc'}";
    }
}
  1. 初始化SpringMVC環境(同Spring一樣創建Config配置Java類)
package com.itheima.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

//springmvc配置類,本質上還是一個spring配置類
@Configuration
@ComponentScan("com.itheima.controller")
public class SpringMvcConfig {
}
  1. 初始化Servlet容器,載入SpringMVC環境,並設置SpringMVC技術處理的請求
/*
我們服務層的實際操作都是放置於Servlet容器中
我們配置的SpringMVC和Spring環境都是用於服務層,所以我們需要把相關Config載入僅Servlet容器中
*/

package com.itheima.config;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;

// web容器配置類
// AbstractDispatcherServletInitializer是SpringMVC為我們設置好的類,繼承並實現相關方法即可
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
    //載入springmvc配置類,產生springmvc容器(本質還是spring容器)
    protected WebApplicationContext createServletApplicationContext() {
        //初始化WebApplicationContext對象
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        //載入指定配置類
        ctx.register(SpringMvcConfig.class);
        return ctx;
    }

    //設置由springmvc控制器處理的請求映射路徑
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    //載入spring配置類
    protected WebApplicationContext createRootApplicationContext() {
        return null;
    }
}

我們對上述新的內容進行解析:

  1. @Controller

    • 名稱:@Controller

    • 類型:類註解

    • 位置:SpringMVC控制類定義上方

    • 作用:設定SpringMVC的核心控制器Bean

  2. @RequestMapping

    • 名稱:@RequestMapping

    • 類型:方法註解

    • 位置:SpringMVC控制器方法定義上方

    • 作用:設置當前控制器方法請求訪問路徑

    • 相關屬性:value(請求訪問路徑)

  3. @ResponseBody

    • 名稱:@ResponseBody

    • 類型:方法註釋

    • 位置:SpringMVC控制器方法定義上方

    • 作用:設置當前控制器方法響應內容為當前返回值,無需解析

  4. AbstractDispatcherServletInitializer類

    • AbstractDispatcherServletInitializer是SpringMVC提供的快速初始化Web3.0容器的抽象類
    • AbstractDispatcherServletInitializer提供三個介面方法供用戶實現
    • createServletApplicationContext方法用於創建Servlet容器時,載入SpringMVC對應的Bean並放入
    • AnnotationConfigWebApplicationContext的作用範圍對應整個Web容器範圍,必須使用WebApplicationcontext類型

最後我們總結一下上述操作的出現頻率:

  • 一次性工作
    • 創建工程,設置伺服器,載入工程
    • 導入坐標
    • 創建Web容器啟動類,載入SpringMVC配置,並設置SpringMVC請求攔截路徑
    • SpringMVC核心配置類(設置配置類,掃描controller包,載入Controller控制器Bean)
  • 常態工作
    • 定義處理請求的控制類
    • 定義處理請求的操作方法,並設置映射路徑(@RequestMapper)與返回Json數據(@ResponseBody)

SpringMVC工作流程

在分析SpringMVC工作流程前,我們需要知道服務層是由下麵的框架組成的:

啟動伺服器初始化過程:

  1. 伺服器啟動,執行ServletContainersInitConfig類,初始化Web容器
  2. 執行createServletApplicationContext方法,創建了WebApplicationContext對象
  3. 載入SpringMvcConfig
  4. 執行@ComponentScan載入對應的bean
  5. 載入UserController,每個@RequestMapping的名稱對應一個具體的方法
  6. 執行getServletMappings方法,定義所有的請求都通過SpringMVC

單次請求過程:

  1. 發送請求localhost/save
  2. Web容器發現所有請求都經過SpirngMVC,將請求交給SpringMVC處理
  3. 解析請求路徑/save
  4. 由/save匹配執行對應的方法save()
  5. 執行save()
  6. 檢測到有@ResponseBody直接將save()方法的返回值作為響應求體返回給請求方

SpringMVC載入控制

在學習SpringMVC之後,我們的Bean的範圍逐漸變大:

  • SpringMVC相關bean(表現層bean)
  • Spring相關bean(業務層Service,功能DataSource等)

但是我們在使用時,需要區分相關bean的導入路徑:

  • SpringMVC載入的bean對應的包均在com.itheima.controller包內
  • Spring載入的bean卻包含有多個文件夾

因而我們給出兩種方法來解決Spring的掃描問題:

  1. Spring載入的bean設定範圍為com.itheima,併排除掉controller包內的bean
package com.itheima.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;

@Configuration
/*
@ComponentScan註解設置掃描範圍
@ComponentScan中包含有value,excludeFilters屬性
value:用於控制掃描範圍
excludeFilters:用於控制排除範圍,需要採用@ComponentScan.Filter過濾器
type:設置排除規則,當前使用按照bean定義時的註解類型進行排除
classes屬性:設置排除的具體註解類,當前設置排除@Controller定義的bean
*/
@ComponentScan(value="com.itheima",
    excludeFilters = @ComponentScan.Filter(
        type = FilterType.ANNOTATION,
        classes = Controller.class
    )
)
public class SpringConfig {
}

/*
這裡做一個小補充內容:
@ComponentScan中除了excludeFilters,還包括有includeFilters
includeFilters:載入指定的bean,需要指定類型(type)和具體項(classes)
*/
  1. Spring載入的bean設定範圍為精準範圍,例如service包,dao包等
package com.itheima.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;

@Configuration
@ComponentScan({"com.itheima.service","com.itheima.dao"})
public class SpringConfig {
}

Servlet容器簡化寫法

我們的Servlet容器中可以定義Spring和SpringMVC的配置文件

package com.itheima.config;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;

public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
    
    // 配置SpringMVC配置文件
    protected WebApplicationContext createServletApplicationContext() {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(SpringMvcConfig.class);
        return ctx;
    }
    
    // 配置Spring配置文件
    protected WebApplicationContext createRootApplicationContext() {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(SpringConfig.class);
        return ctx;
    }
    
    // 配置攔截路徑
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

}

我們可以註意到:

Spring和SpringMVC導入方法中均採用AnnotationConfigWebApplicationContext來創建對象

兩者之間的區別僅僅是class包的不同

Spring給了我們一種新的繼承類用於簡化開發:

package com.itheima.config;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;
//web配置類簡化開發,僅設置配置類類名即可
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {

    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }

    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }

    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

註意:

AbstractAnnotationConfigDispatcherServletInitializer是createServletApplicationContext的繼承類

我們同樣繼承它的三個方法,但這次我們只需要在裡面標明相關類和路徑即可

常用工具推薦Postman

在我們的SpringMVC中岔開一個話題:

  • 關於我們的網頁調試的複雜性

我們在一個網頁開發中,會不斷的調試網頁,通過各種路徑反覆查詢或者採用不同的訪問方式(GET/POST)

如果我們採用正常的網頁進行測試,無疑會出現非常麻煩的步驟

所以我們推薦採用Postman軟體,下麵我們將會簡單做一下介紹

Postman鏈接

首先為大家附上鏈接:

Postman操作講解

在瞭解操作前,我們需要明白Postman的作用:

  • 用於分類存儲網頁請求
  • 用於發送請求進行測試

關於安裝註冊的過程我們不再贅述

Postman頁面展示

我們先來查看Postman的主頁:

首先我們可以看到左上角的Workspaces,這個是最大的分類空間

我們可以看到左上角SpringMVC,這是我所創建的WorkSpaces,關於我在SpringMVC所做的網頁測試部分將都在這裡進行

除此之外,我們可以看到右側的DEMO1,以及內部的測試用例文件夾,以及項目save

以上就是我們的Postman的基本頁面

Postman具體使用

我們的Postman的具體使用流程如下:

  1. 創建新的Workspaces

  1. 選定主界面,創建對應文件夾

  1. 創建項目(點擊中間區域的加號)

  1. 書寫項目內容(GET可以更換其他類型,後面書寫URL,下方key,value書寫傳遞數據)

  1. 下方的數據傳遞可以更換類型,例如更換為body體的raw來書寫JSON格式

  1. 書寫後保存到相應列表並標註名稱

到這裡,我們Postman的基本使用基本就結束了,到後面我們會對具體內容做具體補充~

SpringMVC設置請求與響應

SpringMVC和Servlet同屬於服務層的工具,那麼必不可少的就是請求與響應的反饋問題

接下來我們將一一介紹請求與響應的相關知識

請求映射路徑設置

首先我們先來想一想我們之前的路徑設置是否有那麼一點點缺陷?

// Book的服務層

package com.itheima.controller;

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

@Controller
public class BookController {
    //請求路徑映射
    @RequestMapping("/save")
    @ResponseBody
    public String save(){
        System.out.println("book save ...");
        return "{'module':'book save'}";
    }
}
// User的服務層

package com.itheima.controller;

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

@Controller
public class UserController {
    //請求路徑映射
    @RequestMapping("/save")
    @ResponseBody
    public String save(){
        System.out.println("user save ...");
        return "{'module':'user save'}";
    }
    //請求路徑映射
    @RequestMapping("/delete")
    @ResponseBody
    public String delete(){
        System.out.println("user delete ...");
        return "{'module':'user delete'}";
    }

}

我們可以註意到我們的單個項目中不可能只包括有一個服務層

但我們的請求映射路徑卻只是簡單設計為相同的名稱,就會導致我們訪問該頁面時,系統無法匹配

所以我們需要給他們採用不同的映射路徑,我們常有的操作是直接在前面加上一層該類的路徑名:

package com.itheima.controller;

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

@Controller
public class BookController {
    //請求路徑映射
    @RequestMapping("/book/save")
    @ResponseBody
    public String save(){
        System.out.println("book save ...");
        return "{'module':'book save'}";
    }
}

但當項目逐漸增多,我們多次書寫路徑名就有可能導致錯誤,所以我們採用類註解@RequestMapping來解決:

package com.itheima.controller;

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

@Controller
//類上方配置的請求映射與方法上面配置的請求映射連接在一起,形成完整的請求映射路徑
@RequestMapping("/user")
public class UserController {
    //請求路徑映射
    @RequestMapping("/save")
    @ResponseBody
    public String save(){
        System.out.println("user save ...");
        return "{'module':'user save'}";
    }
    //請求路徑映射
    @RequestMapping("/delete")
    @ResponseBody
    public String delete(){
        System.out.println("user delete ...");
        return "{'module':'user delete'}";
    }

}

註意:@RequestMapping不僅僅可以用於方法表示映射,也可以用於整個Bean類中表示映射首碼

參數傳遞問題

關於參數傳遞我們從三個方面來講解:

  • 傳遞方式
  • 傳遞參數類型
  • 特殊參數類型

按傳遞方式

我們的傳遞方式通常採用GET或者POST方式

但在前面的學習中我們可以知道我們的傳遞方式是有不同的,我們在Postman的書寫形式也是不同的

例如我們先給出一個簡單的參數傳遞函數

package com.itheima.controller;

import com.itheima.domain.User;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
//請求參數
@Controller
public class UserController {

    //普通參數:請求參數與形參名稱對應即可完成參數傳遞
    @RequestMapping("/commonParam")
    @ResponseBody
    public String commonParam(String name ,int age){
        System.out.println("普通參數傳遞 name ==> "+name);
        System.out.println("普通參數傳遞 age ==> "+age);
        return "{'module':'common param'}";
    }

}

我們的GET方式直接在網頁後用?和&來書寫傳遞參數:

我們的POST方式只能在下方的body中書寫參數:

然後我們需要註意到的是這裡的中文同樣會出現亂碼行為

這次我們選擇在ServletContainersInitConfig中處理數據:

// 下述代碼基本屬於我們創建項目的固定代碼

package com.itheima.config;

import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

import javax.servlet.Filter;

public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
    protected Class<?>[] getRootConfigClasses() {
        return new Class[0]{SpringConfig.class};
    }

    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }

    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    //亂碼處理
    @Override
    protected Filter[] getServletFilters() {
        // CharacterEncodingFilter 屬於處理中文編碼的過濾器,我們直接創建即可(一次性操作)
        CharacterEncodingFilter filter = new CharacterEncodingFilter();
        filter.setEncoding("UTF-8");
        return new Filter[]{filter};
    }
}

按參數方式

我們按參數來分類主要分為五種:

  • 普通參數
  • POJO類
  • 嵌套式POJO類
  • 數組參數
  • 集合參數

我們下麵來一一介紹

普通參數

普通參數:請求參數和形參變數名相同時,自動匹配

package com.itheima.controller;

import com.itheima.domain.User;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
//請求參數
@Controller
public class UserController {

    //普通參數:請求參數與形參名稱對應即可完成參數傳遞
    @RequestMapping("/commonParam")
    @ResponseBody
    public String commonParam(String name ,int age){
        System.out.println("普通參數傳遞 name ==> "+name);
        System.out.println("普通參數傳遞 age ==> "+age);
        return "{'module':'common param'}";
    }

}

Postman操作:

這裡需要註意:當請求參數名與形參名不同時,使用@RequestParam註解關聯請求參數名稱與形參名稱之間的關係

package com.itheima.controller;

import com.itheima.domain.User;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
//請求參數
@Controller
public class UserController {

    //普通參數:請求參數名與形參名不同時,使用@RequestParam註解關聯請求參數名稱與形參名稱之間的關係
    @RequestMapping("/commonParamDifferentName")
    @ResponseBody
    public String commonParamDifferentName(@RequestParam("name") String userName , int age){
        System.out.println("普通參數傳遞 userName ==> "+userName);
        System.out.println("普通參數傳遞 age ==> "+age);
        return "{'module':'common param different name'}";
    }

}

Postman操作:

@RequestParam:綁定請求參數與處理器方法形參間的關係

包含有兩個參數

required:是否為必傳參數

defaultValue:參數預設值

POJO參數

POJO參數:請求參數名與形參對象屬性名相同,定義POJO類型形參即可接收參數

package com.itheima.controller;

import com.itheima.domain.User;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
//請求參數
@Controller
public class UserController {

    //POJO參數:請求參數與形參對象中的屬性對應即可完成參數傳遞
    @RequestMapping("/pojoParam")
    @ResponseBody
    public String pojoParam(User user){
        System.out.println("pojo參數傳遞 user ==> "+user);
        return "{'module':'pojo param'}";
    }

}

Postman操作:

嵌套POJO參數

嵌套POJO參數:請求參數名與形參對象屬性名相同,按照對象層次結構關係即可接收嵌套POJO屬性參數

package com.itheima.controller;

import com.itheima.domain.User;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
//請求參數
@Controller
public class UserController {

    //嵌套POJO參數:嵌套屬性按照層次結構設定名稱即可完成參數傳遞
    @RequestMapping("/pojoContainPojoParam")
    @ResponseBody
    public String pojoContainPojoParam(User user){
        System.out.println("pojo嵌套pojo參數傳遞 user ==> "+user);
        return "{'module':'pojo contain pojo param'}";
    }

}

Postman操作:

數組參數

數組參數:請求參數名與形參對象屬性名相同且請求參數為多個,定義數組類型形參即可接收參數

package com.itheima.controller;

import com.itheima.domain.User;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
//請求參數
@Controller
public class UserController {

    //數組參數:同名請求參數可以直接映射到對應名稱的形參數組對象中
    @RequestMapping("/arrayParam")
    @ResponseBody
    public String arrayParam(String[] likes){
        System.out.println("數組參數傳遞 likes ==> "+ Arrays.toString(likes));
        return "{'module':'array param'}";
    }

}

Postman操作:

集合保存普通參數

集合保存普通參數:請求參數與形參集合對象名相同且請求參數為多個,@RequestParam綁定參數關係

package com.itheima.controller;

import com.itheima.domain.User;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
//請求參數
@Controller
public class UserController {

    //集合參數:同名請求參數可以使用@RequestParam註解映射到對應名稱的集合對象中作為數據
    @RequestMapping("/listParam")
    @ResponseBody
    public String listParam(@RequestParam List<String> likes){
        System.out.println("集合參數傳遞 likes ==> "+ likes);
        return "{'module':'list param'}";
    }

}

Postman參數:

按特殊參數方式

我們的特殊參數主要介紹兩種:

  • JSON類型
  • 日期類型

我們下麵一一介紹

JSON類型

JSON類型是我們Web開發中最常用的類型,所以這一部分算是一個小重點

我們將一一講解JSON類型傳遞的步驟:

  1. 導入JSON坐標
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.itheima</groupId>
  <artifactId>springmvc_04_request_param</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <dependencies>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.2.10.RELEASE</version>
    </dependency>
      <!--JSON坐標--->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.0</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.tomcat.maven</groupId>
        <artifactId>tomcat7-maven-plugin</artifactId>
        <version>2.1</version>
        <configuration>
          <port>80</port>
          <path>/</path>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

  1. 在SpringMVC配置類中添加JSON類型轉換註解
package com.itheima.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

import javax.servlet.Filter;
import javax.servlet.annotation.WebFilter;

@Configuration
@ComponentScan("com.itheima.controller")
//開啟json數據類型自動轉換
@EnableWebMvc
public class SpringMvcConfig {
}
  1. 在Controller中書寫相關Web代碼(註意:需要使用@RequestBody表示將請求體數據傳遞給請求參數)
package com.itheima.controller;

import com.itheima.domain.User;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
//請求參數
@Controller
public class UserController {

    //集合參數:json格式
    //1.開啟json數據格式的自動轉換,在配置類中開啟@EnableWebMvc
    //2.使用@RequestBody註解將外部傳遞的json數組數據映射到形參的集合對象中作為數據
    @RequestMapping("/listParamForJson")
    @ResponseBody
    public String listParamForJson(@RequestBody List<String> likes){
        System.out.println("list common(json)參數傳遞 list ==> "+likes);
        return "{'module':'list common for json param'}";
    }

    //POJO參數:json格式
    //1.開啟json數據格式的自動轉換,在配置類中開啟@EnableWebMvc
    //2.使用@RequestBody註解將外部傳遞的json數據映射到形參的實體類對象中,要求屬性名稱一一對應
    @RequestMapping("/pojoParamForJson")
    @ResponseBody
    public String pojoParamForJson(@RequestBody User user){
        System.out.println("pojo(json)參數傳遞 user ==> "+user);
        return "{'module':'pojo for json param'}";
    }

    //集合參數:json格式
    //1.開啟json數據格式的自動轉換,在配置類中開啟@EnableWebMvc
    //2.使用@RequestBody註解將外部傳遞的json數組數據映射到形參的保存實體類對象的集合對象中,要求屬性名稱一一對應
    @RequestMapping("/listPojoParamForJson")
    @ResponseBody
    public String listPojoParamForJson(@RequestBody List<User> list){
        System.out.println("list pojo(json)參數傳遞 list ==> "+list);
        return "{'module':'list pojo for json param'}";
    }
    
}

Postman操作:

在上面我們有兩個註解需要特別註意一下:

  1. @EnableWebMvc
  • 名稱:@EnableWebMvc
  • 類型:配置類註解
  • 位置:SpringMVC配置類定義上方
  • 作用:開啟SpringMVC多項輔助功能
  1. @RequestBody
  • 名稱:@RequestBody
  • 類型:形參註解
  • 位置:SpringMVC控制器方法形參定義前面
  • 作用:將請求中請求體所包含的數據傳遞給請求參數,此註解一個處理器方法只能使用一次

@RequestBody和@RequestParam區別

  • 區別
    • @RequestParam用於接收url地址傳參,表單傳參[application/x-www-form-urlencoded]
    • @RequestBody用於接收JSON數據[application/json]
  • 應用
    • 後期開發中,發送json數據為主,@RequestBody應用較廣
    • 如果發送非json格式數據,選用@RequestParam接收請求參數
日期型參數類型

我們的日期類型數據基於系統不同格式也不相同,大致有以下幾種:

  • 2022-10-05
  • 2022/10/05
  • 10/05/2022

接收形參時,我們根據不同的日期格式設置不同的接收方式

package com.itheima.controller;

import com.itheima.domain.User;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
//請求參數
@Controller
public class UserController {

    //日期參數
    //使用@DateTimeFormat註解設置日期類型數據格式,預設格式yyyy/MM/dd
    @RequestMapping("/dataParam")
    @ResponseBody
    public String dataParam(Date date,
                            @DateTimeFormat(pattern="yyyy-MM-dd") Date date1,
                            @DateTimeFormat(pattern="yyyy/MM/dd HH:mm:ss") Date date2){
        System.out.println("參數傳遞 date ==> "+date);
        System.out.println("參數傳遞 date1(yyyy-MM-dd) ==> "+date1);
        System.out.println("參數傳遞 date2(yyyy/MM/dd HH:mm:ss) ==> "+date2);
        return "{'module':'data param'}";
    }

}

/*
名稱:@DateTimeFormat
類型:形參註解
位置:SpringMVC控制器方法前
作用:設定日期時間型數據格式
屬性:pattern:日期時間格式字元串
*/

Postman操作:

這裡我們簡單介紹一下@DateTimeFormat的轉換原理Converter介面:

public interface Converter<S,T>{
	@Nullable
    T convert(S var1)
}

Converter介面屬於頂層介面,由它為起源創建了許多相關的介面與類用於各種轉化:

  • 請求參數年齡數據(String->Integer)
  • 日期格式轉發(String->Date)

@EnableWebMvc功能之一:根據類型匹配對應的類型轉換器

設置響應

在瞭解請求的相關知識之後,我們回到Controller代碼中學習一下響應

跳轉響應

在正常情況下,我們的響應給出的是當前項目的文檔,相當於頁面的跳轉效應:

package com.itheima.controller;

import com.itheima.domain.User;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Controller
public class UserController {

    //響應頁面/跳轉頁面
    //返回值為String類型,設置返回值為頁面名稱,即可實現頁面跳轉
    @RequestMapping("/toJumpPage")
    public String toJumpPage(){
        System.out.println("跳轉頁面");
        return "page.jsp";
    }

}

信息響應

如果我們希望得到一些信息響應,就需要採用註解解釋:

package com.itheima.controller;

import com.itheima.domain.User;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Controller
public class UserController {
    
    //響應文本數據
    //返回值為String類型,設置返回值為任意字元串信息,即可實現返回指定字元串信息,需要依賴@ResponseBody註解
    @RequestMapping("/toText")
    @ResponseBody
    public String toText(){
        System.out.println("返回純文本數據");
        return "response text";
    }

    //響應POJO對象
    //返回值為實體類對象,設置返回值為實體類類型,即可實現返回對應對象的json數據,需要依賴@ResponseBody註解和@EnableWebMvc註解
    @RequestMapping("/toJsonPOJO")
    @ResponseBody
    public User toJsonPOJO(){
        System.out.println("返回json對象數據");
        User user = new User();
        user.setName("itcast");
        user.setAge(15);
        return user;
    }

    //響應POJO集合對象
    //返回值為集合對象,設置返回值為集合類型,即可實現返回對應集合的json數組數據,需要依賴@ResponseBody註解和@EnableWebMvc註解
    @RequestMapping("/toJsonList")
    @ResponseBody
    public List<User> toJsonList(){
        System.out.println("返回json集合數據");
        User user1 = new User();
        user1.setName("傳智播客");
        user1.setAge(15);

        User user2 = new User();
        user2.setName("黑馬程式員");
        user2.setAge(12);

        List<User> userList = new ArrayList<User>();
        userList.add(user1);
        userList.add(user2);

        return userList;
    }
}

/*
名稱:@ResponseBody
類型:方法註解
位置:SpringMVC控制器方法定義上方
作用:設置當前控制器返回值作為響應體
*/

當我們使用Postman訪問該鏈接時就會給出對應反饋,這裡就不做演示了

REST風格

首先我們來簡單介紹一下REST:

  • REST(Representational State Transfer),表現形式狀態轉換

我們給出正常風格和REST風格兩種書寫形式,我們可以明顯看到REST的內容做出大規模的省略:

REST風格優點:

  • 書寫簡化
  • 隱藏資源的訪問行為,無法通過地址得知對資源的操作

REST風格簡介

我們來對REST風格做出簡單解釋:

  • REST風格是採用訪問資源的行為動作來區別對資源進行了何種操作

我們給出五種常見行為動作:

我們通常將根據REST風格進行的訪問稱為RESTful

上述行為是約定方式,約定不是規範,是可以打破的,所以稱為REST風格,而不是REST規範

描述模塊的名稱通常使用負數,也就是加s的格式描述,表示此類,而非單個資源

RESTful入門案例

從本質上而言,REST只是一種規範形式,我們對於REST的風格修改僅針對於Controller

我們下麵將逐步進行RESTful的修改:

  1. 設置http請求動作
package com.itheima.controller;

import com.itheima.domain.Book;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

@Controller
public class BookController {

    // RequestMapping中包含value和method兩種屬性
    // value:訪問路徑
    // method:訪問方法
    @RequestMapping(value = "/users",method = Request.POST)
    @RequestBody
	public String save(@RequestBody User user){
		System.out.println("user save" + user);
        return "{'module':'user save'}"
    }
}

/*
名稱:@RequestMapping
類型:方法註解
位置:SpringMVC控制器方法定義上方
作用:設置當前控制器方法請求訪問路徑
屬性:value訪問路徑,method請求動作
*/
  1. 設置請求參數(路徑變數)
package com.itheima.controller;

import com.itheima.domain.Book;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

@Controller
public class BookController {

    // 首先針對我們所需參數給出@PathVariable註解,併在訪問路徑中採用{}占位表示所傳數據
    // 簡單來說就是,系統根據請求路徑,得到所需數據,再帶入到方法中
    @RequestMapping(value = "/users/{id}" ,method = RequestMethod.DELETE)
    @RequestBody
    public String delete(@PathVariable Integer id){
        System.out.println("book delete..." + id);
        return "{'module':'book delete'}";
    }
}

/*
名稱:@PathVariable
類型:形參註解
位置:SpringMVC控制器方法形參定義前面
作用:綁定路徑參數與處理器方法形參間的關係,要求路徑參數名與形參名一一對應
*/

下麵我們給出所有情況案例:

package com.itheima.controller;

import com.itheima.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

@Controller
public class UserController {

    //設置當前請求方法為POST,表示REST風格中的添加操作
    @RequestMapping(value = "/users",method = RequestMethod.POST)
    @ResponseBody
    public String save(){
        System.out.println("user save...");
        return "{'module':'user save'}";
    }

    //設置當前請求方法為DELETE,表示REST風格中的刪除操作
    //@PathVariable註解用於設置路徑變數(路徑參數),要求路徑上設置對應的占位符,並且占位符名稱與方法形參名稱相同
    @RequestMapping(value = "/users/{id}",method = RequestMethod.DELETE)
    @ResponseBody
    public String delete(@PathVariable Integer id){
        System.out.println("user delete..." + id);
        return "{'module':'user delete'}";
    }

    //設置當前請求方法為PUT,表示REST風格中的修改操作
    @RequestMapping(value = "/users",method = RequestMethod.PUT)
    @ResponseBody
    public String update(@RequestBody User user){
        System.out.println("user update..."+user);
        return "{'module':'user update'}";
    }

    //設置當前請求方法為GET,表示REST風格中的查詢操作
    //@PathVariable註解用於設置路徑變數(路徑參數),要求路徑上設置對應的占位符,並且占位符名稱與方法形參名稱相同
    @RequestMapping(value = "/users/{id}" ,method = RequestMethod.GET)
    @ResponseBody
    public String getById(@PathVariable Integer id){
        System.out.println("user getById..."+id);
        return "{'module':'user getById'}";
    }

    //設置當前請求方法為GET,表示REST風格中的查詢操作
    @RequestMapping(value = "/users",method = RequestMethod.GET)
    @ResponseBody
    public String getAll(){
        System.out.println("user getAll...");
        return "{'module':'user getAll'}";
    }

}


/*
	下述為原有代碼:

    @RequestMapping
    @ResponseBody
    public String delete(){
        System.out.println("user delete...");
        return "{'module':'user delete'}";
    }

    @RequestMapping
    @ResponseBody
    public String update(){
        System.out.println("user update...");
        return "{'module':'user update'}";
    }

    @RequestMapping
    @ResponseBody
    public String getById(){
        System.out.println("user getById...");
        return "{'module':'user getById'}";
    }

    @RequestMapping
    @ResponseBody
    public String getAll(){
        System.out.println("user getAll...");
        return "{'module':'user getAll'}";
    }
*/

我們在這裡給出@RequestBody,@RequestParam,@PathVariable區別

區別:

  • @RequestParam用於接收url地址傳參或表單傳參
  • @RequestBody用於接收json數據
  • @PathVariable用於接收路徑參數,使用{參數名稱}描述路徑參數

應用:

  • 後期開發中,發送請求參數超過1個時,以json格式為主,@RequestBody應用較廣
  • 如果發送非json格式數據,選用@RequestParam接受請求參數
  • 採用RESTful進行開發,當參數數量較少時,如1個,可以採用@PathVariable接收請求路徑變數,常用來傳遞id值

REST快速開發

我們在上一小節中會發現有許多重覆性的代碼:

// 每次都填寫value,method導致代碼繁冗
// 包括每次填寫ResponseBody使代碼繁冗

@RequestMapping(value = "/users",method = RequestMethod.GET)
@ResponseBody

所以我們可以採用一些小技巧來簡化代碼:

  • 將首碼地址和相關註解放於類中:
package com.itheima.controller;

import com.itheima.domain.Book;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

//@Controller
//@ResponseBody
@RestController
@RequestMapping("/books")
public class BookController {

}
/*
正常情況下,我們的類本身具有@Controller,並且為了省略類中的@ResponseBody而直接標註在類頭
但Spring提供了一種新的註解@RestController,相當於@Controller和@ResponseBody的結合,我們只需要書寫這一個註解即可 

名稱:@RestController
類型:類註解
位置:基於SpringMVC的RESTful開發控制器類定義上方
作用:設置當前控制器為RESTful風格,等同於@Controller與@ResponseBody兩個註解組合功能
*/
  • 採用新的地址註解代替老註解:
package com.itheima.controller;

import com.itheima.domain.Book;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/books")
public class BookController {

	//@RequestMapping( method = RequestMethod.POST)
    //使用@PostMapping簡化Post請求方法對應的映射配置
    @PostMapping        
    public String save(@RequestBody Book book){
        System.out.println("book save..." + book);
        return "{'module':'book save'}";
    }

	//@RequestMapping(value = "/{id}" ,method = RequestMethod.DELETE)
    //使用@DeleteMapping簡化DELETE請求方法對應的映射配置
    @DeleteMapping("/{id}")     
    public String delete(@PathVariable Integer id){
        System.out.println("book delete..." + id);
        return "{'module':'book delete'}";
    }

	//@RequestMapping(method = RequestMethod.PUT)
    //使用@PutMapping簡化Put請求方法對應的映射配置
    @PutMapping         
    public String update(@RequestBody Book book){
        System.out.println("book update..."+book);
        return "{'module':'book update'}";
    }

	//@RequestMapping(value = "/{id}" ,method = RequestMethod.GET)
    //使用@GetMapping簡化GET請求方法對應的映射配置
    @GetMapping("/{id}")    
    public String getById(@PathVariable Integer id){
        System.out.println("book getById..."+id);
        return "{'module':'book getById'}";
    }

	//@RequestMapping(method = RequestMethod.GET)
    //使用@GetMapping簡化GET請求方法對應的映射配置
    @GetMapping             
    public String getAll(){
        System.out.println("book getAll...");
        return "{'module':'book getAll'}";
    }
}

/*
名稱:@GetMapping @PostMapping @PutMapping @DeleteMapping
類型:方法註解
位置:基於SpringMVC的RESTful開發控制器方法定義上方
作用:設置當前控制器方法請求訪問路徑與請求動作,每種對應一個請求動作,例如@GetMapping對應GET請求
參數:value請求訪問路徑
*/

結束語

好的,關於SpringMVC的內容就介紹到這裡,希望能為你帶來幫助!

附錄

該文章屬於學習內容,具體參考B站黑馬程式員李老師的SSM框架課程

這裡附上鏈接:SpringMVC-01-SpringMVC簡介_嗶哩嗶哩_bilibili


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 我們看到下麵的示例圖是 在右鍵文件夾上查看菜單,帶有兩級的菜單選項。 文件夾 空白處 需要使用管理員許可權運行 因為右鍵菜單需要註冊表信息,打開註冊表需要管理員許可權UAC,所以在執行命令過程中需要使用管理員許可權來執行命令 import sys import winreg as reg import o ...
  • 我的博客 這個教程只適合windows,linux不適用,不過話說回來了,linux都是自帶python的,所以已經預置好了,只要打python就行了,根本不用加環境變數 言歸正傳 寫了好長時間的python,最近發現個很基礎的問題,就是很多同學已經安裝python了,但是不知道怎麼運行,找了教程, ...
  • 一、SpringMVC簡介 1、什麼是MVC MVC是一種軟體架構的思想,將軟體按照模型、視圖、控制器來劃分 **M:**Model,模型層,指工程中的JavaBean,作用是處理數據 JavaBean分為兩類: 一類稱為實體類Bean:專門存儲業務數據的,如Student、User等 一類稱為業務 ...
  • 本文講述了朴素貝葉斯的原理,概率的計算方式,給出代碼的詳細解釋,並最後給出代碼的運行過程的總結,然後又用了兩個實例來講述朴素貝葉斯代碼的計算過程 ...
  • 前言 相信接觸過併發系統的小伙伴們基本都使用過線程池,或多或少調整過對應的參數。以 Java 中的經典模型來說,能夠配置核心線程數、最大線程數、隊列容量等等參數。 public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, lon ...
  • 在項目或產品的迭代過程中,通常會有多套環境,常見的有: dev:開發環境 sit:集成測試環境 uat:用戶接收測試環境 pre:預生產環境 prod:生產環境 環境之間配置可能存在差異,如介面地址、全局參數等。在基於 vue-cli (webpack) 的項目中只需要添加 .env.xxx 文件, ...
  • 一、前情回顧 在討論迴流與重繪之前,我們要知道: 瀏覽器使用流式佈局模型 (Flow Based Layout)。 瀏覽器會把HTML解析成DOM,把CSS解析成CSSOM,DOM和CSSOM合併就產生了Render Tree。 有了RenderTree,我們就知道了所有節點的樣式,然後計算他們在頁 ...
  • 今天我們來聊一個老生常談的話題,跨域!又是跨域,煩不煩 ?網上跨域的文章那麼多,跨的我眼睛都疲勞了,不看了不看了
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...