对controller层进行深入学习

news2024/9/8 23:48:26

目录

  • 1. controller层是干什么的?
    • 1.1 controller原理图
    • 1.2 controller层为什么要存在?
      • 1.2.1 分离关注点
      • 1.2.2 响应HTTP请求
      • 1.2.3 数据处理与转换
      • 1.2.4 错误处理与状态管理
      • 1.2.5 流程控制
      • 1.2.6 依赖注入与测试
    • 1.3 controller层的优点
      • 1.3.1 多端支持
      • 1.3.2 安全性保障
      • 1.3.3 性能优化
    • 1.4 All in All
  • 2. 研究Restful风格
    • 2.1 什么是Restful风格?
      • 2.1.1 功能
      • 2.1.2 Restful风格与传统风格的区别
        • 2.1.2.1 请求方法
        • 2.1.2.2 数据格式
        • 2.1.2.3 状态码使用
        • 2.1.2.4 异常处理
        • 2.1.2.5 无状态性
        • 2.1.2.6 总结
  • 3. controller层代码
    • 3.1 定义controller风格的注解
      • 3.1.1 @RestController
      • 3.1.2 @RequestMapping
      • 3.1.3 @Slf4j
    • 3.2 依赖注入注解
      • 3.2.1 @Resource和@Autowired的相同点
      • 3.2.2 @Resource和@Autowired的不同点
      • 3.2.3 总结
    • 3.3 依赖注入三种方式
      • 3.3.1 字段注入(最简单,有风险)
      • 3.3.2 构造器注入(最安全,推荐)
      • 3.3.3 Setter方法注入
  • 4. controller层接口代码详解
    • 4.0 HTTP常见请求方法合集
    • 4.1 模糊查询---接口
    • 4.2 findAll---接口
    • 4.3 根据id查询---接口
    • 4.4 增加---接口
    • 4.5 删除---接口
    • 4.5 更新---接口
  • 5 总结

1. controller层是干什么的?

1.1 controller原理图

在这里插入图片描述
在Web应用程序中,控制器层(Controller)是模型-视图-控制器(MVC)架构模式的一个关键组成部分。控制器负责接收用户的输入调用业务逻辑层来处理这些输入并返回适当的响应给视图层
举个例子吧:

平时登陆账号的时候,你想要输入账号和密码吧,然后点击登陆的时候,用户请求是最先传到controller层的,然后controller层再传到service层,为什么不直接传给service层?例如,密码长度不符合要求,或者账号不是有效的电子邮件格式,那么没有必要将请求转发到服务层或数据库层进行更深入的验证。通过在控制器层进行初步验证,可以减少不必要的服务层或数据库层操作,从而提高系统性能和响应速度。另外,在控制器层进行格式验证可以作为安全措施的一部分,防止恶意或格式错误的数据到达后端服务,减少潜在的安全风险。以前的黑客不就玩的sql注入吗,当时的开发者都没有意识到在数据库查询中直接使用用户输入的危险。

1.2 controller层为什么要存在?

在现代Web应用程序中,用户请求通常不会直接传递给服务层(Service),而是通过控制器层(Controller)来处理,这种设计主要是基于以下几个原因:

1.2.1 分离关注点

控制器层和业务逻辑层分离,使得每一层都只关注自己的职责。控制器层关注如何接收请求、验证输入和调用相应的业务逻辑。服务层则关注业务规则和业务流程的具体实现。

1.2.2 响应HTTP请求

在Spring框架中,Controller通过@Controller或@RestController注解标识,配合@RequestMapping等注解,能够响应不同路径的HTTP请求。如果没有Controller,系统将无法正确解析和响应用户请求,导致功能无法实现。

1.2.3 数据处理与转换

Controller负责将接收到的数据(如用户输入的用户名和密码)传递给Service层进行验证,并将验证结果转换为适合客户端展示的格式。例如,使用@ResponseBody注解可以将Java对象自动转换为JSON格式,方便前端处理。

