【零基础入门SpringMVC】第四期——RESTFUL专题

news2025/7/9 3:15:19

一、RESTFul 概述

1、什么是 RESTFul

  • REST 全称 Representational State Transfer 代表 表现层资源状态转移
    • 视图层 + 控制层 == 表现层
  • 百度百科这样说:
    • RESTFUL是一种网络应用程序的设计风格和开发方式,基于HTTP,可以使用XML格式定义或JSON格式定义。
    • RESTFUL 适用于移动互联网厂商作为业务接口的场景,实现第三方 OTT 调用移动网络资源的功能,动作类型为新增、变更、删除所调用资源。

2、主要是对网络资源进行操作,那么什么是资源?

  • web工程放到服务器上的过程叫部署,在服务器上,万物皆资源
  • 是一种理解方式的名词定义,将服务器当做由很多离散资源组成的一个整体
  • URI 是资源的名称,同时也是资源在Web服务器上的地址,用户可以在客户端应用通过URI对感兴趣的资源进行交互
  • 一个资源可以由一个或多个URI来标识

3、什么是资源的表述?【就是资源的体现形式】

  • 资源的表述是一段对于资源在某个特定时刻的状态的描述。例如HTML、XML、音频视频等【资源表述的不同格式】
  • 资源的表述格式可以通过协商机制来确定,请求和响应方向的表述通过使用不同的格式
  • 资源可以在客户端和服务器端进行交换(转移)【将服务器的资源呈现到客户端】

4、什么是状态转移?

  • 通过转移和操作资源的表述,来简介实现操作资源
    • 转移:将服务器中的资源转移到客户端
    • 操作资源的表述:请求路径

二、操作方式说明

  • 在HTTP协议里面,有四个表示基本操作的动词:

    • GET 获取资源
    • PUT 更新资源
    • POST 新建资源
    • DELETE 删除资源
  • REST 风格提倡使用地址传值的方式

    • 不使用问号键值对的方式携带请求参数,而是从前到后各个单词用斜杠分开
    • 意思是将要发送给服务器的数据作为URL的值的一部分
    • 属于对URL地址使用统一的规范,进而保证整体风格的一致性
  • 不从功能角度,从思想角度我们分析一下应该如何实现?【针对某个资源而言】

    • 同一个请求路径,不同的请求方式来表示不同的操作

      • 这个不同的操作可以通过RequestMapping注解的method属性指定,也可以使用对应的派生注解
    • 如果我们需要传递参数, 我们在控制器方法上的RequestMapping注解对应位置,使用 /{参数名}的方式

      • 假设我们希望通过 id 查询用户数据 【超链接是GET请求】
      @GetMapping("/user/{id}")
      public String getUserById(){
      	System.out.println("根据id查询用户信息");
      	return "success";
      }
      

      对应请求的超链接我们可以这样写,使用了占位符,就必须传递对应位置参数的数据

      <a th:href="@{/user/1}">根据id查询用户信息</a><br>
      
    • 如果我们需要通过前端表单获取数据,然后添加我们的用户信息【我们采用POST方式】

      @PostMapping("/user")
      public String insertUser(String username, String password){
      	System.out.println("添加用户信息: " + username + " " + password);
      	return "success";
      }
      

      在前端页面表单method的属性需要指定为 POST【测试POST有两种办法,表单、AJAX

      <form th:action="@{/user}" method="post">
          用户名 <input type="text" name="username"><br>
          密码 <input type="text" name="password"><br>
          <input type="submit" value="添加">
      </form>
      
  • 对于浏览器大多只支持 POSTGET 请求,其他请求默认为 GET 请求,那么我们想实现PUTDELETE 请求应该怎么办呢?

