Spring Web MVC

ops/2024/11/17 8:51:57/

Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架,从⼀开始就包含在 Spring 框架中。

它的正式名称“Spring Web MVC”来⾃其源模块的名称(Spring-webmvc),但它通常被称为"Spring

MVC".

Servlet 是⼀种实现动态⻚⾯的技术. 准确来讲Servlet是⼀套 Java Web 开发的规范,或者说是⼀套
Java Web 开发的技术标准. 只有规范并不能做任何事情,必须要有⼈去实现它. 所谓实现 Servlet 规范,就是真正编写代码去实现 Servlet 规范提到的各种功能,包括类、⽅法、属性等.
Servlet 规范是开放的,除了 Sun 公司,其它公司也可以实现 Servlet 规范,⽬前常⻅的实现了
Servlet 规范的产品包括 Tomcat、Weblogic、Jetty、Jboss、WebSphere 等,它们都被称
为"Servlet 容器". Servlet 容器⽤来管理程序员编写的 Servlet 类.

MVC

MVC 是 Model View Controller 的缩写,它是软件⼯程中的⼀种软件架构设计模式,它把软件系统分为模型、视图和控制器三个基本部分

View(视图) 指在应⽤程序中专⻔⽤来与浏览器进⾏交互,展⽰数据的资源.

Model(模型) 是应⽤程序的主体部分,⽤来处理程序中数据逻辑的部分.

Controller(控制器)可以理解为⼀个分发器,⽤来决定对于视图发来的请求,需要⽤哪⼀个模型

来处理,以及处理完后需要跳回到哪⼀个视图。即⽤来连接视图和模型

---------------------------------------------------------------------------------------------------------------------------------

什么是Spring MVC

Spring MVC 是⼀个实现了 MVC 模式的 Web 框架

Spring Boot 只是实现Spring MVC的其中⼀种⽅式⽽已.

Spring Boot 可以添加很多依赖, 借助这些依赖实现不同的功能. Spring Boot 通过添加Spring Web

MVC框架, 来实现web功能

不过Spring在实现MVC时, 也结合⾃⾝项⽬的特点, 做了⼀些改变

---------------------------------------------------------------------------------------------------------------------------------

学习Spring MVC

既然是 Web 框架, 那么当⽤⼾在浏览器中输⼊了 url 之后,我们的 Spring MVC 项⽬就可以感知到⽤⼾的请求, 并给予响应.

咱们学习Spring MVC, 重点也就是学习如何通过浏览器和⽤⼾程序进⾏交互.

主要分以下三个⽅⾯:

1. 建⽴连接:将⽤⼾(浏览器)和 Java 程序连接起来,也就是访问⼀个地址能够调⽤到我们的

Spring 程序。

2. 请求: ⽤⼾请求的时候会带⼀些参数,在程序中要想办法获取到参数, 所以请求这块主要是 获取参数

的功能.

3. 响应: 执⾏了业务逻辑之后,要把程序执⾏的结果返回给⽤⼾, 也就是响应

建⽴连接

@RequestMapping 注解介绍

@RequestMapping 是 Spring Web MVC 应⽤程序中最常被⽤到的注解之⼀,它是⽤来注册接⼝的

路由映射的.

表⽰服务收到请求时, 路径为 /sayHi 的请求就会调⽤ sayHi 这个⽅法的代码.

路由映射: 当⽤⼾访问⼀个 URL 时, 将⽤⼾的请求对应到程序中某个类的某个⽅法的过程就叫路由映射

