MyBaits注解开发

news2024/11/23 2:00:29

1、注解开发介绍

在过去使用框架开发项目,基本都采用xml作为框架的核心配置文件存在,但是这种方式开发效率还是比较地下、不灵活。

现在企业开发为了能够更快的提高开发效率,必然会使用企业级框架进行项目开发,而现在主流的框架都支持基于注解的方式开发项目。

mybatis框架已经全面支持基于注解的开发。

使用mybatis的注解开发,并不能省略mybatis的核心配置文件,而注解仅仅只是代替Mapper文件

MyBatis 的注解开发主要代替了以下功能:

  1. 替代映射器接口(Mapper XML)
  • 使用@Mapper标注接口为映射器接口
  • 使用@Select、@Update等注解写SQL语句
  1. 替代结果映射(ResultMap)
  • 使用@Results和@Result注解配置结果映射
  1. 替代字段与属性映射
  • 使用@Column注解指定数据库列名
  • 使用@Id注解指定主键字段
  1. 替代关联查询
  • 使用@One、@Many注解配置一对一、一对多关系
  1. 替代动态SQL
  • 使用@SelectProvider、@UpdateProvider等注解执行动态SQL
  1. 替代缓存配置
  • 使用@CacheNamespace、@CacheFlush等注解配置缓存

注解开发使配置更简单,直接在接口及字段上通过注解即可实现XML方式的大部分功能。

但注解方式有限制。比如复杂的结果映射、动态SQL等还是建议用XML方式配置。所以在复杂场景下,注解+XML配置可以发挥两者优势。

2、Mybatis注解开发

mybatis注解开发主要介绍:

1、 注解开发的环境搭建

2、 单表的CRUD操作(使用代理方式)

3、 多表查询操作

4、 缓存的配置

2.1、注解开发环境搭建

2.1.1、创建maven项目

选择File > New > Project ,进入创建界面
请添加图片描述
选择New Project ,右侧填写项目名,选择项目存储路径,选择语言,构建工具,jdk版本,maven高级设置:
请添加图片描述

2.1.2、maven的配置文件

<?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.qbzaixian</groupId>
    <artifactId>qbzaixian</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.13</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.34</version>
        </dependency>
        <!-- lombok简化实体类开发,需要idea安装lombok的插件哦~~~-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.8</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

    </dependencies>
</project>

2.1.3、书写mybatis的核心配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--  properties 引入外部的配置文件,必须使用resource属性  -->
    <properties resource="db.properties"/>
    <!--settings 标签 -->
    <settings>
        <!-- 设置mybatis 的缓存-->
        <setting name="cacheEnabled" value="true"/>
        <!-- 开启驼峰式命名规则-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    <!-- 设置别名 -->
    <typeAliases>
        <package name="com.qbzaixian.pojo"/>
    </typeAliases>
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}" />
                <property name="url" value="${url}" />
                <property name="username" value="${username}" />
                <property name="password" value="${password}" />
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!-- 这里必须采用包的方式配置,因为没有mapper文件,书写接口所在的包-->
        <package name="com.qbzaixian.mapper"/>
    </mappers>
</configuration>

2.1.4、创建数据库

-- 创建数据库
CREATE DATABASE mybatis;
USE mybatis;
DROP TABLE IF EXISTS `tb_item`;
-- 创建商品表
CREATE TABLE `tb_item` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `item_name` VARCHAR(32) NOT NULL COMMENT '商品名称',
  `item_price` FLOAT(6,1) NOT NULL COMMENT '商品价格',
  `item_detail` TEXT COMMENT '商品描述',
  PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;


INSERT INTO `tb_item` VALUES ('1', 'iPhone 6', '5288.0', '苹果公司新发布的手机产品。');
INSERT INTO `tb_item` VALUES ('2', 'iPhone 6 plus', '6288.0', '苹果公司发布的新大屏手机。');

-- 创建用户表