1.2.4 错误处理与状态管理

Controller还负责处理请求过程中可能出现的错误情况,并管理HTTP状态码。如果去掉Controller,这些错误处理和状态管理将无处安放,可能导致用户体验不佳和安全风险

1.2.5 流程控制

Controller通过方法调用和返回值决定后续执行流程。例如,如果用户登录失败,Controller可以决定重新显示登录页面和错误信息;如果登录成功,则跳转到用户的主页。这种流程控制能力是细粒度处理请求不可或缺的。

1.2.6 依赖注入与测试

Spring框架中的Controller可以利用依赖注入(DI)集成其他组件(如Service、DAO等),并通过@Autowired注解自动装配所需的依赖。这使得单元测试变得更加容易,同时也降低了组件间的耦合度。

1.3 controller层的优点

1.3.1 多端支持

在一个多端应用(如网页、移动端)中,不同的前端可能发送类似的请求(如获取用户信息)。Controller可以统一处理这些请求,减少重复代码。

1.3.2 安全性保障

Controller可以结合Spring Security等安全框架,提供认证、授权和跨站请求伪造(CSRF)防护等功能,增强应用的安全性。

1.3.3 性能优化

通过合理的Controller设计(如缓存、异步处理),可以提升系统的响应速度和并发处理能力。

1.4 All in All

Controller在Web应用中扮演着核心角色,负责处理请求、响应、数据转换、错误处理和流程控制等关键任务。去掉Controller将导致系统无法正常响应用户请求,破坏架构的模块化和可维护性。因此,在实际开发中应充分重视Controller的设计和实现。

以下是控制器层的详细阐述:

2. 研究Restful风格

2.1 什么是Restful风格?

Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

2.1.1 功能

  1. 资源:互联网所有的事物都可以被抽象为资源
  2. 资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作。
  3. 分别对应 添加、 删除、修改、查询。

2.1.2 Restful风格与传统风格的区别

2.1.2.1 请求方法

Restful风格:Restful风格的Controller全面使用HTTP的方法,包括GET、POST、PUT、DELETE等。每种方法都有具体的含义,例如GET用于获取资源,POST用于创建新资源,PUT用于更新资源,DELETE用于删除资源。
传统风格:传统风格的Controller通常只使用GET和POST请求方法。这意味着不管需要进行什么样的操作,基本都依赖于这两种方法,可能导致一个操作对应多个URL。

2.1.2.2 数据格式

Restful风格:Restful风格的接口通常使用JSON或XML作为数据交换格式,它们易于解析和生成,同时具有良好的可读性。
传统风格:通常使用xml。

2.1.2.3 状态码使用

Restful风格:Restful风格的Controller充分利用了HTTP状态码来表示不同的结果状态,如200(成功)、201(已创建)、404(未找到)、500(服务器错误)等,这些状态码能明确告诉客户端请求的处理结果。
传统风格:传统风格的Controller中,状态码的使用较为单一,通常只有200(成功)被频繁使用,其他状态码较少出现。

2.1.2.4 异常处理

Restful风格:Restful风格的Controller采用统一的异常处理器,可以集中管理错误处理逻辑,并返回统一的错误信息和状态码。
传统风格:传统风格的异常处理可能分散在不同的Controller中,导致代码重复和管理不便。

2.1.2.5 无状态性

Restful风格:Restful风格的设计是无状态的,每次请求都包含了所有必需的信息,这使得系统更加简单且易于扩展。
传统风格:传统风格的Controller可能会依赖存储在服务器端的会话(Session)状态,这导致系统在水平扩展时面临挑战。

2.1.2.6 总结

Restful风格的Controller在URL设计、HTTP方法使用、状态码管理等方面具有明显优势,使得后端服务更加标准化和易于维护。在实际开发中,应当尽量采用Restful风格的设计原则来构建Web应用的后端服务。

3. controller层代码

