Mybatis(搭建,CRUD,方法参数,XML映射文件,动态SQL)【详解】

news2024/11/14 21:31:48

目录

一.准备基础代码

Mybatis的通用配置

二. 基本CURD操作

1.查询-根据id查询一条

2.查询-查询数量

3.删除

4.新增

获取主键值

5.修改

6.查询-模糊查询

预编译SQL

#{}与${}的区别【面试题】

三. Mybatis的方法参数与结果集

1.SQL里取方法参数的值

2.查询结果集的封装

方案一:SQL语句里给字段起别名

方案二:使用@Results和@Result手动映射

四.Mybatis的XML映射文件

1.介绍

2.用法

3.示例

4.给idea配置代码模板

五、Mybatis的动态SQL【重点】

1. 动态SQL介绍

2. if标签和where标签

3. set标签

4. foreach标签

5. sql标签和include标签


一.准备基础代码

把基础工程《资料\00.基础工程\web09-mybatis-curd》拷贝到不含中文、空格、特殊字符的目录里,然后使用idea直接open打开项目

准备基础环境

  • 依赖pom.xml

<properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.3</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>

        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>8.0.33</version>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

配置文件application.properties

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/db4
spring.datasource.username=root
spring.datasource.password=root

引导类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MybatisCurdApplication {
    public static void main(String[] args) {
        SpringApplication.run(MybatisCurdApplication.class, args);
    }
}

查询所有员工

  • 实体类

import lombok.Data;

import java.time.LocalDate;
import java.time.LocalDateTime;

@Data
public class Emp {
    private Integer id;
    private String username;
    private String password;
    private String name;
    private Integer gender;
    private String image;
    private Integer job;
    private LocalDate entrydate;
    private Integer deptId;
    private LocalDateTime createTime;
    private LocalDateTime updateTime;
}

EmpMapper

import com.itheima.pojo.Emp;
import org.apache.ibatis.annotations.Select;

import java.util.List;

@Mapper
public interface EmpMapper {
    @Select("select * from emp")
    List<Emp> queryAll();
}

功能测试

import com.itheima.mapper.EmpMapper;
import com.itheima.pojo.Emp;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
public class CurdTest {
    @Autowired
    private EmpMapper empMapper;

    @Test
    public void testQueryAll(){
        List<Emp> emps = empMapper.queryAll();
        emps.forEach(System.out::println);
    }
}

Mybatis的通用配置

Mybatis的日志输出

直接修改application.properties,增加配置:

mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

Mybatis下划线与驼峰命名转换

直接修改application.properties,增加配置:

#开启下划线与驼峰命名的自动映射。
# 如果设置为true,那么数据库里下划线命名风格的字段,会自动映射到Java里驼峰式命名的属性
# 比如:数据库字段是dept_id, Java里的成员变量名是deptId。 Mybatis会认为这两个是对应的
mybatis.configuration.map-underscore-to-camel-case=true

基本CURD操作

使用Mybatis,无论什么功能,都只需要:

  • 在Mapper接口里写一个方法

  • 给方法配置SQL语句:用注解

二. 基本CURD操作

1.查询-根据id查询一条

EmpMapper:实现功能

/**
 * 0. 先准备好SQL语句
 * 1. 方法的参数:根据SQL语句需要的参数来定
 *      这些参数都是给SQL语句使用。SQL语句里需要几个参数,方法上就要加几个形参
 *      SQL语句里要获取参数值,如果方法只有一个参数,写法是:#{随意写},建议写成#{参数名}
 * 2. 方法的返回值:根据我们想要得到什么结果来定
 *      我们期望Mybatis帮我们把查询结果封装成什么对象。
 *      写成Emp,Mybatis就会把查询的结果封装成一个Emp对象
 *      注意:实体类里的属性名,要和表的字段名 一致(相同,或者符合下划与驼峰命名的规则)
 */
@Select("select * from emp where id = #{id}")
Emp queryById(Integer id);

CurdTest:功能测试

@Test
public void testQueryById(){
    Emp emp = empMapper.queryById(1);
    System.out.println("emp = " + emp);
}

2.查询-查询数量

EmpMapper:实现功能

/**
 * 查询数量:SQL语句 select count(*) from emp
 * 方法要参数吗?不需要。因为SQL语句不需要参数
 * 方法返回值是什么类型?能够封装查询结果即可,可使用int、long
 */