DROP TABLE IF EXISTS `tb_user`;
CREATE TABLE `tb_user` (
  `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
  `user_name` VARCHAR(100) DEFAULT NULL COMMENT '用户名',
  `password` VARCHAR(100) DEFAULT NULL COMMENT '密码',
  `name` VARCHAR(100) DEFAULT NULL COMMENT '姓名',
  `age` INT(10) DEFAULT NULL COMMENT '年龄',
  `sex` TINYINT(1) DEFAULT NULL COMMENT '性别,1男性,2女性',
  `birthday` DATE DEFAULT NULL COMMENT '出生日期',
  `created` DATETIME DEFAULT NULL COMMENT '创建时间',
  `updated` DATETIME DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`user_name`)
) ENGINE=INNODB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;


INSERT INTO `tb_user` VALUES ('1', 'zhangsan', '123456', '张三', '30', '1', '1984-08-08', '2022-09-19 16:56:04', '2022-09-21 11:24:59');
INSERT INTO `tb_user` VALUES ('2', 'lisi', '123456', '李四', '21', '2', '1991-01-01', '2022-09-19 16:56:04', '2022-09-19 16:56:04');
INSERT INTO `tb_user` VALUES ('3', 'wangwu', '123456', '王五', '22', '2', '1989-01-01', '2022-09-19 16:56:04', '2022-09-19 16:56:04');
INSERT INTO `tb_user` VALUES ('4', 'zhangwei', '123456', '张伟', '20', '1', '1988-09-01', '2022-09-19 16:56:04', '2022-09-19 16:56:04');
INSERT INTO `tb_user` VALUES ('5', 'lina', '123456', '李娜', '28', '1', '1985-01-01', '2022-09-19 16:56:04', '2022-09-19 16:56:04');
INSERT INTO `tb_user` VALUES ('6', 'lilei', '123456', '李磊', '23', '1', '1988-08-08', '2022-09-20 11:41:15', '2022-09-20 11:41:15');

-- 订单表
DROP TABLE IF EXISTS `tb_order`;
CREATE TABLE `tb_order` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `user_id` BIGINT(20) NOT NULL,
  `order_number` VARCHAR(20) NOT NULL COMMENT '订单号',
  PRIMARY KEY (`id`),
  KEY `FK_orders_1` (`user_id`),
  CONSTRAINT `FK_orders_1` FOREIGN KEY (`user_id`) REFERENCES `tb_user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=INNODB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;


INSERT INTO `tb_order` VALUES ('1', '1', '20220921001');
INSERT INTO `tb_order` VALUES ('2', '2', '20220921002');
INSERT INTO `tb_order` VALUES ('3', '1', '20220921003');

-- 创建订单明细表

DROP TABLE IF EXISTS `tb_orderdetail`;
CREATE TABLE `tb_orderdetail` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `order_id` INT(32) DEFAULT NULL COMMENT '订单号',
  `item_id` INT(32) DEFAULT NULL COMMENT '商品id',
  `total_price` DOUBLE(20,0) DEFAULT NULL COMMENT '商品总价',
  `status` INT(11) DEFAULT NULL COMMENT '状态',
  PRIMARY KEY (`id`),
  KEY `FK_orderdetail_1` (`order_id`),
  KEY `FK_orderdetail_2` (`item_id`),
  CONSTRAINT `FK_orderdetail_1` FOREIGN KEY (`order_id`) REFERENCES `tb_order` (`id`),
  CONSTRAINT `FK_orderdetail_2` FOREIGN KEY (`item_id`) REFERENCES `tb_item` (`id`)
) ENGINE=INNODB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;


INSERT INTO `tb_orderdetail` VALUES ('1', '1', '1', '5288', '1');
INSERT INTO `tb_orderdetail` VALUES ('2', '1', '2', '6288', '1');
INSERT INTO `tb_orderdetail` VALUES ('3', '2', '2', '6288', '1');
INSERT INTO `tb_orderdetail` VALUES ('4', '3', '1', '5288', '1');

2.2、注解开发快速入门

2.2.1、编写pojo类

@Data
public class User {
    private Long id;
    // 用户名
    private String userName;
    // 密码
    private String password;
    // 姓名
    private String name;
    // 年龄
    private Integer age;
    // 性别,1男性,2女性
    private Integer sex;
    // 出生日期
    private Date birthday;
    // 创建时间
    private Date created;
    // 更新时间
    private Date updated;
}

2.2.2、编写接口

/**
 * MyBaits的注解开发
 */
