【SSM详细教程】-15-Spring Restful风格【无敌详细】

news2024/11/4 17:51:33

精品专题:

01.《C语言从不挂科到高绩点》课程详细笔记

https://blog.csdn.net/yueyehuguang/category_12753294.html?spm=1001.2014.3001.5482

02. 《SpringBoot详细教程》课程详细笔记

https://blog.csdn.net/yueyehuguang/category_12789841.html?spm=1001.2014.3001.5482

03.《SpringBoot电脑商城项目》课程详细笔记

https://blog.csdn.net/yueyehuguang/category_12752883.html?spm=1001.2014.3001.5482

04.《VUE3.0 核心教程》课程详细笔记 

https://blog.csdn.net/yueyehuguang/category_12769996.html?spm=1001.2014.3001.5482

05. 《SSM详细教程》课程详细笔记 

https://blog.csdn.net/yueyehuguang/category_12806942.html?spm=1001.2014.3001.5482

================================

||     持续分享系列教程,关注一下不迷路 ||

||                视频教程:墨轩大楼               ||

================================

📚 一、Rest风格简介

        Rest风格是一种表现形式状态转换,它是一种软件架构风格,当我们想表示一个网络资源的时候,可以使用两种方式:

  • 传统风格资源描述形式:

http://localhost/user/getById?id=1 查询id为1的用户信息

http://localhost/user/saveUser 保存用户信息

  • Rest风格描述形式

http://localhost/user/1

http://localhost/user

       传统方式一般是一个请求对应一种操作,这样做不仅麻烦,也不安全,因为会程序的人读取了请求URL地址,就大概知道该URL实现的是一个什么样的操作。

        查看REST风格的描述,你会发现请求地址变的简单了,并且如果只看请求URL并不容易猜出该URL的具体功能。

        REST的优点:隐藏资源的访问行为,无法通过地址得知对资源是何种操作,并且书写简单。

        但是随之而来的就会有一个问题,一个相同的URL地址,即可以是新增也可以是修改或者查询,那么到底该如何区分请求到底是什么操作呢?

        REST风格访问资源时使用行为动作区分对资源进行了何种操作:

http://localhost/users 查询全部用户信息 GET(查询)

http://localhost/users/1 查询指定用户信息 GET(查询)

http://localhost/users 添加用户信息 POST(新增/保存)

http://localhost/users 修改用户信息 PUT(修改/更新)

http://localhost/users/1 删除用户信息 DELETE(删除)

        请求方式比较多,但是比较常用的有4种,分别是 GET、POST、PUT、DELETE,不同的请求方式代表不同的操作类型:

发送GET请求时做查询操作

发送POST请求时做新增操作

发送PUT请求时做修改操作

发送DELETE请求时做删除

        但是需要注意的是,上面的内容仅仅是约定而不是规则,约定是可以打破的,所以称为REST规范而不是REST规则,这就好比变量的命名规范和命名规则一样。

        REST提供了对应的架构方式,按照这种架构设计项目可以降低开发的复杂性,提高系统的可伸缩性。REST种规定GET/POST/PUT/DELETE针对的是查询/新增/修改/删除。

📚 二、Restful 入门案例

通常以REST风格对资源进行访问,我们称为Restful,下面我们以一个案例详细了解一下Restful。

🌾 新建项目,并在pom.xml中导入依赖

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>5.2.10.RELEASE</version>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.9.0</version>
</dependency>
<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  <version>RELEASE</version>
  <scope>compile</scope>
</dependency>

🌾 在项目的resources目录中新建springmvc.xml

<?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/task"
       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/task http://www.springframework.org/schema/task/spring-task.xsd">

    <context:component-scan base-package="com.moxuan.mvc_restful.controller"></context:component-scan>
    <mvc:annotation-driven/>
    <!--    配置视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--        在/WEB-INF/view/ 目录下,寻找后缀为.jsp的文件-->
        <property name="prefix" value="/WEB-INF/view/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters">
            <list>
                <bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
                <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
            </list>
        </property>
    </bean>


</beans>

🌾 配置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">
    <servlet>
        <servlet-name>restful</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>
    </servlet>
    <servlet-mapping>
        <servlet-name>restful</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

    <filter>
        <filter-name>code</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>
    </filter>
    <filter-mapping>
        <filter-name>code</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

🌾 实体类Hero

package com.moxuan.mvc_restful.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Hero {
        private Integer id;
        private String name;
        private int level;
        private String job;
    }

🌾 控制器Controller类

package com.moxuan.mvc_restful.controller;

import com.moxuan.mvc_restful.pojo.Hero;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

@Controller
public class HeroController {
    @RequestMapping(value = "/heros",method = RequestMethod.POST)
    @ResponseBody
    public String save(@RequestBody Hero hero){
        System.out.println("hero save..." + hero);
        return "{'message':'hero save'}";
    }