⼀个项⽬中, 会有很多类, 每个类可能有很多的⽅法, Spring程序怎么知道要执⾏哪个⽅法呢?
Spring会对所有的类进⾏扫描, 如果类加了注解@RestController, Spring才会去看这个类⾥⾯的⽅法
@RequestMapping 既可修饰类,也可以修饰⽅法 ,当修饰类和⽅法时,访问的地址是类路径 + ⽅法路径.
@RequestMapping标识⼀个类:设置映射请求的请求路径的初始信息
@RequestMapping标识⼀个⽅法:设置映射请求请求路径的具体信息
@RequestMapping("/user")
@RestController
public class UserController {@RequestMapping("/sayHi")public String sayHi(){return "hello,Spring MVC";}
}
访问地址: http://127.0.0.1:8080/user/sayHi
注意:
@RequestMapping 的URL 路径最前⾯加不加 / (斜杠)都可以, Spring程序启动时, 会进⾏判断, 如果前⾯没有加 / , Spring会拼接上⼀个 /
---------------------------------------------------------------------------------------------------------------------------------

请求

传递单个参数

接收单个参数, 在 Spring MVC 中直接⽤⽅法中的参数就可以,⽐如以下代码:

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/param")
public class ParamController {@RequestMapping("/m1")public String method1(String name){return "接收到参数name:"+ name;}
}

可以看到, 后端程序正确拿到了name参数的值.

Spring MVC 会根据⽅法的参数名, 找到对应的参数, 赋值给⽅法

如果参数不⼀致, 是获取不到参数的.

⽐如请求URL: http://127.0.0.1:8080/param/m1?name1=spring

响应结果

注意事项

使⽤基本类型来接收参数时, 参数必须传(除boolean类型), 否则会报500错误

类型不匹配时, 会报400错误

@RequestMapping("/m1/int")
public Object method1GetInt(int age){return "接收到参数age:" + age;
}

1. 正常传递参数

http://127.0.0.1:8080/param/m1/int?age=1

浏览器响应情况:

2. 不传递age参数

http://127.0.0.1:8080/param/m1/int

浏览器响应情况:

3. 传递参数类型不匹配

http://127.0.0.1:8080/param/m1/int?age=abc

浏览器响应情况:

对于包装类型, 如果不传对应参数,Spring 接收到的数据则为null

所以企业开发中,对于参数可能为空的数据,建议使⽤包装类型

---------------------------------------------------------------------------------------------------------------------------------

传递多个参数

和接收单个参数⼀样, 直接使⽤⽅法的参数接收即可. 使⽤多个形参

@RequestMapping("/m2")
public Object method2(String name, String password) {
return "接收到参数name:" + name + ", password:" + password;
}

使⽤浏览器发送请求并传参: http://127.0.0.1:8080/param/m2?name=zhangsan&password=123456

当有多个参数时,前后端进⾏参数匹配时,是以参数的名称进⾏匹配的,因此参数的位置是不影响后端获取参数的结果.

---------------------------------------------------------------------------------------------------------------------------------

传递对象

如果参数⽐较多时, ⽅法声明就需要有很多形参. 并且后续每次新增⼀个参数, 也需要修改⽅法声明.

我们不妨把这些参数封装为⼀个对象.

Spring MVC 也可以⾃动实现对象参数的赋值,⽐如 Person 对象:

public class Person {private int id;private String name;private String password;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}@Overridepublic String toString() {return "Person{" +"id=" + id +", name='" + name + '\'' +", password='" + password + '\'' +'}';}
}

传递对象代码实现:

@RequestMapping("/m3")
public Object method3(Person p){return p.toString();
}

可以看到, 后端程序正确拿到了Person对象⾥各个属性的值

Spring 会根据参数名称⾃动绑定到对象的各个属性上, 如果某个属性未传递, 则赋值为null(基本类型则赋值为默认初识值, ⽐如int类型的属性, 会被赋值为0)

---------------------------------------------------------------------------------------------------------------------------------

后端参数重命名(后端参数映射)

某些特殊的情况下,前端传递的参数 key 和我们后端接收的 key 可以不⼀致,⽐如前端传递了⼀个time 给后端,⽽后端是使⽤ createtime 字段来接收的,这样就会出现参数接收不到的情况,如果出现这种情况,我们就可以使⽤ @RequestParam 来重命名前后端的参数值.

具体⽰例如下,后端实现代码:

@RequestMapping("/m4")
public Object method_4(@RequestParam("time") String createtime) {return "接收到参数createtime:" + createtime;
}