public interface UserMapper {

    @Select("select * from tb_user where id = #{id}")
    public User selectById(Integer id);
}

2.2.3、编写测试类

public class MyBatisTest {
    private SqlSessionFactory factory;

    @Before
    public void init() throws Exception {
        //1、获取配置文件
        InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
        factory = new SqlSessionFactoryBuilder().build(in);
    }

    @Test
    public void testFindUserById(){
        SqlSession session = factory.openSession(true);
        UserMapper mapper = session.getMapper(UserMapper.class);
        User user = mapper.selectById(1);
        System.out.println(user);
    }
}

3、注解开发CRUD

mybatis注解开发主要使用的注解有:

  • @Select:完成查询sql语句的编写
  • @Update:完成修改的SQL语句编写
  • @Delete:完成删除的SQL语句编写
  • @Insert:完成插入的SQL语句编写

3.1、@Select注解

@Select:标记在方法上,表示该方法对应的SQL是查询语句。

public interface UserMapper {

    @Select("select * from tb_user where id = #{id}")
    public User selectById(Integer id);

    @Select("select * from tb_user")
    public List<User> selectUsers();
}
@Test
public void testFindUserById(){
    SqlSession session = factory.openSession(true);
    UserMapper mapper = session.getMapper(UserMapper.class);
    User user = mapper.selectById(1);
    System.out.println(user);
    System.out.println("--------------------");
    List<User> users = mapper.selectUsers();
    users.forEach(System.out::println);
}

3.2、@Update注解

@Update:表示该方法对应的SQL是更新语句。

@Update("update tb_user set age = #{age} , user_name = #{userName} WHERE id = #{id}")
public void updateUser(User user);
@Test
public void testUpdate(){
    SqlSession session = factory.openSession(true);
    UserMapper mapper = session.getMapper(UserMapper.class);
    User user = new User();
    user.setAge(30);
    user.setUserName("小羊苏西");
    user.setId(3L);
    mapper.updateUser(user);
}

3.3、@Delete注解

@Delete:表示该方法对应的SQL是删除语句。

@Delete("delete from tb_user where id = #{id}")
public void deleteById(Integer id);
@Test
public void testDelete(){
    SqlSession session = factory.openSession(true);
    UserMapper mapper = session.getMapper(UserMapper.class);
    mapper.deleteById(6);
}

3.4、@Insert注解

@Insert:表示该方法对应的SQL是插入语句。

@Insert("insert into tb_user(user_name,name,age,password,sex) values(#{userName},#{name},#{age},#{password},#{sex})")
public void addUser(User user);
@Test
public void testInsert(){
    SqlSession session = factory.openSession(true);
    UserMapper mapper = session.getMapper(UserMapper.class);
    User user = new User();
    user.setName("zwj");
    user.setUserName("张无忌");
    user.setAge(20);
    user.setPassword("123123");
    user.setSex(1);
    mapper.addUser(user);
}

4、@Results注解

Results注解主要完成在查询的时候列名和pojo的属性不对应时的映射操作的(类似于Mapper文件中使用resultMap进行配置解决),为了演示这个问题,这里故意修改pojo中的属性与列名不一致。

@Data
public class User2 {
    private Long id;
    // 用户名:故意修改userName为uName,方便下面测试
    private String uName;
    // 密码:故意修改password为pwd,方便下面测试
    private String pwd;
    // 姓名
    private String name;
    // 年龄
    private Integer age;
    // 性别,1男性,2女性
    private Integer sex;
    // 出生日期
    private Date birthday;
    // 创建时间
    private Date created;
    // 更新时间
    private Date updated;
}

为了方便,测试,这里在上面演示的CRUD中,对口和测试都是直接复制,在接口和类名后面添加了数字2.

public interface UserMapper2 {
    @Select("select * from tb_user where id = #{id}")
    public User2 selectById(Integer id);

    @Select("select * from tb_user")
    public List<User2> selectUsers();
}
public class MyBatisTest2 {
    private SqlSessionFactory factory;

    @Before
    public void init() throws Exception {
        //1、获取配置文件
        InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
        factory = new SqlSessionFactoryBuilder().build(in);
    }

