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

从请求到响应:初探spring web

引入:

首先小编想分享下一些开发小知识

2000年——手写servlet/JSP时代

在这个阶段中,那时候写后端代码,可谓是个麻烦事。

毕竟什么都要自己干

发来的请求都要写extends HttpServlet的类,手动在web.xml配置

<servlet>、<servlet-mapping>……

JDBC连接、SQL、事务都得自己写,配置全靠XML。

产生的痛点可太多了,比如xml配置多、代码臃肿、模块耦合高。

JSP:全称JavaServer Pages(Java服务端页面),它是基于Java的动态网页技术,允许开发者在HTML页面中嵌入Java代码,用于生成动态内容。

2004——Spring FrameWork1.0诞生

此时的框架,引入很多东西,比如

IOC(控制反转):Bean的创建、依赖由Spring容器负责,代码里不在到处new

DI(依赖注入):可以用XML、注解(@Atutowired)声明依赖

AOP(面向切面):用来做事务,日志,权限等横切逻辑

模块化:把核心容器拆成spring-core、spring-beans、spring-context、spring-app、spring-tx、spring-jdbc……

这些东西进入进来后,起到了配置简化的作用,至少有了统一的对象管理和切面支持。

2005——spring web mvc :基于servlet的web框架

引入DispatcherServlet:接收所有的请求并分发

注解驱动:后续版本支持@Controller、@RequestMapping,彻底替代web.xml中<servlet>映射.

视图解析:整合JSP、FreeMarker、Velocity、Thymeleaf等多种模板。

数据绑定/校验:支持@RequestParam、@ModelAttribute、@valid等注解

2006——2013:Spring 生态快速扩张

Spring Security:全面安全框架。

Spring Data:简化JPA、MonggoDB、Redis、Elasticsearch等数据访问。

Spring Integration / Batch / AMQP:消息、批处理、集成解决方案。

Spring Cloud:进一步演化,提供微服务的配置中心,注册中心,断路器、网关等

引入了这么多,但还是有痛点:因为还需要每次都要大量配置XML或JavaConfig,项目的脚手架都要自己搭建。

脚手架:是一个用于快速创建和搭建项目基础结构的工具或模板。

脚手架工具,目前来说也有是比较多的

比如 Spring Boot Initializr、Yeoman、JHipster……

 2014——Spring Boot 1.0:开箱即用,约定优于配置

自动配置:根据classpath下依赖和定义好的”条件“自动装配Bean,绝大部分配置”不用写“

starters:一组起步依赖,比如spring-boot-starter-web(包含SpringMVC、Jackson、Tomcat),

spring-boot-starter-data-jpa。

内嵌容器:默认内嵌Tomcat(可选Jetty、Undertow),打成可执行Jar,运维更简单

外部配置:统一使用application.properties / application.yml,支持Profile

Actuator:一组监控 / 健康检查断点,自动暴露/actuator/heath、/metrics

2016——目前:Spring Boot 2.x/3.x 支持微服务和云原生

Spring Boot 2.x:升级到5.x,支持Reactive WebFlux,Kotlin

Spring Boot 3.x:基于Spring Framework6.x,要求Java17、JakartaEE9

SPring Cloud:与Boot紧密集成,Netfilx OSS,Consul、Nacos、Gateway、Sleuth/Zipkin/Brave分布式链路追踪

CLI / DevTools:命令行工具、热重载,开发体验进一步提示。

那么对于以上这些呢,算是小编分享基于Spring开发的时间线。

对于讲到Spring而言

它本质上就是个容器,它里面存储有很多核心组件,这些核心组件负责各自的内容。

MVC:

它是Model View Controller的缩写,它是软件工程中的一种软件架构设计模式

它把软件系统分为模型、视图和控制器三个基本部分:

既然MVCVC是一种架构设计模式,那么人人也是可以实现它的,所以SpringMVC就是实现了它

除此之外,SpringMVC还是个web框架。

SpringMVC 结合了自身的特点,做出了些改变,不过整体还是以Model——View——Controller为基准的

这幅图或许是更加形象些:

刚刚分享到时间线中,提到注解

所以接下来小编分享下SpringMVC的注解吧

注解学习:

跟注解名字相像的,还有一个叫注释的

注释:

注释是写给程序员看的文字,不会被编译器或程序执行的,是起到解释说明作用

作用:

1.帮助别人或自己理解代码

2.暂时屏蔽部分代码

3.提供文档说明

注解:

注解是写给编译器或运行时看的结构化信息,它是一种元数据,用来对代码进行标记,指示行为,甚至自动生成代码。

作用:

1.在编译、类加载、运行时被读取,用来执行特定逻辑

2.框架大量依赖注解来完成”自动配置“和控制反转

元数据

元数据是”描述数据的数据“,它本身不是一个业务数据,而是用来描述、标记、解释其他数据的信息

看起来比较抽象,那么可以举个这样的例子

在现实生活中,你拍了一张照片,照片内容是一个风景图(这个就是一份数据)

当然这个文件中,还有很多内在信息:

  • 拍摄时间
  • 拍摄地点
  • 使用设备
  • 分辨率

……

这些信息呢,就是元数据

在代码中呢,元数据就是来描述代码的”额外信息“,比如

  • 一个类是干啥的
  • 一个类是否重写了父类
  • 一个字段是否需要注入

………………

这类信息不是程序主要逻辑,但是框架/工具/编译器会看这些注解来”做事”。

其实注解,我们开始学习Java语法基础的时候,也是接触过的

比如:

Java
@Override
public String toString() {
    return "Hello!";
}

这个注解@Override就是注解,它是表示对父类方法的重写,编译器会检查方法签名是否是正确

那么注解也是有类型的。

注解类型:

一.运行时注解

这种注解,编译完后,不仅是存在于.class文件中,程序运行的时候还可以通过反射读取到