package com.goblin.BIbackend.controller;

import com.goblin.BIbackend.common.BaseResponse;
import com.goblin.BIbackend.common.ListWithTotal;
import com.goblin.BIbackend.common.ResultUtils;
import com.goblin.BIbackend.model.entity.Complaints;
import com.goblin.BIbackend.service.ComplaintsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;

@RestController
@RequestMapping("/complaints")
@Slf4j
public class ComplaintsController {
    @Resource
    private ComplaintsService complaintsService;

    //模糊查询
    @PostMapping("/search")
    public BaseResponse<ListWithTotal<Complaints>> search(@RequestBody Complaints keyword) {
        log.info("查询投诉信箱:{}", keyword);
        List<Complaints> complaints = complaintsService.search1(keyword);
        int total = complaints.size();
        log.info("查询投诉信箱总数:{}", total);
        ListWithTotal<Complaints> list = new ListWithTotal<>(complaints, total);
        return ResultUtils.success(list);
    }

    @GetMapping("/list")
    public BaseResponse<ListWithTotal<Complaints>> list() {
        List<Complaints> complaints = complaintsService.getList();
        int total = complaintsService.count1();
        log.info("查询投诉信箱总数:{}", total);
        ListWithTotal<Complaints> list = new ListWithTotal<>(complaints, total);
        return ResultUtils.success(list);
    }

    @GetMapping("/select2")
    public BaseResponse<Complaints> select2(Long id) {
        log.info("查询投诉信息:{}", id);
        Complaints complaints = complaintsService.select2(id);
        log.info("查询投诉信息:{}", complaints);
        return ResultUtils.success(complaints);
    }

    @PostMapping("/insert2")
    public BaseResponse<Complaints> insert2(@RequestBody Complaints complaints) {
        Complaints result = complaintsService.insert2(complaints);
        return ResultUtils.success(result);
    }

    @DeleteMapping("/delete2")
    public BaseResponse<Long> delete2(Long id) {
        complaintsService.delete2(id);
        return ResultUtils.success(id);
    }

    @PutMapping("/update2")
    public BaseResponse<Complaints> update2(@RequestBody Complaints complaints) {
        complaintsService.update2(complaints);
        return ResultUtils.success(complaints);
    }

}

这段代码是一个Spring Boot应用程序中的ComplaintsController类,它使用Spring MVC框架来处理(Complaints)相关的HTTP请求。以下是对代码的逐行解析:

3.1 定义controller风格的注解

@RestController
@RequestMapping("/complaints")
@Slf4j

这段代码的主要作用是定义一个处理与"/complaints"相关的HTTP请求的控制器,并自动生成日志对象。

3.1.1 @RestController

这是Spring 4之后新加入的注解,原来在@Controller中返回json需要@ResponseBody来配合,如果直接用@RestController替代@Controller就不需要再配置@ResponseBody,默认返回json格式。这个注解标识这个类是一个RestController,即控制器(Controller),主要用来处理由DispatcherServlet分发的请求,还可以对数据进行校验等操作。

DispatcherServlet是Spring MVC框架中的一个核心组件,它作为前端控制器(Front Controller),负责将接收到的HTTP请求转发到相应的处理器(Controller)。DispatcherServlet是Spring MVC中的中央调度器,它扩展了Servlet API,提供了一种机制来映射请求URL到对应的处理器方法。

3.1.2 @RequestMapping

这个注解用于映射Web请求,即访问"/complaints"路径时,会执行该类下的某个方法。它可以应用于类或方法上,当应用于类上时,表示类中的所有响应请求的方法都是以该地址作为父路径。

3.1.3 @Slf4j

这是Lombok库中的一个注解,用于自动生成日志对象。在使用时,只需在类上添加此注解,就可以自动生成名为log的SLF4J、Log4j、java.util.logging、Commons Logging、Logback以及java.lang.Appendable的实例。