    @Test
    public void testFindUserById(){
        SqlSession session = factory.openSession(true);
        UserMapper2 mapper = session.getMapper(UserMapper2.class);
        User2 user = mapper.selectById(1);
        System.out.println(user);
    }
}

查看打印的执行结果:

User2(id=1, uName=null, pwd=null, name=张三, age=30, sex=1, birthday=Wed Aug 08 00:00:00 CST 1984, created=Mon Sep 19 16:56:04 CST 2022, updated=Wed Sep 21 11:24:59 CST 2022)

注意,uName和pwd并没有封装到数据,因为pojo的属性名和列名不对应。无法自动封装。

mybatis提供Results注解解决这个问题

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Results {
  /**
   * Returns the id of this result map.
   *
   * @return the id of this result map
   */
  String id() default "";

  /**
   * Returns mapping definitions for property.
   *
   * @return mapping definitions
   */
  Result[] value() default {};
}

其中的id,是给当前这个Results注解起名字,方便在别的地方引用。

其中的Result用来书写具体的列名和属性名的对应关系。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Repeatable(Results.class)
public @interface Result {
  /**
   * Returns whether id column or not.
   *
   * @return {@code true} if id column; {@code false} if otherwise
   */
  boolean id() default false;

  /**
   * Return the column name(or column label) to map to this argument.
   *
   * @return the column name(or column label)
   */
  String column() default "";

  /**
   * Returns the property name for applying this mapping.
   *
   * @return the property name
   */
  String property() default "";

  /**
   * Return the java type for this argument.
   *
   * @return the java type
   */
  Class<?> javaType() default void.class;

  /**
   * Return the jdbc type for column that map to this argument.
   *
   * @return the jdbc type
   */
  JdbcType jdbcType() default JdbcType.UNDEFINED;

  /**
   * Returns the {@link TypeHandler} type for retrieving a column value from result set.
   *
   * @return the {@link TypeHandler} type
   */
  Class<? extends TypeHandler> typeHandler() default UnknownTypeHandler.class;

  /**
   * Returns the mapping definition for single relationship.
   *
   * @return the mapping definition for single relationship
   */
  One one() default @One;

  /**
   * Returns the mapping definition for collection relationship.
   *
   * @return the mapping definition for collection relationship
   */
  Many many() default @Many;
}

Result注解中常用的几个属性解释:

id:当前的列是否为主键

column:对应数据库中的列名

property:对应pojo中的属性名

javaType:对应的属性名的数据类型

jdbcType:对应的数据库列类型

public interface UserMapper2 {

    @Select("select * from tb_user where id = #{id}")
    @Results(
            id = "uDemo",
            value = {
                    @Result(column = "user_name",property = "uName",id = false),
                    @Result(column = "password",property = "pwd",id = false),
            }
    )
    public User2 selectById(Integer id);

    @Select("select * from tb_user")
    public List<User2> selectUsers();
}

重新执行测试,会发现对应的属性已经可以自动封装数据

User2(id=1, uName=zhangsan, pwd=123456, name=张三, age=30, sex=1, birthday=Wed Aug 08 00:00:00 CST 1984, created=Mon Sep 19 16:56:04 CST 2022, updated=Wed Sep 21 11:24:59 CST 2022)

在接口中,如果某个方法上已经使用Results定义好映射关系,别的方法上也需要相同的映射关系,可以使用ResultMap注解引用(前提是Results注解必须使用id属性给其命名)

public interface UserMapper2 {

    @Select("select * from tb_user where id = #{id}")
    @Results(
            id = "uDemo",
            value = {
                    @Result(column = "user_name",property = "uName",id = false),
                    @Result(column = "password",property = "pwd",id = false),
            }
    )
    public User2 selectById(Integer id);

    @Select("select * from tb_user")
    // 引用上面已经定义好的结果集映射处理注解Results
    @ResultMap(value="uDemo")
    public List<User2> selectUsers();
}

5、多表操作

实体类

@Data
public class Order {
    private Integer id;
    private Long userId;
    private String orderNumber;
    // 添加用户引用
    private User user;
    // 添加订单明细引用(一个订单对应多个明细,需要使用集合来封装)
    private List<Orderdetail> orderdetails;
}
@Data
public class Orderdetail {
    private Integer id;
    private Double totalPrice;
    private Integer status;
    // 一个订单明细对应一个商品
    private Item item;
}
@Data
public class Item {
    private Integer id;
    private String itemname;
    private Float itemprice;
    private String itemdetail;
}

