Java29:Spring MVC

一:Springmvc简介

1.简介:

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

在控制层框架历经 Strust ,WebWork,Strust2等诸多产品的历代更迭之后,目前业界普遍选择了Spring MVC 作为JavaEE 项目表述层开发的首先方案。

优势:

》Spring 家族的原生产品,与IOC容器等基础设施无缝对接

》表述层各细分领域需要解决的问题全方位覆盖,提供全面解决方案

》代码清新简洁,大幅度提升开发效率

》 内部组件化程度高,可插拔式组件即插即用,想要什么功能配置相应组件即可

》性能卓著,尤其适合现代大型/超大型互联网项目要求

2.作用:

3.核心组件:

1.DispatcherServlet:SpringMVC提供,我们需要使用web.xml配置使其生效,它式整个流程处理的核心,所有请求都经过它的处理和分发

2.HandlerMapping:SpringMVC提供,我们需要进行Ioc配置使其假如Ioc容器方可生效,它内部缓存handler和handler访问路径数据,被DispatcherServlet调用,用于查找路径对应的handler!

3.HandlerAdapter:SpringMVC提供,我们需要进行Ioc配置使其假如Ioc容器方可生效,它可以

处理请求参数和处理响应数据,每次DispatcherServlet都是通过HandlerAdapter间接调用handler,它是handler和DispatcherServlet之间的适配器

4.Handler:handler又称为处理器,它是Controller类内部方法的简称,是由我们自己定义,用来接收参数,向后调用业务,最终返回响应结果!

5.ViewResovler: SpringMVC提供,我们需要进行Ioc配置使其假如Ioc容器方可生效,视图解析器主要作用简化模板视图页面查找的,但是需要注意,前后端分离项目,后端只返回JSON数据,不返回界面,那就不需要视图解析器,相对其他组件不是必须的。

二:快速入门程序

步骤1:创建项目并导入依赖:

<dependency><groupId>jakarta.platform</groupId><artifactId>jakarta.jakartaee-web-api</artifactId><version>9.1.0</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>6.0.6</version>
</dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>6.0.6</version>
</dependency>

步骤2:创建控制层处理器并添加注解

@Controllerpublic class HelloHandler {@RequestMapping("spring/hello")//配置访问路径@ResponseBody //返回前端字符串,不调用视图解析器public String hello(){System.out.println("hello handler");return "hello springmvc";}
}

步骤3:创建配置类

@Configuration
@ComponentScan("com.cn.handler")
public class MyConfig {@Beanpublic  RequestMappingHandlerMapping  getRequestMapping(){RequestMappingHandlerMapping requestMappingHandlerMapping = new RequestMappingHandlerMapping();return requestMappingHandlerMapping;}@Beanpublic RequestMappingHandlerAdapter getRequestMappingHandlerAdapter(){RequestMappingHandlerAdapter requestMappingHandlerAdapter = new RequestMappingHandlerAdapter();return requestMappingHandlerAdapter;}}

步骤4:加载配置类并初始化容器

package com.cn.config;import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.server.adapter.AbstractReactiveWebInitializer;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;public class SpringMvcInit extends AbstractAnnotationConfigDispatcherServletInitializer {@Overrideprotected Class<?>[] getRootConfigClasses() {return new Class[0];}//指定配置类@Overrideprotected Class<?>[] getServletConfigClasses() {return new Class[]{MyConfig.class};}//设置DispatcherServlet的处理路径,一般情况下 /代表处理所有请求@Overrideprotected String[] getServletMappings() {return new String[]{"/"};}
}

步骤5:工程设置为web工程,并部署到tomcat(10.0以上版本)

1. 工程右键-选择JBLJavaToWeb 把工程设置为web工程

2.把工程部署到tomcat,并重启服务

3.浏览器地址输入:http://localhost:8080/spring/hello

4.浏览器显示:hello springmvc 表示程序运行成功

三:Spring MVC接收数据

1.访问路径设置:

@RequestMapping注解的作用就是将请求的URL地址和处理请求的方式(handler 方法)关联起来,建立映射关系。

SpringMVC接收到指定的请求,就会来找到在映射关系中对应的方法来处理这个请求。@RequestMapping(不用必须使用/开头) user/login  

1.精准地址【1个|多个】/user/login    {"地址1","地址2"}