3.2 依赖注入注解

    @Resource
    private ComplaintsService complaintsService;

先说说@Resource和@Autowired。@Resource和@Autowired都是Spring框架提供的依赖注入(DI)注解,用于实现自动装配bean。

3.2.1 @Resource和@Autowired的相同点

1.依赖注入:两者都用于将Spring容器中的bean自动注入到字段、构造函数或setter方法中。
2.减少代码:通过使用这两个注解,可以减少样板代码,即不需要手动编写代码来从容器中获取bean。
3.支持类型注入:它们都支持通过类型来自动装配,意味着Spring会查找容器中相应类型的bean来注入。

3.2.2 @Resource和@Autowired的不同点

1.来源:@Autowired是Spring自己的注解,属于org.springframework.beans.factory.annotation包。
@Resource是Java EE的注解,适用于更广泛的Java应用,不仅限于Spring框架。
2.注入方式:@Autowired:默认按类型(byType)注入,需要时可以结合@Qualifier指定具体的bean名称。
@Resource:默认按名称(byName)注入,也可通过配置type属性改为按类型注入。
3.参数配置:@Autowired:只有一个required参数,表示是否需要这个依赖。
@Resource:包含多个参数,最重要的是name和type,灵活性更高。
4.使用场景:@Autowired更常用于Spring应用程序中,特别是在使用Spring框架的注解配置时。
@Resource可以用于那些需要兼容Java EE注解的场合,或者在某些特定情况下,开发者可能更倾向于使用Java EE的注解风格。
5.应用建议:@Autowired:更适合Spring环境,特别是当需要更灵活的依赖注入时(例如构造器注入)。
@Resource:更适合与Spring解耦的情境,或者在EE环境中使用。
在Spring配置中,如果同时使用了@Autowired和@Resource,Spring会首先尊重@Autowired的配置。
7.异常处理:@Autowired在找不到bean时会抛出NoSuchBeanDefinitionException。
@Resource在找不到bean时可能会抛出ResourceException。

3.2.3 总结

@Autowired和@Resource都可以用来实现依赖注入,但它们在自动装配的默认行为、来源、使用场景和异常处理等方面存在差异。在Spring应用程序中,推荐使用@Autowired,因为它提供了更好的Spring集成和更灵活的配置选项。

3.3 依赖注入三种方式

依赖注入是一种设计模式,用来实现对象之间的依赖关系。传统的面向对象编程中,类与类之间的依赖关系是通过硬编码来实现的,而依赖注入则将这种依赖关系交给外部容器来处理,从而实现了解耦。
在Spring中依赖注入有三大类:字段注入、构造器注入、Setter方法注入。

3.3.1 字段注入(最简单,有风险)

字段注入是通过在类的字段上使用注解来直接注入依赖对象的一种方式,虽然简单直接,但并不推荐使用,因为它破坏了类的封装性。
字段注入会引起以下的问题

  1. 对象的外部可见性
  2. 可能导致循环依赖
  3. 无法设置注入的对象为final,也无法注入静态变量

什么是字段注入?举例如下:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class MyClass {
    // 使用@Autowired注解进行字段注入
    @Autowired
    private MyService myService;

    public void doSomething() {
        myService.performAction();
    }
}

字段注入非常的简便,通过以上代码我们可以轻松的使用MyService类。

MyService myService= new MyService();
myService.performAction();

这样执行结果为空指针异常,这就是字段注入的第一个问题:对象的外部可见性

public class TestA(){

    @Autowired
    private TestB testB;

}
public class TestB(){

    @Autowired
    private TestA testA;

}

上面两段代码卡bug,这段代码在idea中不会报任何错误,但是启动项目时会发现报错,大致意思是:创建Bean失败,原因是当前Bean已经作为循环引用的一部分注入到了其他Bean中。
这就是字段注入的第二个问题:可能导致循环依赖
字段注入还有第三个问题:无法设置注入的对象为final,也无法注入静态变量,原因是变量必须在类实例化进行初始化。