@Select("select count(*) from emp")
int queryCount();

CurdTest:功能测试

@Test
public void testQueryCount(){
    int count = empMapper.queryCount();
    System.out.println("count = " + count);
}

3.删除

EmpMapper:实现功能

/**
 * 根据id删除一个员工:delete from emp where id = ?
 * 配置查询语句:@Select
 * 配置新增语句:@Insert
 * 配置修改语句:@Update
 * 配置删除语句:@Delete
 */
@Delete("delete from emp where id = #{id}")
void deleteById(Integer id);

CurdTest:功能测试

@Test
public void testDeleteById(){
    empMapper.deleteById(17);
}

4.新增

EmpMapper:实现功能

/**
 * 插入一条员工数据:
 * INSERT INTO emp (id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time)
 * VALUES (16, 'songyuanqiao', '123456', '宋远桥', 1, '16.jpg', 2, '2010-01-01', 2, '2023-08-19 10:39:37', '2023-08-19 10:39:37');
 *
 * 方法的参数:
 *      如果SQL语句需要的参数过多,方法的形参可以使用一个实体类
 *      SQL语句里使用 #{JavaBean的属性名}
 *      注意:
 *          不要写成 '#{JavaBean属性名}'
 *          #{属性名}的顺序,必须与前边的字段顺序是一致对应的
 */
@Insert("INSERT INTO emp (username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time)\n" +
        "VALUES (#{username}, #{password}, #{name}, #{gender}, #{image}, #{job}, #{entrydate}, #{deptId}, #{createTime}, #{updateTime})")
void insert(Emp emp);

CurdTest:功能测试

@Test
public void testInsert(){
    Emp emp = new Emp();
    emp.setUsername("tom");
    emp.setPassword("123");
    emp.setName("汤姆");
    emp.setGender(1);
    emp.setCreateTime(LocalDateTime.now());
    emp.setUpdateTime(LocalDateTime.now());
    empMapper.insert(emp);
}
获取主键值

如果执行insert时,需要获取数据的主键值,我们可以做:

  • 在Mapper接口里插入的方法上,再增加注解:@Options(useGeneratedKeys=true, keyProperty="JavaBean里的属性名")

/**
     * 插入一条员工数据:
     * INSERT INTO emp (id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time)
     * VALUES (16, 'songyuanqiao', '123456', '宋远桥', 1, '16.jpg', 2, '2010-01-01', 2, '2023-08-19 10:39:37', '2023-08-19 10:39:37');
     *
     * 方法的参数:
     *      如果SQL语句需要的参数过多,方法的形参可以使用一个实体类
     *      SQL语句里使用 #{JavaBean的属性名}
     *      注意:
     *          不要写成 '#{JavaBean属性名}'
     *          #{属性名}的顺序,必须与前边的字段顺序是一致对应的
     * 如果插入数据之后,需要获取数据的主键值:@Options
     *      useGeneratedKeys:利用数据库的主键自增得到主键值
     *      keyProperty:把得到的主键值,存储到参数实体类对象的哪个属性上
     */
    @Options(useGeneratedKeys = true, keyProperty = "id")
    @Insert("INSERT INTO emp (username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time)\n" +
            "VALUES (#{username}, #{password}, #{name}, #{gender}, #{image}, #{job}, #{entrydate}, #{deptId}, #{createTime}, #{updateTime})")
    void insert(Emp emp);

5.修改

EmpMapper:实现功能

/**
 * 修改id为19的数据:
 * UPDATE emp SET username = 'jerry', password = '123', name = '杰瑞', gender = 1, image = null, job = null, entrydate = null, dept_id = null, create_time = '2023-08-19 14:54:29', update_time = '2023-08-19 14:54:29' WHERE id = 19;
 */
@Update("UPDATE emp SET username = #{username}, password = #{password}, name = #{name}, gender = #{gender}, image = #{image}, job = #{job}, " +
        "entrydate = #{entrydate}, dept_id = #{deptId}, create_time = #{createTime}, update_time = #{updateTime} WHERE id = #{id}")
void updateById(Emp emp);

CurdTest:功能测试

@Test
public void testUpdateById(){
    Emp emp = empMapper.queryById(19);

    emp.setUsername("robin li");
    emp.setGender(2);

    empMapper.updateById(emp);
}