    @RequestMapping(value = "/heros/{id}",method = RequestMethod.DELETE)
    @ResponseBody
    public String delete(@PathVariable Integer id){
        System.out.println("hero delete..." + id);
        return "{'message':'hero delete'}";
    }

    @RequestMapping(value = "/heros",method = RequestMethod.PUT)
    @ResponseBody
    public String update(@RequestBody Hero hero){
        System.out.println("hero update..." +hero);
        return "{'message':'hero update'}";
    }

    @RequestMapping(value = "/heros/{id}",method = RequestMethod.GET)
    @ResponseBody
    public String getById(@PathVariable Integer id){
        System.out.println("hero getById..." + id);
        return "{'message':'hero getById'}";
    }

    @RequestMapping(value = "/heros",method = RequestMethod.GET)
    @ResponseBody
    public String getAll(){
        System.out.println("hero getAll...");
        return "{'message':'hero getAll'}";
    }

}

✍️ 【笔 记】 关于@PathVariable,它的作用是绑定路径参数与处理器方法中的参数间的关系,要求路径参数名与方法中的参数名一样。

❓ 【面试题】@RequestBody、@RequestParam 、@PathVariable 都是用来接收参数的,它们之间的区别和应用分别是什么?

区别:

@RequestParam 用于接收url地址传参或表单传参,比如:/getUserById?id=1, 中的id值。

@RequestBody 用于接收Json格式的数据。

@PathVariable 用于接收路径参数,使用{参数名}描述路径参数,比如:/users/{id},中的id值

应用:

后期开发中,发送请求参数超过1个时,建议使用json格式,@RequestBody运用的会比较广泛。

如果发送非json格式数据,选用@RequestParam接收请求参数。

采用RESTful进行开发,当参数数量较少时,例如1个,可以采用@PathVariable接收请求路径变量,通常用于传递id值。

🌾打开PostMan进行测试

1️⃣ 测试新增数据

👀 首先设置content-type为application/json

👀 然后设置json格式的数据,然后以post方式发送请求:

⚠️ 注意: 新增操作,需要发送Post请求

👀 运行结果:

2️⃣ 测试修改数据

👀 修改请求方式为PUT,发送请求

👀 测试结果,如下图所示:

3️⃣ 测试查询数据

👀 修改请求方式为GET,发送请求

请求后面不带数据,表示查询所有的数据,测试结果:

👀 请求方式为GET,在地址后面添加1

请求后面携带的有一个1,表示查询id为1的数据,测试结果:

4️⃣ 测试删除数据

👀 修改请求方式为DELETE发送请求

测试结果如下:

📚 RESTful 快速开发

🌾 问题描述

前面我们使用了restful,可以看出避免了一些请求的外显,而且现在发送请求也相对之前来说简易一些。但是目前任然还存在一些麻烦点,如下图所示:

每个方法的@RequestMapping注解中都定义了访问路径 /heros, 重复性太高了。

每个方法的@RequestMapping注解中都要使用method属性定义请求方式,重复性太高了。

每个方法响应json都需要加上@ResponseBody注解,重复性太高。

🌾 解决方案

  1. 采用前面讲过的请求路径映射,在Controller类的上方统一加上@RequestMapping
  2. 使用@RestController 代替@Controller注解,@RestController=@Controller + @ResponseBody.
  3. 分别使用@PostMapping、@GetMapping、@PutMapping、@DeleteMapping 来替换@RequestMapping中的method设定

👇👇👇且看下面代码

package com.moxuan.mvc_restful.controller;

import com.moxuan.mvc_restful.pojo.Hero;
import org.springframework.web.bind.annotation.*;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: moxuan
 * @Date: 2023/08
 * @Description:
 */
@RestController
@RequestMapping("/heros")
public class HeroController {
//    @RequestMapping(value = "/heros",method = RequestMethod.POST)
//    @ResponseBody
    @PostMapping
    public String save(@RequestBody Hero hero){
        System.out.println("hero save..." + hero);
        return "{'message':'hero save'}";
    }

//    @RequestMapping(value = "/heros",method = RequestMethod.PUT)
//    @ResponseBody
    @PutMapping
    public String update(@RequestBody Hero hero){
        System.out.println("hero update..." +hero);
        return "{'message':'hero update'}";
    }

//    @RequestMapping(value = "/heros/{id}",method = RequestMethod.DELETE)
//    @ResponseBody
    @DeleteMapping("/{id}")
    public String delete(@PathVariable Integer id){
        System.out.println("hero delete..." + id);
        return "{'message':'hero delete'}";
    }

//    @RequestMapping(value = "/heros/{id}",method = RequestMethod.GET)
//    @ResponseBody
    @GetMapping("/{id}")
    public String getById(@PathVariable Integer id){
        System.out.println("hero getById..." + id);
        return "{'message':'hero getById'}";
    }

//    @RequestMapping(value = "/heros",method = RequestMethod.GET)
//    @ResponseBody
    @GetMapping
    public String getAll(){
        System.out.println("hero getAll...");
        return "{'message':'hero getAll'}";
    }

}