☀️ 在SpringMVC 中提供了HiddenHttpMethodFilter 帮我们将POST请求转换为 DELETEPUT 请求

  • 我们如何使用这个机制?

    • 需要在 web.xml 中注册这个过滤器,因为过滤器是按注册位置先后执行的,所以我们要把设置编码的过滤器放到最前面

      <filter>
          <filter-name>HiddenHttpMethodFilter</filter-name>
          <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
      </filter>
      <filter-mapping>
          <filter-name>HiddenHttpMethodFilter</filter-name>
          <url-pattern>/*</url-pattern>
      </filter-mapping>
      
    • 然后通过表单发起请求,并将请求方式设置为 POST,再添加一个name属性参数值为 _method = “请求方式”【PUT / DELETE

      <form th:action="@{/user}" method="put">
          <input type="hidden" name="_method" value="PUT">
          用户名 <input type="text" name="username"><br>
          密码 <input type="text" name="password"><br>
          <input type="submit" value="修改">
      </form>
      
    • 在控制器中设置对应的方法就行

      @PutMapping("/user")
      public String updateUser(String username, String password){
      	System.out.println("修改用户信息: " + username + " " + password);
      	return "success";
      }
      
    • 这里使用了控制器方法的形参获取请求参数,如果对获取请求参数不太了解可以参考 传送门

  • 接下来我们通过一个CRUD案例,来演示具体功能的实现

三、案例演示

  • 需求:实现对员工信息的增删改查 【我们写一个集合来存储数据,并不真正的去连接数据库】

  • 准备工作:

    • 创建新模块 springMVC-rest,添加打包方式和使用的依赖

      <?xml version="1.0" encoding="UTF-8"?>
      <project xmlns="http://maven.apache.org/POM/4.0.0"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
          <modelVersion>4.0.0</modelVersion>
      
          <groupId>com.atguigu</groupId>
          <artifactId>springMVC-reset</artifactId>
          <version>1.0-SNAPSHOT</version>
          <packaging>war</packaging>
          <dependencies>
              <!-- SpringMVC -->
              <dependency>
                  <groupId>org.springframework</groupId>
                  <artifactId>spring-webmvc</artifactId>
                  <version>5.3.1</version>
              </dependency>
      
              <!-- 日志 -->
              <dependency>
                  <groupId>ch.qos.logback</groupId>
                  <artifactId>logback-classic</artifactId>
                  <version>1.2.3</version>
              </dependency>
      
              <!-- ServletAPI -->
              <dependency>
                  <groupId>javax.servlet</groupId>
                  <artifactId>javax.servlet-api</artifactId>
                  <version>3.1.0</version>
                  <scope>provided</scope>
              </dependency>
      
              <!-- Spring5Thymeleaf整合包 -->
              <dependency>
                  <groupId>org.thymeleaf</groupId>
                  <artifactId>thymeleaf-spring5</artifactId>
                  <version>3.0.12.RELEASE</version>
              </dependency>
          </dependencies>
          <properties>
              <maven.compiler.source>8</maven.compiler.source>
              <maven.compiler.target>8</maven.compiler.target>
              <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
          </properties>
      
      </project>
      
    • 编写我们的 pojo 类,封装员工信息 Employee

      package com.atguigu.rest.bean;
      
      /**
       * @author Bonbons
       * @version 1.0
       */
      public class Employee {
          private Integer id;
          private String lastName;
          private String email;
          // 1代表男,0代表女
          private Integer gender;
      
          public Employee() {
          }
      
          public Employee(Integer id, String lastName, String email, Integer gender) {
              this.id = id;
              this.lastName = lastName;
              this.email = email;
              this.gender = gender;
          }
      
          public Integer getId() {
              return id;
          }
      
          public void setId(Integer id) {
              this.id = id;
          }
      
          public String getLastName() {
              return lastName;
          }
      
          public void setLastName(String lastName) {
              this.lastName = lastName;
          }
      
          public String getEmail() {
              return email;
          }
      
          public void setEmail(String email) {
              this.email = email;
          }
      
          public Integer getGender() {
              return gender;
          }
      
          public void setGender(Integer gender) {
              this.gender = gender;
          }
      
          @Override
          public String toString() {
              return "Employee{" +
                      "id=" + id +
                      ", lastName='" + lastName + '\'' +
                      ", email='" + email + '\'' +
                      ", gender=" + gender +
                      '}';
          }
      }
      
    • dao层创建一个类完成对数据库的操作,在这个类中用一个集合模拟数据库 EmployeeDao

      package com.atguigu.rest.dao;
      
      import com.atguigu.rest.bean.Employee;
      import org.springframework.stereotype.Repository;
      
      import java.util.Collection;
      import java.util.HashMap;
      import java.util.Map;
      
      /**
       * 我们用Dao模拟操作数据库,实际不去连接数据库
       * @author Bonbons
       * @version 1.0
       */
      @Repository
      public class EmployeeDao {
      
          private static Map<Integer, Employee> employees = null;
      
          static{
              employees = new HashMap<Integer, Employee>();
      
              employees.put(1001, new Employee(1001, "E-AA", "aa@163.com", 1));
              employees.put(1002, new Employee(1002, "E-BB", "bb@163.com", 1));
              employees.put(1003, new Employee(1003, "E-CC", "cc@163.com", 0));
              employees.put(1004, new Employee(1004, "E-DD", "dd@163.com", 0));
              employees.put(1005, new Employee(1005, "E-EE", "ee@163.com", 1));
          }
      
          // 记录下一个用户可获得的 ID
          private static Integer initId = 1006;
      
          /**
           * 添加和修改用户信息
           * @param employee 一个员工对象
           */
          public void save(Employee employee){
              if(employee.getId() == null){
                  employee.setId(initId++);
              }
              employees.put(employee.getId(), employee);
          }
      
          /**
           *
           * @return
           */
          public Collection<Employee> getAll(){
              return employees.values();
          }
      
          public Employee get(Integer id){
              return employees.get(id);
          }
      
          public void delete(Integer id){
              employees.remove(id);
          }
      }
      
    • web.xml 中注册过滤器和前端控制器

      <?xml version="1.0" encoding="UTF-8"?>
      <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
               version="4.0">
          <!--配置编码过滤器-->
          <filter>
              <filter-name>CharacterEncodingFilter</filter-name>
              <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
              <init-param>
                  <param-name>encoding</param-name>
                  <param-value>UTF-8</param-value>
              </init-param>
              <init-param>
                  <param-name>forceResponseEncoding</param-name>
                  <param-value>true</param-value>
              </init-param>
          </filter>
          <filter-mapping>
              <filter-name>CharacterEncodingFilter</filter-name>
              <url-pattern>/*</url-pattern>
          </filter-mapping>
      
          <!--处理put和delete请求的HiddenHttpMethodFilter-->
          <filter>
              <filter-name>HiddenHttpMethodFilter</filter-name>
              <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
          </filter>
          <filter-mapping>
              <filter-name>HiddenHttpMethodFilter</filter-name>
              <url-pattern>/*</url-pattern>
          </filter-mapping>
      
          <!--springMVC的前端控制器DispatcherServlet-->
          <servlet>
              <servlet-name>DispatcherServlet</servlet-name>
              <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
              <init-param>
                  <param-name>contextConfigLocation</param-name>
                  <param-value>classpath:springMVC.xml</param-value>
              </init-param>
              <load-on-startup>1</load-on-startup>
          </servlet>
          <servlet-mapping>
              <servlet-name>DispatcherServlet</servlet-name>
              <url-pattern>/</url-pattern>
          </servlet-mapping>
      </web-app>
      
    • 编写我们springMVC的核心配置文件

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:context="http://www.springframework.org/schema/context"
             xmlns:mvc="http://www.springframework.org/schema/mvc"
             xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
      
          <!--扫描组件-->
          <context:component-scan base-package="com.atguigu.rest.controller,
                                                com.atguigu.rest.dao"/>
          <!--配置Thymeleaf视图解析器-->
          <bean id="ViewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
              <property name="order" value="1" />
              <property name="characterEncoding" value="UTF-8" />
              <property name="templateEngine">
                  <bean class="org.thymeleaf.spring5.SpringTemplateEngine">
                      <property name="templateResolver">
                          <bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
                              <property name="prefix" value="/WEB-INF/templates/" />
                              <property name="suffix" value=".html"/>
                              <property name="templateMode" value="HTML5"/>
                              <property name="characterEncoding" value="UTF-8" />
                          </bean>
                      </property>
      
                  </bean>
              </property>
          </bean>
      
          <!--配置访问首页-->
          <mvc:view-controller path="/" view-name="index"></mvc:view-controller>
          <mvc:view-controller path="/toAdd" view-name="employee_add"></mvc:view-controller>
          <!--开启mvc注解配置-->
          <mvc:annotation-driven />
          <!--开放对静态资源的访问-->
          <mvc:default-servlet-handler />
      </beans>
      
  • 开始对我们提供的功能展开分析:
    在这里插入图片描述

    • 为了能够更加直观的显示操作结果,我们让添加、修改、删除操作完成之后,都重定向到查询全部数据的请求上
    • 修改操作我们希望能显示我们指定id的信息,然后在显示信息的表单上作出我们想要的修改
    • 对于员工id我们采用自增的方式,当调用我们save方法时,如果携带了id那么就修改原来的数据,如果没有携带id就保存当前数据
    • 删除操作相对复杂,我们通过VUE将一个删除操作的超链接绑定当一个表单上,将请求方式替换为DELETE
  • 接下来逐步实现我们的功能:

☀️ 首页

我们在视图控制器处已经完成了首页自动定位的工作,在首页里面通过一条超链接查询全部数据 index.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>首页</h1>
<a th:href="@{/employee}">查询所有员工信息</a>
</body>
</html>

☀️ 查询所有员工信息

编写我们查询结果显示页面 employee_list

  • 表单用于收集数据,表格用于显示数据 【th 代表表头,可以自动加粗】
    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>EmployInfo</title>
    </head>
    <body>
    
    <table border="1" cellspacing="0" cellpadding="0" style="text-align: center">
        <tr>
            <th colspan="5">Employee Info</th>
        </tr>
        <tr>
            <th>id</th>
            <th>lastName</th>
            <th>email</th>
            <th>gender</th>
            <th>options(<a th:href="@{/toAdd}">add</a> )</th>
        </tr>
        <tr th:each="employee : ${employeeList}">
            <td th:text="${employee.id}"></td>
            <td th:text="${employee.lastName}"></td>
            <td th:text="${employee.email}"></td>
            <td th:text="${employee.gender}"></td>
            <td>
                <!--当把id放到@{}内部+就不会报错了, 删除功能的超链接-->
                <a class="deleteA" @click="deleteEmployee" th:href="@{'/employee/'+${employee.id}}">delete</a>
                <a th:href="@{'/employee/'+${employee.id}}">update</a>
            </td>
        </tr>
    </table>
    </body>
    </html>
    

编写我们的控制器方法,后续只给出方法 EmployeeController

package com.atguigu.rest.controller;

import com.atguigu.rest.bean.Employee;
import com.atguigu.rest.dao.EmployeeDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;


import java.util.Collection;

/**
 * @author Bonbons
 * @version 1.0
 */
