Administrator
Administrator
发布于 2026-01-22 / 3 阅读
0
0

SSM+SpringBoot

Spring

概述

  • 什么是Spring框架

    • 核心思想是控制反转(把对象创建和依赖管理的工作交给框架,不用手动new对象,降低代码耦合度)和面向切面编程(将日志、事务等重复的代码抽出来,单独管理)

  • Spring中的设计模式有哪些

    • 工厂模式:创建和管理bean对象

    • 单例模式:bean默认单例,避免重复创建浪费资源

    • 代理模式:aop实现方式,不修改源代码基础上在目标方法前后加日志、事务等逻辑

IOC

  • 什么是IOC

    • 控制反转(Inversion of Control),DI依赖注入是主要实现方式。传统开发对象的创建、对象之间的依赖需要手动设置,ioc将控制权交给容器,有容器负责对象的创建、装配和对象之间的依赖关系管理。可以降低代码耦合度。

<!-- applicationContext.xml -->
<bean id="userService" class="com.example.UserService">
    <property name="userDao" ref="userDao"/>
</bean>

<bean id="userDao" class="com.example.UserDao"/>



// 不再这样写
// UserService userService = new UserService(new UserDao());

// 而是通过容器获取
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = context.getBean("userService", UserService.class);
@Component
public class UserDao {
    // ...
}

@Service
public class UserService {
    @Autowired
    private UserDao userDao;
}


@SpringBootApplication
public class MyApp {
    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(MyApp.class, args);
        UserService userService = context.getBean(UserService.class);
        // 使用 userService,其内部的 userDao 已由 Spring 自动注入
    }
}
  • 什么是依赖注入,有哪些实现方式?

    • 依赖注入:在对象创建时,由容器自动将依赖对象注入到需要依赖的对象中。构造器注入、setter注入、@Autowired注入

// UserDao.java
public class UserDao {
    public void save() {
        System.out.println("User saved via DAO");
    }
}


// UserService.java
public class UserService {

    private UserDao userDao;

    // 1. 构造器(用于构造器注入)
    public UserService(UserDao userDao) {
        this.userDao = userDao;
    }

    // 2. Setter 方法(用于 Setter 注入)
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
}
<bean id="userDao" class="com.example.UserDao" />

    <bean id="userService" class="com.example.UserService">
        <!-- 调用 setUserDao(userDao) 方法 -->
        <property name="userDao" ref="userDao" />
    </bean>
<!-- 定义 userDao Bean -->
    <bean id="userDao" class="com.example.UserDao" />

    <!-- 通过 constructor-arg 注入依赖 -->
    <bean id="userService" class="com.example.UserService">
        <constructor-arg ref="userDao" />
    </bean>
@Service
public class UserService {

    @Autowired
    private UserDao userDao; // 直接注入字段

    public void register() {
        userDao.save();
    }
}
  • IOC和DI的关系

    • ioc是一种思想,解决对象依赖管理问题;di是ioc思想的一种实现方式,包括三种注入方式

Bean

  • 什么是Bean

    • IOC容器管理的对象称为Bean

  • 将一个类声明为Bean的注解有哪些?

    • @Component-标注任意一个类

    • @Repository-用于数据库相关操作

    • @Service-服务层

    • @Controller-控制层

    • @Bean-手动定义Bean,主要引入第三方类时使用

@Component/@Service/@Controller/@Repository
class UtilityTool {
    public String process(String input) {
        return "Processed: " + input;
    }
}


//@Bean使用举例
// 假设这是一个你无法修改源码的第三方类
class ThirdPartyLogger {
    public void log(String message) {
        System.out.println("[ThirdPartyLogger] " + message);
    }
}

// 配置类,用于定义 @Bean
@org.springframework.context.annotation.Configuration
class AppConfig {

    @Bean
    public ThirdPartyLogger thirdPartyLogger() {
        return new ThirdPartyLogger(); // 手动创建并交给 Spring 容器管理
    }
}

// 可选:在 Service 中使用这个第三方 Bean
@Service
class LoggingService {

    @Autowired
    private ThirdPartyLogger logger;