1. 使⽤ @RequestParam 进⾏参数重命名时, 请求参数只能和 @RequestParam 声明的名称⼀

致, 才能进⾏参数绑定和赋值.

2. 使⽤ @RequestParam 进⾏参数重命名时, 参数就变成了必传参数.

⾮必传参数设置
@RequestMapping("/m4")
public Object method4(@RequestParam(value = "time", required = false) String 
createtime) {return "接收到参数createtime:" + createtime;
}

---------------------------------------------------------------------------------------------------------------------------------

传递数组

@RequestMapping("/m5")
public String method5(String[] arrayParam) {return Arrays.toString(arrayParam);
}
使⽤浏览器发送请求并传参:
数组参数:请求参数名与形参数组名称相同且请求参数为多个, 后端定义数组类型形参即可接收参数
http://127.0.0.1:8080/param/m5?
arrayParam=zhangsan&arrayParam=lisi&arrayParam=wangwu
或者使⽤ http://127.0.0.1:8080/param/m6?listParam=zhangsan%2clisi%2cwangwu
或者使⽤ http://127.0.0.1:8080/param/m5?arrayParam=zhangsan,lisi,wangwu
---------------------------------------------------------------------------------------------------------------------------------

传递集合

集合参数:和数组类似, 同⼀个请求参数名有为多个, 且需要使⽤ @RequestParam 绑定参数关系

默认情况下,请求中参数名相同的多个值,是封装到数组. 如果要封装到集合,要使⽤

@RequestParam 绑定参数关系

请求⽅式和数组类似:

浏览器传参:

⽅式⼀: http://127.0.0.1:8080/param/m6?listParam=zhangsan&listParam=lisi&listParam=wangwu

⽅式⼆: http://127.0.0.1:8080/param/m6?listParam=zhangsan%2clisi%2cwangwu

%2c 是逗号的转义编码, 解码后的url为: http://127.0.0.1:8080/param/m6?

listParam=zhangsan,lisi,wangwu

后端接收代码:

@RequestMapping("/m6")
public String method6(@RequestParam List<String> listParam){return "size:"+listParam.size() + ",listParam:"+listParam;
}

---------------------------------------------------------------------------------------------------------------------------------

传递JSON数据

JSON概念

JSON:JavaScript Object Notation 【JavaScript 对象表⽰法】

就是⼀种数据格式, 有⾃⼰的格式和语法, 使⽤⽂本表⽰⼀个对象或数组的信息, 因此
JSON本质是字符串. 主要负责在不同的语⾔中数据传递和交换.
JSON语法

JSON的语法:

1. 数据在 键值对(Key/Value)

2. 数据由逗号 "," 分隔

3. 对象⽤ "{}" 表⽰

4. 数组⽤ "[]" 表⽰

5. 值可以为对象, 也可以为数组, 数组中可以包含多个对象

JSON的两种结构

1. 对象: ⼤括号 {} 保存的对象是⼀个⽆序的 键值对 集合. ⼀个对象以左括号 { 开始, 右括号 }

结束。每个"键"后跟⼀个冒号 : ,键值对使⽤逗号 , 分隔

2. 数组: 中括号 [] 保存的数组是值(value)的有序集合. ⼀个数组以左中括号 [ 开始, 右中括

] 结束,值之间使⽤逗号 , 分隔。