@Controller
public class EmployeeController {
    @Autowired
    private EmployeeDao employeeDao;

    @RequestMapping(value = "/employee", method = RequestMethod.GET)
    public String getAllEmploy(Model model){
        Collection<Employee> employeeList = employeeDao.getAll();
        // 通过Model的对象将我们查询的所有员工信息添加到请求域中
        model.addAttribute("employeeList", employeeList);
        return "employee_list";
    }
}

在这里插入图片描述
☀️ 保存新员工信息

  • 我们肯定是需要一个表单来接收新的数据,所以我们通过一个 employee_add.html 页面收集数据
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>添加员工信息</title>
    </head>
    <body>
      <form th:action="@{/employee}" method="post">
        lastName <input type="text" name="lastName"><br>
        email <input type="text" name="email"><br>
        gender <input type="radio" name="gender" value="1"> male
               <input type="radio" name="gender" value="0"> female <br>
    
        <input type="submit" value="add"><br>
      </form>
    </body>
    </html>
    
  • 在我们的 options 选项后添加一个超链接,用于发起添加数据的请求
    <th>options(<a th:href="@{/toAdd}">add</a> )</th>
    
  • 在控制器中编写我们处理请求的方法,表单会携带数据过来,我们直接用员工类对象接收数据
    // 添加员工信息
    @RequestMapping(value = "/employee", method = RequestMethod.POST)
    public String addEmployeeAdd(Employee employee){
    	employeeDao.save(employee);
    	// 为了显示添加效果,在添加成功后直接跳转到我们的查询全部员工的页面
    	return "redirect:/employee";
    }
    