5.1、注解一对一

演示通过订单明细查询对应的商品,订单明细和商品之间是一对一的关系。

在mybatis提供的@Result注解中有:one和many属性,用于完成多表操作注解映射关系配置

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Repeatable(Results.class)
public @interface Result {
  // 其他的在上面已经解释过,这里删除省略了...........
    
  One one() default @One;
  Many many() default @Many;
}
  • one属性表示的一对一的映射配置
  • many属性表示一对多的映射配置
public interface OrderdetailMapper {
    /**
     * 通过订单明细查询对应的商品,订单明细和商品之间是一对一的关系
     * 接收订单明细的id
     */
    // 主查询:根据订单明细的id查询订单明细,但由于订单明细中关联对应的商品信息
    // 需要使用@Results注解配置关联商品信息映射关系
    @Select("select * from tb_orderdetail where id = #{id}")
    // 配置关联查询
    @Results(value = {
            // 配置id属性
            @Result(column = "id",property = "id",id = true),
            @Result(column = "total_price",property = "totalPrice",id = false),
            // column配置关联表中的列名
            // property配置实体类中对应的属性
            @Result(column = "item_id",property = "item",id = false,
            // one配置关联的查询
            // one注解中的select配置对应的关联查询所在的接口中的方法
            // fetchType配置关联查询是即时查询,还是懒加载查询
            one=@One(select="com.qbzaixian.mapper.ItemMapper.findById",fetchType = FetchType.EAGER)),
    })
    public Orderdetail findOrderdetailAndItem(Integer id);
}
public interface ItemMapper {
    @Select("select * from tb_item where id = #{id}")
    public Item findById(Integer id);
}
@Test
public void testOneToOne(){
    SqlSession session = factory.openSession(true);
    OrderdetailMapper mapper = session.getMapper(OrderdetailMapper.class);
    Orderdetail orderdetail = mapper.findOrderdetailAndItem(1);
    System.out.println(orderdetail);
}

在MyBatis注解开发中,FetchType是一个枚举,它定义了关联对象的加载方式,主要有三个值:

  • LAZY:延迟加载:指示MyBatis在加载主对象时,不会主动加载关联对象,只有当访问关联对象属性时,才会发起加载。

  • EAGER:急加载:指示MyBatis在每次加载主对象时,会 joins 一并加载关联对象,相当于SQL的子查询。

  • DEFAULT:默认加载:指示MyBatis按照全局配置来决定使用延迟加载或急加载。

在MyBatis中,默认一对一采用急加载,一对多采用延迟加载。FetchType可以根据需要指定关联对象的加载方式。

5.2、注解一对多

查询订单信息,每个订单都关联着多个订单详情,需要使用@Results注解进行配置

public interface OrderMapper {
    @Select("select * from tb_order where id = #{id}")
    @Results(value = {
            @Result(property = "id",column = "id",id = true),
            @Result(property = "orderdetails",column = "id",
            many = @Many(select = "com.qbzaixian.mapper.OrderdetailMapper.findOrderdetailAndItem",fetchType = FetchType.LAZY))
    })
    public Order selectOrderAndOrderDetail(Integer id);
}
@Test
public void testOneToMany(){
    SqlSession session = factory.openSession(true);
    OrderMapper mapper = session.getMapper(OrderMapper.class);
    Order order = mapper.selectOrderAndOrderDetail(1);
    System.out.println(order);
}

5.3、注解多对多

上面演示的一对多的查询,由于在订单明细中关联查询了商品信息,其实上面的演示已经完成多对多的查询。

一个订单对应多个商品,每个商品可能被添加到不同的订单中。

6、注解开启缓存

注解开启二级缓存,只需要在类上添加@CacheNamespace,并且将blocking属性设置为true即可。

@CacheNamespace(blocking = true)
public class MyBatisTest2 {
    private SqlSessionFactory factory;
}

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

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

相关文章

华人画家戴渭作品 3000 万拍出,牛津艺术学院发出任教邀请