6.查询-模糊查询

EmpMapper:实现功能

/**
     * 模糊查询:查询姓名里包含“张”的员工列表
     * select * from emp where name like '%张%';
     * SQL语句里拼接字符串函数:concat(字符串1, 字符串2, 字符串3,....)
     */
    @Select("select * from emp where name like concat('%', #{name}, '%')")
    List<Emp> queryByName1(String name);

    @Select("select * from emp where name like '%${name}%'")
    List<Emp> queryByName2(String name);

CurdTest:功能测试

  @Test
    public void testQueryByName1(){
        List<Emp> list = empMapper.queryByName1("张");
        list.forEach(System.out::println);
    }

    @Test
    public void testQueryByName2(){
        List<Emp> list = empMapper.queryByName2("张");
        list.forEach(System.out::println);
    }
预编译SQL

预编译:不是Mybatis的概念,而是JDBC的概念。

  • 不使用预编译:RDBMS先编译SQL(解析SQL语句,确定SQL的执行方案);再执行SQL语句,得到结果

  • 使用了预编译:先把SQL语句进行解析确定执行方案;然后设置参数值执行SQL

好处1-预编译执行SQL性能更高

好处2-可以防止SQL注入漏洞

#{}${}的区别【面试题】
  • #{}:底层使用的是预编译方式。

    更安全,因为可以防止SQL注入漏洞

    执行SQL的性能更高

  • ${}:没有使用预编译,是直接拼接SQL字符串

    不安全,可能存在SQL注入漏洞

    执行SQL的性能不如预编译

三. Mybatis的方法参数与结果集

1.SQL里取方法参数的值

如果方法只有一个参数:

  • 如果参数是简单值(8种基本数据类型及包装类、String),SQL语句里取参数值是:#{参数名}

  • 如果参数是JavaBean对象,SQL语句里取JavaBean的属性值:#{属性名}

如果方法有多个参数,SQL语句里取参数值:

  • 从SpringBoot2版本开始:#{形参名}

  • 在SpringBoot2以前版本:【了解】

    首先,给方法参数起名称,添加注解:@Param("名称")

    然后,在SQL语句里使用:#{名称} 获取对应参数值

/**
     * 需求:根据姓名、性别、入职时间范围 搜索员工信息
     * SQL:select * from emp where name like ? and gender = ? and entrydate between ? and ?
     * 如果方法有多个参数,SQL语句里取参数值:#{参数名称}。从SpringBoot2开始提供的功能
     */
@Select("select * from emp where name like concat('%',#{name}, '%') and gender = #{gender} and entrydate between #{begin} and #{end}")
List<Emp> queryEmpList(String name,
                       Integer gender,
                       LocalDate begin,
                       LocalDate end);

@Select("select * from emp where name like concat('%',#{a}, '%') and gender = #{b} " +
        "and entrydate between #{c} and #{d}")
List<Emp> queryEmpList2(@Param("a") String name,
                        @Param("b") Integer gender,
                        @Param("c") LocalDate begin,
                        @Param("d") LocalDate end);

2.查询结果集的封装

Mybatis会自动帮我们把查询的结果集封装成实体类对象,前提条件是:

  • 要么 JavaBean的属性名,和 表的字段名完全相同。

    比如:字段名是gender,Emp类里的属性名也叫gender

  • 要么 JavaBean的属性名,和 表的字段名按照 下划线与驼峰映射 是一致的。

    比如:字段名是dept_id,Emp类里属性名是deptId

    前提:开启下划线与驼峰的命名转换,修改application.properties配置文件,添加参数

    mybatis.configuration.map-underscore-to-camel-case=true

如果JavaBean的属性名和字段名完全不匹配,就需要处理这种情况

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Employee {
    private Integer id;
    /*对应的字段名是username*/
    private String uname;
    /*对应的字段名是password*/
    private String pword;
    private String name;
    private Integer gender;
    private String image;
    private Integer job;
    private LocalDate entrydate;
    private Integer deptId;
    private LocalDateTime createTime;
    private LocalDateTime updateTime;
}
方案一:SQL语句里给字段起别名
/**
 * JavaBean属性名 与  表字段名 完全不匹配:
 * SQL语句里给字段起别名,别名和JavaBean属性名相同
 */
