当前位置: 首页 > news >正文

SpringMVC复习笔记

文章目录

  • SpringMVC 概念和基本使用
    • SpringMVC 简介
    • SpringMVC 核心组件和调用流程
    • SpringMVC 基本使用
      • 第一步:导入依赖
      • 第二步:Controller 层开发
      • 第三步:SpringMVC 配置类配置核心组件
      • 第四步:SpringMVC 环境搭建
      • 第五步:部署 Tomcat 并运行测试
  • SpringMVC 访问路径设置
    • 路径注解 `@RequestMapping`
      • 方法级别
      • 类级别
      • 特定请求方式限制
      • 特定请求方式限制-注解方式
    • 精确路径匹配
    • 模糊路径匹配
  • SpringMVC 接收参数
    • param 和 json 参数比较
    • SpringMVC 各种数据接收
      • 简单类型接值
      • 简单类型接值【形参和请求参数不一致】
      • 数组类型接收
      • 集合类型接收
      • 实体类类型接收
      • 日期参数接收
      • 路径参数接收
      • JSON 参数接收
      • Cookie 数据接收
      • 请求头信息接收
  • 原生 API 参数调用
    • 共享域对象操作
      • request 级别共享域
      • session 级别共享域
      • Application 级别共享地域
  • SpringMVC 响应数据
    • 开发模式介绍
    • 页面跳转
      • 快速返回模板视图
      • 请求转发和响应重定向
    • 返回 JSON 数据
      • 基本使用
      • `@ResponseBody` 注解
      • `@RestController` 注解
    • 返回静态资源
  • RESTFul 风格设计规范
    • HTTP 协议请求方式要求
    • URL 风格要求
    • 传递参数设计要求
    • 实战举例
  • SpringMVC 声明式全局异常处理
  • SpringMVC 拦截器
    • 拦截器方法拦截位置
    • 拦截器使用
    • 多个拦截器情况
  • SpringMVC 参数校验
    • 为什么使用参数校验
    • 校验注解详解
    • 参数校验使用
    • 易混淆注解总结

SpringMVC 概念和基本使用

SpringMVC 简介


Spring Web MVC 是基于 Servlet API 构建的原始Web框架,从一开始就包含在 Spring Framework中。正式名称 “Spring Web MVC” 来自其源模块的名称( spring-webmvc ),但它通常被称为“Spring MVC”。

在这里插入图片描述

SpringMVC 核心组件和调用流程


在这里插入图片描述
调用 Controller 层方法

请求映射查找

  • 通过 DispatcherServletrequest 对象传递给 HandlerMapping 。然后 HandlerMapping 基于这个 request 对象中的请求路径等信息。从其缓存中查找匹配的 hander(Controller 方法) ,对应路径等内容。然后把匹配到的信息返回给 DispatcherServlet

.

请求处理与响应

  • DispatcherServlet 拿到匹配的信息后。会来到 HandlerAdpter,并将 requestresponse 传递过来。HandlerAdpter 借助 request 进行请求参数绑定。然后才执行 handler(Controller 方法)。返回的数据封装到 response 中让 HandlerAdapter 处理。然后 response 返回给客户端

.

动态视图资源处理

  • handler(Controller 方法) 返回的是一个字符串就到视图解析器。通过视图解析器前缀和后缀拼接访问视图

SpringMVC 基本使用


第一步:导入依赖

<properties><spring.version>6.0.6</spring.version><servlet.api>9.1.0</servlet.api><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties><dependencies><!-- springioc相关依赖  --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><!-- web相关依赖  --><!-- 在 pom.xml 中引入 Jakarta EE Web API 的依赖 --><!--在 Spring Web MVC 6 中,Servlet API 迁移到了 Jakarta EE API,因此在配置 DispatcherServlet 时需要使用Jakarta EE 提供的相应类库和命名空间。错误信息 “‘org.springframework.web.servlet.DispatcherServlet’is not assignable to ‘javax.servlet.Servlet,jakarta.servlet.Servlet’” 表明你使用了旧版本的Servlet API,没有更新到 Jakarta EE 规范。--><dependency><groupId>jakarta.platform</groupId><artifactId>jakarta.jakartaee-web-api</artifactId><version>${servlet.api}</version><scope>provided</scope></dependency><!-- springwebmvc相关依赖  --><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency></dependencies>

第二步:Controller 层开发

  • @RequestMapping:对外访问的地址
  • @ResponseBody:告诉Spring框架,被注解的方法的返回值应该直接写入HTTP响应体(而不是视图名称),并且不需要进行视图解析。
public class HelloController {@RequestMapping("/springmvc/hello")@ResponseBodypublic String hello() {System.out.println("Hello springmvc");return "hello springmvc";}
}

第三步:SpringMVC 配置类配置核心组件

需要把 HandlerAdapterHandlerMapping 放入 IOC 容器 并扫描组件。其实用@EnableWebMvc 也可以自动配置。

@Configuration
@ComponentScan(basePackages = "com.mangfu.controller")
public class SpringMvcConfig {@Beanpublic RequestMappingHandlerAdapter requestMappingHandlerAdapter() {return new RequestMappingHandlerAdapter();}@Beanpublic RequestMappingHandlerMapping requestMappingHandlerMapping() {return new RequestMappingHandlerMapping();}
}

第四步:SpringMVC 环境搭建

作用:可以被 web 项目加载,会初始化 ioc 容器, 会设置 dispatcherServlet 的地址

public class SpringMvcInit extends AbstractAnnotationConfigDispatcherServletInitializer {@Overrideprotected Class<?>[] getRootConfigClasses() {return new Class[0];}//指定 springmvc 的配置类。会自动加载配置类@Overrideprotected Class<?>[] getServletConfigClasses() {return new Class[]{SpringMvcConfig.class};}//设置dispatcherServlet的处理路径!//一般情况下为 / 代表处理所有请求!@Overrideprotected String[] getServletMappings() {return new String[]{"/"};}
}

第五步:部署 Tomcat 并运行测试

在这里插入图片描述
在这里插入图片描述

SpringMVC 访问路径设置


路径注解 @RequestMapping

方法级别

直接在方法上加 @RequestMapping。当多个方法处理同一个路径的不同操作时,可以使用方法级别的 @RequestMapping 注解进行更精细的映射。

@Controller                                             
public class UserController {//这里路径就是 /index 访问就会执行这个方法@RequestMapping("/index")public String index() {return null;}
}

类级别

在类上加 @RequestMapping,方法上还要再设置一次 @RequestMapping 设置了 ReqquestMapping 的参数那就自动加上 类级别的地址当前缀,如果没有参数就直接用 类地址地址