在这里插入图片描述
☀️ 修改员工信息

  • 点击对应员工信息对应的 update,会携带对应id发起请求,我们先会根据这个id查询用户数据,将数据添加到请求域中
  • 然后跳转到我们更新操作的页面,根据请求域中的数据进行回显【在表单中显示出这个用户除id的全部信息】
  • 然后我们可以修改表单中的数据,提交后再次发起请求,将封装后的信息覆盖原信息

完善在 表格中的 update 超链接

<a th:href="@{'/employee/'+${employee.id}}">update</a>

在控制器中完成根据 id 查询信息并保存到 request 请求域中,跳转到我们的更新页面

// 根据id查询,然后回显数据到更新表单
@RequestMapping(value = "/employee/{id}", method = RequestMethod.GET)
public String getEmployeeById(@PathVariable("id") Integer id, Model model){
	// 根据传递进来的参数进行查询
	Employee employee = employeeDao.get(id);
	// 将查询到的数据添加到我们的请求域中
	model.addAttribute("employee", employee);
	return "employee_update";
}

编写我们更新数据的页面 employee_update.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>更新员工信息</title>
</head>
<body>
<form th:action="@{/employee}" method="post">
    <!--这里需要完成数据回显,就是显示出每项原来的数据是什么-->
    <!--尽管我们添加对象的时候不用传入id,但是应该设置隐藏属性,到时候传递回去封装数据用-->
    <!--回显后我们需要修改数据,所以将请求方式设置为 put,在点击提交后再次发起请求-->
    <input type="hidden" name="_method" value="put" />
    <input type="hidden" name="id" th:value="${employee.id}">
    lastName: <input type="text" name="lastName" th:value="${employee.lastName}"><br>
    email: <input type="text" name="email" th:value="${employee.email}"><br>
    gender: <input type="radio" name="gender" value="1" th:field="${employee.gender}">male
    <input type="radio" name="gender" value="0" th:field="${employee.gender}">female<br>
    <input type="submit" value="update"><br>