@Select("select id, username as uname, password as pword,name,gender,image,job," +
        "entrydate,dept_id,create_time, update_time from emp")
List<Employee> queryEmployeeList2();
方案二:使用@Results@Result手动映射

只需要把不同的字段配置一下,如果字段和属性名匹配,就不需要做配置

/**
 * JavaBean属性名 与  表字段名 完全不匹配:
 * 我们使用@Results和@Result注解,手动设置一下,哪个字段对应哪个属性
 *      注解1:@Results,用于配置当前查询里所有字段的映射关系
 *      注解2:@Result,用于配置某一个字段与属性的对应关系
 *          property:写的是JavaBean的属性名
 *          column:写的是表里的字段名
 */
@Select("select * from emp")
@Results({
        @Result(property = "uname", column = "username"),
        @Result(property = "pword", column = "password")
})
List<Employee> queryEmployeeList3();

四.Mybatis的XML映射文件

1.介绍

Mybatis的SQL语句,可以使用注解直接配置到Mapper接口里的方法上,也可以定义到XML文件里

  • 如果SQL语句写到接口里的方法上:注解方式,适合于简单SQL或者固定不变的SQL

  • 如果SQL语句写到XML文件里:xml方式,更适合于复杂SQL或者动态变化的SQL

注意:XML方式和注解方式可以同时使用,但是要注意

  • 一个方法的SQL语句,要么用注解方式配置,要么用XML方式配置,不能重复配置

2.用法

XML文件的要求:

  1. XML文件的位置:要和Mapper同一包下,按照maven规范,要放到resources里边的同名文件夹下

  2. XML文件的名称:要和Mapper接口的名称相同

XML内容的要求:

  • 根标签<mapper namespace="Mapper接口的全限定类名">:表示当前XML是给哪个Mapper接口配置语句的

  • 在mapper标签里边,配置SQL语句:

    • select标签:配置select语句,SQL语句写到标签里边。需要配置id属性和resultType属性

      • id属性:配置方法名。表示当前SQL语句是给哪个方法配置的

      • resultType属性:告诉Mybatis要把查询结果中的每一行数据,封装成什么对象

    • insert标签:配置insert语句,SQL语句写到标签里边。需要配置id属性

      • id属性:配置方法名。表示当前SQL语句是给哪个方法配置的

    • update标签:配置update语句,SQL语句写到标签里边。需要配置id属性

      • id属性:配置方法名。表示当前SQL语句是给哪个方法配置的

    • delete标签:配置delete语句,SQL语句写到标签里边。需要配置id属性

      • id属性:配置方法名。表示当前SQL语句是给哪个方法配置的

3.示例

Mapper接口

/**
 * 使用XML方式配置SQL语句
 * XML文件的位置:Mapper接口在什么包,XML文件就必须在同包下。
 *      在resources目录下右键,创建Directory文件夹,以/为分隔符,千万不要以.为分隔符。
 *      比如:com/itheima/mapper
 * XML文件的名称:Mapper接口叫什么名字,XML文件也叫什么名字
 *
 */
List<Emp> queryEmpListXml(String name,Integer gender,LocalDate begin,LocalDate end);

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">
<!--
mapper标签:根标签
    namespace:要写Mapper接口的全限定类名。表示当前xml文件,是给哪个Mapper接口配置的
mapper的子标签:
    select标签:配置select语句,SQL语句写到标签里边
    insert标签:配置insert语句,SQL语句写到标签里边
    update标签:配置update语句,SQL语句写到标签里边
    delete标签:配置delete语句,SQL语句写到标签里边
    以上标签都有的属性:
        id:写方法名。表示当前语句是给哪个方法配置的
        resultType:select标签专用的属性
            用于告诉Mybatis,SQL查询语句的结果,要封装成什么对象
            写JavaBean的全限定类名,不需要写List、Set等等