特点:

  • 必须用@Retention(RetentionPolicy RUNTIME)中声明
  • 运行时用反射去拿到它的内容
  • 常用于Spring、Mybatis、Junit框架做自动处理

二.编译期注解

这种注解,只会在编译阶段有用,比如校验、生成代码,或者 抛出编译错误;但是运行时是看不到的

特点:

  • 用@Retention(RetentionPolicy SOURCE)或者@Retention(RetentionPolicy CLASS)声明
  • 靠Annotation Processor(注解处理器),在编译阶段扫描处理
  • 常用于Lombok、MapStruct、AutoValue等这类工具

注解还有生效类型,它有Retention策略来决定:

类型

用法

是否可以通过反射获取

举例

SOURCE

只存在于源码中,编译时丢弃

Lombok(自动生成代码)

CLASS

编译后存在于class文件中,但运行后不保存

常用于框架预编译扫描

RUNTIME

编译后保留,并且运行时可反射获取

Spring、Junit中常见注解

接下来我们来看看SpringMVC中,有哪些注解吧

一:RestController、RequestMapping

RequestMapping这个注解是用来处理请求映射路径的,

可以用来类上,此时称为父路径,可以用在方法上,此时称为子路径

注意:如若没有加上路径中,没有加上/,那么RequestMapping会自动帮我们加上

常用属性:

属性

说明

示例

value / path

请求路径

@RequestMapping("/login")

method

HTTP方法

RequestMethod.GET,POST,PUT,DELETE

params

请求参数过滤

params="id=10"

headers

请求头过滤

headers="ContentType=application/json"

对于RestController而言,这个是复合注解,由@Controller+@ResposeBody而成

Controller注解:


它是用来标识一个类是控制器,当前端请求发送来后,这个类的方法就会接收并处理这些请求

它通常用来返回页面视图

比如:

Java
@Controller
public class PageController {
    @RequestMapping("/loginPage")
    public String loginPage() {
        return "login.html"; // 实际跳转到 login.html
    }
}

ResponseBody注解

这个注解就是把方法返回值直接写到HTTP响应体,不会再找视图页面,进行返回

常用于返回JSON、字符串等数据

比如:

Java
@Controller
public class ApiController {
    @RequestMapping("/api/hello")
    @ResponseBody
    public String sayHello() {
        return "Hello, JSON!";
    }
}

所以对于RestController注解而言,它标注在类上,表示这个类是一个REST风格的控制器,方法返回的是JSON或XML,而不是跳转页面。

REST风格控制器

它是一种软件架构风格,强调资源的唯一标识和标准HTTP方法(GET、PUT、DEPETE、POST等操作)

所以基于这两个注解,我们就可以写上一小段代码:

Java
@RestController
@RequestMapping("/user")
public class helloController {
    @RequestMapping(value = "/v1",method = RequestMethod.POST)
    public String v1(){
        return "first response";
    }
    @RequestMapping("/v2")
    public String v2(){
        return "first response";
    }
  }

此时我们运行程序后,访问http:127.0.0.1:8080/user/v2

结果:

值得注意的是RequestMapping中,是默认支持get和post请求的,所以在v1中我这样写,意思是仅支持post请求

当然,此时我们要是觉得写RequestMapping里面的参数太长,代码还可以这样写:

Java
@GetMapping("/v3")
public String v3(){
    return "V3 first response";
}
@PostMapping("v4")
public String v4(){
    return "v4 first response";
}

这两个注解,其实就是代表仅支持GET和POST请求

此时,我们还可以发现个问题,如若我们每次测试代码返回结果,都要浏览器输入的话,那么岂不是很麻烦?

所以,小编后面就会使用构造http请求的软件,这里小编使用的是Postman,文章后面会附上如何下载

刚刚讲到的代码是无参数的,接下来分享是有参数的

单个参数:

typescript
@RequestMapping("/param")
@RestController
public class ParamController {
    @RequestMapping("/p1")
    public String name(String name){
        return "接收到参数:"+ name;
    }
}

通过postman构造请求,返回结果:

要值得注意的是,参数名字要一一对应

多个参数:

Java
//注意父路径与单个参数代码一致
@RequestMapping("/p4")
public String p4(String name,Integer age){
    return "name:"+name+" "+"age:"+age;
}

构造请求,返回结果:

对象形式:

首先编写一个对象:

Java
public class User {
    private Integer age;
    private String name;
    private String gender;
  }

然后通过idea生成的setter/getter/toString方法,这里就省略了。

Java
@RequestMapping("/p5")
public String p5(User user){
    return "user"+user;
}

构造请求,返回结果:

为什么传输对象可以得到正确数据呢?

这是因为在Springboot中,使用@RequestMapping接收参数时,如果是一个自定义对象,Spring会自动进行参数绑定,将http请求中的查询参数或表单数据映射到对象的属性上。

二.@RequestParam

刚刚说到我们请求过来的参数是要一致的,那么这是不是必须的呢?

当然不是,前端传过来的参数和方法中的参数是可以不一致的,此时,就使用RequestParam注解这个注解用于从

http请求参数中获取值的,就类似于参数重命名.

参数重命名

比如:

Java
@RequestMapping("/p7")
public String p7(@RequestParam("username")
                     String name,@RequestParam(value = "userAge",required = false) Integer age){
    return "name:"+name+" "+"age:"+age;
}

构造请求返回结果:

那么可以看到username与代码中的name是对应,userAge和代码中的age是一一对应。

这个RequesParam注解也是可以设置参数的,此时呢,我在代码中写required=f=alse,这个是说明这个age参数不是必传的,而name参数中,没有设置,那么它就是默认为true它就是要必传的,还有,如若这个注解中,什么参数都没有,此时就可以默认为前端传来的参数和方法中的参数是一致的。