3.3.2 构造器注入(最安全,推荐)

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class MyClass {
    private final MyService myService;

    // 使用@Autowired注解进行构造器注入
    @Autowired
    public MyClass(MyService myService) {
        this.myService = myService;
    }

    public void doSomething() {
        myService.performAction();
    }
}

在这个例子中,MyClass的构造函数接收一个MyService类型的参数,并通过@Autowired注解告诉Spring框架自动注入一个合适的MyService实例。这样,当创建MyClass的实例时,Spring会自动调用带有@Autowired注解的构造函数,并将相应的依赖项传递给它。

构造器注入通过在类的构造函数上使用注解来自动装配依赖对象。与字段注入相比,构造器注入有以下优点:
1.强制依赖关系:构造器注入要求必须提供所有必需的依赖项,否则将无法创建类的实例。这有助于确保类在使用之前已经正确地初始化了其依赖项。
2.不可变性:由于构造器注入是在构造函数中完成的,一旦对象被创建,其依赖项就无法更改。这有助于保持对象的不变性,并减少潜在的错误和副作用。
3.可测试性:构造器注入使得单元测试更加容易,因为可以在测试时轻松地提供模拟或存根依赖项。

3.3.3 Setter方法注入

Setter方法注入是依赖注入的一种方式,它**通过在目标类中定义一个或多个setter方法来接收依赖项的实例。**这种方式允许将依赖项的创建和管理从使用对象的类中分离出来,从而实现解耦和易于维护的代码。

public class MyClass {
    private MyDependency myDependency;

    // Setter method for dependency injection
    public void setMyDependency(MyDependency myDependency) {
        this.myDependency = myDependency;
    }

    public void doSomething() {
        // Use the injected dependency
        myDependency.performAction();
    }
}

在这个例子中,MyClass 有一个 myDependency 属性,它需要被注入一个 MyDependency类型的实例。通过定义一个名为 setMyDependency的setter方法,我们可以在外部容器(如Spring)中配置并注入所需的依赖项。
当Spring容器启动时,它会扫描所有的bean定义,并根据配置文件或其他配置信息自动调用相应的setter方法,将依赖项注入到目标对象中。这样,我们就可以在不修改目标类的代码的情况下,灵活地更改依赖项的实现或配置。
需要注意的是,尽管setter方法注入是一种常见的依赖注入方式,但它并不是唯一的选择。其他依赖注入方式,如构造器注入、字段注入和接口注入等,也可以用来满足不同的需求和场景。

4. controller层接口代码详解

4.0 HTTP常见请求方法合集

在RESTful API设计中,通常使用GET、POST、PUT、PATCH和DELETE方法来操作资源。这些方法的选择反映了操作的语义,有助于保持API的直观性和一致性。例如,使用GET来请求数据,使用POST来创建新资源,使用PUT来更新现有资源,使用DELETE来删除资源。

  1. GET:请求获取指定的资源。
  2. POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。
  3. PUT:从客户端向服务器传送的数据取代指定的文档的内容。
  4. DELETE:请求服务器删除指定的内容。
  5. PATCH:对资源进行部分修改。

4.1 模糊查询—接口

@PostMapping("/search")
    public BaseResponse<ListWithTotal<Complaints>> search(@RequestBody Complaints keyword) {
        log.info("查询投诉信箱:{}", keyword);
        List<Complaints> complaints = complaintsService.search1(keyword);
        int total = complaints.size();
        log.info("查询投诉信箱总数:{}", total);
        ListWithTotal<Complaints> list = new ListWithTotal<>(complaints, total);
        return ResultUtils.success(list);
    }

模糊查询:客户端返回一个Complaints 类对象到controller层,用POST接口。

