Spring MVC(三)- 处理器与注解

 Spring MVC 用@Controller及@RestController 注解来标志(自动扫描并注册成bean)该类是一个控制器容器类,在该类下,使用@RequestMapping及其扩展注解来定义处理器。使用注解,可以定义请求的映射、请求的输入、异常处理等。

1 映射请求

使用@RequestMapping 注解来将不同的请求映射到对应的处理器方法上,可以通过URL、请求方法、请求参数、请求头及媒体类型来作匹配。基于其的扩展注解是针对了具体的请求方法做匹配:@GetMapping、@PostMapping等。

1.1 URI 模式

可以使用通配符来匹配请求的URL。

模式

描述

例子

?

匹配一个任意字符。

“/user/get?”

匹配:“/user/get1”

不匹配:“/user/get12”

*

匹配0个或多个任意字符。

“/user/*/get”

匹配:“/user/g1/get”

不匹配:“/user/g1/g2/get”

**

匹配0或多个路径段,直到路径段结束。

“/user/*/get”

匹配:“/user/get”、

“/user/g1/g2/get”

{name}

匹配一个路径段,并捕获它赋值到变量“name”。

“/user/{id}/info”

匹配:“/user/1234/info”,变量id 值为1234。

不匹配:“/user/12/34/info”

{name:[a-z]+}

匹配一个符合表达式段路径段、并捕获它赋值到变量“name”。

“/user/{id:\\d+}/info”,

匹配:“/user/1234/info”

不匹配:“/user/12a/info”

表 @RequestMapping 支持的匹配模式

上面捕获并赋值到变量,可以在处理器方法参数中,通过@PathVariable注解来获取。

@GetMapping("/user/{id:\\d+}/info")
public Pet findPet(@PathVariable Long id) {
    // 请求 /user/123/info,则该方法参数id的值为123
}

1.1.1 RFD(反射型文件下载)漏洞

是一个针对客户端的攻击漏洞,主要发生在响应中设置了“Content-Disposition”头,并且该头的filename属性是由用户请求输入的。这是因为Spring 并没有对用户请求传入的文件名进行严格检测。为了防止该漏洞,开发者应该:

  1. 对filename 参数进行严格的验证和过滤,确保它只包含合法的字符,并且不会造成混淆。
  2. 使用白名单验证,只允许预定义的、安全的文件名格式。
  3. 避免将用户提供的输入直接用作文件名。
@Controller 
public class FileDownloadController { 

    // 假设我们有一个文件路径 
    private static final String FILE_PATH = "path/to/your/file.txt"; 

    @GetMapping("/download") 
    public void downloadFile(@RequestParam String filename, HttpServletResponse response) throws IOException { 

        // 这里故意没有验证和过滤filename参数,导致RFD漏洞 
        Path filePath = Paths.get(FILE_PATH); 
        String contentType = Files.probeContentType(filePath); 
        response.setContentType(contentType); 

        // 使用用户提供的filename作为Content-Disposition中的文件名 
        String headerValue = String.format("attachment; filename=\"%s\"", filename); 
        response.setHeader("Content-Disposition", headerValue); 
        // 将文件内容写入响应输出流 
        Files.copy(filePath, response.getOutputStream()); 
        response.flushBuffer(); 
    } 
}
上面代码中,假如用户的请求是:http://localhost:8080/download?filename=malicious.txt%0D%0AContent-Type:%20text/html%0D%0A%0A<script>alert('Your computer has been compromised!')</script>
那么将可能导致客户端浏览器接收到一个格式不正确的响应,并且可能会执行注入的脚本。

1.2 窄化请求

@RequestMapping 注解还可以通过Media Types、请求参数及请求头等方式来窄化请求匹配。

1.2.1 Media Types

其属性consumes表示请求头的Content-Type,而produces表示响应的Content-Type,由请求头的Accept属性决定。

@PostMapping(path = "/pets", consumes = "application/json",produces = "application/json")
public Object addPet(@RequestBody Pet pet) {
    // 表示该请求头的Content-Type 包含 application/json,Accept包含application/json
}

1.2.2 请求参数与请求头

其属性params 用来表示匹配的请求参数值,而headers 则表示匹配的请求头属性值。