爱丁堡,2023年7月 - 画家戴渭以他独特的画风、深邃的意境和慈悲智慧的属性,将艺术与宗教融合于作品之中。初看他的作品,可能会被其高超的艺术水准所震撼,然而仔细品味,方能领略到他深邃的艺术造诣与宗教智慧的深度融合。 作为国内最年轻的华人80后画家之一,戴渭近期被英国牛津…

若依cloud -【 22 ~ 25 】

22 认证中心介绍 1 概述 用户身份认证的过程ruoyi-cloud认证中心的实现没有依赖任何插件&#xff0c;相对简单&#xff0c;一看就懂从架构图的角度看认证中心&#xff1a; 登录请求&#xff0c;进到网关网关直接调用认证中心。查看ruoyi-gateway-dev.yml&#xff1a; # 结论…

【历史上的今天】8 月 22 日:改变世界的程序员们;网络直播的鼻祖;何小鹏离开阿里巴巴

整理 | 王启隆 透过「历史上的今天」&#xff0c;从过去看未来&#xff0c;从现在亦可以改变未来。 今天 2023 年 8 月 22 日。历史上的今天&#xff0c;Masatoshi Shima 出生&#xff0c;他和 英特尔&#xff08;Intel&#xff09; 合作设计的芯片让第一个微处理器 Intel 400…

【SpringSecurity】二、密码处理与获取当前登录用户

文章目录 一、密码处理1、加密方案2、BCryptPasswordEncoder类初体验3、使用加密码加密 二、获取当前登录用户1、方式一&#xff1a;通过安全上下文的静态调用2、方式二&#xff1a;做为Controller中方法的参数3、方式三&#xff1a;从HTTPServletRequest中获取4、方式四&#…

无涯教程-PHP Installation on Windows NT/2000/XP with IIS函数

在Windows Server上运行IIS的PHP的安装比在Unix上简单得多,因为它涉及的是预编译的二进制文件而不是源代码。 如果您打算在Windows上安装PHP,那么这是先决条件列表- 运行中的PHP支持的Web服务器。一个正确安装的PHP支持的数据库,如MySQL或Oracle等。(如果您打算使用的话) PHP…

smiley-http-proxy-servlet 实现springboot 接口反向代理,站点代理,项目鉴权,安全的引入第三方项目服务

背景&#xff1a; 项目初期 和硬件集成&#xff0c;实现了些功能服务&#xff0c;由于是局域网环境&#xff0c;安全问题当时都可以最小化无视。随着对接的服务越来越多&#xff0c;部分功能上云&#xff0c;此时就需要有一种手段可以控制到其他项目/接口的访问权限。 无疑 反向…

硬件解码example

使用方法&#xff1a; ./hw_decode vaapi juren-30s.mp4 juren-30s.mp4 验证播放&#xff1a; ffplay -video_size 1920x1080 -pixel_format yuv420p juren-30s.yuv av_hwdevice_iterate_types(type)如果你填入的参数不对&#xff0c;那么这函数这个函数的作用相当于以下命令&…

飞天使-k8s基础组件分析-pod

文章目录 pod介绍pod 生命周期init 容器容器handlerpod中容器共享进程空间sidecar 容器共享 参考链接 pod介绍 最小的容器单元 为啥需要pod? 答: 多个进程丢一个容器里&#xff0c;会因为容器里个别进程出问题而出现蝴蝶效应&#xff0c;pod 是更高级的处理方式pod 如何共享相…

简述docker映射(Mapping)和挂载(Mounting)

映射的概念&#xff1a; 将容器内的端口映射到主机的端口上&#xff0c;这样就可以通过主机的网络接口与容器内部进行通信。主机上对应端口的请求会被转发到容器内部&#xff0c;从而实现对容器内部程序的通信访问&#xff08;注意&#xff01;这里提到的容器内部的端口并不一定…

网络安全(黑客)了解学习路线

谈起黑客&#xff0c;可能各位都会想到&#xff1a;盗号&#xff0c;其实不尽然&#xff1b;黑客是一群喜爱研究技术的群体&#xff0c;在黑客圈中&#xff0c;一般分为三大圈&#xff1a;娱乐圈 技术圈 职业圈。 娱乐圈&#xff1a;主要是初中生和高中生较多&#xff0c;玩网恋…