在Spring框架中,@PostMapping(“/search”)是一个注解,用于将HTTP的POST请求映射到特定的处理方法。这里的"/search"是URL路径的一部分,表示当客户端向服务器发送一个POST请求到"/search"路径时,该请求将被路由到带有@PostMapping(“/search”)注解的方法进行处理。
具体来说,@PostMapping(“/search”)中的"search"是一个字符串字面量,它定义了处理POST请求的URL路径。在这个例子中,当客户端发送一个POST请求到"/search"路径时,服务器会调用带有@PostMapping(“/search”)注解的方法来处理这个请求。这个方法可以接收和处理来自客户端的数据,并返回相应的响应。

BaseResponse是一个通用的响应类,用于封装API接口的返回结果。它包含一些常见的属性,如code、message和data。BaseResponse表示返回的数据类型是一个包含投诉的列表和总数的对象。

@RequestBody Complaints keyword是一个Spring框架中的注解,用于将HTTP请求体中的数据绑定到方法参数上。在上面的代码中,Complaints是一个Java类,表示投诉信息的数据结构。keyword 是这个类的一个实例,用于接收客户端发送的投诉信息。
当客户端发送一个POST请求到服务器的"/search"路径时,请求体中的数据会被解析并转换为Complaints类的实例。然后,这个实例会被传递给search方法作为参数keyword。