</form>
</body>
</html>

编写我们实际更新员工信息的控制器方法

// 更新我们的员工信息
@RequestMapping(value = "/employee", method = RequestMethod.PUT)
public String updateEmployee(Employee employee){
	employeeDao.save(employee);
	return "redirect:/employee";
}

在这里插入图片描述
☀️ 删除员工信息

  • 删除只需要在对应员工信息后面点击一下,所以通过超链接发起请求【@click=“deleteEmployee” 通过vue处理点击事件】

    <a @click="deleteEmployee" th:href="@{'/employee/'+${employee.id}}">delete</a>
    
  • 因为删除是 DELETE 请求,所以我们通过一个表单转换请求

    <!-- 通过超链接控制表单的提交,将post请求转换为delete请求 -->
    <form id="delete_form" method="post">
        <!-- 我们使用了HiddenHttpMethodFilter过滤器,传递_method请求参数,value为最终的请求方式 -->
        <input type="hidden" name="_method" value="delete"/>
    </form>
    
  • 需要引入我们的 vue.js ,点击可以跳转下载vue.js

    <script type="text/javascript" th:src="@{/static/js/vue.js}"></script>
    
  • 引入资源之后,需要重新打包导入我们的资源,然后需要在核心配置文件中配置开放静态资源的访问

    <!--开启mvc注解配置-->
    <mvc:annotation-driven />
    <!--开放对静态资源的访问-->
    <mvc:default-servlet-handler />
    
  • 这俩都要配置,如果只有第二个配置(handler),就会导致只能访问静态资源

  • 接下来通过vue完成绑定【注意是一个单独的标签,不嵌套到表单内】

    script type="text/javascript">
        var vue = new Vue({
            el:"#dataTable",
            methods:{
                //event表示当前事件
                deleteEmployee:function (event) {
                    //通过id获取表单标签
                    var delete_form = document.getElementById("deleteEmployee");
                    //将触发事件的超链接的href属性为表单的action属性赋值
                    delete_form.action = event.target.href;
                    //提交表单
                    delete_form.submit();
                    //阻止超链接的默认跳转行为
                    event.preventDefault();
                }
            }
        });
    </script>
    
  • 在控制器中编写控制器方法

    // 根据id删除员工信息
    @RequestMapping (value = "/employee/{id}",  method = RequestMethod.DELETE)
    public String deleteEmployee(@PathVariable("id") Integer id){
    	employeeDao.delete(id);
    	return "redirect:/employee";
    }
    

在这里插入图片描述

📖 补充知识点:

  • tomcat中的web.xml 是所有我们部署的工程中的web.xml的父类【发生冲突就近原则】
  • 客户端发送的请求先被我们的Dispatcher处理,处理不了交给我们DefaultServlet处理 ,再处理不了就404

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

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