JSON字符串和Java对象互转
package com.example.demo;import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;public class JsonTest {public static void main(String[] args) throws JsonProcessingException {ObjectMapper objectMapper = new ObjectMapper();User user = new User();user.setAge(18);user.setName("chen");user.setGender(1);//对象 -> JsonString s = objectMapper.writeValueAsString(user);System.out.println(s);//Json -> 对象User user1 = objectMapper.readValue(s, User.class);System.out.println(user1);}
}
JSON优点

1. 简单易⽤: 语法简单,易于理解和编写,可以快速地进⾏数据交换

2. 跨平台⽀持: JSON可以被多种编程语⾔解析和⽣成, 可以在不同的平台和语⾔之间进⾏数据交换和传输

3. 轻量级: 相较于XML格式, JSON数据格式更加轻量级, 传输数据时占⽤带宽较⼩, 可以提⾼数据传输速度

4. 易于扩展: JSON的数据结构灵活,⽀持嵌套对象和数组等复杂的数据结构,便于扩展和使⽤

5. 安全性: JSON数据格式是⼀种纯⽂本格式,不包含可执⾏代码, 不会执⾏恶意代码,因此具有较⾼的安全性

传递JSON对象

接收JSON对象, 需要使⽤ @RequestBody 注解

RequestBody: 请求正⽂,意思是这个注解作⽤在请求正⽂的数据绑定,请求参数必须在写在请求正⽂中

@RequestMapping(value = "/m7")
public Object method7(@RequestBody Person person) {
return person.toString();
}

---------------------------------------------------------------------------------------------------------------------------------

获取URL中参数@PathVariable

path variable: 路径变量

和字⾯表达的意思⼀样, 这个注解主要作⽤在请求URL路径上的数据绑定

默认传递参数写在URL上,SpringMVC就可以获取到

后端实现代码:

@RequestMapping("/m8/{id}/{name}")
public String method8(@PathVariable Integer id, @PathVariable("name") String 
userName){return "解析参数id:"+id+",name:"+userName;
}

使⽤浏览器发送请求: http://127.0.0.1:8080/param/m8/5/zhangsan

如果⽅法参数名称和需要绑定的URL中的变量名称⼀致时, 可以简写, 不⽤给@PathVariable的属性赋值, 如上述例⼦中的id变量

如果⽅法参数名称和需要绑定的URL中的变量名称不⼀致时, 需要@PathVariable的属性value赋值,

如上述例⼦中的userName变量.

---------------------------------------------------------------------------------------------------------------------------------

上传⽂件@RequestPart 

@RequestMapping("/m9")
public String getfile(@RequestPart("file") MultipartFile file) throws
IOException {
//获取⽂件名称
String fileName = file.getOriginalFilename();
//⽂件上传到指定路径
file.transferTo(new File("D:/temp/" + file.getOriginalFilename()));return "接收到⽂件名称为: "+fileName;
}

---------------------------------------------------------------------------------------------------------------------------------

获取Cookie/Session

HTTP 协议⾃⾝是属于 "⽆状态" 协议.

"⽆状态" 的含义指的是:

默认情况下 HTTP 协议的客⼾端和服务器之间的这次通信, 和下次通信之间没有直接的联系.

但是实际开发中, 我们很多时候是需要知道请求之间的关联关系的.

例如登陆⽹站成功后, 第⼆次访问的时候服务器就能知道该请求是否是已经登陆过了

上述图中的 "令牌" 通常就存储在 Cookie 字段中

此时在服务器这边就需要记录"令牌"信息, 以及令牌对应的⽤⼾信息, 这个就是 Session 机制所做的⼯作.

---------------------------------------------------------------------------------------------------------------------------------

理解Session

会话: 对话的意思

服务器同⼀时刻收到的请求是很多的. 服务器需要清楚的区分每个请求是属于哪个⽤⼾, 也就是属于哪个会话, 就需要在服务器这边记录每个会话以及与⽤⼾的信息的对应关系.

Session是服务器为了保存⽤⼾信息⽽创建的⼀个特殊的对象.

Session的本质就是⼀个 "哈希表", 存储了⼀些键值对结构. Key 就是SessionID, Value 就是⽤⼾信息(⽤⼾信息可以根据需求灵活设计).

SessionId 是由服务器⽣成的⼀个 "唯⼀性字符串", 从 Session 机制的⻆度来看, 这个唯⼀性字符串称为 "SessionId". 但是站在整个登录流程中看待, 也可以把这个唯⼀性字符串称为 "token".

上述例⼦中的令牌ID, 就可以看做是SessionId, 只不过令牌除了ID之外, 还会带⼀些其他信息, ⽐如时间, 签名等.

1. 当⽤⼾登陆的时候, 服务器在 Session 中新增⼀个新记录, 并把 sessionId返回给客⼾端. (通过

HTTP 响应中的 Set-Cookie 字段返回).

2. 客⼾端后续再给服务器发送请求的时候, 需要在请求中带上 sessionId. (通过 HTTP 请求中的

Cookie 字段带上).

3. 服务器收到请求之后, 根据请求中的 sessionId在 Session 信息中获取到对应的⽤⼾信息, 再进⾏后续操作.找不到则重新创建Session, 并把SessionID返回

Session 默认是保存在内存中的. 如果重启服务器则 Session 数据就会丢失.
---------------------------------------------------------------------------------------------------------------------------------
 Cookie 和 Session 的区别

Cookie 是客⼾端保存⽤⼾信息的⼀种机制. Session 是服务器端保存⽤⼾信息的⼀种机制.

Cookie 和 Session之间主要是通过 SessionId 关联起来的, SessionId 是 Cookie 和 Session 之间的桥梁

Cookie 和 Session 经常会在⼀起配合使⽤. 但是不是必须配合.

完全可以⽤ Cookie 来保存⼀些数据在客⼾端. 这些数据不⼀定是⽤⼾⾝份信息, 也不⼀定是 SessionId

Session 中的sessionId 也不需要⾮得通过 Cookie/Set-Cookie 传递, ⽐如通过URL传递.

---------------------------------------------------------------------------------------------------------------------------------

获取Cookie
    @RequestMapping("/getCookie")public String getCookie(HttpServletRequest request) {Cookie[] cookies = request.getCookies();if(cookies == null) {return "null cookie";}for (Cookie cookie: cookies) {System.out.println(cookie.getName() + ":" + cookie.getValue());}return "getCookie success";}@RequestMapping("/getCookie2")public String getCookie2(@CookieValue("name") String name) {return "name:" + name;}
Session 存储和获取
    @RequestMapping("/setSession")public String setSession(HttpServletRequest request) {HttpSession session = request.getSession();session.setAttribute("userName", "zhangsan");session.setAttribute("age", "15");return "setSession success";}@RequestMapping("/getSession")public String getSession(HttpServletRequest request) {HttpSession session = request.getSession();if(session == null) {return "null session";}String userName = (String) session.getAttribute("userName");System.out.println(session.getAttribute("age"));return "userName: " + userName;}@RequestMapping("/getSession2")public String getSession2(HttpSession session) {String userName = (String) session.getAttribute("userName");System.out.println(session.getAttribute("age"));return "userName: " + userName;}@RequestMapping("/getSession3")public String getSession3(@SessionAttribute String userName) {return "userName: " + userName;}

获取Header

@RequestMapping("/getHeader")public String getHeader(HttpServletRequest request) {String userAgent = request.getHeader("user-Agent");return "user-Agent: " + userAgent;}@RequestMapping("/getHeader2")public String getHeader2(@RequestHeader("user-Agent") String userAgent) {return "user-Agent: " + userAgent;}

---------------------------------------------------------------------------------------------------------------------------------

响应

返回静态⻚⾯

@RestController
public class IndexController {@RequestMapping("/index")public Object index(){//返回index.htmlreturn "/index.html";}
}

运行结果:

结果却发现, ⻚⾯未正确返回, http响应把 "/index.html" 当做了http响应正⽂的数据

那Spring MVC如何才能识别出来 index.html 是⼀个静态⻚⾯, 并进⾏返回呢?

我们需要把 @RestController 改为 @Controller

正确代码如下:

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

结果:

随着互联⽹的发展, ⽬前项⽬开发流⾏"前后端分离"模式, Java主要是⽤来做后端项⽬的开发, 所以也就不再处理前端相关的内容了

MVC的概念也逐渐发⽣了变化, View不再返回视图, ⽽是返回显⽰视图时需要的数据.

所以前⾯使⽤的 @RestController 其实是返回的数据.

@RestController = @Controller + @ResponseBody

@Controller : 定义⼀个控制器, Spring 框架启动时加载, 把这个对象交给Spring管理.

@ResponseBody : 定义返回的数据格式为⾮视图, 返回⼀个 text/html 信息

加在类上,表示该类的所有方法都返回数据;

加在方法上,表示该方法返回数据,其他的方法不受影响

返回数据@ResponseBody

@Controller
@ResponseBody
public class IndexController {@RequestMapping("/index")public Object index(){return "/index.html";}
}

加上 @ResponseBody 注解, 该⽅法就会把 "/index.html" 当做⼀个数据返回给前端.

运⾏:http://127.0.0.1:8080/index

@ResponseBody 既是类注解, ⼜是⽅法注解

如果作⽤在类上, 表⽰该类的所有⽅法, 返回的都是数据, 如果作⽤在⽅法上, 表⽰该⽅法返回的是数据.

也就是说: 在类上添加 @ResponseBody 就相当于在所有的⽅法上添加了 @ResponseBody 注解.

同样, 如果类上有 @RestController 注解时:表⽰所有的⽅法上添加了 @ResponseBody 注解, 也就是当前类下所有的⽅法返回值做为响应数据

如果⼀个类的⽅法⾥, 既有返回数据的, ⼜有返回⻚⾯的, 就把 @ResponseBody 注解添加到对应的⽅法上即可

返回HTML代码⽚段

@RequestMapping("/returnHtml")
@ResponseBody
public String returnHtml() {return "<h1>Hello,HTML~</h1>";
}
运⾏程序, 浏览器响应结果如下: http://127.0.0.1:8080/returnHtml

响应中的 Content-Type 常⻅取值有以下⼏种:

text/html : body 数据格式是 HTML

text/css : body 数据格式是 CSS

application/javascript : body 数据格式是 JavaScript

application/json : body 数据格式是 JSON

如果请求的是js⽂件, Spring MVC会⾃动设置Content-Type为 application/javascript

如果请求的是css⽂件, Spring MVC会⾃动设置Content-Type为 text/css

@RequestMapping("/index2")
public Object index2(){return "/a.js";
}
@RequestMapping("/index3")
public Object index3(){return "/b.css";
}

返回JSON

Spring MVC 也可以返回JSON

后端⽅法返回结果为对象.

@RequestMapping("/returnJson")
@ResponseBody
public HashMap<String, String> returnJson() {HashMap<String, String> map = new HashMap<>();map.put("Java", "Java Value");map.put("MySQL", "MySQL Value");map.put("Redis", "Redis Value");return map;
}

设置状态码

Spring MVC会根据我们⽅法的返回结果⾃动设置响应状态码, 程序员也可以⼿动指定状态码

通过Spring MVC的内置对象HttpServletResponse 提供的⽅法来进⾏设置

@RequestMapping(value = "/setStatus")
@ResponseBody
public String setStatus(HttpServletResponse response) {response.setStatus(401);return "设置状态码成功";
}

运⾏程序, 浏览器响应结果如下: http://127.0.0.1:8080/setStatus

设置Header (了解)

Http响应报头也会向客⼾端传递⼀些附加信息, ⽐如服务程序的名称,请求的资源已移动到新地址等, 如: Content-Type, Local等.

这些信息通过 @RequestMapping 注解的属性来实现

先来看 @RequestMapping 的源码:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
@Reflective({ControllerMappingReflectiveProcessor.class})
public @interface RequestMapping {String name() default "";@AliasFor("path")String[] value() default {};@AliasFor("value")String[] path() default {};RequestMethod[] method() default {};String[] params() default {};String[] headers() default {};String[] consumes() default {};String[] produces() default {};
}

1. value: 指定映射的URL

2. method: 指定请求的method类型, 如GET, POST等

3. consumes: 指定处理请求(request)的提交内容类型(Content-Type),例如application/json,

text/html;

4. produces: 指定返回的内容类型,还可以同时设置返回值的字符编码

5. Params: 指定request中必须包含某些参数值时,才让该⽅法处理

6. headers: 指定request中必须包含某些指定的header值,才能让该⽅法处理请求

设置Content-Type
我们通过设置 produces属性的值, 设置响应的报头Content-Type
@RequestMapping(value = "/returnJson2",produces = "application/json")
@ResponseBody
public String returnJson2() {return "{\"success\":true}";
}

设置其他Header
设置其他Header的话, 需要使⽤Spring MVC的内置对象HttpServletResponse 提供的⽅法来进⾏设置
@RequestMapping(value = "/setHeader")
@ResponseBody
public String setHeader(HttpServletResponse response) {response.setHeader("MyHeader","MyHeaderValue");return "设置Header成功";
}


http://www.ppmy.cn/ops/134377.html

相关文章

python:用 sklearn 构建 K-Means 聚类模型

pip install scikit-learn 或者 直接用 Anaconda3 sklearn 提供了 preprocessing 数据预处理模块、cluster 聚类模型、manifold.TSNE 数据降维模块。 编写 test_sklearn_3.py 如下 # -*- coding: utf-8 -*- """ 使用 sklearn 构建 K-Means 聚类模型 "&…

MACA-PEG-NHS中PEG链段能够增加修饰后材料的溶解度和稳定性

一、基本信息 英文名称&#xff1a;MACA-PEG-NHS&#xff0c;Methacrylamide-PEG-NHS&#xff0c;MACA PEG NHS ester。 中文名称&#xff1a;甲基丙烯酰胺PEG活性酯&#xff0c;甲基丙烯酰胺聚乙二醇活性酯。 结构&#xff1a;融合了甲基丙烯酸酯&#xff08;MACA&#xff…

Python | 处理CMIP6 NC数据,以tas为例

各位同学&#xff0c;一般在文章最后一章我们可能会做不同气候情景下变量的未来时空变化特征&#xff0c;类似上图。从cmip6下载的nc数据常需要转换格式、裁剪到研究区和重采样等&#xff0c;本期代码可以解决这类问题。 1. Python代码 以tas为例&#xff0c;代码提取nc数据中…

实现一个BLE HID鼠标

这个程序将 ESP32 或类似设备变成了一个简单的蓝牙鼠标&#xff0c;通过 4 个 GPIO 引脚来控制鼠标的上下左右移动。连接到蓝牙后&#xff0c;按下相应的按键会发送 HID 鼠标移动事件。包含了一个简单的测试函数&#xff0c;用于验证鼠标的移动和点击功能。 # MicroPython Hum…

【数据结构】10.线索二叉树

一、线索二叉树的产生 采用先序、中序、后序三种方法遍历二叉树后都可以得到一个线性序列&#xff0c;序列上的每一个结点&#xff08;除了第一个和最后一个&#xff09;都有一个前驱和一个后继&#xff0c;但是&#xff0c;这个线性序列只是逻辑的概念&#xff0c;不是物理结…

MySQL的编程语言

一、MySQL基础 使用系统的全局变量@@VERSION查看当前使用的MySQL的版本信息,SQL语句如下: select @@version; 将局部变量varl声明为char的类型,长度值为10,并为其赋值为“程菲” begin declare var1 char(10); set @var1="程菲"; end 通过局部变量查看d_eams数…

Flink_DataStreamAPI_源算子Source

Flink_DataStreamAPI_源算子Source 1从集合中读取数据2从文件读取数据3从Socket读取数据4从Kafka读取数据5从数据生成器读取数据Flink支持的数据类型1&#xff09;Flink的类型系统2&#xff09;Flink支持的数据类型3&#xff09;类型提示&#xff08;Type Hints&#xff09; 1从…

springboot整合security5.7.16实现用户登录及超时自动登录

1、问题概述? 提供源码下载,springSecurity关键技术,仔细阅读。 解决如下问题: 1、使用springboot2.7.16整合springSecurity5.7.16实现用户登录 2、解决新版本的Security的配置文件-提供完整配置。 3、当用户登录信息失效后,在界面发送的ajax,如何重定向到login.htm…