-->
<mapper namespace="com.itheima.mapper.EmpMapper">
    <select id="queryEmpListXml" resultType="com.itheima.pojo.Emp">
        select * from emp
         where name like concat('%',#{name}, '%')
           and gender = #{gender}
           and entrydate between #{begin} and #{end}
    </select>
</mapper>

功能测试

@Test
public void testQueryEmpListXml(){
    LocalDate begin = LocalDate.of(2010, 1, 1);
    LocalDate end = LocalDate.of(2015, 12, 31);
    List<Emp> emps = empMapper.queryEmpListXml("张", 1, begin, end);
    for (Emp emp : emps) {
        System.out.println("emp = " + emp);
    }
}

4.给idea配置代码模板

配置方式:File | Settings | Editor | Live Templates

<?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">
<mapper namespace="$namespace$">
    $END$
</mapper>

五、Mybatis的动态SQL【重点】

1. 动态SQL介绍

当进行多条件搜索时,搜索条件通常是不确定的,导致SQL语句的条件也是不确定的:需要根据条件,来确定要拼接哪些查询条件。这样的SQL语句,就是所谓的动态SQL

Mybatis提供了一些xml的标签,用于实现动态SQL语句:

  • if标签:用于判断

    • where标签:用于代替where关键字

    • set标签:用于代替set关键字

  • foreach标签:用于循环遍历

  • sql标签和include标签:用于抽取重用sql片段

2. if标签和where标签

if标签:用于进行判断。如果判断为true,标签里的sql才会生效

<if test="判断条件">
    如果判断为true,这里的内容才会生效
</if>

where标签:用于代替where关键字,它可以帮我们处理多余的and和or,还有处理我们的空集合,不是null

演示:

Mapper接口

     /**
     * 动态SQL:根据条件查询员工。根据name和gender动态查询
     */
    List<Emp> searchEmp1(String name, Integer gender);

XML映射

<!--
    if标签:用于判断
      语法:
        <if test="判断条件表达式">
            如果判断为true,这里的内容将会生效
        </if>
      判断条件表达式:其实使用的是OGNL的表达式语法:
        名称,取对应参数的值。#{}是怎么取参数值的,这里也怎么取参数值
        判断运算:>, <, >=, <=, ==, !=
        逻辑运算:&&, ||, ! 或者 and or not
        调用参数的属性或者方法
    where标签:用于代替where关键字
        还会帮我们处理掉SQL语句里多余的and关键字
        使用了where标签之后,建议给所有的条件前边都加上and
    -->
    <select id="searchEmp1" resultType="com.itheima.pojo.Emp">
        select * from emp
        <where>
            <!-- 如果参数name值非空 并且不是空串,就添加上name的条件-->
            <if test="name!=null and name.length()>0">
                and name like concat('%',#{name}, '%')
            </if>
            <!-- 如果参数gender非空,就添加上gender的条件 -->
            <if test="gender!=null">
                and gender = #{gender}
            </if>
        </where>
    </select>

3. set标签

set标签:用于代替update语句里的set关键字,可以帮我们处理多余的逗号

Mapper

void update(Emp emp);

XML映射

<!--
set标签:用于代替update语句里的set关键字
    可以帮我们处理掉多余的,逗号
    把所有要修改的字段sql片段,都写到set标签里边
-->
<update id="update">
    update emp
    <set>
        <if test="username!=null and username.length()>0">username=#{username},</if>
        <if test="password!=null and password.length()>0">password= #{password},</if>
        <if test="name!=null and name.length()>0">name= #{name},</if>
        <if test="gender!=null">gender= #{gender},</if>
        <if test="image!=null and image.length()>0">image= #{image},</if>
        <if test="entrydate!=null">entrydate= #{entrydate},</if>
        <if test="deptId!=null">dept_id= #{deptId},</if>
        <if test="updateTime!=null">update_time= #{updateTime}</if>
    </set>
    where id = #{id}
</update>

4. foreach标签

foreach标签:用于循环遍历,比如我们的批量删除,多个数据

Mapper

void batchDelete(List<Integer> ids);

XML映射

<!--
foreach标签:
    collection:被循环的集合或数组
    item:定义一个变量名,通过这个变量名可以获取集合或数组里的每个值
    separator:拼接每个值时候,使用的分隔符
    open:拼接结果的前缀部分
    close:拼接结果的后缀部分
假如:ids值是 1,2,3
循环拼接的结果是:
    delete from emp where id in (1,2,3)
    (1,2,3)
for(Integer id:ids){}
-->
<delete id="batchDelete">
    delete from emp where
    <foreach collection="ids" open="id in(" item="id" separator="," close=")">
        #{id}
    </foreach>
</delete>

5. sql标签和include标签

sql标签:定义一个sql片段

include标签:引用一个sql片段

用法 :如果多条SQL语句里,有某些片段是完全相同的,可以使用sql标签抽取出去,需要使用时用include引用即可

<!--定义一个SQL片段-->
<sql id="selectEmp">select * from emp</sql>

<!-- 引用一个SQL片段 -->
<select id="queryEmpListXml" resultType="com.itheima.pojo.Emp">
    <!--利用include标签,引用:select * from emp-->
    <include refid="selectEmp"></include>
    where name like concat('%',#{name}, '%')
    and gender = #{gender}
    and entrydate between #{begin} and #{end}
</select>

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

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

相关文章

react native常用插件

react-native-async-storage/async-storage 说明&#xff1a;AsyncStorage 是一个在 react-native 中轻量存储的库&#xff1b;跟 localStorage 类似&#xff0c;API 也几乎一样&#xff1b;存储的时候需要将存储内容转成字符串存储。 react-navigation/material-bottom-tabs …

Ubuntu Flask 运行 gunicorn+Nginx 部署

linux Ubuntu 下运行python 程序出现killed 原因&#xff1a;CPU或内存限制&#xff1a;在华为云上&#xff0c;你可能有CPU或内存使用的限制。例如&#xff0c;如果你使用的是一个固定大小的实例&#xff0c;那么超过该实例的CPU或内存限制可能会导致进程被杀死。 参考&am…

Gateway网关在url参数带有特殊字符的情况下转发失败(响应400)

本文主要分享了&#xff0c;SpringCloud Gateway网关在url参数带有空格或者特殊字符的情况下&#xff0c;转发失败导致响应错误码400的解决方案。 响应400错误码的2种场景&#xff1a; 1.参数带空格&#xff0c;Gateway会误认为该空格是切割符&#xff0c;如?phone 135****6…

基于单片机的公交车IC卡操作系统的设计

目 录 摘 要 III Abstract IV 前 言 1 第一章 绪论 2 1.1 设计的背景和意义 2 1.2 设计的现状和发展 2 1.3 设计的目的与意义 2 第二章 总体设计 4 2.1 总体方案的设计与实现 4 2.1.1 主要设计的内容 4 2.1.2 系统的总体设计 4 2.2 系统方案论证 5 2.2.1 单片机的选择 6 2.2.2…

Java基于微信小程序的电影推荐系统的实现,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

机器学习 Python库 乱记录

MLFlow—模型实验和跟踪 MLflow是一个平台&#xff0c;帮助你从头到尾管理你的机器学习实验&#xff0c;确保可追溯性和可重复性。它提供了一个集中的存储库&#xff0c;用于存储你的代码、数据和模型工件&#xff0c;以及一个跟踪系统&#xff0c;记录你所有的实验&#xff0c…

【Node.js从基础到高级运用】十一、构建RESTful API

在本篇博客中&#xff0c;我们将综合之前讨论的内容&#xff0c;深入探索如何使用Node.js构建一个RESTful API。我们将重点讨论设计合理的API端点&#xff0c;展示如何通过代码实现这些端点&#xff0c;并指导如何使用Postman测试我们的API&#xff0c;确保其按预期工作。 前提…

Python-sklearn-diabetes项目实战

目录 1 下载数据集和预处理 1.1 加载/下载数据集 1.2 数据可视化 1.3 数据清洗 1.4 特征工程 1.5 构建特征集和标签集 1.6 拆分训练集和测试集 2 训练模型 2.1 选择算法和确定模型 2.2 训练拟合模型 3 评估并优化模型性能 本文以糖尿病数据集diabetes为基础进行线性…

Spring Cloud Gateway如何实现熔断

Spring Cloud Gateway熔断集成 熔断应用&#xff1a; 金融市场中的熔断机制&#xff1a;在金融交易系统中&#xff0c;熔断机制&#xff08;Circuit Breaker&#xff09;是一种市场保护措施&#xff0c;旨在预防市场剧烈波动时可能导致的系统性风险。当某个基准指数&#xff08…

【微服务-Nacos】Nacos集群的工作原理及集群间数据同步过程

上篇文章我们介绍了Nacos集群的搭建方法及步骤&#xff0c;下面我们来看一下Nacos集群的工作原理&#xff0c;一共有两部分&#xff1a;Leader节点选举及各节点数据同步。 1、Nacos集群中Leader节点是如何产生的 Nacos集群采用了Raft算法实现。它是一种比较简单的选举算法&am…

【javaWeb】在webapp中手动发布一个应用

标题 &#x1f432;一、为什么要在webapp中手动发布一个应用&#x1f389;二、手动发布步骤1.下载Tomcat2.解压并安装3.在webapps中创建文档 ✨三、总结 &#x1f432;一、为什么要在webapp中手动发布一个应用 好处解释灵活性手动发布应用程序可以根据自己的需求进行自定义配置…

Abaqus三维梯度泰森多边形插件:Voronoi FGM 3D(Mesh)- AbyssFish

插件介绍 Voronoi FGM 3D (Mesh) V1.0 - AbyssFish 插件可在Abaqus软件内生成梯度分布的三维泰森多边形长方体模型。插件可用于梯度功能材料(Functionally Gradient Materials)、梯度纳米金属材料、梯度金属结构等梯度晶体模型的建立。模型基于背景网格实现&#xff0c;通过单…

YOLO_项目环境配置

YOLOv5官方项目地址 https://github.com/ultralytics/yolov5 下载 5.0和1.0源码 5.0 master-Tags-v5.0 Code-Download.ZIP 切换到1.0下载 解压缩提取 打开V5.0 使用Pycharm打开V5.0的文件夹 环境配置 参考 http://t.csdnimg.cn/Zdfh2 http://t.csdnimg.cn/Nqkwr 然后在Pyc…

学习JAVA的二十二天(基础)

目录 网络编程 三要素&#xff1a; IP InetAddress类 端口号 协议 UDP协议 TCP协议 前言&#xff1a;学习JAVA的第二十一天&#xff08;基础&#xff09;-CSDN博客 网络编程 在网络通信协议下&#xff0c;不同计算机上运行的程序,进行的数据传输。 三要素&#xff1a;…

Qt篇——QChartView获取鼠标停留位置的数值

需求&#xff1a;鼠标停留在QChartView上时&#xff0c;想要计算停留位置的数值。 一开始的方法是想要通过鼠标移动事件计算鼠标在QChartView上的坐标&#xff0c;在换算成数值&#xff0c;后来发现QChartView中除了图表数据&#xff0c;还有坐标轴与坐标轴数值标签占了高度&a…

Python数据分析-Matplotlib1

一、折线图的绘制 1.数据分析流程 2.运用Matplot绘制折线图 #encodingutf-8 import random from matplotlib import pyplot as plt #绘图工具库 from matplotlib import font_manager #解决中文显示问题 from cProfile import label #设置字体方式 my_font font_manager.Fon…

个人简历主页搭建系列-02:github 仓库作为联系方式

这篇文章暂时没有开始正式搭建网站。首先是最重要的注意事项&#xff1a;隐私。 真实姓名如果大家自己不介意的话其实我觉得还好&#xff0c;现在在互联网上想扒个姓名挺简单的&#xff0c;而且很多人都实名上网hh&#xff08;比如我的几位田径队学弟笑&#xff09;。 电话&a…

怎样基于“用户”思维让内容营销更有效

当下互联网流量见顶&#xff0c;内容已经成为互联网竞争新的制高点&#xff0c;可以说在数字化驱动的新时代下&#xff0c;“内容为王”仍然是真理。然后信息泛滥的时代下&#xff0c;如何让内容营销脱颖而出呢&#xff1f;媒介盒子认为“用户思维”是关键&#xff0c;今天就和…

2024.3.14jsp

一、实验目的 1、安装配置JSP运行环境 2、设置web服务目录&#xff0c;修改TomCAT服务器的端口号、访问web服务目录下的jsp页面。 二、实验项目内容&#xff08;实验题目&#xff09; 1、编写两个简单的JSP页面&#xff1b;参考第一章上机实验1、2 &#xff08;1&#xff09…

Spring Cloud Alibaba微服务从入门到进阶(四)(服务发现-Nacos )

Nacos是服务发现组件和配置服务器 作为服务发现注册组件Nacos Server 搭建Nacos Server 下载、启动 访问nacos,默认 用户/密码 nacos/nacos 将应用注册到nacos 加依赖 在SpringCloud子项目中&#xff0c;Feign是属于OpenFeign&#xff0c;Sentinel、Nacos是属于alibaba的&…