2.支持模糊 * 任意一层字符串| **任意层任意字符串

   /user/* ->  /user/a  user/aaaa 可以, /user/a/b 不行

 /user/** ->  /user/a   /user/a/a/a/a

3.类上和方法上添加@RequestMapping的区别

  类上提取通用的访问地址

  方法上时具体的handler地址

访问: 类地址+方法地址即可

4.请求方式指定

 客户端-> http(get|post|put|delete)->ds->handler

默认情况:@RequestMapping("login")主要地址正确,任何请求方式都可以访问

指定请求方式:method={RequestMethod.GET,RequestMethod.POST}

不符合请求方式:会出现405异常!

5注解进阶:

get @GetMapping ==@RequestMapping(xxx,method=GET);

post@PostMapping ==@RequestMapping(xxx,method=POST);

put@PUTMapping ==@RequestMapping(xxx,method=PUT);

delete@DeleteMapping ==@RequestMapping(xxx,method=DELETE);

2.参数接收:

2.1 param和json参数比较

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

1.参数编码:

 param 类型的参数被编码为ASCII码。JSON类型会被编码为UTF-8

2.参数顺序:

param类型的参数没有顺序限制。但是,JSON类型的参数是有序的。JSON采用键值对的形式进行传递,其中键值对是有序排列的

3.数据类型:

param类型的参数仅支持字符串类型,数值类型和布尔类型等简单数据类型。而JSON类型的参数则支持更复杂的数据类型,如数组,对象等。

4.嵌套性:

param类型的参数不支持嵌套。但是,JSON类型的参数支持嵌套,可以传递更为复杂的数据结构。

5.可读性:

param 类型的参数格式比JSON类型的参数更加简单,易读。但是JSON格式在传递嵌套数据结构时更加清晰易懂。

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

2.2 param接收参数:
@Controller
@RequestMapping("user")
public class MyHandler {/** 1 直接接收* /user/login?name=root&age=18* 形参列表,填写对应名称的参数即可!请求参数名=形参参数名即可!* 1)名称相同* 2)可以不传递,不报错** */@RequestMapping("/login")@ResponseBodypublic String login(String name,int age){System.out.println("name = " + name + ", age = " + age);return "name = " + name + ", age = " + age;}/** 2 注解指定* 指定任意的请求参数名,要求必须传递  ,要求不必须传递,给一个默认值* /user/login?account=root&age=18* account必须传递 ,page可以必须传递,如果不传递默认值就是1@RequestParam-> 形参列表 指定请求参数名 或者是否必须传递,或者非必须传递设置默认值用法:@RequestParam(value="指定请求参数名,如果形参名和请求参数名一致,可以省略!",required=false 前端是否必须传递此参数,默认是必须,不传400异常!,* defaultValue="1" 当非必须传递false,可以设置默认值)** */@RequestMapping("/login2")@ResponseBodypublic String login2(@RequestParam("account")String name, @RequestParam(required = false,defaultValue = "10") int age){System.out.println("name = " + name + ", age = " + age);return "name = " + name + ", age = " + age;}/** 3 特殊值* /user/login3?hbs=吃&hbs=喝* 不加注解@RequestParam 将hbs对应的一个字符串直接赋值给集合! 类型异常!* 加了注解,会将集合加入对应的字符串* */@RequestMapping("/login3")@ResponseBodypublic String login3(@RequestParam  List<String> hbs){System.out.println(hbs);return hbs.toString();}/** 4 使用实体对象接值* /user/login4?name=tom&age=10  准备一个对应属性和get|set 方法的实体类即可,* 形参列表声明对象参数即可!* */@RequestMapping("/login4")@ResponseBodypublic String login3(User user){System.out.println("name = " + user.getName() + ", age = " + user.getAge());return "name = " + user.getName() + ", age = " + user.getAge();}}
2.3 路径传参:
@Controller
@RequestMapping("path")
@ResponseBody
public class PathHandler {// path/用户名/密码//动态路径设计{key}//必须使用 注解@PathVariable@RequestMapping("{name}/{password}")public String  hello(@PathVariable String name , @PathVariable String password){System.out.println("name = " + name + ", password = " + password);return "name = " + name + ", password = " + password;}
}
2.4 JSON数据接收(重点):

前端传递JSON数据时,SpringMVC 框架可以使用@RequestBody 注解 来将JSON