此时,使用这个参数后,我们还可以传输数组内容了

Java
//传输数组:
@RequestMapping("/p8")
public String p8(@RequestParam("userArr") String [] arr){
    return "数组:"+ List.of(arr);
}

构造请求返回结果:

当然,数据还可以这样传输:

传递集合类:

Java
@RequestMapping("/p9")
public String p9(@RequestParam List<Integer> list){
    return "list:"+list;
}

构造请求返回结果:

传递json对象:


此时前端传递json对象,使用的注解,就是RequestBody,这个在一开始讲到,这里就不做解释

Java
@RequestMapping("/p10")
public String p10(@RequestBody User user){
    return "user:"+user;
}

构造请求返回结果

三.@PathVariable

这个注解是将URL路径中的一部分变量映射到方法参数上

代码:

Java
//获取url中参数
@RequestMapping("/article/{articleId}")
public String p11(@PathVariable String articleId){
    return "articleID:"+articleId;
}

构造请求返回结果

获取多个参数:

Java
//获取多个url参数
@RequestMapping("article/{articleID}/{articleName}")
public String p12(@PathVariable("articleID") Integer id,
                  @PathVariable("articleName") String name){
    return "id:" +id+" "+
            "name:"+name;
}

构造请求返回结果:

当然,我们也可以发现这个注解也是可以参数重命名了,同时我们还得注意的是,参数类型要传输正确,比如

id是Integer,name是String,如若反过来传输,就会出现以下错误:

四.@RequestPart

这个注解是用于从multipart/form-data类型的请求中获取请求的一部分,通常用于上传文件+其他字段的组合场景

typescript
//获取上传文件参数
@RequestMapping("/p13")
public String p13(@RequestPart("file2") MultipartFile upFile) throws IOException {
    //这里就是获取到file2的名字,这就是原始名字
  String name=upFile.getOriginalFilename();
  //这里是获取上传文件的名字
  String ret=upFile.getName();
  //这个是保存到磁盘中某个目录
    upFile.transferTo(new File("E:/视频/" + upFile.getOriginalFilename()));
  return "ret:"+ret;
}

此时呢,一般是要和搭配一个类进行,使用,这个类是MultipartFile

这个是Spring提供的一个接口,用来处理文件上传的内容

当前端以multipart/form-data方式去提交表单(或者使用FromData)上传文件的时候,Spring会自动将文件封装为

MultipartFile对象,交给控制器处理

它有一些常见方法:

方法名

作用方法

getOriginalFilename()

获取原始文件名

getContentType()

获取文件MIME类型(如image/png)

getSize()

获取文件大小

getInputStream()

获取输入流,可用于保存到磁盘

getBytes()

获取文件的字节数组

transferTO(File dest)

将文件直接保存到目标位置

构造请求返回结果

五.操作请求头

学习前面的一些请求头后,那么可以对请求头中一些参数进行操作了,比如cookie ,session

cookie:

cookie是存储在客户端(通常是浏览器)上的小数据片段,每个cookie都有一个名称,值以及一些可选的属性

如过期时间、路径、域等

作用:

  • 存储用户的偏好设置(例如语言,主题等)
  • 跟踪用户的活动
  • 维持登录状态,通过在客户端保存会话ID或令牌s

特点:

  • 客户端存储,可以被用户查看和修改
  • 每次请求都会自动发送到服务器(符合path和domain条件)
  • 可以设置HttpOnly标记来防止JavaScript访问,提高安全性
  • 有大小限制(通常为4kb)

Session:

session是一种服务端机制,用来跟踪用户状态。当用户访问网站时,服务器会生成一个唯一的会话ID,并将

其存储在服务器上。通常这个Cookie传递给客户端,以便后续请求能够识别用户

  • 作用:
    存储敏感信息,这些数据是保存在服务器,不会暴露在客户端
  • 管理会话状态,如用户登录后的行为,购物车内容等

特点:

  • 数据存储在服务器端,更加安全
  • 不直接向客户端暴露具体数据内容,仅通过会话ID关联
  • 生命周期可以与用户的交互挂钩,也可以设定固定的超时时间

举个例子:

当用户进行首次登录的时候,服务器收到请求,创建一个SessionID,并通过Cookie返回到客户端中

在后续的请求中,浏览器将自动包含SessionID发送到服务器中,服务器根据这个ID恢复用户的会话状态。

那么先来讲讲这个cookie吧

代码:

typescript
@RestController
@RequestMapping("/header")
public class HeaderController {
    //使用原生api获取cookie值
    @RequestMapping("/getcookie")
    public String getCookie(HttpServletRequest request){
    //得到cookie,那么就要用cookie类型的数组存储内容
        Cookie[] cookies = request.getCookies();
        if(cookies==null){
            return "cookie为null!";
        }
        for(Cookie cookie:cookies){
            System.out.println(cookie.getName()+" :"+cookie.getValue());
        }
        return "cookie获取成功!";
    }
  }

这个HttpServletRequest 是Java Web开发常用接口,简单而言他代表的是客户端发来的请求

而且也比较万能,因为它可以得到请求中的很多信息

比如请求方式,请求路径,请求参数,请求头,cookie,session……

请求:

不要慌张!我们通过chrome浏览器来设置cookie即可

首先点击:

然后:

再刷新:

服务器中也得到结果:

此时如若出现,chrome浏览器无法把cookie带过去,那么可以使用以下命令回车:

document.cookie = "key=value; path=/; domain=127.0.0.1; SameSite=None; Secure";

在控制台输入

当然,这个获取cookie内容,不止可以使用原生api,还可以使用注解:

这个注解就是:@CookieValue

该注解自动帮你从请求里的cookie中,按照名字,拿出某个值,直接注入你的方法参数中

代码:

typescript
//使用注解获取cookie中某个值
@RequestMapping("/getcookie2")
public String getCookie2(@CookieValue("java") String ret){
    return "获取到cookie:" +ret;
}

结果是差不多,这里不做结果展示。

接下来,讲下session

首先分享的是如何设置session:
代码:

typescript
//设置session值通过原生api
@RequestMapping("/SetSession")
public String setSession(HttpServletRequest request){
    //这里是会解析请求中是否带有sessionId,不带有就生成一个空session
    //顺带生成一个sessionID
    HttpSession session = request.getSession();
    //setAttribute:设置属性
    session.setAttribute("userName","张三");
    session.setAttribute("age",18);
    return "session设置成功!";
}

生成后,此时呢我们就可以去得到session了

代码:

typescript
//通过原生api去得到session值
@RequestMapping("getSession")
public String getSession(HttpServletRequest request){
    //可以设置getSession(false),此时就不会设置sessionID
    HttpSession session = request.getSession();
    //注意session一定不为空,因为判断为空就会立即生成一个sessionID
    String userName=(String) session.getAttribute("userName");
    Integer userAge=(Integer) session.getAttribute("age");

    if(userAge==null && userName==null){
        return "session为null,请先设置!";
    }
    return "从session获取到信息:"+userName+" "+userAge;
}

此时我们访问SetSession路径:

可以观察到,下面的cookie中,是带有了sessionID了

访问getSession,就可以获得结果:

当然,获取的方法也不是只有这一个,还可以通过HttpSesstion 来获取

代码:

Java
//通过httpsession获取session值
@RequestMapping("/getSession2")
public String getSession2(HttpSession request){
    String userName=(String) request.getAttribute("userName");
    Integer age=(Integer) request.getAttribute("age");
    return "获取到的session值:"+userName+" "+age;
}

甚至还可以通过注解来获得:

Java
//通过注解获得session值
@RequestMapping("/getSession3")
public String getSession3(@SessionAttribute("userName") String name){
    return "获取到session值:"+name;
}

六.操作响应内容

之前大多讲解的是请求的内容,接下来看看是如何操作这个响应内容的。

1.返回视图(比如网页)


用到的注解是controller,这个注解在上面讲过了,所以就不做过多讲解

typescript
@Controller
@RequestMapping("response")
public class ResponseController {
    //服务端返回响应
    @RequestMapping("/returnHtml")
    public String returnHtmlContext(){
        //此时返回的是页面
        return "/Welcome.html";
    }
 }

此时返回视图的话,那么就是通过Controller注解,而不是RestController

此时,我们Welcome.html是在项目resource/static目录下

访问内容:

此时它为什么可以直接展示出网页内容,大致流程如下:

浏览器请求/response/returnHtml

Controller返回字符串“Welome.html”

SpringMVC的视图解析器会拿到这个字符串,去找该/Welcome.html这个资源

找到了,就会把该/Welcome.html的内容渲染成HTTP响应,浏览器自然就会拿到内容。

2.返回内容:


此时呢,使用了Controller后,返回的是视图了,那么我就是要返回内容呢?

可以使用这个ResponseBody,这个注解,前面也是讲过,就不做过多解释

代码:

Java
//此时返回的内容被浏览器自动解析为html
@ResponseBody
@RequestMapping("returnData")
//此时返回的是内容
public String returnHtml(){
    return "htmlDemo";
}

请求返回结果:

值得注意的是,返回的字符串内容会被浏览器自动解析为html内容

如何查看?

刷新页面:

然后点击这个后,会出现以下页面:

这里的text/html说明了,浏览器把该内容解析为这样的类型。

当然返回内容,也是可以返回为html格式内容:

Java
return "<h1>welcome</h1>";

此时呢,网页会按照返回内容,进行一级标题渲染。

当然,对于这个ResponseBody来说,它还可以返回json内容

json:

它是一种轻量级的数据交换格式,易于人类阅读和编写,同时也是易于机器解析和生成。

基本语法:

  • 数据以键/值对的方式存储,例如"name":"John"
  • 键必须是字符串,使用双括号括起来,值可以是字符串、数字、对象、数组、布尔值或者null
  • 对象使用花括号{}括起来,数组用方括号[]括起来

代码:

Java
//返回Json值
@RequestMapping("returnJson")
@ResponseBody
//返回对象的时候,浏览器会自动解析为Json
public User returnJson(){
    User user=new User();
    user.setName("张三");
    user.setAge(18);
    return user;
}

此时,它是以对象形式返回,那么spring mvc消息转换器会自动把它转换为Json格式

postman构造请求返回结果:

此时可以看到返回内容为JSON格式内容了

那么字符串也是可以返回为JSON格式的

代码:

Java
//返回解析类型
@ResponseBody
@RequestMapping(value = "/setType",produces = "application/Json")
public String returnType(){
//双引号内容带有"",需要转义
    return "{\"success\":true }";
}

通过设置produces参数,就可以返回想要格式,同样的想返回JSON,那么就写成application/json,就可以了。

构造请求返回结果

请求头有HttpServletRequest,那么响应头中,也有HttpServletResponse,这个也是原生的API,可以说是万能的。它同样可以设置/得到响应头的内容,比如状态码、cookie……

那么举个例子,设置状态码

Java
@ResponseBody
@RequestMapping("/returnStatus")
public User returnStatus(HttpServletResponse response){
    User user=new User();
    user.setAge(18);
    user.setName("李四");
    response.setStatus(404);
    return user;
}

构造请求,返回结果

同样的,可以看到即使的得到结果了,也是返回404,这是因为我们手动设置了。

ok,对于springmvc中,一些常见的注解,就分享到这里。

postman下载

postman是一个流行的API开发工具,简化了构建、测试和文档化RESTful APIs的过程,对于开发人员还是测试人员等等,它都可以提高工作效率。