@GetMapping(path = "/pets/{petId}", params = "myParam=myValue", headers = "Content-Type =application/json ")
public void findPet(@PathVariable String petId) {
  // .请求参数中,参数名为myParam的值要为myValue,请求头的Content-Type属性为//application/json(如果是这个请求头属性,则最好用consumes属性来指定)
}

1.3 其他请求方法

HEAD

与GET请求类似,但是响应只返回HTTP头信息,不返回实际的响应体。请求会被服务器处理。用于请求资源的元数据,常用于检查资源是否存在、更新状态或其他头部信息。

OPTIONS

用于获取目标资源所支持的请求方法。常用于跨域请求,在发送可能被视为有风险的请求(如POST或PUT)之前,浏览器可能会先发出一个OPTIONS请求来检查服务器是否允许这种请求。

表 HEAD 与 OPTION 请求

1.4 动态注册处理器

可以通过动态编程方式来动态地注册映射器。

@Autowired
public void setHandlerMapping(RequestMappingHandlerMapping mapping, DynamicHandler handler) throws NoSuchMethodException {
    RequestMappingInfo mappingInfo = RequestMappingInfo.paths("/dynamic").methods(RequestMethod.GET).build();
    Method method = DynamicHandler.class.getMethod("showInfo"); // 处理方法
    mapping.registerMapping(mappingInfo,handler,method);
}

2 处理器方法

@RequestMapping 注解方法时,可以为这个方法定义灵活的签名。选择一些列受支持的参数类型和返回值类型。

常见的方法类型参数有:

  1. HttpServletRequest 和 HttpServletResponse 对象。
  2. @PathVariable、@RequestParam、@RequestHeader等注解标注的参数,用于从请求中提取信息。
  3. @ModelAttribute注解标记的参数,用于绑定请求参数到模型对象。
  4. java.util.Map或org.springframework.ui.Model对象,用于添加模型属性等。

常见的返回值类型有:

  1. 字符串(通常表示逻辑视图名)。
  2. ModelAndView对象(包含视图和模型数据)。
  3. ResponseEntity对象(用于构建HTTP响应)。
  4. @ResponseBody 注解标记的对象(Spring MVC会将其序列化为JSON或XML并返回给客户端)。
  5. void(通常与HttpServletResponse对象一起使用以之间写入响应体)。

2.1 参数变量

2.1.1 矩阵变量

URL中,允许在路径段中使用键值对参数。变量用;分割。例如:

/usr;name=黄先生;gender=男/city;address=深圳

注意: 默认情况下,Spring MVC并不支持从URL中解析矩阵变量。要启用对矩阵变量的支持,需要自定义RquestMappingHanddlerMapping的PathMatcher,或者重写WebMvcConfigurer接口的configurePathMatch方法,并设置一个自定义UrIPathHelper,调用其方法setRemoveSemicolonContent(false),来告诉Spring不要移除URL中的分号。

@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
    UrlPathHelper urlPathHelper = new UrlPathHelper();
    urlPathHelper.setRemoveSemicolonContent(false);// 不要移除URL中的分号
    configurer.setUrlPathHelper(urlPathHelper);
}

可以通过@MatrixVariable 来提取这些变量,用MultiValueMap来装载所有的变量。

// /parameter/matrix1/admin;color=blue;name=jack
@GetMapping("/matrix1/{usr}") // 注意,这里一定要使用路径变量,路径变量后的矩阵变量才会生效
// 所以 /parameter/matrix1;color=red,yellow;size=big/admin;color=blue;name=jack 将匹配失败
public void matrix1(@PathVariable String usr,@MatrixVariable MultiValueMap<String,Object> map) {
    System.out.println("user:" + usr); // user:admin
    System.out.println("map:" + map); //map:{color=[blue], name=[jack]}
}

// parameter/matrix2/admin;subject=English,computer;age=19/sz;subject=math
@GetMapping("/matrix2/{usr}/{address}")
public void matrix2(@PathVariable String usr,@PathVariable String address,@MatrixVariable MultiValueMap<String,Object> map) {
    System.out.println("user:" + usr + ";address:" + address); // user:admin;address:sz
    System.out.println("map:" + map); // map:{subject=[English, computer, math], age=[19]}
}