@Controller
@RequestMapping("/user")
public class UserController {@RequestMapping //这里没有参数就直接用类级别的参数也就是 /userpublic String index() {return null;}@RequestMapping(value = "login") //这里有参数就是自动加上类级别的地址当前缀也就是 /user/loginpublic String login() {return null;}}

特定请求方式限制

注意:违背请求方式,会出现405异常!!!

设HTTP 协议定义了八种请求方式,在 SpringMVC 中封装到了下面这个枚举类:

public enum RequestMethod {GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE
}
@Controller
public class UserController {/*** 精准设置访问地址 /user/login* method = RequestMethod.POST 可以指定单个或者多个请求方式!* 注意:违背请求方式会出现405异常!*/@RequestMapping(value = {"/user/login"} , method = RequestMethod.POST)@ResponseBodypublic String login(){System.out.println("UserController.login");return "login success!!";}  
}

特定请求方式限制-注解方式

注意:进阶注解只能添加到handler方法上,无法添加到类上!

还有 @RequestMapping 的 HTTP 方法特定快捷方式变体:

  • @GetMapping
  • @PostMapping
  • @PutMapping
  • @DeleteMapping
  • @PatchMapping
@RequestMapping(value="/login",method=RequestMethod.GET)
就等于
@GetMapping(value="/login")

精确路径匹配

SpringMVC@RequestMapping/ 可以省略
.
/ 就表示绝对路径 ,Tomcat 中表示 http://localhost:8080/,设置 Tomcat 上下文路径为 / 缺省就可以直接使用 / + 地址 访问对应的 Servlet

   @RequestMapping(value = "/login", method = RequestMethod.POST) public String login() {return null;}

模糊路径匹配

  • @RequestMapping 注解指定 URL 地址时,通过使用通配符,匹配多个类似的地址。
  • * 表示任意单层:/user/* 这种就是一层可以访问,/user/a/b 这就是两层访问不了
  • **表示任意层/user/** ,比如:/user/a/user/a/b 都可以
@Controller
public class ProductController {/***  路径设置为 /product/*  *    /* 为单层任意字符串  /product/a  /product/aaa 可以访问此handler  *    /product/a/a 不可以* *  路径设置为 /product/** *   /** 为任意层任意字符串  /product/a  /product/aaa 可以访问此handler  *   /product/a/a 也可以访问*/@RequestMapping("/product/*")@ResponseBodypublic String show(){System.out.println("ProductController.show");return "product show!";}
}

SpringMVC 接收参数


param 和 json 参数比较

在 HTTP 请求中,我们可以选择不同的参数类型,如 param 类型和 JSON 类型。下面对这两种参数类型进行区别和对比:

  • paramkey = value & key = value
  • json{ key : value, key : value }
    .
  1. 参数编码:
    param 类型的参数会被编码为 ASCII 码。例如,假设 name=john doe,则会被编码为 name=john%20doe。而 JSON 类型的参数会被编码为 UTF-8。
    .
  2. 参数顺序
    param 类型的参数没有顺序限制。但是,JSON 类型的参数是有序的。JSON 采用键值对的形式进行传递,其中键值对是有序排列的。
    .
  3. 数据类型
    param 类型的参数仅支持字符串类型、数值类型和布尔类型等简单数据类型。而 JSON 类型的参数则支持更复杂的数据类型,如数组、对象等。
  4. 嵌套性
    param 类型的参数不支持嵌套。但是,JSON 类型的参数支持嵌套,可以传递更为复杂的数据结构。
    .
  5. 可读性
    param 类型的参数格式比 JSON 类型的参数更加简单、易读。但是,JSON 格式在传递嵌套数据结构时更加清晰易懂。
    .

总的来说,param 类型的参数适用于单一的数据传递,而 JSON 类型的参数则更适用于更复杂的数据结构传递。根据具体的业务需求,需要选择合适的参数类型。在实际开发中,常见的做法是:在 GET 请求中采用 param 类型的参数,而在 POST 请求中采用 JSON 类型的参数传递。
返回对象就是 json

SpringMVC 各种数据接收

简单类型接值

  • 客户端请求
    在这里插入图片描述

  • Hander 接收参数

  • 只要形参参数名和类型与传递的参数相同,即可自动接收!
  • 也可以不传递参数
@Controller
@RequestMapping("param")
public class ParamController {/*** 前端请求: http://localhost:8080/param/value?name=xx&age=18** 可以利用形参列表,直接接收前端传递的param参数!*    要求: 参数名 = 形参名*          类型相同* 出现乱码正常,json接收具体解决!!* @return 返回前端数据*/@GetMapping(value="/value")@ResponseBodypublic String setupForm(String name,int age){System.out.println("name = " + name + ", age = " + age);return name + age;}
}

简单类型接值【形参和请求参数不一致】

  • 指定绑定的请求参数名:@RequestParam(value="指定请求参数名") 【形参名和请求参数名一致可以省略】
  • 要求请求参数必须传递:required = false【前端是否必须传递此此参数,默认是必须,不传报400异常】
  • 为请求参数提供默认值: defaultValue = "1"【当非必须传递的时候, 可以设置默认值】)
  • 浏览器请求
    在这里插入图片描述

  • handler 接收参数

public class HelloController {//绑定请求参数为 myname 和 myage。myage 不必须传递。默认值为 0@RequestMapping(value = "/springmvc/hello")@ResponseBodypublic String hello(@RequestParam(value = "myname") String name, 		@RequestParam(value = "myage", required =false, defaultValue = "0") int age) {System.out.println("name:" + name + ",age:" + age);return name + ":" + age;}
}

数组类型接收

param 的 key 和 数组参数名一致就会接收

  • 客户端请求

在这里插入图片描述

  • handler 接收参数
@Controller
@RequestMapping("user")
public class testcontroller {@ResponseBody@RequestMapping//注意这里的 数组 参数名要和 param 的 key 一致public String test1(@RequestParam String[] names) {System.out.println(Arrays.toString(names));return Arrays.toString(names);}
}

集合类型接收

一个名字对应多个值

  • 多选框,提交的数据的时候一个key对应多个值,我们可以使用集合进行接收!集合用 @RequestParam 声明

注意param 的 key 要和集合名字一样

  • 客户端请求

在这里插入图片描述

  • handler 接收参数