    public void doSomething() {
        logger.log("Business operation started.");
    }
}
  • 注入Bean的注解有哪些

    • @Autowired-默认按照类型寻找Bean,如果一个类型有多个Bean,要搭配@Qualifier注解指定具体名称

    • @Resource-默认按照名称寻找Bean,找不到再按类型

    • @Inject-按照类型寻找,多个类型Bean,要用@Named制定名称

@Autowired
    @Qualifier("emailService")
    private MessageService emailService;

@Resource
    private MessageService wechatService; // 自动找名为 "wechatService" 的 Bean

    // 也可以显式指定 name
    @Resource(name = "defaultService")
    private MessageService fallbackService;

AOP

  • 什么是AOP

    • Aspect-Oriented Programming,面向切面编程。通过代理的方式,在调用想要的对象方法时,进行拦截处理,执行切入的逻辑,然后调用真正的方法实现。实际开发中常用在记录日志、检查登录权限等场景。

@Aspect
@Component
public class ComprehensiveLoggingAspect {

    // 1. @Pointcut:定义可复用的切入点(匹配 com.example.service 包下所有 public 方法)
    @Pointcut("execution(public * com.example.service..*(..))")
    public void serviceMethods() {}

    // 2. @Before:前置通知 —— 方法执行前
    @Before("serviceMethods()")
    public void logBefore(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        System.out.println("[Before] Calling method: " + methodName +
                " with arguments: " + Arrays.toString(args));
    }

    // 3. @After:后置通知 —— 方法执行后(无论是否异常)
    @After("serviceMethods()")
    public void logAfter(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("[After] Finished method: " + methodName);
    }

    // 4. @AfterReturning:返回通知 —— 方法成功返回后
    @AfterReturning(pointcut = "serviceMethods()", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("[AfterReturning] Method " + methodName +
                " returned: " + result);
    }

    // 5. @AfterThrowing:异常通知 —— 方法抛出异常时
    @AfterThrowing(pointcut = "serviceMethods()", throwing = "exception")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable exception) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("[AfterThrowing] Exception in " + methodName +
                ": " + exception.getClass().getSimpleName() + " - " + exception.getMessage());
    }

    // 6. @Around:环绕通知 —— 完全控制方法调用(可用于性能监控、重试等)
    @Around("serviceMethods()")
    public Object logExecutionTime(ProceedingJoinPoint pjp) throws Throwable {
        long start = System.currentTimeMillis();

        // 获取方法名
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        String methodName = signature.getMethod().getName();

        try {
            System.out.println("[Around] Starting " + methodName);
            Object result = pjp.proceed(); // 执行目标方法
            long duration = System.currentTimeMillis() - start;
            System.out.println("[Around] " + methodName + " completed in " + duration + " ms");
            return result;
        } catch (Throwable t) {
            long duration = System.currentTimeMillis() - start;
            System.out.println("[Around] " + methodName + " failed after " + duration + " ms");
            throw t; // 重新抛出异常,保证行为一致
        }
    }
}
  • Spring AOP和AspectJ AOP区别

    • spring aop集成了aspectj,spring-aop轻量简单,aspectj功能全面但复杂

  • AspectJ定义的通知类型

    • Before-目标方法执行之前

    • After-不管目标方法有没有异常,执行完都会触发

    • After Returning-目标方法正常返回结果才会执行

    • After Throwing-目标方法抛出异常才会执行

    • Around-包裹目标方法,控制方法的执行过程

注解

  • 重要的Spring注解

    • @Controller、@Service、@Repository、@RestController(@Controller+@ResponseBody,返回值放入响应体)、@Component、@Bean

    • @RequestMapping、@ResponseBody、@PathVariable、@RequestParam、@RequestBody、@GetMapping、@PostMapping、@PutMapping、@DeleteMapping

    • @Autowired、@Qualifier、@Resource

    • @Aspect、@Before、@After、@Around、@Pointcut

// ==================== Controller 层(Web 层)====================
@RestController
@RequestMapping("/api/users")
public class UserController {

    @Autowired
    private UserService userService;

    // GET /api/users/1
    @GetMapping("/{id}")
    public UserDto getUser(@PathVariable Long id) {
        return userService.getUserById(id);
    }

    // POST /api/users
    @PostMapping
    public UserDto createUser(@RequestBody CreateUserRequest request) {
        return userService.createUser(request.getName(), request.getAge());
    }