// parameter/matrix3/admin;subject=English,computer;age=19/sz;subject=math
@GetMapping("/matrix3/{usr}/{address}")
public void matrix3(@PathVariable String usr,@PathVariable String address,@MatrixVariable(name = "subject", pathVar = "usr") List<String> subject1
,@MatrixVariable(name = "subject", pathVar = "address") String subject2) {
    System.out.println("subject1:" + subject1); // subject1:[English, computer]
    System.out.println("subject2:" + subject2); // subject2:math
}

2.1.2 会话变量

会话允许开发者在多个请求之间保持用户的状态信息。

HTTP协议本身是无状态的,服务器不会记住每个用户的请求之间的任何信息。然而,在实际开发者,我们经常需要跟踪用户的会话状态,如登录状态。

在Spring MVC中,会话通常由HttpServletSession对象来管理,这是Java Servlet API的一部分。其提供了存储和检索属性的方法,这些属性可以在用户的整个会话期间保持。

当用户第一次访问一个需要会话支持的Web应用时,Servlet容器在会话被创建时自动生成JESSIONID。如果要保持同一会话,则每次请求时,在cookie中需要携带这个会话ID。

@SessionAttributes

作用于类级别,将模型Model中的属性同步到HTTP会话中。默认请求下,模型中的数据存储到request域。该注解可以指定哪些模型属性存储到session中,使得这些属性可以在其他请求中共享。

@SessionAttribute

从会话中提取属性值

表Spring MVC中的会话属性注解

@RequestMapping("/session")
@RestController
@SessionAttributes("user")
public class SessionController {
    @GetMapping("/login")
    public void login(@RequestParam("username") String username, HttpServletRequest request, Model model) {
        System.out.println("login:" + request.getSession().getId());
        model.addAttribute("user",username);
        model.addAttribute("info","登录了");
    }

    @GetMapping("/info")
    public String info(@SessionAttribute("user") String user,HttpServletRequest request) { // 如果该sessionAttribute的值不存在,则请求会失败
        System.out.println("info:" + request.getSession().getId()); // 会话id需与上面的请求保持一致,才能获取到特定会话的值
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            System.out.println(cookie.getName() + ":" + cookie.getValue());
        }
        return user;
    }
}

2.1.3 @ModelAttribute

可以作用于有返回值的方法及处理器的参数,用于将属性值绑定到model的属性中,以用于在视图中使用。

作用于方法级别时,会在每次请求处理之前被调用,并且返回的模型属性会被添加到模型中,供后续的请求处理方法使用。

作用于处理器参数时,先从上面的方法返回值来填充模型,然后如果请求参数中包含了相应属性,则会用请求参数值进行覆盖。

@RequestMapping("/modelAttribute")
@RestController
public class ModelAttributeController {
    @ModelAttribute // 该方法会在每次请求处理之前被调用
    public User createUser() {
        return new User("刘女士","123456");
    }

    // /modelAttribute?username=黄先生
    @GetMapping
    public void get2(@ModelAttribute("user") User user) { // 如果传参的时候没有username及password属性,
        // 那么user的值为createUser的返回值,否则request的参数会覆盖其属性值
        System.out.println(user); // ModelAttributeController.User(username=黄先生, password=123456)
    }

    @Data
    public static class User {
        public String username;
        public String password;
        public User(String username, String password) {
            this.username = username;
            this.password = password;
        }
    }
}

2.1.4 @RequestParam 与 @RequestPart

@RequestPart 主要用于处理multipart/form-data类型的请求。注意,@RequestParam 同样也可以读取该类型的参数。区别在于,@RequestPart能读取参数类型为json的参数,并将其转化为对于的类型,而@RequestParam只能把它当作String类型处理。

@RequestMapping("/paramAndPart")
@RestController
public class ParamAndPartController {
    @PostMapping("/param")
    public void param(@RequestParam("jsonValue") String jsonValue,@RequestParam("file") MultipartFile file) throws IOException {
        System.out.println("jsonValue:" + jsonValue);
        System.out.println("file:" + file); // 获取的是文件路径或者文件名等文本信息,而不是文件本身的内容
        System.out.println(file.getInputStream()); // 到这里才涉及文件的操作,获取文件本身的内容
    }

    @PostMapping("/part")
    public void part(@RequestPart("jsonValue") User jsonValue, @RequestPart("file") MultipartFile file) throws IOException {
        System.out.println("jsonValue:" + jsonValue);
        System.out.println("file:" + file); // 会接收客户端发送的数据文件,并将其存储在服务端的临时文件中
        System.out.println(file.getInputStream());
    }