数据转换为Java对象,@RequestBody 注解表示当前方法参数的值应该从请求体中获取,并且需要指定value 属性来指示请求体应该映射到哪个参数上,其使用方式和示类代码如下:

步骤1 .前端发送JSON数据(使用postman)

{"name":"zhangsan","age":18,"gender":"男"}

步骤2.定义一个用于接收JSON数据的Java 类

@Data
public class Person {private String name;private int age;private String gender;
}

步骤3.在控制器中使用@RequestBody注解来接收JSON数据,并将器转换为Java对象:

@Controller
@RequestMapping("json")
@ResponseBody
public class JsonHandler {@PostMapping("data")
    public String data(@RequestBody Person person){System.out.println("person = " + person);return person.toString();}}

步骤4:添加JSON解析依赖:

<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.15.0</version>
</dependency>

步骤5:在配置类添加注解:@EnableWebMvc,给SpringMVC HandlerAdpater配置JSON转换器

@EnableWebMvc
@Configuration
@ComponentScan("com.cn.json")
public class MyConfig {}

步骤6:测试并查看响应数据:

Person(name=zhangsan, age=18, gender=nan)

2.5 cookie和Header接收:

1.使用@CookieValue 注解获取cookie数据

存取cookie

@GetMapping("save")
public String save(HttpServletResponse httpResponse){Cookie  cookie = new Cookie("cookieName","cookieValue");httpResponse.addCookie(cookie);return "ok";
}

获取cookie

 @RequestMapping("data")
public String data(@CookieValue(name="cookieName") String value){System.out.println("value = " + value);return value;
}

2.使用注解@RequestHeader 获取header信息

@Controller
@ResponseBody
@RequestMapping("header")
public class HeaderController {@GetMapping("data")public String  data(@RequestHeader(value = "Host") String host){System.out.println("host = " + host);return host;}}
2.6 接收数据总结:

四:Spring MVC响应数据

1.开发模式介绍:

在Web开发中,有两种主要的开发模式:前后端分离和混合开发

前后端分离模式(重点)

指将前端的界面和后端的业务逻辑通过接口分离开发的一种方式。开发人员使用不同的

技术和框架,前端开发人员主要负责界面的呈现和用户交互,后端开发人员主要

负责业务逻辑和数据存储。前后端通信通过API接口完成,数据格式一般使用JSON

或XML。前后端分离模式可以提高开发效率,同时也有助于代码重用和维护。

混合开发模式:

指将前端和后端的代码集成在同一个项目中,共享相同的技术栈和框架。这种模式在

小型项目中比较常见,可以减少学习成本和部署难度。但是,在大型项目中,这种模式

会导致代码耦合性很高,维护和升级难度较大。

2.快速返回逻辑视图:

1.创建项目并添加依赖:

<dependency><groupId>jakarta.servlet.jsp.jstl</groupId><artifactId>jakarta.servlet.jsp.jstl-api</artifactId><version>3.0.0</version>
</dependency>

2. 在WEB-INF下创建视图目录和jsp文件:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body><font color="red">${data}</font>
</body>
</html>

3. 在配置类下配置视图解析器

@Configuration
@ComponentScan("com.cn.controller")
@EnableWebMvc
public class Myconfig  implements WebMvcConfigurer {
// 视图解析器,指定前后缀
public  void configureViewResolvers(ViewResolverRegistry registry) {registry.jsp("/WEB-INF/views/",".jsp");}}

4.创建handler

@Controller
@RequestMapping("jsp")
public class JspHandler {/** 快速查找视图方法* 1.方法的返回值是字符串类型* 2.不能添加ResponseBody,直接返回字符串给浏览器,不找视图,不走视图解析器* 3.返回值 对应中间的视图名称即可* */@GetMapping("index")public String  data(HttpServletRequest request){request.setAttribute("data","hello jsp!");return "index";}
}

5.创建初始化接口

import com.cn.config.Myconfig;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;public class SpringMvcInit  extends AbstractAnnotationConfigDispatcherServletInitializer {@Overrideprotected Class<?>[] getRootConfigClasses() {return new Class[0];}@Overrideprotected Class<?>[] getServletConfigClasses() {return new Class[]{Myconfig.class};}@Overrideprotected String[] getServletMappings() {return new String[]{"/"};}
}

6.转换为web项目部署到服务器 并测试:

浏览器输入:http://localhost:8080/jsp/index