✍️ 【笔记】

@RestController

基于SpringMVC的RESTful开发控制器类,设置当前控制器类为RESTful风格,等同于@Controller与@ResponseBody两个注解的组合。

@GetMapping、@PostMapping、 @PutMapping 、 @DeleteMapping

设置当前控制器方法请求访问路径与请求动作,每一种对应一个请求动作,比如@GetMapping对应GET请求。

🌲 综合案例

使用SSM整合RESTful风格实现对英雄数据的增删改查,现在很多新项目都采用前后端分离的方式进行开发,前面在讲SSM整合的时候,我们已经使用过一般风格的方式整合了,这里我们采用前后端分离的方式整合RESTful风格。

🌿 数据表

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `hero`
-- ----------------------------
DROP TABLE IF EXISTS `hero`;
CREATE TABLE `hero` (
  `id` int NOT NULL AUTO_INCREMENT,
  `hname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `job` varchar(255) DEFAULT NULL,
  `level` int DEFAULT NULL,
  `sex` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8mb3;

-- ----------------------------
-- Records of hero
-- ----------------------------
INSERT INTO `hero` VALUES ('1', '夏侯惇', '战士', '2', '男');
INSERT INTO `hero` VALUES ('3', '甄姬', '法师', '2', '女');
INSERT INTO `hero` VALUES ('4', '安琪拉', '法师', '3', '女');
INSERT INTO `hero` VALUES ('5', '廉颇', '辅助', '1', '男');
INSERT INTO `hero` VALUES ('6', '张飞', '辅助', '1', '男');
INSERT INTO `hero` VALUES ('7', '后羿', '射手', '3', '男');
INSERT INTO `hero` VALUES ('8', '虞姬', '射手', '3', '女');
INSERT INTO `hero` VALUES ('9', '阿珂', '刺客', '3', '女');
INSERT INTO `hero` VALUES ('10', '孙悟空', '刺客', '3', '男');
INSERT INTO `hero` VALUES ('12', '王昭君', '法师', '3', '女');
INSERT INTO `hero` VALUES ('13', '王昭君', '法师', '3', '女');

🌿 搭建项目环境

🍁创建项目
  • 按照下图所示建立项目结构,并导入配置文件,配置文件在本文档后续内容中获取:

  • 导入SSM项目整合所需的依赖
<dependencies>
  <!--Spring所需Jar-->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <!--spring集成Junit-->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>${spring.version}</version>
    <scope>provided</scope>
  </dependency>
  <!--Log4j所需Jar-->
  <dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
  </dependency>
  <!--AOP所需Jar-->
  <dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.8.10</version>
  </dependency>
  <dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.8.10</version>
  </dependency>
  <!--Servlet所需Jar-->
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
  </dependency>
  <!--SpringMVC依赖-->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <!--Mybatis依赖-->
  <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.2.2</version>
  </dependency>
  <!--Spring和Mybatis集成插件-->
  <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>1.2.2</version>
  </dependency>
  <!--Mysql连接连接驱动-->
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.25</version>
  </dependency>
  <!--数据源JDBC、C3P0、Druid-->
  <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.8</version>
  </dependency>
  <!-- JSTL标签类 -->
  <dependency>
    <groupId>jstl</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
  </dependency>
  <!--可添加-->
  <!-- 上传组件包 -->
  <dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
  </dependency>
  <dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
  </dependency>
  <dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.9</version>
  </dependency>

  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.10.2</version>
  </dependency>
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.10.2</version>
  </dependency>
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.10.2</version>
  </dependency>
  <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.36</version>
  </dependency>
  <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.7</version>
  </dependency>
  <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>RELEASE</version>
    <scope>compile</scope>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>5.3.29</version>
  </dependency>
</dependencies>
  • 在resources中添加日志相关的配置文件log4j.properties
#定义LOG输出级别
log4j.rootLogger=INFO,Console,File
#定义日志输出目的地为控制台
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.Target=System.out
#可以灵活地指定日志输出格式,下面一行是指定具体的格式
log4j.appender.Console.layout = org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=[%c] - %m%n

#文件大小到达指定尺寸的时候产生一个新的文件
log4j.appender.File = org.apache.log4j.RollingFileAppender
#指定输出目录(需要配一个绝对路径)
log4j.appender.File.File = c:/logs/ssm.log
#定义文件最大大小
log4j.appender.File.MaxFileSize = 10MB
# 输出所以日志,如果换成DEBUG表示输出DEBUG以上级别日志
log4j.appender.File.Threshold = ALL
log4j.appender.File.layout = org.apache.log4j.PatternLayout
log4j.appender.File.layout.ConversionPattern =[%p] [%d{yyyy-MM-dd HH\:mm\:ss}][%c]%m%n
🍁日志组件
  • 在config包中添加AOP日志切面ServiceLogAspect.java,代码如下:
package com.example.SSM_restful.config;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;


@Component
@Aspect
public class ServiceLogAspect {
    // 日志记录员
    private static final Logger logger = LoggerFactory.getLogger(ServiceLogAspect.class);

    @Pointcut("execution(* com.example.SSM_restful.service.*.*(..))")
    public void pointcut(){

    }

    /**
     * 前置通知
     * @param joinPoint
     */
    @Before("pointcut()")
    public void before(JoinPoint joinPoint) {
        // 用户[IP 地址], 在某个时间访问了 [com.moxuan.SSM.service.xxx]
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes == null) {
            return ;
        }
        // 获取请求
        HttpServletRequest request = attributes.getRequest();
        // 获取ip
        String ip = request.getRemoteHost();
        // 获取系统当前时间
        String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        // 获取执行的方法
        String target = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
        // 记录日志
        logger.info(String.format("用户[%s], 在[%s], 访问了[%s].", ip, time, target));
    }

}

🌿 创建实体类

在entity包中新建实体类Hero,代码如下:

package com.example.SSM_restful.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Hero {
    private Integer id;
    private String hname;
    private String job;
    private Integer level;
    private String sex;
}

🌿 添加映射器

在dao包中新建HeroDao接口,作为映射器,代码如下:

package com.example.SSM_restful.dao;

@Repository
public interface HeroDao {
   
}

在resources目录下的mappers中新建数据库映射文件Hero.xml,代码如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 此处的namespace需要对应上dao包中的数据操作接口-->
<mapper namespace="com.example.SSM_restful.dao.HeroDao">

</mapper>

🌿 添加配置文件

🍁Mybatis相关配置

在resources目录下新建一个mysql.properties,添加数据源相关配置,代码如下:

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/study?useUnicode=true&characterEncoding=utf-8
username=root
password=123456
#定义初始连接数
initialSize=0
#定义最大连接数
maxActive=20
#定义最小空闲
minIdle=1
#定义最长等待时间
maxWait=60000

在resources目录中新建一个spring-mybatis.xml,配置数据源以及mybatis相关的配置,代码如下:

<?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:utils="http://www.springframework.org/schema/util" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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/util https://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
    <!-- 自动扫描的路径-->
    <context:component-scan base-package="com.example.SSM_restful"></context:component-scan>
    <!-- 引入配置文件
    classpath:只会到你指定的class路径中查找找文件;
    -->
    <utils:properties location="classpath*:mysql.properties" id="mysql"></utils:properties>

    <!-- 配置数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <!-- 配置数据库链接基本信息-->
        <property name="url" value="#{mysql.url}" />
        <property name="driverClassName" value="#{mysql.driver}"/>
        <property name="username" value="#{mysql.username}" />
        <property name="password" value="#{mysql.password}" />
        <!-- 初始化连接大小-->
        <property name="initialSize" value="#{mysql.initialSize}"/>
        <!-- 连接池最大数量-->
        <property name="maxActive" value="#{mysql.maxActive}"/>
        <!-- 连接池最小空闲 -->
        <property name="minIdle" value="#{mysql.minIdle}"/>
    </bean>

    <!-- Mapping 文件-->
    <!-- Spring 和mybatis完美整合,不需要mybatis的配置文件-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!-- 配置实体类的别名-->
        <property name="typeAliasesPackage" value="com.example.SSM_restful.entity"/>
        <!-- 自动扫描mapping.xml映射文件-->
        <property name="mapperLocations" value="classpath:mappers/*.xml"/>
    </bean>

    <!-- Dao 接口-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 配置 Dao 接口所在的包名,Spring会自动查找其下的类-->
        <property name="basePackage" value="com.example.SSM_restful.dao"/>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>

    <!-- (事务管理)transaction manager, use JtaTransactionManager for global tx -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager" />
    <aop:config>
        <aop:pointcut expression="execution(* com.example.SSM_restful.service.*.*(..))" id="productServiceMethods" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="productServiceMethods" />
    </aop:config>
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="save*" propagation="REQUIRED" />
            <tx:method name="delete*" propagation="REQUIRED" />
            <tx:method name="modify*" propagation="REQUIRED" />
            <tx:method name="insert*" propagation="REQUIRED" />
            <tx:method name="remove*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED" />
            <tx:method name="find*" propagation="REQUIRED" read-only="true" />
            <tx:method name="get*" propagation="REQUIRED" read-only="true" />
            <tx:method name="*" />
        </tx:attributes>
    </tx:advice>
</beans>

🛎️注意:需要将配置文件中的一些路径修改成你自己项目的实际路径

  • 自动扫描的路径
<context:component-scan base-package="com.example.SSM_restful"></context:component-scan>
  • 数据源配置文件路径
<utils:properties location="classpath*:mysql.properties" id="mysql"></utils:properties>
  • 实体类路径以及映射文件路径
<!-- 配置实体类的别名-->
<property name="typeAliasesPackage" value="com.example.SSM_restful.entity"/>
<!-- 自动扫描mapping.xml映射文件-->
<property name="mapperLocations" value="classpath:mappers/*.xml"/>
  • 自动扫描dao映射器接口的路径
 <!-- 配置 Dao 接口所在的包名,Spring会自动查找其下的类-->
<property name="basePackage" value="com.example.SSM_restful.dao"/>
  • 事务管理中,service业务层的路径
<aop:pointcut expression="execution(* com.example.SSM_restful.service.*.*(..))" id="productServiceMethods" />

🍁 添加springMvc相关配置

在resources目录下,新建spring-mvc.xml,添加关于web相关的配置,代码如下:

<?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:anotation="http://www.springframework.org/schema/p" xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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 http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--自动扫描包路径,扫描@Controller控制器类-->
    <context:component-scan base-package="com.example.SSM_restful"/>
    <!-- 开启mvc注解扫描-->
    <mvc:annotation-driven/>

    <mvc:default-servlet-handler/>
    <!-- 开启对aop注解的支持-->
    <aop:aspectj-autoproxy/>
    <!--
        JSON 转换器
    -->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters">
            <list>
                <bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
                <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
            </list>
        </property>
    </bean>

    <!-- 3.x version -->
    <!-- HandlerMapping 托管映射处理器 RequestMappingHandlerMapping -->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
    <!-- HandlerAdapter 托管适配处理器 RequestMappingHandlerAdapter-->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
    <!-- 避免IE执行Ajax时,返回JSON出现下载文件-->
    <bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
        <property name="supportedMediaTypes">
            <list>
<!--                防止后端返回json对象中文乱码-->
                <value>application/json;charset=utf-8</value>
                <value>text/html;charset=utf-8</value>
                <!-- application 可以在任意 form 表单里面 enctype 属性默认找到 -->
                <value>application/x-www-form-urlencoded</value>
            </list>
        </property>
    </bean>

    <!-- ViewResolver 托管视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--前缀-->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!--后缀-->
        <property name="suffix" value=".jsp"/>

    </bean>

    <!-- 配置文件上传,如果没有使用文件上传可以不用配置,当然如果不配,那么配置文件中也不必引入上传组件包 -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 默认编码 -->
        <property name="defaultEncoding" value="utf-8"/>
        <!-- 文件大小最大值 -->
        <property name="maxUploadSize" value="10485760000"/>
        <!-- 内存中的最大值 -->
        <property name="maxInMemorySize" value="40960"/>
    </bean>

</beans>

🛎️ 配置文件中需要注意的点:

  • 开启自动扫描的包路径一定要是自己项目的实际路径
  • Restful前后端分离,涉及了频繁的json访问以及json转换,我们添加了json相关的配置,可以帮我们自动进行转换。
  • 视图解析器,由于是前后端分离,我们给前端只返回数据,可以不配置
  • 文件上传的配置,本案例中不涉及,也可以不配置。

🍁 web.xml配置

在web.xml中配置DispatchcerServlet以及相关过滤器以及监听器等等,代码如下:

<?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">
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-mybatis.xml</param-value>
    </context-param>

    <!-- 配置编码过滤器-->
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <async-supported>true</async-supported>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- Spring 监听器-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <!-- 防止Spring内存溢出监听器-->
    <listener>
        <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
    </listener>
    <!--  配置DispatcherServlet  -->
    <servlet>
        <servlet-name>SSM</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>SSM</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

🌿 查询英雄列表

在entity包中新建一个Result类,用来封装后端给前端传输的数据,代码如下:

package com.example.SSM_restful.entity;

import lombok.Data;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: moxuan
 * @Date: 2023/08
 * @Description: 对返回数据进行统一封装
 */
@Data
public class Result {

    private int code;// 状态码
    private String msg;// 消息
    private Object data;// 数据源

    public static final int SUCCESS_CODE=200;
    public static final int ERROR_CODE=-1;
    public  static final String SUCCESS_MSG="请求成功";
    public  static final String ERROR_MSG="请求失败";

    public static Result success(){
        Result result = new Result();
        result.setCode(SUCCESS_CODE);
        result.setMsg(SUCCESS_MSG);
        return result;
    }
    public static Result error(){
        Result result = new Result();
        result.setCode(ERROR_CODE);
        result.setMsg(ERROR_MSG);
        return result;
    }


    public static Result sendResult(int code, String msg,Object obj){
        Result result =  new Result();
        result.setData(obj);
        result.setMsg(msg);
        result.setCode(code);
        return result;
    }

    public static Result sendResult(int code, String msg) {
        Result result =  new Result();
        result.setMsg(msg);
        result.setCode(code);
        return result;
    }
}

在controller包中新增HeroController,添加查询的方法,代码如下:

package com.example.SSM_restful.controller;

import com.example.SSM_restful.entity.Hero;
import com.example.SSM_restful.entity.Result;
import com.example.SSM_restful.service.HeroService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;


import java.util.List;

@RestController
@RequestMapping("/hero")
@CrossOrigin("*") // 解决前后端分离项目跨域问题,
public class HeroController {

    @Autowired
    HeroService service;

    @GetMapping
    public Result heros(){
        Result result = service.getAllHeros();
        System.out.println(result);

        return result;
    }

}

注意:

  • 查询请求使用的是@GetMapping
  • 如果前端项目和后端项目不在同一个服务器,就会存在跨域问题,此时可以在Controller上方添加@CrossOrigin("*"),来解决跨域问题

在service包中新建HeroService接口,代码如下:

package com.example.SSM_restful.service;

import com.example.SSM_restful.entity.Hero;
import com.example.SSM_restful.entity.Result;

public interface HeroService {
    Result getAllHeros();
}

在service包中新建impl包,然后在其中新建一个HeroServiceImpl类去实现HeroService接口,代码如下:

package com.example.SSM_restful.service.impl;

import com.example.SSM_restful.dao.HeroDao;
import com.example.SSM_restful.entity.Hero;
import com.example.SSM_restful.entity.Result;
import com.example.SSM_restful.service.HeroService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class HeroServiceImpl implements HeroService {
    @Autowired
    private HeroDao dao;

    @Override
    public Result getAllHeros() {
        List<Hero> heroList = dao.findAllHeros();
        if (heroList.size()==0){
            return Result.sendResult(Result.ERROR_CODE,"未查询到数据");
        }
        return Result.sendResult(Result.SUCCESS_CODE,"操作成功",heroList);
    }
}

在HeroDao中添加查询数据的方法,findAllHeros(),代码如下:

@Select("select * from hero")
List<Hero> findAllHeros();

启动服务器,打开postman进行测试:

🌿 根据id查询数据

接下来我们来看看,如果要查询id为1的英雄数据,按照restful风格的话,我们的地址就需要使用:http://localhost:8080/hero/1

在HeroController中添加处理根据id查询数据的请求方法,在请求的@GetMapping 中添加{id},然后使用@PathVariable获取请求中的参数值,代码如下:

@GetMapping("/{id}")
public Result getHeroByID(@PathVariable int id){
    Result result = service.getHero(id);
    return result;
}

在HeroServiceImpl中实现getHero方法,代码如下:

@Override
public Result getHero(int id) {
    Hero hero = dao.findHeroById(id);
    if(hero==null){
        return Result.sendResult(Result.ERROR_CODE,"未查询到数据");
    }
    return Result.sendResult(Result.SUCCESS_CODE,"操作成功",hero);
}

在HeroDao中添加findHeroById方法,代码如下:

@Select("select * from hero where id=#{id}")
Hero findHeroById(@Param("id") int id);

打开Postman进行测试:

🌿 添加英雄数据

  • 做添加操作时,我们需要处理的请求是Post请求,我们在HeroController中添加对应的处理请求的方法,代码如下:
@PostMapping
public Result saveHero(Hero hero){
	Result result = service.saveHero(hero);
	return result;
}
  • 在业务层中,添加saveHero的实现方法,代码如下:
@Override
public Result saveHero(Hero hero) {
    int num = dao.addUser(hero);
    if(num==0){
        return Result.sendResult(Result.ERROR_CODE,"添加数据失败");
    }
    return Result.sendResult(Result.SUCCESS_CODE,"成功添加数据");
}
  • 在HeroDao中添加对应的方法,代码如下:
@Insert("insert into hero (hname,job,level,sex) values(#{h.hname},#{h.job},#{h.level},#{h.sex})")
int addUser(@Param("h") Hero hero);
  • 打开postman进行测试:

🌿修改数据

  • 做修改操作时,我们需要处理的请求是Put请求,我们在HeroController中添加对应的处理请求的方法,代码如下:
@PutMapping
public Result updateHero(Hero hero){
	Result result = service.updateHero(hero);
	return result;
}
  • 在业务层Service中添加对应的方法,代码如下:
@Override
public Result updateHero(Hero hero) {
    int num = dao.updateHero(hero);
    if(num==0){
        return Result.sendResult(Result.ERROR_CODE,"修改数据失败");
    }
    return Result.sendResult(Result.SUCCESS_CODE,"成功修改数据");
}
  • 在HeroDao中添加对应的updateHero方法,代码如下:
@Update("update hero set " +
        " hname=#{h.hname}," +
        " job=#{h.job}," +
        " level=#{h.level}," +
        " sex=#{h.sex} " +
        "where id=#{h.id}")
int updateHero(@Param("h") Hero hero);
  • 打开postman测试yH5BAAAAAAALAAAAAAOAA4AAAIMhI+py+0Po5y02qsKADs=

🌿 删除数据

  • 删除数据时,我们需要处理的请求是Delete请求,我们在HeroController中添加对应的方法,代码如下:
@DeleteMapping("/{id}")
public Result deleteHero(@PathVariable int id){
    Result result = service.deleteHero(id);
    return result;
}
  • 在业务层Service中添加对应的deleteHero方法,代码如下:
@Override
public Result deleteHero(int id) {
    int num = dao.deleteHero(id);
    if(num==0){
        return Result.sendResult(Result.ERROR_CODE,"删除数据失败");
    }
    return Result.sendResult(Result.SUCCESS_CODE,"成功删除数据");
}
  • 在HeroDao中添加deleteHero方法,代码如下:
@Delete("delete from hero where id=#{id}")
int deleteHero(@Param("id") int id);
  • 打开Postman进行测试:

至此,案例中后端部分功能接口已经完毕,前端只需按照对应的接口要求发送请求和数据即可。

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

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

相关文章

使用Python爬取某发地网市场蔬菜价格数据

前言 随着互联网技术的发展&#xff0c;数据抓取成为了获取大量公开数据的重要手段。本文将介绍如何利用 Python 编程语言结合 DrissionPage 和自定义的 DataRecorder 模块&#xff0c;实现对新发地市场蔬菜价格数据的自动化抓取&#xff0c;并将抓取到的数据保存至 CSV 文件中…

免费好用又好看且多端自动同步第三方终端工具Termius你值得拥有

使用目的&#xff1a; 本地终端功能一样&#xff0c;都是为了登录服务器查看日志等操作。 本地终端 优点&#xff1a;方便简单&#xff0c;无需额外下载安装、免费。 缺点&#xff1a;每次都需要重新登陆输入命令&#xff0c;步骤繁琐无法简化&#xff1b;不能跨端同步。 第…

Postman:高效的API测试工具

在现代软件开发中&#xff0c;前后端分离的架构越来越普遍。前端开发者与后端开发者之间的协作需要一种高效的方式来测试和验证API接口。在这个背景下&#xff0c;Postman作为一款强大的API测试工具&#xff0c;受到了广泛的关注和使用。 今天将介绍什么是Postman、为什么要使用…

计算机网络-以太网小结

前导码与帧开始分界符有什么区别? 前导码--解决帧同步/时钟同步问题 帧开始分界符-解决帧对界问题 集线器 集线器通过双绞线连接终端, 学校机房的里面就有集线器 这种方式仍然属于共享式以太网, 传播方式依然是广播 网桥: 工作特点: 1.如果转发表中存在数据接收方的端口信息…

基于Retinex算法的图像去雾matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 2.算法运行软件版本 matlab2022a 3.部分核心程序 &#xff08;完整版代码包含详细中文注释和操作步骤视频&#xff09…

Nature Medicine病理AI汇总|TORCH:预测未知原发部位癌症的肿瘤起源|顶刊精析·24-11-01

小罗碎碎念 今天分析Nature Medicine病理AI系列的第三篇文章——《Prediction of tumor origin in cancers of unknown primary origin with cytology-based deep learning》 这篇文章报道了一种基于细胞学图像的深度学习方法TORCH&#xff0c;用于预测未知原发部位癌症的肿瘤…

Ubuntu 安装CUDA, cuDNN, TensorRT(草稿)

文章目录 写在前面一、CUDA, cuDNN, TensorRT 三个库的版本的确定二、解决方法参考链接 写在前面 自己的测试环境&#xff1a; Ubuntu20.04, 本文安装的版本&#xff1a; cuda_11.1.0&#xff1b;cuDNN-8.2.1&#xff1b;TensorRT-8.2.4.2 一、CUDA, cuDNN, TensorRT 三个库…

豆包,攻克数字是个什么工具?《GKData-挖掘数据的无限可能》(数据爬虫采集工具)

豆包&#xff0c;攻克数字是个什么工具&#xff1f; “攻克数字” 指的是 “攻克数字&#xff08;GKData&#xff09;” 这样一款工具。是一款针对网页、APP中数据自动解析转表存入数据库的软件&#xff0c;为数据工作者而生。它是一个不会编程也能用的可视化数据解析为标准二…

rust编写的系统监测器

系统监测器 技术栈 rusttaurivue3vue-echartsrsbuild 软件介绍 用于查看电脑的硬件信息&#xff0c;实时监测cpu&#xff0c;内存&#xff0c;硬盘&#xff0c;网络&#xff0c;进程等系统资源 图形化&#xff0c;动态化展示&#xff0c;美观实用 软件截图 下载 https:/…

实体类中为什么要实现serializable接口

最近见到好多项目中写的代码&#xff0c;在实体类中实现了Serializable接口。说实话&#xff1a;这个在以前学习的时候&#xff0c;貌似学过&#xff0c;但是一直没有用过&#xff0c;所以看着一脸懵逼&#xff0c;但是别人总不可能随便写的吧.....所以就去查了一下这个接口。 …

github打不开网络问题

当打开github出现超时或者网络不能访问的情况时&#xff0c;我们进行如下方法解决&#xff1a; 1&#xff0c;ping gitbub.com查看域名分析的DNS IP C:\Users\86156>ping github.com 正在 Ping github.com [20.205.243.166] 具有 32 字节的数据: 来自 20.205.243.166 的回复…

基于NVIDIA NIM平台实现盲人过马路的demo(一)

前言:利用NVIDIA NIM平台提供的大模型进行编辑,通过llama-3.2-90b-vision-instruct模型进行初步的图片检测 step1: 部署大模型到本地,引用所需要的库 import os import requests import base64 import cv2 import time from datetime import datetimestep2: 观看官方使用文…

Java日志脱敏(二)——fastjson Filter + 注解 + 工具类实现

背景简介 日志脱敏 是常见的安全需求&#xff0c;最近公司也需要将这一块内容进行推进。看了一圈网上的案例&#xff0c;很少有既轻量又好用的轮子可以让我直接使用。我一直是反对过度设计的&#xff0c;而同样我认为轮子就应该是可以让人拿去直接用的。所以我准备分享两篇博客…

上海亚商投顾:沪指缩量调整 华为概念股午后爆发

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 市场全天震荡调整&#xff0c;沪指、深成指午后跌超1%&#xff0c;创业板指一度跌逾2%&#xff0c;尾盘跌幅有…

从0开始学PHP面向对象内容之(类,对象,构造/析构函数)

上期我们讲了面向对象的一些基本信息&#xff0c;这期让我们详细的了解一下 一、面向对象—类 1、PHP类的定义语法&#xff1a; <?php class className {var $var1;var $var2 "constant string";function classfunc ($arg1, $arg2) {[..]}[..] } ?>2、解…

利用Docker Compose构建微服务架构

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 利用Docker Compose构建微服务架构 引言 Docker Compose 简介 安装 Docker Compose 创建项目结构 编写 Dockerfile 前端 Dockerf…

CPU用户时间百分比

在计算机系统中&#xff0c;"CPU用户时间百分比&#xff08;CPU User Time&#xff09;"是一个性能监控指标&#xff0c;它描述了CPU在用户模式下执行的累积时间与总的CPU时间的比例。这个指标可以帮助我们了解系统在执行用户态程序时的负载情况。下面是一些关于CPU用…

TEC半导体致冷工作原理:【图文详讲】

目录 1&#xff1a;什么是TEC 2&#xff1a;TEC工作原理 3&#xff1a;TEC结构 4&#xff1a;TEC技术参数 5&#xff1a;TEC选型 6&#xff1a;实物TEC 7&#xff1a;手机散热器 1&#xff1a;什么是TEC TEC半导体致冷器&#xff08;Thermo Electric Cooler&#xff09…

排序 (插入/选择排序)

目录 一 . 排序概念及运用 1.1 排序的概念 1.2 排序的应用 1.3 常见的排序算法 二 . 插入排序 2.1 直接插入排序 2.1 复杂度分析 2.3 希尔排序 2.4 希尔排序时间复杂度分析 三 . 选择排序 3.1 直接选择排序 3.2 堆排序 一 . 排序概念及运用 1.1 排序的概念 排序 : 所…

由 GPT 引发的这波「大模型热」将会如何洗牌?

大模型,是风口还是陷阱?正如零一万物CEO李开复所言,模型落地是关键,性能、基础设施、应用缺一不可。这场由GPT引发的“大模型热”,正上演着一场残酷的洗牌游戏,淘汰赛早就开始了! 我个人认为由GPT引发的这波AI热潮,最终的胜负将取决于:市场竞争格局中头部企业与中小企…