EasyImage简单图床 - 快速搭建私人图床云盘同时远程访问【无公网IP内网穿透】

憧憬blog主页 在强者的眼中&#xff0c;没有最好&#xff0c;只有更好。我们是移动开发领域的优质创作者&#xff0c;同时也是阿里云专家博主。 ✨ 关注我们的主页&#xff0c;探索iOS开发的无限可能&#xff01; &#x1f525;我们与您分享最新的技术洞察和实战经验&#xff0…

阿里云CDN加速器基本概念与购买开通

文章目录 1.CDN加速器的基本概念1.1.CDN加速器基本介绍1.2.网站引入CDN加速器的架构图1.3.CDN加速器的工作原理1.4.引入CDN后域名解析变成了CNAME&#xff1f; 2.开通阿里云CDN加速服务 1.CDN加速器的基本概念 CDN加速器官方文档&#xff1a;https://help.aliyun.com/product/…

USB音频芯片SSS1700 鑫创优势替代CM6533参考设计|SSS1700规格24bit 96KHZ |替换CM6533方案

Cmedia CM6533是一款US B音频编解码器&#xff0c;内部嵌入8051内核&#xff0c;适用于耳麦&#xff0c;移动娱乐设备直插移动音箱&#xff08;docking&#xff09;&#xff0c;US B音箱&#xff0c;US B麦克风等应用。通过内部8051可以研发出各种应用&#xff0c;例如微软语音…

vue3 pdf、word等文件下载

效果&#xff1a; <div class"byLawBox"><div class"titleBox">规章制度公示</div><div class"contentBox"><TableList:loading"byLawloading"ref"byLawtablistRef":hasImport"false"…

Unity - 特殊文件夹

地址记录&#xff1a;https://www.cnblogs.com/zouqiang/p/6841399.html Assets Assets文件夹是unity项目中放置游戏资源的主文件夹。 该文件夹中的内容将直接反应在编辑器的Project视口中。许多系统API基于该文件夹路径。 Resources Unity允许你按需动态加载游戏资源到场景中…

ubuntu 对多CPU统一设置高性能模式

一、问题描述 之前在网上找到的CPU设置高性能模式&#xff0c;只能设置CPU0单个CPU&#xff0c;下述是对多核CPU统一设置工作模式。 二、软件安装与设置 执行下述命令sudo apt-get install indicator-cpufreq,然后重启电脑。此时&#xff0c;界面右上角会出现如下图标&#xf…

爬虫异常捕获与处理方法详解

Hey&#xff01;作为一名专业的爬虫代理供应商&#xff0c;我今天要和大家分享一些关于爬虫异常捕获与处理的方法。在进行爬虫操作时&#xff0c;我们经常会遇到各种异常情况&#xff0c;例如网络连接错误、请求超时、数据解析错误等等。这些异常情况可能会导致程序崩溃或数据丢…

威班8.19PMP考试爱心送考再出发,能量补给站为学员提供考试保障

8月19日&#xff0c;2023年的第三场PMP考试准时开考。 对于准备了个把月的学员们来说&#xff0c;这一时刻无比重要&#xff0c;为了给威班的PMP学员们考试加油打气&#xff0c;威班特地组织了送考活动&#xff0c;在考场外提前布置应援点&#xff0c;给前去参加考试的学员们带…

5.1 汇编语言:汇编语言概述

汇编语言是一种面向机器的低级语言&#xff0c;用于编写计算机程序。汇编语言与计算机机器语言非常接近&#xff0c;汇编语言程序可以使用符号、助记符等来代替机器语言的二进制码&#xff0c;但最终会被汇编器编译成计算机可执行的机器码。 相较于高级语言&#xff08;如C、P…

紧跟老板思维,这款数据可视化工具神了

在今时今日&#xff0c;依靠大数据可视化分析工具做出一张形象直观、符合企业审美的数据可视化分析报表都不是什么难事&#xff0c;难就难在于做出一张能够紧随老板思维变化展开可视化分析的数据可视化分析报表。接下来要介绍的这款数据可视化工具就是这么一款神奇的BI工具&…