@Controller
@RequestMapping("user")
public class testcontroller {@ResponseBody@RequestMapping//注意这里的 List 参数名要和 param 的 key 一致public String test1(@RequestParam List<String> names) {System.out.println(names);return names.toString();}}

实体类类型接收

要通过对象接收参数值,只需创建一个实体类,为每个属性配备 get 和 set 方法,客户端传递的 param key 要和 实体类的属性名一致。接收参数时,在形参列表中声明实体类对象即可。
.
如果是实体类对象的属性还是个对象那就用 address.provice 这样来做 param 的 key

注意点:实体类必须有 get 和 set

  • pojo
@Data
public class User {private int age;private String name;private Address address;
}
@Data
public class Address {private String province;private String city;}
  • 客户端

在这里插入图片描述

  • handler
@Controller
@RequestMapping("user")
public class testcontroller {@ResponseBody@RequestMappingpublic String test1(User user) {System.out.println(user);return user.toString();}}

日期参数接收

param 的 key 要和 日期类型的参数名一样。并且用 @DateTimeFormat 指定格式

  • 客户端
    在这里插入图片描述
  • handler
@Controller
@RequestMapping("user")
public class testcontroller {@ResponseBody@RequestMappingpublic String test1(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDate updateTime) {System.out.println(updateTime);return updateTime.toString();}}

路径参数接收

{} 声明的路径原理就是 *

动态路径参数http://localhost:8080/path/key/root 这里的 key/root 假如是动态路径。那它可以当参数传递给 handler

  • 接收动态路径参数必须要用 @PathVariable 声明
  • 如果 handler 形参名和路径的名字一样。那就直接 @PathVariable 就行。不一样就手动指定 @PathVariable 的 name
  • 客户端
    在这里插入图片描述

  • handler

@Controller
//这里 key 和 password 可以传递给下面的 handler
@RequestMapping("path/{key}/{password}")
public class testcontroller {@ResponseBody@RequestMappingpublic String //第一个参数因为形参名和路径名不一样所以要设置 name 参数test1(@PathVariable(name= "key") String mykey, @PathVariable String password) {System.out.println(mykey + ":" + password);return mykey + ":" + password;}}

JSON 参数接收

前端发送 JSON 数据时,Spring MVC 框架可通过 @RequestBody 注解将其转为 Java 对象。此注解表示方法参数值从请求体获取,Springboot 中直接添加该注解就行,无需额外操作,且不用指定 value 属性,它会自动映射到相应的参数上。

  • 第一步:导入 jackson 依赖
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.15.0</version>
</dependency>
  • 第二步:在配置类上添加 @EnableWebMvc注解
  • 不做一二步会报 415 错误,因为原生 java api 不支持 JSON
  • 这一步会自动加上 RequestMappingHandlerMappingRequestMappingHandlerAdapterioc 容器 并且给 RequestMappingHandlerAdapter 配置 json 转换器
@EnableWebMvc //给 handlerAdapter 配置了 json 转化器
@Configuration
@ComponentScan("com.atguigu.json")
public class MvcConfig {}
  • 第三步:给前端来的JSON存储的 POJO 类
@Data
public class Person {private String name;private int age;private String gender;}
  • 第四步:接收 JSON
@RequestMapping("/json")
@Controller
@ResponseBody
public class JsonController {//data -> 请求体 post {name,age,gender}//前端 传了一个 json 报 415//原因: java原生的api 只支持路径参数和 param 参数 不支持 json// json 本身就是前端的格式//解决: 1. 导入 json 处理的依赖 2.handlerAdapter 配置 json 转化器@PostMapping("data")public String data(@RequestBody Person person) {System.out.println("person = " + person);return person.toString();}
}

Cookie 数据接收

在这里插入图片描述

可以使用 @CookieValue 注解将 HTTP Cookie 的值绑定到的方法参数。

@Controller
@ResponseBody
@RequestMapping("/test")
public class testcontroller {@RequestMapping("/cooie")//形参名和 cookie  key 一样就不用给 @CookieValue 指定 namepublic String addPerson(@CookieValue String cookieName){System.out.println("value = " + cookieName);return cookieName;}//创建 Cookie@GetMapping("save")public String save(HttpServletResponse response) {Cookie cookie = new Cookie("cookieName", "root");response.addCookie(cookie);return "ok";}}

请求头信息接收

在这里插入图片描述

  • 第一种根据:参数接收

@RequestHeader("请求头的 key")

@GetMapping("/demo")
public void handle(@RequestHeader("Accept-Encoding") String encoding, @RequestHeader("Keep-Alive") long keepAlive) { ...
}
  • 第二种:根据形参名自动匹配
//获取 token
//这种是根据根据参数名自动匹配
@GetMapping("/demo")
public void handle(@RequestHeader String token) { }

原生 API 参数调用

直接在形参传就行

/*** 如果想要获取请求或者响应对象,或者会话等,可以直接在形参列表传入,并且不分先后顺序!* 注意: 接收原生对象,并不影响参数接收!*/
@GetMapping("api")
@ResponseBody
public String api(HttpSession session , HttpServletRequest request,HttpServletResponse response){String method = request.getMethod();System.out.println("method = " + method);return "api";
}

共享域对象操作

1. ServletContext 共享域:ServletContext 对象可以在整个 Web 应用程序中共享数据,是最大的共享域。一般可以用于保存整个 Web 应用程序的全局配置信息,以及所有用户都共享的数据。在 ServletContext 中保存的数据是线程安全的。
.
2. HttpSession 共享域:HttpSession 对象可以在同一用户发出的多个请求之间共享数据,但只能在同一个会话中使用。比如,可以将用户登录状态保存在 HttpSession 中,让用户在多个页面间保持登录状态。
.
3. HttpServletRequest 共享域:HttpServletRequest 对象可以在同一个请求的多个 handler 方法之间共享数据。比如,可以将请求的参数和属性存储在 HttpServletRequest 中,让处理器方法之间可以访问这些数据。

API功能
void setAttribute(String name,String value)向域对象中添加/修改数据
Object getAttribute(String name);从域对象中获取数据
removeAttribute(String name); 移除域对象中的数据

request 级别共享域

@RequestMapping("/attr/request/original")
@ResponseBody
// 拿到原生对象,就可以调用原生方法执行各种操作
public String testAttrOriginalRequest(HttpServletRequest request) {request.setAttribute("requestScopeMessageOriginal", "i am very happy[original]");return "target";
}

session 级别共享域

在这里插入图片描述
在这里插入图片描述