它功能,可是有很多的,比如

发送请求、环境和变量管理、自动化测试、监控、Mock Server、文档生成功能、团队协作、安全性测试……

这是它的下载地址:

https://www.postman.com/downloads/

下载后,它是一个压缩包,然后找个地方解压,运行即可。

接下来介绍一下,基本使用。

简单使用

首先打开后,可能会让你进行注册登录,那么你就按照提示进行注册登录即可

在构建请求区域中,有这些选项,小编这里简单解释下:

1.Param

Params这一行指的是“Query Params”部分,它允许你在发送HTTP请求时添加查询参数。具体来说:

  • Key:这是参数的名称,用来标识这个参数代表什么信息。
  • Value:这是与Key对应的值,表示该参数的具体内容。

2.body

Body 标签页用于定义请求体的内容,这对于 POST, PUT, PATCH 等需要发送数据到服务器的请求非常重要。它支持多种格式的数据输入:

  • form-data:用于模拟HTML表单提交,通常用于上传文件或发送键值对数据。
  • x-www-form-urlencoded:与form-data类似,但是不支持文件上传。适合发送简单的键值对数据。
  • raw:允许你手动输入请求体内容。支持多种格式,如JSON、XML、Text、JavaScript等。当你需要发送结构化的数据(如JSON对象)时非常有用。
  • binary:用于上传任意类型的文件。例如,上传图片、视频或其他二进制文件。

3.Headers

Headers 标签页让你可以为你的请求添加自定义头部信息。这可以包括认证令牌(如Bearer Token)、内容类型(Content-Type)、接受类型(Accept)以及其他任何你想要传递给服务器的元数据。

4.Authorization

Authorization 标签页提供了一个简单的方式来设置请求的授权方法。你可以选择不同的授权类型,如No Auth, Basic Auth, Bearer Token, OAuth 1.0, OAuth 2.0等,并根据所选类型填写相应的凭证。

5.Script

这个标签允许你在发送请求之前执行一段脚本。这可以用来设置环境变量、发送额外的HTTP请求或者做任何你需要在请求前完成的事情。例如,生成一个动态的时间戳并将其存储在一个变量中,以便在请求体中使用。

6.Setting

虽然不是直接参与构建请求的部分,但Settings选项提供了配置Postman行为的方式,比如SSL证书验证、代理设置等

但是还有一个值得注意的是,像前面所说的上传文件中

你要是觉得英文版,不太好用,那么这里提供国产同类型产品,功能强大,界面友好

下载地址:https://apifox.com/

对于spring mvc注解的分享,小编就分享到这里

相关文章:

从请求到响应:初探spring web

引入&#xff1a; 首先小编想分享下一些开发小知识 2000年——手写servlet/JSP时代 在这个阶段中&#xff0c;那时候写后端代码&#xff0c;可谓是个麻烦事。 毕竟什么都要自己干 发来的请求都要写extends HttpServlet的类&#xff0c;手动在web.xml配置 <servlet>…...

【中间件】bthread_基础_TaskControl

TaskControl 1 Definition2 Introduce**核心职责** 3 成员解析**3.1 数据结构与线程管理****3.2 任务调度与负载均衡****3.3 线程停放与唤醒&#xff08;ParkingLot&#xff09;****3.4 统计与监控** 4 **工作流程**5 **设计亮点**6 **使用场景示例**7 **总结**8 学习过程中的疑…...

systemd和OpenSSH

1 systemd 1.1 配置文件 /etc/systemd/system /lib/systemd/system /run/systemd/system /usr/lib/systemd/user 1.2 commands systemctl list-unit-files | grep enable systemctl cat dlt-daemon.service systemctl cat dlt-system.service systemctl show dlt-daemon.ser…...

08 Python集合:数据 “去重神器” 和运算魔法

文章目录 一、Python 中的集合概述1. 集合的特性 二、集合的创建三、元素的遍历四、集合的运算1. 成员运算2. 二元运算3. 比较运算 五、集合的方法六、不可变集合 一、Python 中的集合概述 在 Python 里&#xff0c;集合&#xff08;Set&#xff09;是一种无序且元素唯一的数据…...

配置和使用基本存储

配置和使用基本存储 文章目录 配置和使用基本存储[toc]一、什么是卷&#xff1f;二、卷的类型三、使用EmptyDir卷存储数据1.了解EmptyDir卷2.测试EmptyDir卷的使用 四、使用HostPath卷挂载宿主机文件1.了解HostPath卷2.测试HostPath卷的使用 五、使用NFS卷挂载NFS共享目录1.准备…...

win11 终端 安装ffmpeg 使用终端Scoop

1、安装scoop (Windows 包管理器) Set-ExecutionPolicy RemoteSigned -Scope CurrentUser iwr -useb get.scoop.sh | iex 2、使用scoop来安装ffmpeg scoop install ffmpeg 3、测试一下ffmpeg&#xff0c;将Mp3文件转为Wav文件 ffmpeg -i A.mp3 A.wav 然后我们就看到A.wav生成…...

navicat中导出数据表结构并在word更改为三线表(适用于navicat导不出doc)

SELECTCOLUMN_NAME 列名,COLUMN_TYPE 数据类型,DATA_TYPE 字段类型,IS_NULLABLE 是否为空,COLUMN_DEFAULT 默认值,COLUMN_COMMENT 备注 FROMINFORMATION_SCHEMA.COLUMNS WHEREtable_schema db_animal&#xff08;数据库名&#xff09; AND table_name activity&#xff08;…...

Azure Monitor 实战指南:全方位监控应用与基础设施

Azure Monitor 是 Azure 云原生的统一监控解决方案,能够实时追踪应用性能、基础设施健康状态及日志数据。本文将通过 实战步骤 演示如何利用 Azure Monitor 监控 GPT-4 服务、虚拟机、存储等资源,并结合自动化告警和日志分析,构建企业级监控体系。 1. Azure Monitor 核心功能…...