3.转发重定向:

@Controller
@RequestMapping("jsp")
public class JspHandler {/** 快速查找视图方法* 1.方法的返回值是字符串类型* 2.不能添加ResponseBody,直接返回字符串给浏览器,不找视图,不走视图解析器* 3.返回值 对应中间的视图名称即可*** */@GetMapping("index")public String  data(HttpServletRequest request){request.setAttribute("data","hello jsp!");return "index";}/** 转发:只能是项目下的资源* 1.方法的返回值写成字符串* 2.不能添加ResponseBody注解* 3.返回的字符串前 forward:+/转发地址** */@GetMapping("forward")public String forward(){System.out.println("jsp forward");return "forward:/jsp/index";}/** 重定向:即可以是项目下的资源,也可以是项目外的资源* 1.方法的返回值写成字符串* 2.不能添加ResponseBody注解* 3.返回的字符串前 redirect:+/转发地址** */@GetMapping("redirect")public String redirect(){System.out.println("jsp redirect");return "redirect:/jsp/index";}@GetMapping("redirect/baidu")public String redirectbaidu(){System.out.println("jsp redirect");return "redirect:http://www.baidu.com";}}

4.返回JSON数据(重点):

步骤1:新建项目并导入依赖:

<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.15.0</version>
</dependency>

步骤2:创建配置类

@Configuration
@ComponentScan("com.cn.handler")
@EnableWebMvc
public class MyConfig {
}

步骤3:创建SpringMvc初始化类

package com.cn.init;import com.cn.config.MyConfig;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;public class SpringMvcInit  extends AbstractAnnotationConfigDispatcherServletInitializer {@Overrideprotected Class<?>[] getRootConfigClasses() {return new Class[0];}@Overrideprotected Class<?>[] getServletConfigClasses() {return new Class[]{MyConfig.class};}@Overrideprotected String[] getServletMappings() {return new String[]{"/"};}
}

步骤4:创建 返回的json对应的实体类

import lombok.Data;@Data
public class User {private String name;private String gender;private int age;
}

步骤5:创建Handler

@Controller
@RequestMapping("json")
@ResponseBody//返回json的注解,不找视图
public class JsonHandler {//返回单个实体类的json数据@GetMapping("data")public User data(){User user =new User();user.setName("zhangsan");user.setAge(18);user.setGender("man");return  user;}//返回集合对应的json数据@GetMapping("data2")public List<User> data2(){List<User> list =new ArrayList<>();User user1 =new User();user1.setName("zhangsan");user1.setAge(18);user1.setGender("man");User user2 =new User();user2.setName("lisi");user2.setAge(20);user2.setGender("woman");list.add(user1);list.add(user2);return  list;}
}

步骤6:部署并测试:

浏览器输入地址:http://localhost:8080/json/data

返回结果:

{"name":"zhangsan","gender":"man","age":18}

浏览器输入地址:http://localhost:8080/json/data2

[{"name":"zhangsan","gender":"man","age":18},{"name":"lisi","gender":"woman","age":20}]

5.访问静态资源:

在配置类中重写方法,开启静态资源查找

@Configuration
@ComponentScan("com.cn.handler")
@EnableWebMvc
public class MyConfig  implements WebMvcConfigurer {/*开启静态资源查找dispatcherServlet->handlerMapping 找有没有对应的handler->没有,找有没有静态资源* */@Overridepublic void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {configurer.enable();}
}

五:其他扩展功能

1.restful 介绍和理解:

1)简介:

2)设计规范:

3)实战

1.需求

2.设计

3.实现:

package com.cn.controller;import com.cn.pojo.User;
import org.springframework.web.bind.annotation.*;import java.util.List;@RestController
@RequestMapping("user")
public class UserController {//分页查询@GetMappingpublic List<User> page(@RequestParam(required = false,defaultValue = "1") int page ,@RequestParam(required = false,defaultValue = "10") int size){return null;}//用户添加
@PostMappingpublic User save(@RequestBody  User user){return user;}//用户详情@GetMapping("{id}")public User  detail(@PathVariable int id){return null;}//用户更新@PutMapping()public User update(@RequestBody User user){return user;}//用户删除
@DeleteMapping("{id}")public int delete(@PathVariable  int id){return 0;
}//用户模糊
public  List<User> search(String keyword,@RequestParam(required = false,defaultValue = "1") int page,@RequestParam(required = false,defaultValue = "10") int size){return null;}
}