ResultUtils.success(list) 是一个方法调用,它是一个工具类中的一个静态方法。这个方法的作用是创建一个成功的响应对象,并将传入的参数 list 作为数据返回给客户端。
在上面的代码中,list 是一个包含投诉信息的列表,而 ResultUtils.success(list) 方法会创建一个BaseResponse 类型的对象,并设置状态码为成功(例如200),同时将 list作为响应的数据部分。这样,当客户端接收到这个响应时,它将能够获取到包含投诉信息的数据。
ResultUtils.success()`方法封装一些常见的响应结构,如状态码、消息和数据等,以便在应用程序中统一处理响应结果。

在这里插入图片描述

4.2 findAll—接口

@GetMapping("/list")
    public BaseResponse<ListWithTotal<Complaints>> list() {
        List<Complaints> complaints = complaintsService.getList();
        int total = complaintsService.count1();
        log.info("查询投诉信箱总数:{}", total);
        ListWithTotal<Complaints> list = new ListWithTotal<>(complaints, total);
        return ResultUtils.success(list);
    }

findAll:请求获取所有的Complaints对象,用GET接口。

4.3 根据id查询—接口

@GetMapping("/select2")
    public BaseResponse<Complaints> select2(Long id) {
        log.info("查询投诉信息:{}", id);
        Complaints complaints = complaintsService.select2(id);
        log.info("查询投诉信息:{}", complaints);
        return ResultUtils.success(complaints);
    }

4.4 增加—接口

@PostMapping("/insert2")
    public BaseResponse<Complaints> insert2(@RequestBody Complaints complaints) {
        Complaints result = complaintsService.insert2(complaints);
        return ResultUtils.success(result);
    }

增加:将一个Complaints 对象传到controller层,用POST接口。

4.5 删除—接口

@DeleteMapping("/delete2")
    public BaseResponse<Long> delete2(Long id) {
        complaintsService.delete2(id);
        return ResultUtils.success(id);
    }

删除:传id给controller层,请求删除指定的Complaints对象,用DELETE接口。

4.5 更新—接口

@PutMapping("/update2")
    public BaseResponse<Complaints> update2(@RequestBody Complaints complaints) {
        complaintsService.update2(complaints);
        return ResultUtils.success(complaints);
    }

更新:将一个Complaints 对象传到controller层取代原有Complaints ,从客户端向服务器传送的数据取代指定的文档的内容,用PUT接口。

5 总结

文章首先讲了controller层的重要性和优点,然后讲了restful风格和传统风格,接着对代码进行分析:分析了依赖注入的三种方法,最后是对接口的解析,不可谓不深刻。看完这篇文章应该能知道什么是controller层。代码谁都会写,真正的区别在于对代码底层的理解。

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

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

相关文章

PHP 程序员是学 Swoole ?还是学 Go ?

大家好&#xff0c;我是码农先森。 面临现状 这次为什么要讨论这个话题&#xff0c;因为 Swoole 和 Go 在 PHP 程序员坊间一直都是茶语饭后的谈资&#xff0c;觉得懂 Swoole 和 Go 的就高人一等。相信有很多的 PHP 程序员&#xff0c;自打 Swoole 发布以来就从来没有使用过。…

Z-Fighting 深度冲突权威指南

Z-Fighting 是渲染管道中深度测试中出现的问题。它是由深度值的有限数值精度引起的。故障将表现为不正确的渲染&#xff0c;即屏幕上错误地显示应该被遮挡在另一个后面的对象。故障主要发生在透视投影变换中&#xff0c;但也可能发生在正交投影变换中。到目前为止&#xff0c;一…

GaussDB关键技术原理:高性能(五)

GaussDB关键技术原理&#xff1a;高性能&#xff08;四&#xff09;从USTORE存储引擎、计划缓存计划技术、数据分区与分区剪枝、列式存储和向量化引擎、SMP并行执行等五方面对高性能关键技术进行解读&#xff0c;本篇将从LLVM动态查询编译执行、SQL-BYPASS执行优化、线程池化、…

threeJS 点击模型出现弹框

前言 需要实现点击模型出现弹框展示模型详细信息 实现代码 // 创建3D渲染器 - 初始化时调用 function createCss3DRender(){labelRenderer new CSS3DRenderer();labelRenderer.setSize(window.innerWidth, window.innerHeight);labelRenderer.domElement.style.position &…

如何将本地仓库中的文件推送到远程git服务器

第一步&#xff1a;进入所在项目&#xff0c;右击打开"Git Bash Here" 第二步&#xff1a;git config --global user.email "18351810763163.com" // 输入你的名称 第三步&#xff1a;git config --global user.name "chenliang-sam&quo…

Mongodb单字段索引详解

学习mongodb&#xff0c;体会mongodb的每一个使用细节&#xff0c;欢迎阅读威赞的文章。这是威赞发布的第89篇mongodb技术文章&#xff0c;欢迎浏览本专栏威赞发布的其他文章。如果您认为我的文章对您有帮助或者解决您的问题&#xff0c;欢迎在文章下面点个赞&#xff0c;或者关…

Github 2024-07-11 Go开源项目日报 Top10

根据Github Trendings的统计,今日(2024-07-11统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Go项目10Solidity项目1Python项目1frp: 一个开源的快速反向代理 创建周期:2946 天开发语言:Go协议类型:Apache License 2.0Star数量:75872 …

【文档+源码+调试讲解】冷冻仓储管理系统

摘 要 随着互联网时代的到来&#xff0c;同时计算机网络技术高速发展&#xff0c;网络管理运用也变得越来越广泛。因此&#xff0c;建立一个B/S结构的冷冻仓储管理系统&#xff0c;会使冷冻仓储管理系统工作系统化、规范化&#xff0c;也会提高冷冻仓储管理系统平台形象&#x…

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第一篇 嵌入式Linux入门篇-第十八章 Linux编写第一个自己的命令

i.MX8MM处理器采用了先进的14LPCFinFET工艺&#xff0c;提供更快的速度和更高的电源效率;四核Cortex-A53&#xff0c;单核Cortex-M4&#xff0c;多达五个内核 &#xff0c;主频高达1.8GHz&#xff0c;2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…

有哪些媒体适合邀请来报道我们的活动?

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 挑选合适的媒体参加活动发布会时&#xff0c;需要考虑活动的主题、目标受众以及预期效果。建议可以考虑邀请以下几类媒体&#xff1a; 行业媒体&#xff1a;专注于您活动所在行业的媒体&…

视图库对接系列(GA-T 1400)十五、视图库对接系列(本级)删除、取消订阅

说明 之前说了订阅和修改订阅,今天我们来实现删除和取消订阅二个接口。删除订阅 逻辑: 请求下级的接口成功我们就删除数据库的对应数据视图库接口定义 实现 service接口层 //删除订阅ResponseStatusListModeObject deleteSubscribes(String idList, HttpServletRequest re…

Python32 极限学习机ELM

极限学习机&#xff08;ELM&#xff09;是一种简单的单层前馈神经网络&#xff08;SLFN&#xff09;学习算法。理论上&#xff0c;极限学习机算法&#xff08;ELM&#xff09;往往以极快的学习速度提供良好的性能&#xff08;属于机器学习算法&#xff09;&#xff0c;由Huang等…

MybatisPlus 使用教程

MyBatisPlus使用教程 文章目录 MyBatisPlus使用教程1、使用方式1.1 引入依赖1.2 构建mapper接口 2、常用注解2.1 TableName2.2 TableId2.3 TableField MyBatisPlus顾名思义便是对MyBatis的加强版&#xff0c;但两者本身并不冲突(只做增强不做改变)&#xff1a; 引入它并不会对原…

krpano开启日志公能

<krpano version"1.21" title"博物馆" debugmode"true" > 之后鼠标右键菜单栏最后一行 点击&#xff08;开启后会发生变化&#xff09;。

【云岚到家】-day05-4-项目迁移-商品搜索

【云岚到家】-day05-4-项目迁移-商品搜索 2 项目迁移-商品搜索2.1 迁移目标2.2 能力基础2.2.1 索引同步方案设计能力2.2.2 Elasticsearch全文检索应用能力 2.3 需求分析2.3.1 界面原型2.3.2 功能列表梳理 2.4 系统设计2.4.1 索引结构2.4.2 索引同步方案2.4.3 搜索自动补全2.4.4…

SpringBoot项目架构实战之“网关zuul搭建“

第三章 网关zuul搭建 前言&#xff1a; 1、主要功能 zuul主要提供动态路由&#xff08;内置ribbon实现&#xff09;和过滤&#xff08;可以做统一鉴权过滤器、灰度发布过滤器、黑白名单IP过滤器、服务限流过滤器&#xff08;可以配合Sentinel实现&#xff09;&#xff09;功能…

【IT领域新生必看】解锁 `final` 关键字的秘密:Java 编程中的终极武器

文章目录 引言什么是 final 关键字&#xff1f;一、 final 变量final 局部变量final 实例变量final 静态变量 二、 final 方法三、 final 类四、 final 关键字的实际应用1. 定义常量2. 防止方法被重写3. 创建不可变类4. 优化性能 五、 final 的一些常见误区1. final 变量不能在…

力扣2356.二维差分模板——子矩阵元素加1

力扣2356.二维差分模板——子矩阵元素加1 模板题 最后将n2*n2的矩阵删去周围一圈变成n*n矩阵的操作 class Solution {public:vector<vector<int>> rangeAddQueries(int n, vector<vector<int>>& queries) {vector<vector<int>> res…

ONLYOFFICE 8.1版本版本桌面编辑器测评

ONLYOFFICE官网链接&#xff1a;ONLYOFFICE - 企业在线办公应用软件 | ONLYOFFICE ONLYOFFICE在线办公套件&#xff1a;在线办公套件 | ONLYOFFICE ONLYOFFICE在线PDF编辑器、阅读器和转换器&#xff1a;在线PDF查看器和转换器 | ONLYOFFICE ONLYOFFICE 8.1版本桌面编辑器是…

【OC】巧用UIStackView简化布局

UIStackView的运用 文章目录 UIStackView的运用引入UIStackView的作用UIStackView的属性compression resistance 和 huggingaxisalignmentDistributionspacing UIStackView的方法UIStackView的示例 引入 在仿写ZARA的过程之中&#xff0c;我看到软件之中是有大量的按钮排列在一…