【人工智能】释放本地AI潜能:LM Studio用户脚本自动化DeepSeek的实战指南

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 随着大型语言模型(LLM)的快速发展,DeepSeek以其高效的性能和开源特性成为开发者关注的焦点。LM Studio作为一款强大的本地AI模型管理工具…...

智能体-CyberTask Orchestrator设计概要(V4.1超长版)

智能体-CyberTask Orchestrator设计概要&#xff08;V4.0超长版&#xff09; 一、深度演进背景与战略定位&#xff08;核心篇幅拓展至2187字&#xff09; &#xff08;本段新增行业趋势与技术必要性论证&#xff09; 1.1 全球网络安全威胁态势分析&#xff08;2023-2025&…...

C# 面向对象实例演示

C# 面向对象编程实例演示 一、基础概念回顾 面向对象编程(OOP)的四大基本特性&#xff1a; ​​封装​​ - 将数据和操作数据的方法绑定在一起​​继承​​ - 创建新类时重用现有类的属性和方法​​多态​​ - 同一操作作用于不同对象产生不同结果​​抽象​​ - 简化复杂系…...

软件产品测试报告:如何全面评估及保障软件质量?

软件产品测试报告可以对软件产品质量做全面评估&#xff0c;还能够把评估结果展示出来&#xff0c;它依靠一系列测试手段和数据分析&#xff0c;能为产品的完善以及决策提供重要依据。下面从不同方面展开说明。 测试目的 开展本次软件产品测试&#xff0c;主要目的有三个。一…...

leetcode42-接雨水

leetcode 42 思路 本题使用 单调栈 来计算每个位置能够接住的雨水量 理解问题 题目要求计算一系列柱子之间可以接住的雨水量。输入是一个数组&#xff0c;每个元素代表柱子的高度。输出是一个整数&#xff0c;表示能够接住的水量。 找到边界条件 什么情况下可以接住雨水…...

普通IT的股票交易成长史--20250430晚

声明&#xff1a;本文章的内容只是自己学习的总结&#xff0c;不构成投资建议。文中观点基本来自yt站Andylee&#xff0c;美股Alpha姐&#xff0c;综合自己的观点得出。感谢他们的无私分享。 送给自己的话&#xff1a; 仓位就是生命&#xff0c;绝对不能满仓&#xff01;&…...

Elastic Security 8.18 和 9.0 中的新功能

作者&#xff1a;来自 Elastic Mark Settle, Tamarian Del Conte, James Spiteri, Tinsae Erkailo, Charles Davison, Raquel Tabuyo, Kseniia Ignatovych, Paul Ewing, Smriti 检测规则的自动迁移、用于 ES|QL 的 Lookup Join、AI 功能增强&#xff0c;以及更多功能。 Elasti…...

使用 Vue 开发 VS Code 插件前端页面(上)

本文的方案主要参考了这篇博客&#xff1a; Vscode 的 extension webview 开发示例&#xff1a; Vue 和 React 实现 https://juejin.cn/post/7325132202970136585样例项目地址&#xff1a; github | vscode-webview-with-vuehttps://github.com/HiMeditator/vscode-webview-w…...

Vue Router路由原理

Vue Router 是 Vue.js 官方的路由管理器&#xff0c;它与 Vue.js 核心深度集成&#xff0c;使得构建单页应用&#xff08;SPA&#xff09;变得非常容易。Vue Router 的主要功能包括动态路由匹配、嵌套路由、编程式导航、命名路由、路由守卫等 Vue Router 原理 单页应用&#x…...

Tauri v1 与 v2 配置对比

本文档对比 Tauri v1 和 v2 版本的配置结构和内容差异&#xff0c;帮助开发者了解版本变更并进行迁移。 配置结构变化 v1 配置结构 {"package": { ... },"tauri": { "allowlist": { ... },"bundle": { ... },"security":…...

详解 MyBatis-Plus 框架中 QueryWrapper 类

QueryWrapper 一、 QueryWrapper 的概念为什么需要 QueryWrapper&#xff1f; 二、 QueryWrapper 的基本使用1. 创建 QueryWrapper 实例2. 添加查询条件3. 执行查询 三、 QueryWrapper 的常见方法1. 基本条件方法1.1 eq - 等于1.2 ne - 不等于1.3 gt - 大于1.4 ge - 大于等于1.…...

小米MiMo-7B大模型:解锁推理潜力的新传奇!

在大语言模型&#xff08;LLMs&#xff09;蓬勃发展的时代&#xff0c;推理能力成为衡量模型优劣的关键指标。今天为大家解读的这篇论文&#xff0c;介绍了小米的MiMo-7B模型&#xff0c;它通过独特的预训练和后训练优化&#xff0c;展现出强大的推理实力&#xff0c;快来一探究…...

联邦学习的收敛性分析(全设备参与,不同本地训练轮次)

联邦学习的收敛性分析 在联邦学习中,我们的目标是分析全局模型的收敛性,考虑设备异构性(不同用户的本地训练轮次不同)和数据异质性(用户数据分布不均匀)。以下推导从全局模型更新开始,逐步引入假设并推导期望损失的递减关系,最终给出收敛性结论。 1. 全局模型更新与泰…...

硬件工程师面试常见问题(10)

第四十六问&#xff1a;锁存器&#xff0c;触发器&#xff0c;寄存器三者的区别 触发器&#xff1a;能够存储一位二值信号的基本单元电路统称为 "触发器"。&#xff08;单位&#xff09; 锁存器&#xff1a;一位触发器只能传送或存储一位数据&#xff0c;而在实际工…...

1295. 统计位数为偶数的数字