    // 异常处理(Controller 层常用)
    @ExceptionHandler(UserNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public String handleUserNotFound(UserNotFoundException ex) {
        return ex.getMessage();
    }
}
  • @Component和@Bean有什么区别

    • @Component作用于类,作为Bean装配到容器中;而@Bean作用于方法,方法的返回对象会被Spring管理,一般使用第三方库时使用

  • @RequestMapping和@GetMapping区别

    • @RequestMapping:注解在类或方法上,可进行get、post、put、delete等请求方法

    • @GetMapping:注解在方法上,只能使用Get请求

  • @Restcontroller和@Controller区别

    • @Restcontroller:在@Controller基础上,增加了@ReponseBody注解,适合在前后端分离的架构下,提供Restful API,返回例如json数据格式

  • @RequestParam和@PathVariable区别

    • @RequestParam:从请求的参数部分拿值,/user?name=张三,拿到张三

    • @PathVariable:从请求的url拿值,/user/123,拿到123

事务

  • 如何启动事务

    • @Transactional,在方法上注解

Spring MVC

  • MVC是什么

    • Model、View、Controller 模型、视图、控制器

    • 模型(包括service和dao):处理数据和业务逻辑、数据存储

    • 视图:用户看到的界面

    • 控制器:接收用户输入,调用模型处理,再把结果给视图显示

Mybatis

  • 什么是Mybatis

    • ORM(对象关系映射)框架,内部封装了JDBC,开发时只需要关注SQL本身

import java.sql.*;

public class JdbcWithExplicitDriver {

    public static void main(String[] args) {
        // 数据库信息
        String driverClassName = "com.mysql.cj.jdbc.Driver"; // MySQL 8+ 驱动类
        String url = "jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=UTC";
        String username = "root";
        String password = "123456";

        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;

        try {
            // ✅ 步骤 1: 显式加载驱动(不省略!)
            Class.forName(driverClassName);
            System.out.println("✅ 驱动加载成功: " + driverClassName);

            // ✅ 步骤 2: 获取连接
            conn = DriverManager.getConnection(url, username, password);
            System.out.println("✅ 数据库连接成功");

            // ✅ 步骤 3: 创建 PreparedStatement
            String sql = "SELECT id, name FROM users WHERE age > ?";
            stmt = conn.prepareStatement(sql);
            stmt.setInt(1, 18); // 设置参数

            // ✅ 步骤 4: 执行查询并处理结果
            rs = stmt.executeQuery();
            System.out.println("✅ 查询结果:");
            while (rs.next()) {
                long id = rs.getLong("id");
                String name = rs.getString("name");
                System.out.println("ID: " + id + ", Name: " + name);
            }

        } catch (ClassNotFoundException e) {
            System.err.println("❌ 驱动类未找到: " + e.getMessage());
            e.printStackTrace();
        } catch (SQLException e) {
            System.err.println("❌ 数据库操作失败: " + e.getMessage());
            e.printStackTrace();
        } finally {
            // ✅ 步骤 5: 关闭资源(按顺序:ResultSet → Statement → Connection)
            try {
                if (rs != null) rs.close();
                if (stmt != null) stmt.close();
                if (conn != null) conn.close();
                System.out.println("✅ 所有资源已关闭");
            } catch (SQLException e) {
                System.err.println("❌ 关闭资源时出错: " + e.getMessage());
            }
        }
    }
}
  • Mybatis编程步骤

public interface UserMapper {
    User selectById(Long id);
    List<User> selectAll();
    void insert(User user);
    void update(User user);
    void delete(Long id);
}
<?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 必须是 Mapper 接口的全限定名 -->
<mapper namespace="com.example.mybatis.mapper.UserMapper">

  <!-- 结果映射(可省略,但推荐写) -->
  <resultMap id="UserResultMap" type="com.example.mybatis.entity.User">
    <id property="id" column="id"/>
    <result property="name" column="name"/>
    <result property="age" column="age"/>
  </resultMap>

  <!-- 查询单个 -->
  <select id="selectById" parameterType="long" resultMap="UserResultMap">
    SELECT id, name, age FROM users WHERE id = #{id}
  </select>