    @Data
    public static class User implements Serializable {
        String username;
        String password;
    }
}

图 使用postman时需要注意的地方

2.1.5 @RequestBody 与 HttpEntity

@RequestBody 的主要作用是自动将HTTP请求的请求体(body)中的数据绑定到方法参数上。这些数据通常以JSON或XML格式发送。使用该注解时,必须确保请求头中的Content-Type属性值正确地制定了请求体的格式。例如,对于JSON数据,Content-Type通常设置为application/json。@RequestBody 只能绑定一个请求体。

HttpEntity 用于表示一个HTTP请求和响应的实体。实例类有RequestEntity、ResponseEntity。如果将其用于参数的绑定请求体的格式要求与@RequestBody一样。

@RestController
@RequestMapping("/myRequestBody")
public class RequestBodyController {
    @PostMapping
    public void requestBody(@RequestBody User user) {
        System.out.println(user);
    }

    @PostMapping("/httpEntity")
    public void httpEntity(HttpEntity<User> userHttpEntity) {
        System.out.println(userHttpEntity.getBody());
    }

    @Data
    public static class User implements Serializable {
        private String username;
        private String password;
    }
}

2.2 响应

2.2.1 Flash Attributes

当我们进行重定向时,需要向后面的处理器传递参数,可以通过URL参数形式传递,但这样不安全。这时我们可以使用Flash Attributes。

其提供了一种在重定向期间保持状态信息的有效方式,同时避免了将状态信息存储在用户会话中的长期副作用。它一旦被读取,就会自动从session中删除。

@Controller
@RequestMapping("/flash")
public class FlashAttributeController {
    @GetMapping("/login")
    public String login(@RequestParam String username, RedirectAttributes redirectAttributes) {
        System.out.println("login username:" + username);
        redirectAttributes.addFlashAttribute("username",username);
        return "redirect:info";
    }

    @GetMapping("/info")
    public @ResponseBody String showInfo(@ModelAttribute("username") String username) {
        System.out.println("hello " + username);
        return username;
    }
}

2.2.2 @ReponseBody 与 ResponseEntity

@ResponseBody 主要用于将控制器方法返回的对象转换为特定的格式,并直接写入HTTP响应的body中。

ResponseEntity 表示整个HTTP响应,包括状态代码、响应体。其优先级高于@ResponseBody,即返回类型为ResponseEntity的情况下,即使方法同时标注了@ResponseBody,也不会对响应体产生影响。

2.2.3 JSON Views

Spring MVC 为Jackson的序列化视图提供了内置支持。序列化视图允许你在一个对象中选择性的包含某些字段,而不是所有字段。要与@ResponseBody或ResponseEntity一起使用。

@RestController
@RequestMapping("/jsonView")
public class JsonViewController {

    @GetMapping
    @JsonView(User.ShowAttribute.class)
    public User showUser() {
        User user = new User("黄先生", 28, "深圳");
        System.out.println(user); // JsonViewController.User(name=黄先生, age=28, address=深圳)
        return user; // 返回给前端 {"name": "黄先生", "address": "深圳"}
    }

    @Data
    public static class User {
        public interface ShowAttribute {}

        @JsonView(ShowAttribute.class)
        public String name;
        private Integer age;
        @JsonView(ShowAttribute.class)
        private String address;
        public User(String name, Integer age, String address) {
            this.name = name;
            this.age = age;
            this.address = address;
        }
    }
}

3 Controller的配置

3.1 @InitBinder

可以在控制器中指定多个@InitBinder方法,这些方法会在请求处理之前被调用,用于配置数据绑定。通过这些方法,可以定制WebDataBinder的行为。其作用范围为当前Controller下的所有请求(有数值绑定的)。

其具体作用是:1)自定义数据绑定;2)全局配置;3)处理特定类型的参数;4)处理空值或缺失值。

@RestController
@RequestMapping("/initBinder")
public class InitBinderController {
    @InitBinder
    public void initBinder1(WebDataBinder webDataBinder) {
        System.out.println("initBinder1");
    }

    @InitBinder
    public void initBinder2(WebDataBinder webDataBinder) {
        webDataBinder.addCustomFormatter(new DateFormatter("yyyy-MM-dd"));
    }

    @GetMapping
    public void req1(@RequestParam String username) {
        System.out.println("req1:" + username);
    }
}