2.全局处理异常:

1.异常处理的方式:

2全局异常处理步骤:

步骤1:声明全局异常处理类并添加注解@RestControllerAdvice

步骤2:在该类中通过添加注解@ExceptionHandler(指定异常.class) 声明handler方法,处理异常

步骤3:在配置类中扫描类中把该包加进去

3.实战:

1)产生异常的handler

@RestController
@RequestMapping("user")
public class UserHandler {@GetMapping("data")public String data(){String s1=null;int length = s1.length();//java.lang.NullPointerExceptionreturn "ok";}@GetMapping("data1")public String data1(){int i= 10/0;//   java.lang.ArithmeticException: / by zeroreturn "ok2";}}

2)全局处理异常的类

package com.cn.excption;import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;@RestControllerAdvice
public class GlobelExceptionHandler {
// 发生异常->ControllerAdvice 注解的类型-》  @ExceptionHandler(指定异常类型)-》handler@ExceptionHandler(NullPointerException.class)public  Object  PowerPointHandler(NullPointerException e){String message = e.getMessage();return message;}@ExceptionHandler(Exception.class)public  Object OtherHandler(Exception e){String message = e.getMessage();return message;}
}

3)把异常处理类添加到配置类扫描中,初始化类省略(SpringMvcInit)

@Configuration
@ComponentScan({"com.cn.handler","com.cn.excption"})
@EnableWebMvc
public class Myconfig {
}

3.拦截器:

1.拦截器和过滤器区别:

2.拦截器使用:

步骤1:创建拦截器:

public class MyInterceptor  implements HandlerInterceptor {@Override//在处理请求的目标handler方法前执行//一般用于编码格式设置,登录保护,权限处理public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("preHandle------------------");//返回true 放行,返回false:不放行return true;}@Override//在目标handler方法之后,handler报错不执行!//此方法只有在preHandle返回true后才执行, 对结果处理,敏感词汇检查   public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle------------------");}@Override//渲染视图之后执行,一定执行public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion------------------");}
}

步骤2:在配置类中开启拦截器,并设置拦截路径

@Configuration
@ComponentScan("com.cn.handler")
@EnableWebMvc
public class MyConfig implements WebMvcConfigurer {@Override//开启拦截器public void addInterceptors(InterceptorRegistry registry) {//拦截所有// registry.addInterceptor(new MyInterceptor());//拦截指定地址registry.addInterceptor(new MyInterceptor()).addPathPatterns("/user/data1");}
}

4.参数校验注解jsr303:

1.校验概述:

jsr303 是java为Bean数据合法性校验提供的标准框架,他已经包含在JAVAEE6.0标准中,jsr303通过在Bean属性上标注类似于@NotNull,@Max等标准的注解指定校验规则,并通过标准的接口对Bean进行验证。

2.校验实现:

步骤1:导入jar包

    <dependency><groupId>org.hibernate.validator</groupId><artifactId>hibernate-validator</artifactId><version>8.0.0.Final</version></dependency><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator-annotation-processor</artifactId><version>8.0.0.Final</version></dependency>
</dependencies>

步骤2:在实体类添加校验注解

@Data
public class User {/*1.name 不为null和空字符串字符串@NotBlank 集合@NotEmpty 包装类@NotNull2.password长度大于63.age必须》=14.email 邮件格式的字符串5.birthday过去实际*** */@NotBlankprivate String name;@Length(min = 6)private String password;@Min(1)private int age;@Emailprivate String email;@Pastprivate Date birthday;
}

步骤3:handler 添加注解@Validated,如果自定义返回异常,添加BindingResult,获取错误信息

@RestController
@RequestMapping("user")
public class RegisterHandler {/** 步骤1:实体类添加校验注解* 步骤2:handler(@Validated 实体类 对象)* 细节:param|json校验都有效果*      json参数-@RequestBody* 如果不符合校验规则,直接向前端抛出异常* 接收绑定错误信息,自定义返回结果,约定参数错误-》{code:400}** 捕捉绑定信息* 1.handler(校验对象,BindingResult result)要求:BindingResult必须紧挨着校验对象* 2.BindingResult获取绑定错误** */@PostMapping("register")public Object  register(@Validated @RequestBody User user){// 自定义返回异常代码       
//    public Object  register(@Validated @RequestBody User user, BindingResult result){
//        if(result.hasErrors()){
//            Map map = new HashMap();
//            map.put("code",400);
//            map.put("msg","参数校验异常");
//            return map;
//
//        }return user;}
}

步骤4:测试

1)正常情况:

2)自定义异常:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/77493.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VLC搭建本机的rtsp直播推流和拉流

媒体---流---捕获设备&#xff0c;选择摄像头&#xff0c;点击串流 x下一步 选择rtsp&#xff0c;点击添加 看到了端口&#xff0c;并设置路径&#xff1a; 选择Video -H 264 mp3(TS) 点击下一个&#xff0c; 点击流&#xff0c;就开始推流了 拉流&#xff0c;观看端&#x…

云点数据读写

一、常见点云数据格式 LAS/LAZ格式 LAS是点云数据的行业标准格式 LAZ是LAS的压缩版本 支持地理参考信息、颜色、强度等属性 PCD格式(Point Cloud Data) PCL(Point Cloud Library)开发的格式 支持ASCII和二进制存储 包含头部信息和数据部分 PLY格式(Polygon File Format…

[RHEL8] 指定rpm软件包的更高版本模块流

背景&#xff1a;挂载RHEL ISO使用kickstart安装操作系统&#xff0c;安装包未指定安装perl&#xff0c;但是安装完可以查到其版本&#xff0c;且安装的是ISO中多个版本中的最低版本。 原因&#xff1a;&#xff08;1&#xff09;为什么没有装perl&#xff0c;perl -v可以看到版…

Spring 事务管理核心机制与传播行为应用

Spring 事务详解 一、Spring 事务简介 Spring 事务管理基于 AOP&#xff08;面向切面编程&#xff09;实现&#xff0c;通过 声明式事务&#xff08;注解或 XML 配置&#xff09;统一管理数据库操作&#xff0c;确保数据一致性。核心目标&#xff1a;保证多个数据库操作的原子…

JavaScript解密实战指南:从基础到进阶技巧

JavaScript加密技术广泛应用于数据保护、反爬虫和代码混淆&#xff0c;但掌握解密方法能帮助开发者突破技术壁垒。本文结合爬虫实战与安全分析场景&#xff0c;系统梳理JS解密的核心方法与工具。 一、基础解密方法 1. Base64解码 适用于简单编码场景&#xff0c;如Cookie加密…

WEMOS LOLIN32

ESP32是結合Wi-Fi和藍牙的32位元系統單晶片&#xff08;SoC&#xff09;與外接快閃記憶體的模組。許多廠商生產採用ESP32模組的控制板&#xff0c;最基本的ESP控制板包含ESP32模組、直流電壓轉換器和USB序列通訊介面IC。一款名為WEMOS LOLIN32的ESP32控制板具備3.7V鋰電池插座。…

俄罗斯方块-简单开发版

一、需求分析 实现了一个经典的俄罗斯方块小游戏&#xff0c;主要满足以下需求&#xff1a; 1.图形界面 使用 pygame 库创建一个可视化的游戏窗口&#xff0c;展示游戏的各种元素&#xff0c;如游戏区域、方块、分数等信息。 2.游戏逻辑 实现方块的生成、移动、旋转、下落和锁…

使用安全继电器的急停电路设计

使用安全继电器的急停电路设计 一&#xff0c;急停回路的设计1&#xff0c;如何将急停接到线路当中&#xff1f;2&#xff0c;急停开关 如何接到安全继电器中 一&#xff0c;急停回路的设计 急停是每一个设备必不可少的部分&#xff0c;因为关乎安全&#xff0c;所以说所以说他…

【读书笔记·VLSI电路设计方法解密】问题64:什么是芯片的功耗分析

低功耗设计是一种针对VLSI芯片功耗持续攀升问题的设计策略。随着工艺尺寸微缩&#xff0c;单颗芯片可集成更多元件&#xff0c;导致功耗相应增长。更严峻的是&#xff0c;现代芯片工作频率较二十年前大幅提升&#xff0c;而功耗与频率呈正比关系。因此&#xff0c;芯片功耗突破…

在 Debian 10.x 安装和配置 Samba

1. 更新系统 sudo apt update sudo apt upgrade -y2. 安装 Samba sudo apt install samba -y3. 配置 Samba 备份默认配置文件 sudo cp /etc/samba/smb.conf /etc/samba/smb.conf.bak编辑配置文件 sudo nano /etc/samba/smb.conf示例配置&#xff08;共享目录&#xff09; …

修改PointLIO项目

添加key_frame_info.msg消息 新建.msg文件&#xff0c;内容填写为&#xff1a; # Cloud Info Header header # cloud messages sensor_msgs/PointCloud2 key_frame_cloud_ori sensor_msgs/PointCloud2 key_frame_cloud_transed sensor_msgs/PointCloud2 key_frame_poses其中k…

关于隔离1

1.隔离的目的&#xff1a; 在隔离电源设计中&#xff0c;输入与输出之间没有直接电气连接&#xff0c;提供绝缘高阻态&#xff0c;防止电流回路。这意味着输入与输出之间呈现为绝缘的高阻态&#xff0c;从而确保了无电流回路的形成。 隔离与可靠保护有关。电隔离是一种电路设…

【java实现+4种变体完整例子】排序算法中【插入排序】的详细解析,包含基础实现、常见变体的完整代码示例,以及各变体的对比表格

以下是插入排序的详细解析&#xff0c;包含基础实现、常见变体的完整代码示例&#xff0c;以及各变体的对比表格&#xff1a; 一、插入排序基础实现 原理 将元素逐个插入到已排序序列的合适位置&#xff0c;逐步构建有序序列。 代码示例 public class InsertionSort {void…

清醒思考的艺术

成为穿越暴风雨后的幸存者 系统性错误是指系统性的偏离理性&#xff0c;偏离最理想的、合乎逻辑的、理智的思考和行为。 “系统”一词很重要&#xff0c;因为我们经常错误地走向同一方向。 幸存偏误 幸存偏误会扭曲概率&#xff0c;系统性的高估了成功概率。一旦混淆选择标准和…

DSA数据结构与算法 6

查找技术&#xff08;Searching Techniques&#xff09; 查找简介 在计算机科学中&#xff0c;“查找”指的是在某个集合或序列中寻找特定元素的过程。这个过程可以是成功的&#xff0c;也可以是失败的&#xff1a; 若目标元素存在于集合中&#xff0c;我们称之为“查找成功”…

FastAPI:现代高性能Python Web框架的技术解析与实践指南

一、FastAPI的诞生背景与技术定位 在数字化转型的浪潮中,API(应用程序接口)作为连接服务与数据的核心枢纽,其性能与开发效率直接影响业务迭代速度。传统Python框架如Django和Flask虽功能丰富,但在高并发场景下面临性能瓶颈,且缺乏对异步编程的原生支持。FastAPI应运而生…

VuePress 使用教程:从入门到精通

VuePress 使用教程&#xff1a;从入门到精通 VuePress 是一个以 Vue 驱动的静态网站生成器&#xff0c;它为技术文档和技术博客的编写提供了优雅而高效的解决方案。无论你是个人开发者、团队负责人还是开源项目维护者&#xff0c;VuePress 都能帮助你轻松地创建和管理你的文档…

1.Vue自动化工具安装(Vue-cli)

目录 1.node.js 安装&#xff1a; 2 npm 安装 3 安装Vue-cli 4总结&#xff1a; 一般情况下&#xff0c;单文件组件&#xff0c;我们运行在 自动化工具vue-CLI中&#xff0c;可以帮我们编译单文件组件。所以我们在学习时一般需要在系统中先搭建vue-CLI工具 下面就是一些我…

IP数据报

IP数据报组成 IP数据报&#xff08;IP Datagram&#xff09;是网络中传输数据的基本单位。 IP数据报头部 版本&#xff08;Version&#xff09; 4bit 告诉我们使用的是哪种IP协议。IPv4版本是“4”&#xff0c;IPv6版本是“6”。 头部长度&#xff08;IHL&#xff0c;Intern…

Leetcode 2158. 每天绘制新区域的数量【Plus题】

1.题目基本信息 1.1.题目描述 有一幅细长的画&#xff0c;可以用数轴来表示。 给你一个长度为 n 、下标从 0 开始的二维整数数组 paint &#xff0c;其中 paint[i] [starti, endi] 表示在第 i 天你需要绘制 starti 和 endi 之间的区域。 多次绘制同一区域会导致不均匀&…