题目 解法一 遍历数组挨个判断元素位数并统计&#xff08;我的第一想法&#xff09; class Solution { public:int findNumbers(vector<int>& nums) {int result 0;for(int n: nums){if(judge(n)) result;}return result;}bool judge(int a){int sum 1;a a / 10…...

3.1/Q1,Charls最新文章解读

文章题目&#xff1a;Social participation patterns and associations with subsequent cognitive function in older adults with cognitive impairment: a latent class analysis DOI&#xff1a;10.3389/fmed.2025.1493359 中文标题&#xff1a;认知障碍老年人的社会参与模…...

楼宇智能化四章【期末复习】

四、火灾自动报警系统 结构组成:火灾探测器、区域报警器、集中报警器 形式:1. 多线制系统 2.总线制系统 3.集中智能系统 4.分布智能系统 5.网络通信系统 工作原理: 以下是关于火灾自动报警系统及相关灭火系统的详细解答: 1. 火灾自动报警系统有哪几种形式? 区…...

Splunk 使用Role 实现数据隔离

很多人知道 Splunk 有很多自带的Role, 今天我就要说说定制化的Role: 1: 在创建新role 的界面: 2: 在如下的界面,可以定制allow index name: 3: 创建好新Role 后,在SAML 添加新的group 的时候,就可以看到Role 给某个group: 4: 这样一个特定组的人来申请Splunk 权限,就可…...

Learning vtkjs之ImplicitBoolean

隐式函数布尔操作 介绍 vtkImplicitBoolean 允许对隐式函数&#xff08;如平面、球体、圆柱体和盒子&#xff09;进行布尔组合。操作包括并集、交集和差集。可以指定多个隐式函数&#xff08;所有函数都使用相同的操作进行组合&#xff09;。 支持的操作&#xff1a;‘UNION…...

LabelVision - yolo可视化标注工具

LabelVision是一款可视化图像标注工具,主要用于计算机视觉研究中的各种标注任务。 支持多边形、矩形、圆形等多种标注方式&#xff0c;并且可以输出JSON、COCO等多种数据格式&#xff0c;方便与其他软件和框架进行集成和互操作。 ‌ 通过它可以很轻易的对图像进行标注,适合Y…...

系统分析师-第十五章

学习目标 通过参加考试&#xff0c;训练学习能力&#xff0c;而非单纯以拿证为目的。 1.在复习过程中&#xff0c;训练快速阅读能力、掌握三遍读书法、运用番茄工作法。 2.从底层逻辑角度理解知识点&#xff0c;避免死记硬背。 3.通过考试验证学习效果。 学习阶段 快速阅读 …...

大连理工大学选修课——机器学习笔记(3):KNN原理及应用

KNN原理及应用 机器学习方法的分类 基于概率统计的方法 K-近邻&#xff08;KNN&#xff09;贝叶斯模型最小均值距离最大熵模型条件随机场&#xff08;CRF&#xff09;隐马尔可夫模型&#xff08;HMM&#xff09; 基于判别式的方法 决策树&#xff08;DT&#xff09;感知机…...

09 Python字典揭秘:数据的高效存储

文章目录 一.字典是什么1.字典的特点 二.字典的创建和使用三.字典的操作1.访问元素2.修改元素3.删除元素4.遍历字典5.成员运算 四.字典方法1.获取字典中的指定元素2.获取字典中的元素3.字典合并4.删除元素 一.字典是什么 在 Python 中&#xff0c;字典&#xff08;dict&#x…...

20250430在ubuntu14.04.6系统上完成编译NanoPi NEO开发板的FriendlyCore系统【严重不推荐,属于没苦硬吃】

【开始编译SDK之前需要更新源】 rootrootubuntu:~/friendlywrt-h3$ sudo apt update 【这两个目录你在ubuntu14.04.6系统上貌似git clone异常了】 Y:\friendlywrt-h3\out\wireguard Y:\friendlywrt-h3\kernel\exfat-nofuse 【需要单线程编译文件系统&#xff0c;原因不明】 Y:…...

第五部分:进阶项目实战

在前面的学习中&#xff0c;我们已经掌握了图像和视频的基础操作、增强滤波、特征提取以及一些基础的目标检测方法。现在&#xff0c;我们将综合运用这些知识来构建一些更复杂、更实用的应用项目。 这一部分的项目将结合前面学到的技术&#xff0c;并介绍一些新的概念和工具&a…...

【Linux】记录一个有用PS1

PS1 是用来定义shell提示符的环境变量 下面是一个带有颜色和丰富信息的 Linux PS1 配置示例&#xff0c;包含用户名、主机名、路径、时间、Git 分支和退出状态提示&#xff1a; # 添加到 ~/.bashrc 文件末尾 PS1\[\e[1;32m\]\u\[\e[m\] # 绿色粗体用户名 PS…...

【SpringBoot】基于mybatisPlus的博客管理系统(2)

目录 1.实现用户登录 Jwt令牌 1.引入依赖 2.生成令牌&#xff08;token&#xff09; Controller Service Mapper 2.实现强制登录 定义拦截器&#xff1a; 配置拦截器&#xff1a; 1.实现用户登录 在之前的项目登录中&#xff0c;我使用的是Session传递用户信息实现校验…...

免费在Colab运行Qwen3-0.6B——轻量高性能实战

Qwen一直在默默地接连推出新模型。 每个模型都配备了如此强大的功能和高度量化的规模,让人无法忽视。 继今年的QvQ、Qwen2.5-VL和Qwen2.5-Omni之后,Qwen团队现在发布了他们最新的模型系列——Qwen3。 这次他们不是发布一个而是发布了八个不同的模型——参数范围从6亿到235…...

精益数据分析(35/26):SaaS商业模式关键指标解析