相关文章

轻松应对80% 的工作场景?GitHub 爆赞的 Java 高并发与集合框架,面试官也拿我没辙

在工作中&#xff0c;笔者经常和掌握不同技术的朋友讨论具体问题的解决方案&#xff0c;发现在 Java 体系中&#xff0c;大家使用最多的是 Java 集合框架&#xff08;JCF&#xff09;和 Java 并发工具包&#xff08;JUC&#xff09;。实际上&#xff0c;JCF 和 JUC 已经能够覆盖…

Flutter高仿微信-第50篇-群聊-查看群成员

Flutter高仿微信系列共59篇&#xff0c;从Flutter客户端、Kotlin客户端、Web服务器、数据库表结构、Xmpp即时通讯服务器、视频通话服务器、腾讯云服务器全面讲解。 详情请查看 效果图&#xff1a; 实现代码&#xff1a; import package:flutter/material.dart; import package:…

Node.js 入门教程 7 从命令行运行 Node.js 脚本 8 如何退出 Node.js 程序

Node.js 入门教程 Node.js官方入门教程 Node.js中文网 本文仅用于学习记录&#xff0c;不存在任何商业用途&#xff0c;如侵删 文章目录Node.js 入门教程7 从命令行运行 Node.js 脚本8 如何退出 Node.js 程序7 从命令行运行 Node.js 脚本 运行 Node.js 程序的常用方法是&#…

【点云处理】点云法向量估计及其加速(5)

在上一篇文章【点云处理】点云法向量估计及其加速(4)中我们尝试对pcl自带的KDTree的k近邻搜索过程使用OpenMP加速&#xff0c;效果比较明显&#xff0c;有将近1倍的提速。在这篇文章中我们暂时放弃pcl自带的KDTree&#xff0c;转而使用另一大杀器nanflann库提供的KDTree。nanof…

玩链子游戏

一 游戏描述 有一条链子&#xff0c;上面有 n 颗钻石&#xff0c;钻石编号为 1&#xff5e;n 。可以对该链子执行两种操作&#xff1a; ① CUT a b c &#xff08;区间切割操作&#xff09; 切下从第 a 颗钻石到第 b 颗钻石的链子&#xff0c;把它插在剩余链子的第 c 颗钻石…

【食品加工技术】第五章 烘烤食品加工技术 笔记

【食品加工技术】第五章 烘烤食品加工技术 笔记5.1 焙烤食品概述烘烤食品的分类按发酵和膨化程度分类安装生产工艺分类烘烤食品的原料面粉糖蛋品乳及乳制品膨松剂烘烤设备常用设备恒温设备常用工具5.2 面包加工工艺和关键技术面包的分类面包的发酵原理面包的工艺流程一次发酵二…

uboot引导应用程序

uboot默认是支持执行应用程序的&#xff0c;就像引导内核一样&#xff0c;我们也可以自己写一个应用程序&#xff0c;让uboot启动时引导。 在uboot examples/standalone 目录下&#xff0c;有hello_world.c文件&#xff0c;编译uboot的时候&#xff0c;会自动编译hello_world.…

详解 InnoDB Cluster 主机名问题

详解 InnoDB Cluster 主机名问题 文章目录详解 InnoDB Cluster 主机名问题导言测试过程结论导言 因在写 【InnoDB Cluster】修改已有集群实例名称及成员实例选项 时发现主机名这块有一些问题&#xff0c;在其中进行了部分测试&#xff0c;但为使其内容精简&#xff0c;故将此部…

程序员必知的三款在线绘图工具

文章目录2.draw.io3.Lucidchart4.PrcessOn5.小结正所谓“一图胜千言”&#xff0c;无论是商务办公、PPT 演示、学习总结、技术交流、项目开发&#xff0c;我们常常都需要制作一些图表、流程图、架构图来更直观地呈现内容以及归类整理知识点。 今天就来说下程序员们常用的三款在…

【矩阵论】正规方程——生成子空间

5.1 子空间 5.1.1. 定义 设 W⊂CnW\subset C^nW⊂Cn &#xff0c;即子空间对线性组合封闭 若(1)对∀α,β∈W&#xff0c;有αβ∈W(对加法封闭)(2)对∀α∈W,∀k∈C&#xff0c;有kα∈W(对数乘封闭)\begin{aligned} 若 &(1)对\forall \alpha,\beta\in W&#xff0c;有\…