  • 获取 Session 对象:HttpSession session = req.getSession();
  • 获取 Session 的 ID:String jSessionId = session.getId();
  • 判断session是不是新创建的session: boolean isNew = session.isNew();
  • 向session对象中存入数据:session.setAttribute("username",username);
@RequestMapping("/attr/session")
@ResponseBody
public String testAttrSession(HttpSession session) {//直接对session对象操作,即对会话范围操作!return "target";
}

Application 级别共享地域

springmvc 会在初始化容器的时候,将 servletContext对象存储到 ioc 容器中!

/自动装配
@Autowired
private ServletContext servletContext;@RequestMapping("/attr/application")
@ResponseBody
public String attrApplication() {servletContext.setAttribute("appScopeMsg", "i am hungry...");return "target";
}
//使用 request 或者 seesion 获取public void data(HttpServletResponse response, HttpServletRequest request, HttpSession session) {//正常使用原生对象就可以ServletContext servletContext = request.getServletContext();ServletContext servletContext1 = session.getServletContext();}

SpringMVC 响应数据


开发模式介绍

在这里插入图片描述

  • 前后端不分离: controller 通过共享域对象,让动态页面从共享域取数据然后返回装配好的 html 文件。然后把 html 文件返回给浏览器

页面跳转

快速返回模板视图

  • 第一步:导入 jsp 依赖
<!-- jsp需要依赖! jstl-->
<dependency><groupId>jakarta.servlet.jsp.jstl</groupId><artifactId>jakarta.servlet.jsp.jstl-api</artifactId><version>3.0.0</version>
</dependency>
  • 第二步:创建 jsp 页面

建议位置:/WEB-INF/下,避免外部直接访问!
位置:/WEB-INF/views/home.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><title>Title</title></head><body><!-- 可以获取共享域的数据,动态展示! jsp== 后台vue -->${msg}</body>
</html>
  • 第三步:配置 jsp 视图解析器
@EnableWebMvc  //json数据处理,必须使用此注解,因为他会加入json处理器
@Configuration
@ComponentScan(basePackages = "com.atguigu.controller") //TODO: 进行controller扫描//WebMvcConfigurer springMvc进行组件配置的规范,配置组件,提供各种方法! 前期可以实现
public class SpringMvcConfig implements WebMvcConfigurer {//配置jsp对应的视图解析器@Overridepublic void configureViewResolvers(ViewResolverRegistry registry) {//registry 可以快速添加前后缀registry.jsp("/WEB-INF/views/",".jsp");}
}
  • 第五步:handler 返回视图
@Controller
@RequestMapping("jsp")
public class JspController {/*** 快速查找视图*  1.方法的返回值是字符串类型*  2.不能添加 @ResponseBody*  3.通过返回值拼接视图名称* @return*/@GetMapping("index")public String index(HttpServletRequest request) {//request 数据发送给 jsprequest.setAttribute("data", "hello");//和前后缀拼接return "index";}
}

请求转发和响应重定向

  • 将方法的返回值,设置String类型
  • 转发使用 forward关键字,重定向使用redirect关键字
  • 总之就是 fordwrad/redirect: /+路径
  • 注意:如果是项目下的资源,转发和重定向都一样都是项目下路径!都不需要添加项目根路径!

请求转发

在这里插入图片描述

  • 客户端只发送了一次请求, 客户端地址栏不变
  • 请求转发可以转发给WEB-INF下受保护的资源
  • 请求转发可以转发给其他Servlet动态资源,也可以转发给一些静态资源以实现页面跳转
@Controller
@RequestMapping("jsp")
public class JspController {@GetMapping("index")public String index(HttpServletRequest request) {//request 数据发送给 jsprequest.setAttribute("data", "hello");//和前后缀拼接return "index";}/*** 转发: 只能是项目下的资源* 	1.方法的返回值写成字符串* 	2.不能添加 responseBody 注解* 	3. 返回的字符串前 forward: /转发地址**/@GetMapping("forward")public String forward() {/* / 表示 http://localhost:8080/  jsp/index 表示要转发的地址*/return "forward:/jsp/index"}
}

响应重定向
在这里插入图片描述

  • 客户端至少发送了两次请求, 客户端地址栏是要变化的
  • 重定向可以是其他Servlet动态资源,也可以是一些静态资源以实现页面跳转
  • 重定向不可以到给WEB-INF下受保护的资源
@Controller
@RequestMapping("jsp")
public class JspController {@GetMapping("index")public String index(HttpServletRequest request) {//request 数据发送给 jsprequest.setAttribute("data", "hello");//和前后缀拼接return "index";}/*** 转发: 只能是项目下的资源* 	1.方法的返回值写成字符串* 	2.不能添加 responseBody 注解* 	3. 返回的字符串前 forward: /转发地址**/@GetMapping("redirect")public String redirect() {/* / 表示 http://localhost:8080/  jsp/index 表示要重定向的地址*/return "redirect:/jsp/index"}
}

返回 JSON 数据

基本使用

  • 导入 json 依赖
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.15.0</version>
</dependency>
  • 添加 @EnableWebMvc 注解
//TODO: SpringMVC对应组件的配置类 [声明SpringMVC需要的组件信息]@EnableWebMvc  //json数据处理,必须使用此注解,因为他会加入json处理器。还会自动导入 handlerMapping 和 handlerAdapter
@Configuration
@ComponentScan(basePackages = "com.atguigu.controller") //TODO: 进行controller扫描//WebMvcConfigurer springMvc进行组件配置的规范,配置组件,提供各种方法! 前期可以实现
public class SpringMvcConfig implements WebMvcConfigurer {}
  • 创建 pojo
@Data
public class User {private String name;private int age;}
  • 响应数据
@RequestMapping("json")
@RestController //@Controller + @ResponseBody
public class JsonController {@GetMapping("data2")public List<User> data1() {User user = new User();user.setName("two dogs!");user.setAge(3);List<User> users = new ArrayList<>();users.add(user);return users;}
}

@ResponseBody 注解

  • 方法上使用 @ResponseBody

在前后端分离项目里,@ResponseBody 注解加在方法上,它会把方法返回的对象序列化成 JSON 或 XML 格式的数据,直接发给客户端。这意味着返回值 不会走视图解析器渲染这一步,而是 直接作为数据响应。]

@RequestMapping(value = "/user/detail", method = RequestMethod.POST)
@ResponseBody
public User getUser(@RequestBody User userParam) {System.out.println("userParam = " + userParam);User user = new User();user.setAge(18);user.setName("John");//返回的对象,会使用jackson的序列化工具,转成json返回给前端!return user;
}
  • 类上使用 @ResponseBody

如果类中每个方法上都标记了 @ResponseBody 注解,那么这些注解就可以提取到类上。

@ResponseBody  //responseBody可以添加到类上,代表默认类中的所有方法都生效!
@Controller
@RequestMapping("param")
public class ParamController {

@RestController 注解

类上的 @RestponseBody 注解可以和 @Controller 注解合并为 @RestController 注解。所以使用了 @RestController 注解就相当于给类中的每个方法都加了 @ResponseBody 注解。

返回静态资源

资源本身已经是可以直接拿到浏览器上使用的程度了,不需要在服务器端做任何运算、处理。典型的静态资源包括:

  • 纯HTML文件
  • 图片
  • CSS文件
  • JavaScript文件
  • ……
  • 在 web 应用中加入静态资源
    在这里插入图片描述

  • 手动构建确保编译
    在这里插入图片描述
    在这里插入图片描述

  • 改造配置类

重写 configureDefaultServletHandling 开启经他i资源处理

@EnableWebMvc  //json数据处理,必须使用此注解,因为他会加入json处理器
@Configuration
@ComponentScan(basePackages = "com.atguigu.controller") //TODO: 进行controller扫描
//WebMvcConfigurer springMvc进行组件配置的规范,配置组件,提供各种方法! 前期可以实现
public class SpringMvcConfig implements WebMvcConfigurer {//配置jsp对应的视图解析器@Overridepublic void configureViewResolvers(ViewResolverRegistry registry) {//快速配置jsp模板语言对应的//这里是前缀和后缀。等下会把 controller 中发过来的字符串进行拼接访问registry.jsp("/WEB-INF/views/",".jsp");}//开启静态资源处理 <mvc:default-servlet-handler/>//dispatcherServlet -> handlerMMapping 找有没有对应的 handler(controller) -> 没有再去找 -> 有没有静态资源@Overridepublic void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {configurer.enable();}
}

RESTFul 风格设计规范


HTTP 协议请求方式要求

REST 风格主张在项目设计、开发过程中,具体的操作符合HTTP协议定义的请求方式的语义。

操作请求方式
查询操作GET
保存操作POST
删除操作DELETE
更新操作PUT

URL 风格要求

RESTful 风格的 API 设计里,URL 路径一般用名词命名,用来表示资源。资源可以是用户、订单这类实体,也能是搜索、计算等服务。设计 URL 路径时,强调用名词标识资源,而非用动词描述操作。比如,把/editEmp(动词)改成/Emp(名词) 。
.
例如:

  • GET /users:检索用户列表
  • POST /users:创建新用户
  • PUT /users/123:更新ID为123的用户
  • DELETE /users/123:删除ID为123的用户
操作传统风格REST 风格
保存/CRUD/saveEmp URL 地址:/CRUD/emp 请求方式:POST
删除/CRUD/removeEmp?empId=2 URL 地址:/CRUD/emp/2 请求方式:DELETE
更新/CRUD/updateEmp URL 地址:/CRUD/emp 请求方式:PUT
查询/CRUD/editEmp?empId=2URL 地址:/CRUD/emp/2 请求方式:GET

传递参数设计要求

  • 获取数据 GET ,删除数据 DELTETE

    • 参数是 id 标识。使用路径 方式 /url/id
    • 参数是 是 范围参数。使用 param 方式 /url?page=1&size=10
  • 保存数据 POST,修改数据 PUT

    • 全部使用请求体传递 JSON 方式

其他原则

  • 请求参数应该限制在 10 个以内,过多的请求参数可能导致接口难以维护和使用。
  • 对于敏感信息,最好使用 POST 采用请求体来传递参数。
  • 如果地址冲突 (请求方式 和 路径都一样) :那就在后面加个动词区分一下,比如 GET /user GET /user/search

实战举例

接口设计

功能接口和请求方式请求参数返回值
分页查询GET /userpage=1&size=10{ 响应数据 }
用户添加POST /user{ user 数据 }{响应数据}
用户详情GET /user/1路径参数{响应数据}
用户更新PUT /user{ user 更新数据}{响应数据}
用户删除DELETE /user/1路径参数{响应数据}
条件模糊GET /user/searchpage=1&size=10&keywork=关键字{响应数据}
  • 用户 pojo
package com.atguigu.pojo;/*** projectName: com.atguigu.pojo* 用户实体类*/
@Data
public class User {private Integer id;private String name;private Integer age;
}
  • controller
/*** projectName: com.atguigu.controller** description: 用户模块的控制器*/
@RequestMapping("user")
@RestController
public class UserController {/*** 模拟分页查询业务接口*/@GetMappingpublic Object queryPage(@RequestParam(name = "page",required = false,defaultValue = "1")int page,@RequestParam(name = "size",required = false,defaultValue = "10")int size){System.out.println("page = " + page + ", size = " + size);System.out.println("分页查询业务!");return "{'status':'ok'}";}/*** 模拟用户保存业务接口*/@PostMappingpublic Object saveUser(@RequestBody User user){System.out.println("user = " + user);System.out.println("用户保存业务!");return "{'status':'ok'}";}/*** 模拟用户详情业务接口*/@PostMapping("/{id}")public Object detailUser(@PathVariable Integer id){System.out.println("id = " + id);System.out.println("用户详情业务!");return "{'status':'ok'}";}/*** 模拟用户更新业务接口*/@PutMappingpublic Object updateUser(@RequestBody User user){System.out.println("user = " + user);System.out.println("用户更新业务!");return "{'status':'ok'}";}/*** 模拟条件分页查询业务接口*/@GetMapping("search")public Object queryPage(@RequestParam(name = "page",required = false,defaultValue = "1")int page,@RequestParam(name = "size",required = false,defaultValue = "10")int size,@RequestParam(name = "keyword",required= false)String keyword){System.out.println("page = " + page + ", size = " + size + ", keyword = " + keyword);System.out.println("条件分页查询业务!");return "{'status':'ok'}";}
}

SpringMVC 声明式全局异常处理


单独写一个异常类。发生异常就会走此类下的 handler 方法

  • ControllerAdvice: 走字符串拼接网址那一套。前后端不分离的
  • RestControllerAdvice:直接返回数据。不拼接。前后端分离

只要发生异常就进入这里寻找对应的异常处理,并且要注意在配置类扫描这个全局异常类

//全局异常发生会走此类下的 handler 方法
//@ControllerAdvice //可以返回逻辑视图 转发和重定向
@RestControllerAdvice 
public class GlobalExceptionHandler {//发生异常 -> 进入 @ControllerAdvice 注解的类型 -> 根据@ExceptionHandler(指定的异常) 去处理//指定的异常 可以精准查找 或者查找父异常@ExceptionHandler(ArithmeticException.class)public Object ArithmeticException(ArithmeticException e) {String message = e.getMessage();System.out.println("message = " + message);return message;}//如果没有 ArithmeticException 就走 Exception@ExceptionHandler(Exception.class)public Object Exception(Exception e) {String message = e.getMessage();System.out.println("message = " + message);return message;}}
 <!-- 扫描controller对应的包,将handler加入到ioc-->@ComponentScan(basePackages = {"com.atguigu.controller","com.atguigu.exceptionhandler"})

SpringMVC 拦截器


拦截器方法拦截位置

在这里插入图片描述

在这里插入图片描述

拦截器使用

在这里插入图片描述

就是自定义一个拦截器类实现 HandlerInterceptor ,然后配置类实现 WebMvcConfigurer 扫描拦截器类。配置拦截路径