  <!-- 查询所有 -->
  <select id="selectAll" resultMap="UserResultMap">
    SELECT id, name, age FROM users
  </select>

  <!-- 插入(支持自增主键回填) -->
  <insert id="insert" parameterType="com.example.mybatis.entity.User"
          useGeneratedKeys="true" keyProperty="id">
    INSERT INTO users (name, age) VALUES (#{name}, #{age})
  </insert>

  <!-- 更新 -->
  <update id="update" parameterType="com.example.mybatis.entity.User">
    UPDATE users SET name = #{name}, age = #{age} WHERE id = #{id}
  </update>

  <!-- 删除 -->
  <delete id="delete" parameterType="long">
    DELETE FROM users WHERE id = #{id}
  </delete>

</mapper>
<?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>
  <!-- 1. 类型别名(简化 XML 中的类型书写) -->
  <typeAliases>
    <package name="com.example.mybatis.entity"/>
  </typeAliases>

  <!-- 2. 环境配置(数据库连接) -->
  <environments default="development">
    <environment id="development">
      <!-- 事务管理器:JDBC(手动 commit/rollback) -->
      <transactionManager type="JDBC"/>
      <!-- 数据源:使用 MyBatis 内置连接池 -->
      <dataSource type="POOLED">
        <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/testdb?useSSL=false&amp;serverTimezone=UTC"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
      </dataSource>
    </environment>
  </environments>

  <!-- 3. 注册 Mapper XML 文件 -->
  <mappers>
    <!-- 方式1:注册单个 XML -->
    <!-- <mapper resource="mapper/UserMapper.xml"/> -->

    <!-- 方式2:自动扫描整个包(推荐) -->
    <package name="com.example.mybatis.mapper"/>
  </mappers>
</configuration>
  • 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 必须是 Mapper 接口的全限定名 -->
<mapper namespace="com.example.mapper.UserMapper">

  <!-- ==================== 1. resultMap:结果映射(处理列名与属性名不一致、关联对象)==================== -->
  <resultMap id="UserResultMap" type="com.example.entity.User">
    <id property="id" column="user_id"/>        <!-- 主键映射 -->
    <result property="name" column="user_name"/> <!-- 普通字段映射 -->
    <result property="age" column="user_age"/>
    
    <!-- 一对一关联:用户所属部门 -->
    <association property="department" javaType="com.example.entity.Department">
      <id property="id" column="dept_id"/>
      <result property="name" column="dept_name"/>
    </association>
  </resultMap>

  <!-- ==================== 2. sql:SQL 片段复用 ==================== -->
  <sql id="userColumns">
    u.id AS user_id, u.name AS user_name, u.age AS user_age,
    d.id AS dept_id, d.name AS dept_name
  </sql>

  <!-- ==================== 3. select:查询 ==================== -->
  <!-- 基础查询 -->
  <select id="selectById" parameterType="long" resultMap="UserResultMap">
    SELECT <include refid="userColumns"/>
    FROM users u
    LEFT JOIN departments d ON u.dept_id = d.id
    WHERE u.id = #{id}
  </select>

  <!-- 动态查询(使用 where + if)-->
  <select id="selectByCondition" parameterType="map" resultMap="UserResultMap">
    SELECT <include refid="userColumns"/>
    FROM users u
    LEFT JOIN departments d ON u.dept_id = d.id
    <where>
      <if test="name != null and name != ''">
        AND u.name LIKE CONCAT('%', #{name}, '%')
      </if>
      <if test="minAge != null">
        AND u.age >= #{minAge}
      </if>
      <if test="deptId != null">
        AND d.id = #{deptId}
      </if>
    </where>
    ORDER BY u.id
  </select>

  <!-- ==================== 4. insert:插入 ==================== -->
  <!-- 普通插入(支持主键回填)-->
  <insert id="insert" parameterType="com.example.entity.User"
          useGeneratedKeys="true" keyProperty="id">
    INSERT INTO users (name, age, dept_id)
    VALUES (#{name}, #{age}, #{department.id})
  </insert>

  <!-- 批量插入(foreach)-->
  <insert id="batchInsert" parameterType="list">
    INSERT INTO users (name, age, dept_id) VALUES
    <foreach collection="list" item="user" separator=",">
      (#{user.name}, #{user.age}, #{user.department.id})
    </foreach>
  </insert>

  <!-- ==================== 5. update:更新 ==================== -->
  <!-- 动态更新(set + if)-->
  <update id="updateSelective" parameterType="com.example.entity.User">
    UPDATE users
    <set>
      <if test="name != null and name != ''">
        name = #{name},
      </if>
      <if test="age != null">
        age = #{age},
      </if>
      <if test="department.id != null">
        dept_id = #{department.id},
      </if>
    </set>
    WHERE id = #{id}
  </update>

  <!-- ==================== 6. delete:删除 ==================== -->
  <!-- 单条删除 -->
  <delete id="deleteById" parameterType="long">
    DELETE FROM users WHERE id = #{id}
  </delete>

  <!-- 批量删除(foreach)-->
  <delete id="batchDelete" parameterType="list">
    DELETE FROM users WHERE id IN
    <foreach collection="list" item="id" open="(" separator="," close=")">
      #{id}
    </foreach>
  </delete>

  <!-- ==================== 7. foreach:遍历集合(用于 IN、批量等)==================== -->
  <!-- 示例:查询多个 ID 的用户 -->
  <select id="selectByIds" parameterType="list" resultMap="UserResultMap">
    SELECT <include refid="userColumns"/>
    FROM users u
    LEFT JOIN departments d ON u.dept_id = d.id
    WHERE u.id IN
    <foreach collection="list" item="id" open="(" separator="," close=")">
      #{id}
    </foreach>
  </select>

  <!-- ==================== 8. choose / when / otherwise:多条件分支(类似 switch)==================== -->
  <select id="selectByPriority" parameterType="map" resultMap="UserResultMap">
    SELECT <include refid="userColumns"/>
    FROM users u
    LEFT JOIN departments d ON u.dept_id = d.id
    <where>
      <choose>
        <when test="userId != null">
          u.id = #{userId}
        </when>
        <when test="userName != null">
          u.name = #{userName}
        </when>
        <otherwise>
          u.age > 18
        </otherwise>
      </choose>
    </where>
  </select>

  <!-- ==================== 9. trim:自定义前缀/后缀(where/set 的底层实现)==================== -->
  <!-- 等价于 <where> 的手动写法 -->
  <select id="selectWithTrim" parameterType="map" resultMap="UserResultMap">
    SELECT <include refid="userColumns"/>
    FROM users u
    LEFT JOIN departments d ON u.dept_id = d.id
    <trim prefix="WHERE" prefixOverrides="AND |OR ">
      <if test="name != null">AND u.name = #{name}</if>
      <if test="age != null">AND u.age = #{age}</if>
    </trim>
  </select>

  <!-- ==================== 10. 调用存储过程(CALLABLE)==================== -->
  <!-- 假设有一个存储过程:get_user_count_by_dept(IN dept_id INT, OUT total INT) -->
  <select id="callGetUserCount" statementType="CALLABLE">
    { CALL get_user_count_by_dept(
        #{deptId, mode=IN, jdbcType=INTEGER},
        #{total, mode=OUT, jdbcType=INTEGER}
      )
    }
  </select>

</mapper>
  • Mybatis如何防止SQL注入

    • #{}是经过预编译的,参数值会被自动处理,不会直接拼接到sql语句中;${}是直接替换变量值,会把参数原样拼到sql中,会有注入问题

  • Mybatis动态SQL

<select id="findUsers" resultType="User">
  SELECT * FROM users
  WHERE 1=1
  <if test="name != null and name != ''">
    AND name LIKE CONCAT('%', #{name}, '%')
  </if>
  <if test="age != null">
    AND age = #{age}
  </if>
</select>
<select id="findUsersSmart" resultType="User">
  SELECT * FROM users
  <where>
    <if test="name != null">name = #{name}</if>
    <if test="age != null">AND age = #{age}</if>
    <if test="email != null">OR email = #{email}</if>
  </where>
</select>
<update id="updateUser">
  UPDATE users
  <set>
    <if test="name != null">name = #{name},</if>
    <if test="age != null">age = #{age},</if>
    <if test="email != null">email = #{email},</if>
  </set>
  WHERE id = #{id}
</update>
<!-- 批量删除 -->
<delete id="deleteByIds">
  DELETE FROM users WHERE id IN
  <foreach collection="list" item="id" open="(" separator="," close=")">
    #{id}
  </foreach>
</delete>

<!-- 批量插入 -->
<insert id="batchInsert">
  INSERT INTO users (name, age) VALUES
  <foreach collection="list" item="user" separator=",">
    (#{user.name}, #{user.age})
  </foreach>
</insert>
<!-- 等价于 <where> -->
<select id="findWithTrim" resultType="User">
  SELECT * FROM users
  <trim prefix="WHERE" prefixOverrides="AND |OR ">
    <if test="name != null">AND name = #{name}</if>
    <if test="age != null">OR age = #{age}</if>
  </trim>
</select>

<!-- 等价于 <set> -->
<update id="updateWithTrim">
  UPDATE users
  <trim prefix="SET" suffixOverrides=",">
    <if test="name != null">name = #{name},</if>
    <if test="age != null">age = #{age},</if>
  </trim>
  WHERE id = #{id}
</update>
从多个条件中只选一个执行(互斥)
<select id="searchUser" resultType="User">
  SELECT * FROM users
  <where>
    <choose>
      <when test="userId != null">
        id = #{userId}
      </when>
      <when test="userName != null">
        name = #{userName}
      </when>
      <when test="email != null">
        email = #{email}
      </when>
      <otherwise>
        status = 'ACTIVE'
      </otherwise>
    </choose>
  </where>
</select>
<select id="findByNameLike" resultType="User">
  <!-- 创建变量 pattern = '%' + name + '%' -->
  <bind name="pattern" value="'%' + name + '%'" />
  SELECT * FROM users
  WHERE name LIKE #{pattern}
</select>
  • Mybatis动态SQL是做什么的

    • 根据不同条件动态生成SQL语句,解决静态SQL写死的问题,比如查询时条件可能有也可能没有,用动态sql就能灵活处理

  • mapper中如何传递多个参数

public interface UserMapper {
    List<User> findUsers(
        @Param("name") String name,
        @Param("minAge") Integer minAge,
        @Param("deptId") Long deptId
    );
}
public class UserQueryDTO {
    private String name;
    private Integer minAge;
    private Long deptId;
    // 必须有 getter/setter
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public Integer getMinAge() { return minAge; }
    public void setMinAge(Integer minAge) { this.minAge = minAge; }
    public Long getDeptId() { return deptId; }
    public void setDeptId(Long deptId) { this.deptId = deptId; }
}



public interface UserMapper {
    List<User> findUsers(UserQueryDTO query);
}
public interface UserMapper {
    List<User> findUsers(Map<String, Object> params);
}

Mybatis-Plus

public interface UserMapper extends BaseMapper<User> { } // 无需声明基础 CRUD 方法!

SpringBoot

  • SpringBoot是什么

    • 基于Spring的框架,简化Spring应用的搭建和开发过程;约定大于配置,不用手写大量配置文件

    • 自动配置:数据库连接、web服务器、日志等

    • 内嵌服务器:内嵌多种常用的web容器,tomcat等,可以直接打包运行

    • 自动化依赖starter:简化依赖管理

  • 项目怎么用SpringBoot

    • 启动:写启动类,@SpringBootApplication注解,直接run

    • 依赖管理:用maven,直接引入springboot提供的starter

    • controller:@RestController注解,定义路径和请求方式等,接受参数返回json对象

    • 数据层:mybatis-plus

    • service:事务管理加@Transactional注解即可

    • 配置:application.yml,包括数据库连接、服务端口、日志,大部分配置可以用注解

  • 运行springboot方法

    • 启动main方法

    • maven:mvn spring-boot:run

    • 打包后使用java -jar 路径

  • springboot核心注解

    • @SpringBootApplication(=@SpringBootConfiguration+@EnableAutoConfiguration+@ComponentScan)

    • 自动配置项目并扫描组件

  • springboot打包的jar包和普通的jar区别

    • springboot打包成的jar包可以直接运行java -jar xxx.jar,内嵌tomcat,但不能被其他项目依赖

    • 普通jar包只是代码和类的集合,无法运行,主要作为第三方依赖


评论