3.2 @ControllerAdvice

允许开发者定义全局的异常处理、数据绑定等逻辑,而不必在每个单独的controller中重复相同的代码。类似于AOP中的切面,但它专为web层设计。

@ControllerAdvice
public class CustomControllerAdvice {
    @InitBinder
    public void initBinder(WebDataBinder binder) { // 在请求中,方法参数中每有一个参数执行绑定,则该方法都会执行
        System.out.println("CustomControllerAdvice 全局数据绑定处理"); // 可用来配置转换器
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> exceptionHandler(Exception e) { // 全局异常处理
        return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
    }

    @ModelAttribute("webName")
    public String webName() {
        System.out.println("全局@ModelAttribute");
        return "Hello Web";
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MAC 帧(数据链路层)

目录 一、MAC帧的格式 二、无效的帧 三、帧间最小间隔 四、帧的发送与接收 五、小结 一、MAC帧的格式 • 常用的以太网 MAC 帧格式有两种标准 &#xff1a; DIX Ethernet V2 标准&#xff1b; IEEE 的 802.3 标准。 • 最常用的 MAC 帧是以太网 V2 的格式。 二、…

python网络爬虫实战教学——requests的使用(1)

文章目录 专栏导读1、前言2、get请求3、抓取网页4、抓取二进制数据5、请求头 专栏导读 ✍ 作者简介&#xff1a;i阿极&#xff0c;CSDN 数据分析领域优质创作者&#xff0c;专注于分享python数据分析领域知识。 ✍ 本文录入于《python网络爬虫实战教学》&#xff0c;本专栏针对…

git push出错: src refspec dev/xxx does not match any

使用如下命令gitp push出错: git push origin 远端分支名 git push origin dev/xxxx error: src refspec dev/xxxx does not match any error: failed to push some refs to https://git.woa.com/..... 解决方案 1: git push origin 本地分支名:远端分支名 解决方案2&#…

SV-6005TP 双键网络对讲求助模块 sip对讲终端音频模块 支持POE供电 带功放输出

SV-6005TP 双键网络对讲求助模块 sip对讲终端音频模块 支持POE供电 带功放输出 一、描述 SV-6005TP模块是我司的一款壁挂式SIP双按键求助对讲模块&#xff0c;具有10/100M以太网接口&#xff0c;其接收网络的音频数据&#xff0c;实时解码播放&#xff0c;还配置了麦克风输入…

python-学习-Linux系统使用

设置变量并输出 [rootldpbzhaonan py]$ cat var01.py str1hello str2worldprintf "${str1} ${str2} \n" printf ${str1} ${str2} \n\n就是代表换行&#xff0c;使用printf输出的话&#xff0c;没有自动换行。 不使用换行如下图显示 [rootldpbzhaonan py]$ cat var0…

【RPG Maker MV 仿新仙剑 战斗场景UI (七)】

RPG Maker MV 仿新仙剑 战斗场景UI 七 法术物品窗口代码仿新仙剑效果 法术物品窗口 继续水点内容 现在发出及确认物品窗口显示及操作。 代码 function Window_BattleItem() {this.initialize.apply(this, arguments); }Window_BattleItem.prototype Object.create(Pal_Wind…

Java中的I/O讲解(超容易理解)(下篇)

如果想观看更多Java内容 可上我的个人主页关注我&#xff0c;地址子逸爱编程-CSDN博客https://blog.csdn.net/a15766649633?typeblog 使用工具 IntelliJ IDEA Community Edition 2023.1.4 使用语言 Java8 代码能力快速提升小方法&#xff0c;看完代码自己敲一遍&#xff0…

智能合约 之 ERC-20介绍

什么是ERC20 ERC20全称为Ethereum Request for Comment 20&#xff0c;是一种智能合约标准&#xff0c;用于以太坊网络上的代币发行 姊妹篇 - 如何部署ERC20 ERC20的应用场景 代币化资产&#xff0c;例如&#xff1a;USDT 是一种以美元为背书的ERC20代币&#xff0c;每个USDT代…

毅速解析:影响金属3D打印零件品质的几大核心因素

金属3D打印零件的品质&#xff0c;是众多因素交织影响下的结果。从设备到材料&#xff0c;从工艺到后处理&#xff0c;每一个环节都可能成为品质的决定因素。不同厂商之间品质的差异&#xff0c;往往就隐藏在这些看似细微的环节中。 首先&#xff0c;设备性能是决定金属3D打印零…

扩容分区和文件系统(Linux)

在ECS控制台上扩容云盘容量后&#xff0c;对应分区和文件系统并未扩容&#xff0c;您还需要进入ECS实例内部继续扩容云盘的分区和文件系统&#xff0c;将扩容部分的容量划分至已有分区及文件系统内&#xff0c;使云盘扩容生效。本文为您介绍如何通过两个步骤完成Linux实例云盘的…

HarmonyOS系统开发ArkTS入门案例及组件(三)

下一章 目录 一、声明式UI 二、ArkTs 快速入门案例 三、组件 四、渲染控制 一、声明式UI 声明式UI就是一种编写用户界面的范式或方式、 ArArkTS 在继承了Typescript语法的基础上&#xff0c;主要扩展了声明式UI开发相关的能力。 声明式UI开发范式大致流程&#xff1a;…

JavaWeb:AOP、配置优先级、Bean管理、SpringBoot原理、Maven高级

1 AOP 1.1 基本语法 面向切面编程、面向方面编程&#xff0c;面向特定方法编程 在管理bean对象的过程中&#xff0c;主要通过底层的动态代理机制&#xff0c;对特定的方法进行编程 应用&#xff1a;统计每一个业务方法的执行耗时 xml引入依赖 <!-- AOP-->&l…

CSS样式,1行文字溢出...省略,2行文字溢出...省略,多行文字溢出...省略

提示&#xff1a;CSS样式文字溢出…省略 文章目录 前言一、1行文字溢出...省略二、2行或多行文字溢出...省略三、1行或多行文字溢出...省略总结 前言 一、1行文字溢出…省略 test.html <!DOCTYPE html> <html lang"en"> <head><meta charset…

华为ensp中ospf基础 原理及配置命令(详解)

CSDN 成就一亿技术人&#xff01; 作者主页&#xff1a;点击&#xff01; ENSP专栏&#xff1a;点击&#xff01; CSDN 成就一亿技术人&#xff01; ————前言———— OSPF 的全称是 Open Shortest Path First&#xff0c;意为“开放式最短路径优先”。是一种内部网关协…

10米等高线地形图图源

让GIS更简单高效&#xff0c;让地图更丰富及时&#xff01; 最近新发现一个图源&#xff0c;这是一个有10米等高线和山体阴影的地形图数据。 我们现在将该图源加载到水经微图&#xff08;以下简称“微图”&#xff09;Web版后&#xff0c;为你分享其城区二维效果图&#xff0…

vscode中转(跳板)连接目标主机

vscode中转&#xff08;跳板&#xff09;连接目标主机 文章目录 引言正文跳转配置本地密钥 总结 引言 简单讲解如何通过vscode经过跳板机到达目标机的方式&#xff0c;本文基于linux平台&#xff0c;理论上vscode是跨平台的1。 如下本机通过两层跳板到目标主机如何通过vscode…

Jenkins安装Role-based Authorization Strategy不生效

Jenkins安装Role-based Authorization Strategy不生效&#xff0c;需开启Role-based 访问策略。 https://blog.51cto.com/zengestudy/1782494

01-JavaScript基础语法

1. 计算机基础 1.1 计算机组成 1.2 数据存储(重点) 计算机内部使用二进制 0 和 1来表示数据。 所有数据&#xff0c;包括文件、图片等最终都是以二进制数据&#xff08;0 和 1&#xff09;的形式存放在硬盘中的。 所有程序&#xff0c;包括操作系统&#xff0c;本质都是各种…

马斯克开源Grok-1

Grok-1是由马斯克AI创企xAI发布的第一代大语言模型&#xff0c;它以其巨大的参数量——高达3140亿&#xff0c;引起了全球范围内的广泛关注。这一参数量远超其他知名模型&#xff0c;如OpenAI的GPT-3.5&#xff0c;后者仅有1750亿参数。在2024年3月17日&#xff0c;马斯克宣布将…

js和go的列表转树形, 执行速度测试对比

js代码&#xff0c;浏览器上运行 // 列表转树形 export function deepTree(list: any[]): any[] {const newList: any[] [];const map: any {};for (let index 0; index < list.length; index) {const e list[index];map[e.id] e;}for (let index 0; index < list…