  • 实现 HandlerInterceptor 实现其所有方法
    在这里插入图片描述
  • 配置类实现 WebMvcConfigurer 添加拦截器
@EnableWebMvc  //json数据处理,必须使用此注解,因为他会加入json处理器
@Configuration
@ComponentScan(basePackages = {"com.atguigu.controller","com.atguigu.exceptionhandler"}) 
public class SpringMvcConfig implements WebMvcConfigurer {//添加拦截器@Overridepublic void addInterceptors(InterceptorRegistry registry) {//配置方案1 拦截全部请求registry.addInterceptor(new MyInterceptor());//配置方案2 指定地址拦截// * 任意一层字符串 ** 任意多层字符串registry.addInterceptor(new MyInterceptor()).addPathPatterns("/user/data");//配置方案3 排除拦截 // addPathPatterns 需要拦截的路径// excludePathPatterns 需要拦截的路径中有哪些不拦截registry.addInterceptor(new MyInterceptor()).addPathPatterns("/user/**").excludePathPatterns("/user/data1");}
}

多个拦截器情况

  • 如果有多个拦截器,执行顺序
    • preHandle() 方法:SpringMVC 会把所有拦截器收集到一起,然后按照配置顺序调用各个 preHandle() 方法。
    • postHandle() 方法:SpringMVC 会把所有拦截器收集到一起,然后按照配置相反的顺序调用各个 postHandle() 方法。
    • afterCompletion() 方法:SpringMVC 会把所有拦截器收集到一起,然后按照配置相反的顺序调用各个 afterCompletion() 方法。

SpringMVC 参数校验


为什么使用参数校验

在这里插入图片描述

本来是要在 Service 写校验的。现在我们直接在 pojo 类加校验注解就行

校验注解详解

注解规则
@Null标注值必须为 null
@NotNull标注值不可为 null
@AssertTrue标注值必须为 true
@AssertFalse标注值必须为 false
@Min(value)标注值必须大于或等于 value
@Max(value)标注值必须小于或等于 value
@DecimalMin(value)标注值必须大于或等于 value
@DecimalMax(value)标注值必须小于或等于 value
@Size(max,min)标注值大小必须在 max 和 min 限定的范围内
@Digits(integer,fratction)标注值值必须是一个数字,且必须在可接受的范围内
@Past标注值只能用于日期型,且必须是过去的日期
@Future标注值只能用于日期型,且必须是将来的日期
@Pattern(value)标注值必须符合指定的正则表达式

JSR 303 只是一套标准,需要提供其实现才可以使用。Hibernate Validator 是 JSR 303 的一个参考实现,除支持所有标准的校验注解外,它还支持以下的扩展注解:

注解规则
@Email标注值必须是格式正确的 Email 地址
@Length标注值字符串大小必须在指定的范围内
@NotEmpty标注值字符串不能是空字符串
@Range标注值必须在指定的范围内

配置 @EnableWebMvc 后,SpringMVC 会默认装配好一个 LocalValidatorFactoryBean,通过在处理方法的入参上标注 @Validated 注解即可让 SpringMVC 在完成数据绑定后执行数据校验的工作。

参数校验使用

  • 第一步:导入依赖
<!-- 校验注解 -->
<dependency><groupId>jakarta.platform</groupId><artifactId>jakarta.jakartaee-web-api</artifactId><version>9.1.0</version><scope>provided</scope>
</dependency><!-- 校验注解实现-->        
<!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->
<dependency><groupId>org.hibernate.validator</groupId><artifactId>hibernate-validator</artifactId><version>8.0.0.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator-annotation-processor -->
<dependency><groupId>org.hibernate.validator</groupId><artifactId>hibernate-validator-annotation-processor</artifactId><version>8.0.0.Final</version>
</dependency>
  • POJO类
public class User {@NotNullprivate String name;@Emailprivate String email;@Size(min = 6, max = 20)private String password;// 省略 getter 和 setter
}
  • Controller 类
@RestController
public class UserController {//User 类用 JSR 303 注解校验属性。//UserController 的 addUser 方法加 @Validated 触发 User 对象校验,请求 /user 时,不符规则会返回错误信息。@PostMapping("/user")public String addUser(@Validated @RequestBody User user) {return "User added successfully";}
}

易混淆注解总结

@NotNull:

  • 适用于包装类型,若被标注字段的值为 null,校验失败并抛出异常。
  • 不能用于字符串类型的校验。
    .

@NotEmpty:

  • 可用于 CharSequence、Collection、Map 或数组对象类型的属性。对于其他类型的属性该注解无效
  • 校验规则:若属性为 null 或 size() 为 0,则校验失败。
  • 对于仅包含空格的字符串(中间有空格也算),不会认为是空字符串,校验不会失败。
    .

@NotBlank:

  • 专门用于字符串类型属性的校验。
  • 校验规则:若属性为 null、空字符串 “” 或仅含空格,则校验失败。
    .

在数据校验时,要根据具体情况选用合适的注解:

  • 包装类型且不能为 null 的,使用 @NotNull
  • 对于 CharSequence、Collection、Map 或数组,不能为 null 且 size() 不为 0 的,使用 @NotEmpty
  • 对于字符串不能为 null、空串或仅含空格的,使用 @NotBlank

相关文章:

SpringMVC复习笔记

文章目录 SpringMVC 概念和基本使用SpringMVC 简介SpringMVC 核心组件和调用流程SpringMVC 基本使用第一步&#xff1a;导入依赖第二步&#xff1a;Controller 层开发第三步&#xff1a;SpringMVC 配置类配置核心组件第四步&#xff1a;SpringMVC 环境搭建第五步&#xff1a;部…...

前端小案例——网页井字棋

前言&#xff1a;我们在学习完了HTML、CSS和JavaScript之后&#xff0c;就会想着使用这三个东西去做一些小案例&#xff0c;不过又没有什么好的案例让我们去练手&#xff0c;本篇文章就提供里一个案例——网页井字棋。 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可…...

ComfyUI-PromptOptimizer:文生图提示优化节点

ComfyUI-PromptOptimizer 是 ComfyUI 的一个自定义节点&#xff0c;旨在优化文本转图像模型的提示。它将用户输入的提示转换为更详细、更多样化、更生动的描述&#xff0c;使其更适合生成高质量的图像。无需本地模型。 1、功能 提示优化&#xff1a;优化用户输入的提示以生成…...

AudioGPT全新的 音频内容理解与生成系统

AudioGPT全新的 音频内容理解与生成系统 ChatGPT、GPT-4等大型语言模型 (LLM) 在语言理解、生成、交互和推理方面表现出的非凡能力,引起了学界和业界的极大关注,也让人们看到了LLM在构建通用人工智能 (AGI) 系统方面的潜力。 现有的GPT模型具有极高的语言生成能力,是目前最…...

thinkphp6 + redis实现大数据导出excel超时或内存溢出问题解决方案

redis下载安装&#xff08;window版本&#xff09; 参考地址&#xff1a;https://blog.csdn.net/Ci1693840306/article/details/144214215 php安装redis扩展 参考链接&#xff1a;https://blog.csdn.net/jianchenn/article/details/106144313 解决思路&#xff1a;&#xff0…...

Hexo + NexT + Github搭建个人博客

文章目录 一、 安装二、配置相关项NexT config更新主题主题样式本地实时预览常用命令 三、主题设置1.侧边栏2.页脚3.帖子发布字数统计 4.自定义自定义页面Hexo 的默认页面自定义 404 页自定义样式 5.杂项搜索服务 四、第三方插件NexT 自带插件评论系统阅读和访问人数统计 五、部…...

使用Sum计算Loss和解决梯度累积(Gradient Accumulation)的Bug

使用Sum计算Loss和解决梯度累积的Bug 学习 https://unsloth.ai/blog/gradient&#xff1a;Bugs in LLM Training - Gradient Accumulation Fix 这篇文章的记录。 在深度学习训练过程中&#xff0c;尤其是在大批量&#xff08;large batch&#xff09;训练中&#xff0c;如何高…...

基于本地消息表实现分布式事务

假设我们有一个电商系统,包含订单服务和库存服务。当用户下单时,需要在订单服务中创建订单,同时在库存服务中扣减库存。这是一个典型的分布式事务场景,我们需要保证这两个操作要么都成功,要么都失败,以保证数据的最终一致性。 项目结构: 订单服务(Order Service)库存服务(Inv…...

Web3与加密技术的结合:增强个人隐私保护的未来趋势

随着互联网的快速发展&#xff0c;个人隐私和数据安全问题越来越受到关注。Web3作为新一代互联网架构&#xff0c;凭借其去中心化的特性&#xff0c;为个人隐私保护提供了全新的解决方案。而加密技术则是Web3的重要组成部分&#xff0c;进一步增强了隐私保护的能力。本文将探讨…...

广播网络实验

1 实验内容 1、构建星性拓扑下的广播网络,实现hub各端口的数据广播,验证网络的连通性并测试网络效率 2、构建环形拓扑网络,验证该拓扑下结点广播会产生数据包环路 2 实验流程与结果分析 2.1 实验环境 ubuntu、mininet、xterm、wireshark、iperf 2.2 实验方案与结果分析…...

Vscode——SSH连接不上的一种解决办法

一、完整报错: > @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ > IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! > Someone could be eavesdropping on you right now (man-in-the...

ChatGPT大模型极简应用开发-目录

引言 要理解 ChatGPT&#xff0c;了解其背后的 Transformer 架构和 GPT 技术一路的演进则变得非常必要。 ChatGPT 背后的 LLM 技术使普通人能够通过自然语言完成过去只能由程序员通过编程语言实现的任务&#xff0c;这是一场巨大的变革。然而&#xff0c;人类通常容易高估技术…...

EI Scopus双检索 | 2025年第四届信息与通信工程国际会议(JCICE 2025)

会议简介 Brief Introduction 2025年第四届信息与通信工程国际会议(JCICE 2025) 会议时间&#xff1a;2025年7月25日-27日 召开地点&#xff1a;中国哈尔滨 大会官网&#xff1a;www.jcice.org 由黑龙江大学和成都信息工程大学主办&#xff0c;江苏科技大学协办的2025年第四届信…...

重学SpringBoot3-Spring Retry实践

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞??收藏评论 重学SpringBoot3-Spring Retry实践 1. 简介2. 环境准备3. 使用方式 3.1 注解方式 基础使用自定义重试策略失败恢复机制重试和失败恢复效果注意事项 3.2 编程式使用3.3 监听重试过程 监…...

TiDB 和 MySQL 的关系:这两者到底有什么不同和联系?

TiDB 和 MySQL 的关系&#xff1a;这两者到底有什么不同和联系&#xff1f; 在了解 TiDB 和 MySQL 之间的关系时&#xff0c;很多人可能会有疑问&#xff1a;这两个数据库到底有什么区别和联系&#xff1f;是不是 TiDB 就是 MySQL 的升级版&#xff1f;或者 TiDB 是一种“替代…...

【Java】JDK17的下载安装(与JDK1.8相互切换)

本文以参考以下链接为主&#xff1a;JDK17 如果上述操作不生效&#xff0c;请看以下操作&#xff1a; 添加以下变量并移动到最上面即可...

CSS3 3D 转换介绍

CSS3 中的 3D 转换提供了一种在二维屏幕上呈现三维效果的方式&#xff0c;主要包括translate3d、rotate3d、scale3d等转换函数&#xff0c;下面来详细介绍&#xff1a; 1. 3D 转换的基本概念 坐标系 在 CSS3 的 3D 空间中&#xff0c;使用的是右手坐标系。X 轴是水平方向&…...

Vue3 Element-Plus el-tree 右键菜单组件

参考代码&#xff1a;实现Vue3Element-Plus(tree、table)右键菜单组件 这篇文章的代码确实能用&#xff0c;但是存在错误&#xff0c;修正后的代码&#xff1a; <template><div style"text-align: right"><el-icon size"12" color"#…...

鸿蒙学习构建视图的基本语法(二)

一、层叠布局 // 图片 本地图片和在线图片 Image(https://developer.huawei.com/allianceCmsResource/resource/HUAWEI_Developer_VUE/images/080662.png) Entry Component//自适应伸缩 设置layoutWeight属性的子元素与兄弟元素 会按照权重进行分配主轴的空间// Position s…...

python-leetcode-存在重复元素 II

219. 存在重复元素 II - 力扣&#xff08;LeetCode&#xff09; class Solution:def containsNearbyDuplicate(self, nums: List[int], k: int) -> bool:seen set()for i, num in enumerate(nums):if num in seen:return Trueseen.add(num)if len(seen) > k:seen.remove…...

P6周:VGG-16算法-Pytorch实现人脸识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 我的环境 语言环境&#xff1a;Python 3.8.12 编译器&#xff1a;jupyter notebook 深度学习环境&#xff1a;torch 1.12.0cu113 一、前期准备 1.设置GPU im…...

BeanFactory 是什么?它与 ApplicationContext 有什么区别?

谈到Spring&#xff0c;那势必要讲讲容器 BeanFactory 和 ApplicationContext。 BeanFactory是什么&#xff1f; BeanFactory&#xff0c;其实就是 Spring 容器&#xff0c;用于管理和操作 Spring 容器中的 Bean。可能此时又有初学的小伙伴会问&#xff1a;Bean 是什么&#x…...

虚幻基础-1:cpu挑选(14600kf)

能帮到你的话&#xff0c;就给个赞吧 &#x1f618; 文章目录 ue非常吃cpu拉满主频打开项目编写蓝图运行原因 时间长 关于压力测试 本文以14600kf为例&#xff0c;双12购入&#xff0c;7月份产。 ue非常吃cpu 经本人测试&#xff0c;ue是非常吃cpu的。 拉满主频 无论任何时间…...

多种vue前端框架介绍

学如逆水行舟&#xff0c;不进则退。 在现今的软件开发领域&#xff0c;Vue.js凭借其高效、灵活和易于上手的特性&#xff0c;成为了前端开发的热门选择。对于需要快速搭建企业级后台管理系统的开发者而言&#xff0c;使用现成的Vue后台管理系统模板无疑是一个明智之举。 本文…...

jenkins-node节点配置

一.简述&#xff1a; Jenkins有一个很强大的功能&#xff1a; 即&#xff1a;支持分布式构建(jenkins配置中叫节点(node),也被称为slave)。分布式构建通常是用来吸收额外的负载。通过动态添加额外的机器应对构建作业中的高峰期&#xff0c;或在特定操作系统或环境运行特定的构建…...

计算机网络 (50)两类密码体制

前言 计算机网络中的两类密码体制主要包括对称密钥密码体制&#xff08;也称为私钥密码体制、对称密码体制&#xff09;和公钥密码体制&#xff08;也称为非对称密码体制、公开密钥加密技术&#xff09;。 一、对称密钥密码体制 定义&#xff1a; 对称密钥密码体制是一种传…...

基于SpringBoot+Vue旅游管理系统的设计和实现(源码+文档+部署讲解)

个人名片 &#x1f525; 源码获取 | 毕设定制| 商务合作&#xff1a;《个人名片》 ⛺️心若有所向往,何惧道阻且长 文章目录 个人名片环境需要技术栈功能介绍功能说明 环境需要 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 数据库&…...

计算机网络-概述

目录 一.互联网 1.0简介 1.1互联网发展的三个阶段 1.2互联网组成 1.2.1 简介 1.2.2 边缘部分 1.2.3 核心部分 1.3计算机网络类别 1.3.1按照范围分类 1.3.2按使用者分类 1.3.3用来把用户接入互联网的网络 1.4计算机网络性能 1. 速率&#xff08;Data Rate / Bit Ra…...

Jenkins-基于Role的鉴权机制

jenkins自带了一些全局性的安全配置。 但无法通过job等相对细粒度的来控制使用者的权限。但它可以借助相关的插件实现细颗粒的权限控制。 插件&#xff1a; Role-based Authorization Strategy 需要在configure global security中配置授权策略如下&#xff1a; 保存后&#x…...

计算机网络介质访问控制全攻略:从信道划分到协议详解!!!

一、信道划分介质访问控制 介质访问控制&#xff1a;多个节点共享同一个“总线型”广播信道时&#xff0c;可能发生“信号冲突” 应该怎么控制各节点对传输介质的访问&#xff0c;才能减少冲突&#xff0c;甚至避免冲突? 时分复用(TDM) 时分复用&#xff1a;将时间分为等长的“…...

在哪里做马可波罗网站/百度网页推广

点击上方 "大数据肌肉猿"关注, 星标一起成长点击下方链接&#xff0c;进入高质量学习交流群今日更新| 950个转型案例分享-大数据交流群本文分为两大节介绍&#xff0c;第一节是数仓建设&#xff0c;第二节是数据治理&#xff0c;内容较长&#xff0c;还请耐心阅读&am…...

做网站zwnet/it教育培训机构

定义&#xff1a;定义对象间一种一对多的依赖关系&#xff0c;使得当每一个对象改变状态&#xff0c;则所有依赖于它的对象都会得到通知并自动更新。类型&#xff1a;行为类模式类图&#xff1a;在软件系统中经常会有这样的需求&#xff1a;如果一个对象的状态发生改变&#xf…...

沧州做网站公司/腾讯广点通广告投放平台

在Windows上开发桌面应用程序最快的方式无疑是使用C#&#xff0c;前有WinForm现有WPF&#xff0c;都是很好的开发框架&#xff0c;不管是MFC还是QT总还是复杂了一些。但是C#有一个最最大的缺点&#xff0c;就是没办法避免反编译&#xff0c;虽然我也经常反编译别人程序&#xf…...

沧州网站制作网站/seo黑帽是什么

检查列表oracle版本信息A&#xff0e;操作说明&#xff1a;检查当前所有已安装的数据库产品的版本信息&#xff1a; oracle7 至 8.0&#xff1a;cd $ORACLE_HOME/orainst./inspdveroracle 8i 或更高:cd $ORACLE_HOME/installcat unix.rgsB&#xff0e;输出结果&#xff1a;检…...

怎样用记事本做网站/搜索引擎广告图片

从零开始用 Flask 搭建一个网站&#xff08;二&#xff09; 从零开始用 Flask 搭建一个网站&#xff08;一&#xff09; 介绍了如何搭建 Python 环境&#xff0c;以及 Flask 应用基本项目结构。我们要搭建的网站是管理第三方集成的控制台&#xff0c;类似于 Slack。 本篇主要讲…...

国外做问卷网站/搜索引擎优化简历

分区是将数据分布在多个Redis实例&#xff08;Redis主机&#xff09;上&#xff0c;以至于每个实例只包含一部分数据。 1、分区的意义 性能的提升&#xff1a;单机Redis的网络I/O能力和计算资源是有限的&#xff0c;将请求分散到多台机器&#xff0c;充分利用多台机器的计算能…...