秋招失利,拿到这份“Java 高分指南(25 专题)”,金三银四翻盘有望

面试造火箭&#xff0c;工作拧螺丝&#xff01;金九银十灰溜溜地落榜&#xff0c;备受打击。正当准备明年金三银四之际&#xff0c;意外喜提朋友赠送的这“Java 高分指南&#xff08;25 专题&#xff09;”&#xff1a;Elasticsearch、微服务、Linux、JavaOOP、集合/泛型、Mysq…

Flutter高仿微信-第57篇-添加好友

Flutter高仿微信系列共59篇&#xff0c;从Flutter客户端、Kotlin客户端、Web服务器、数据库表结构、Xmpp即时通讯服务器、视频通话服务器、腾讯云服务器全面讲解。 详情请查看 效果图&#xff1a; 实现代码&#xff1a; /*** Author : wangning* Email : maoning20080809163.c…

ThreadLocal

文章目录一、ThreadLocal是什么二、ThreadLocal作用三、ThreadLocal的设计结构早期:现在:四、ThreadLocal核心方法1. set方法2. get方法3. remove方法五、ThreadLocal内存泄漏六、使用场景七、参考资料前言&#xff1a; 再写博客时&#xff0c;遇到了如何处理保存用户的信息时出…

基于共享储能电站的工业用户 日前优化经济调度matlab程序(yalmip+cplex)(yalmip+gurobi)

基于共享储能电站的工业用户 日前优化经济调度matlab程序&#xff08;yalmipcplex&#xff09;&#xff08;yalmipgurobi&#xff09; 参考文献&#xff1a;基于共享储能电站的工业用户 日前优化经济调度 摘要: 文章提出一种基于共享储能电站的工业用户日前优化经济调度方法。…

nginx反向代理,负载均衡配置

文章目录一.nginx代理简介二.nginx配置简介三.nginx作为反向代理的配置四.nginx作为负载均衡的配置五.使用nginx代理的坑一.nginx代理简介 其实nginx作为代理有两种 正向代理: 隐藏客户端的信息;如科学上网 反向代理: 隐藏服务端的信息;如负载均衡 二.nginx配置…

11.26

目录 一.做题出错 1. 2.数组长度的一半 3.选择题 二.优先级队列(堆) 1.二叉树的顺序存储 1.1 存储方式 1.2下标关系 2.堆(heap) 2.1概念 2.2 操作-向下调整 三 建堆 四.优先级队列 1 概念 2 内部原理 3.操作-入队 offer() 4.操作-出队 五.计算糖果 一.做题出错…

docker如何下载国外镜像

目录背景解决方案1、创建阿里云镜像仓库2、使用https://labs.play-with-docker.com下载镜像3、将镜像上传到阿里云镜像仓库4、从阿里云镜像仓库中拉取镜像到我们linux系统中5、改变我们linux系统中拉取的镜像名称背景 今天在安装grafana和prometheus&#xff0c;但是在下载下面…

Java数据结构

目录 1、栈 2、队列 3、数组 4、链表 5、树 7、平衡二叉树 8、红黑树 1、栈 特点&#xff1a;先进后出&#xff0c;后进先出 数据进入栈模型的过程称为:压/进栈 数据离开栈模型的过程称为:弹/出栈 2、队列 特点&#xff1a;先进先出&#xff0c;后进后出 数据从后…

MyBatis-Plus中的更新操作(通过id更新和条件更新)

目录 前言 一、通过id更新 二、条件更新 2.1 使用QueryWrapper进行条件更新 2.2 使用UpdateWrapper进行条件更新 总结 前言 本文学习MP中的更新操作方法&#xff0c;带大家一起查看源码&#xff0c;了解更新操作的方法。学会熟练地去运用更新方法解决自己在项目中的问题…

Linus 文件处理(三)

目录 一、前言 二、扫描目录 1、opendir 2、readdir 3、telldir 4、seekdir 5、 closedir 6、A Directory-Scanning Program 三、Errors 1、strerror 2、perror 一、前言 本文将简单介绍Linux文件和目录&#xff0c;以及如何操作它们&#xff08;如何创建文件、打开…