精益数据分析&#xff08;35/26&#xff09;&#xff1a;SaaS商业模式关键指标解析 在创业与数据分析的征程中&#xff0c;我们持续探索不同商业模式的运营奥秘。今天&#xff0c;我们带着共同进步的期望&#xff0c;深入研读《精益数据分析》&#xff0c;聚焦SaaS商业模式&am…...

【论文速读】《Scaling Scaling Laws with Board Games》

论文链接&#xff1a;https://arxiv.org/pdf/2104.03113 《Scaling Scaling Laws with Board Games》&#xff1a;探索棋盘游戏中的扩展规律 摘要 如今&#xff0c;机器学习领域中规模最大的实验所需的资源&#xff0c;超出了仅有几家机构的预算。幸运的是&#xff0c;最近的…...

C++ 与多技术融合的深度实践:从 AI 到硬件的全栈协同

在数字化技术高速发展的今天&#xff0c;C 凭借其卓越的性能优势和底层控制能力&#xff0c;成为连接上层应用与底层硬件的核心纽带。这种独特定位使其在与 AI 深度学习、Python 生态及硬件加速技术的融合中展现出不可替代的价值&#xff0c;构建起从算法实现到硬件优化的全栈技…...

AdaBoost算法的原理及Python实现

一、概述 AdaBoost&#xff08;Adaptive Boosting&#xff0c;自适应提升&#xff09;是一种迭代式的集成学习算法&#xff0c;通过不断调整样本权重&#xff0c;提升弱学习器性能&#xff0c;最终集成为一个强学习器。它继承了 Boosting 的基本思想和关键机制&#xff0c;但在…...

无刷马达驱动芯片算法逐步革新着风扇灯行业--其利天下

风扇灯市场热度持续攀升&#xff0c;根据行业数据&#xff0c;风扇灯市场规模从2010年的100亿元增长至2019年的200亿元&#xff0c;年均复合增长率超10%&#xff0c;预计2025年将达30%&#xff0c;借此其利天下有限公司进一步提升了无刷风扇灯驱动方案。 一、性能参数 电压&a…...

数据库系统综合应用与深度实践指南

前言 在当今数据驱动的时代&#xff0c;数据库技术已成为信息系统的核心支柱。从简单的数据存储到复杂的企业级应用&#xff0c;数据库系统支撑着现代社会的方方面面。本文作为一篇综合性的数据库科普文章&#xff0c;旨在为读者提供从基础到进阶的完整知识体系&#xff0c;涵…...

「Unity3D」TextMeshPro使用TMP_InputField实现,输入框高度自动扩展与收缩

先看实现效果&#xff1a; 要实现这个效果&#xff0c;有三个方面的问题需要解决&#xff1a; 第一&#xff0c;输入框的高度扩展&#xff0c;内部子元素会随着锚点&#xff0c;拉伸变形——要解决这个问题&#xff0c;需要将内部元素改变父类&#xff0c;然后增加父类高度&am…...

SAP-ABAP:在SAP系统中,COEP表(成本控制对象行项目表)详解

在SAP系统中&#xff0c;**COEP表&#xff08;成本控制对象行项目表&#xff09;**是成本控制&#xff08;CO&#xff09;模块的核心数据表之一&#xff0c;主要用于存储与成本核算相关的详细行项目数据。以下是对其作用的详细解析&#xff1a; 一、 COEP表的核心作用 存储成本…...

crashpad 编译

一环境配置 1.1设置系统UTF8编码 1.2vs2017语言环境设置英文包 二.获取depot_tools&#xff08;此步骤可以跳过 最新工具包已上传下载使用即可&#xff09; windows下载压缩包&#xff0c;然后放到系统PATH中 下载完以后&#xff0c;基本就是靠depot_tools这个工具集合了&am…...

Windows系统安装Docker(Win10系统升级,然后安装)

有时需要在自己笔记本跑下代码&#xff0c;所以安装Dockers&#xff0c;步骤如下&#xff1a; 1. 升级系统&#xff08;Windows10专业版或者Windows11&#xff09; Windows10家庭版装Docker较麻烦&#xff0c;所以我将Win10升级为Win11了&#xff08;免费&#xff09;&#x…...

【Fifty Project - D21】

今日完成记录 TimePlan完成情况9&#xff1a;00 - 10&#xff1a;00爬楼梯√12&#xff1a;00 - 14&#xff1a;00Leetcode√14&#xff1a;00 - 15&#xff1a;00《挪威的森林》√ Leetcode 每日一题 今天的每日一题是个easy&#xff1a;给定一个数组&#xff0c;要求统计…...

中央网信办部署开展“清朗·整治AI技术滥用”专项行动

为规范AI服务和应用&#xff0c;促进行业健康有序发展&#xff0c;保障公民合法权益&#xff0c;近日&#xff0c;中央网信办印发通知&#xff0c;在全国范围内部署开展为期3个月的“清朗整治AI技术滥用”专项行动。 中央网信办有关负责人表示&#xff0c;本次专项行动分两个阶…...

《Python实战进阶》 No46:CPython的GIL与多线程优化

Python实战进阶 No46&#xff1a;CPython的GIL与多线程优化 摘要 全局解释器锁&#xff08;GIL&#xff09;是CPython的核心机制&#xff0c;它保证了线程安全却限制了多核性能。本节通过concurrent.futures、C扩展优化和多进程架构&#xff0c;实战演示如何突破GIL限制&#…...

BOTA新六维力传感器PixONE:用12维度力矩与运动感测,驱动人形机器人力控未来

在机器人技术日益发展的今天&#xff0c;六维力传感器对于提升机器人感知环境、增强操作精度发挥着重要作用。瑞士BOTA Systems是一家专注于机器人传感器技术的公司&#xff0c;致力于为原始设备制造商提供高性能的传感器解决方案。 PixONE是BOTA推出的一款创新的高精度传感器&…...