SpringBoot常用框架

SpringBoot Mail 邮箱验证码

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
spring:
mail:
host: your.SMTP.host
username: your_server_email@email.com
password: your_passowrd
@Resource
JavaMailSender sender;

@PostMapping("/verification-email")
public String sendVerificationEmail(@RequestParam String targetEmail,
HttpSession session) {
SimpleMailMessage message = new SimpleMailMessage();
message.setSubject(EMAIL_TITLE);
int vCode = getVerificationCode();
session.setAttribute("vcode", vCode);
session.setAttribute("uemail", email);

message.setText(EMAIL_CONTEXT + code);
message.setTo(targetEmail);
message.setFrom(EMAIL_SERVEREMAIL); // 与配置文件中的保持一致

sender.send(message);
return "发送成功"; // 前端弹窗可以接受此参数
}

@PostMapping("/register")
public String register(@RequestParam String username,
@RequestParam String email,
@RequestParam String code,
@RequestParam String password,
HttpSession session) {
String sessionCode = session.getAttribute("vcode").toString;
String sessionEmail = session.getAttribute("uemail").toString;

if (sessionCode == null) {
return "验证码为空";
}
if (!sessionCode.equals(code)) {
return "验证码错误!";
}
if (!sessionEmail.equals(email)) {
return "请获取验证码";
}
}

SpringBoot Validation 接口参数校验

Validation

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

方法1:参数前注解

@Validation
@Controller
public class SomeController {
@PostMapping("/submit")
public String submit(@Length(min = 3) String username, @Length(min = 8) String password) {
// ...
}
}

方法2:Entity注解

public class SomeEntity {
@Length(min = 3)
String username;
}

@Validation
@Controller
public class SomeController {
@PostMapping("/submit")
public String submit(@Valid String username, @Valid String password) {
// ...
}
}

Swagger 自动接口文档

SpringDoc

<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.1.0</version>
</dependency>

访问localhost/swagger-ui/index.html即可查看文档。

添加文档说明

@Bean
public OpenAPI springDocOpenAPI() {
return new OpenAPI().info(new Info()
.title("Title of your Document")
.description("Description of your Document")
.version("Version") // 当前API版本
.license(new License().name("License Name")
.url("https://your.url")));
}

// 使用@Tag注解来添加Controller描述信息
@Tag(name = "XX功能相关", description = "包括 ... 等操作。")
public class SomeController {
...
@ApiResponses({
@ApiResponse(responseCode = "200", description = "测试成功"),
@ApiResponse(responseCode = "500", description = "测试失败") // 不同返回状态码描述
})

@Operation(summary = "请求用户数据测试接口") // 接口功能描述
@ResponseBody
@GetMapping("/hello")
// 请求参数描述和样例
public String hello(@Parameter(description = "测试文本数据", example = "KFCvivo50") @RequestParam String text) {
return "Hello World";
}

// 使用@Hidden忽略接口
@Hidden
private String helperMethod() { ... }
}

// 实体类
@Data
@Schema(description = "用户信息实体类")
public class User {
@Schema(description = "用户编号")
int id;
@Schema(description = "用户名称")
String name;
@Schema(description = "用户邮箱")
String email;
@Schema(description = "用户密码")
String password;
}

生成环境一键关闭接口文档

springdoc:
api-docs:
enabled: false

JPA

优点:不用手写SQL
缺点:使用Hibernate重量级框架;完全屏蔽了底层SQL显示,对后期优化不友好;方法名太长

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

实体类注解映射数据表

@Data
@Entity // 表示这个类是一个实体类
@Table(name = "your_table_name") // 对应的数据库中表名称
public class SomeEntity {

@GeneratedValue(strategy = GenerationType.IDENTITY)
// 生成策略,这里配置为自增
@Column(name = "id") // 对应表中id这一列
@Id // 此属性为主键
int id;

@Column(name = "username") // 对应表中username这一列
String username;

@Column(name = "password") // 对应表中password这一列
String password;
}

使用Repository帮你编写sql

@Repository
public interface AccountRepository extends JpaRepository<Account, Integer> { }

// 使用
@Resource
AccountRepository repository;

@Test
void contextLoads() {
Account account = new Account();
account.setUsername("小红");
account.setPassword("1234567");
System.out.println(repository.save(account).getId());
// 使用save来快速插入数据,并且会返回插入的对象,如果存在自增ID,对象的自增id属性会自动被赋值,这就很方便了
}

根据方法名自动匹配sql

@Repository
public interface AccountRepository extends JpaRepository<Account, Integer> {
// 模糊匹配用户名
List<Account> findAllByUsernameLike(String input);
}

实体类关联外键

@Data
@Entity // 表示这个类是一个实体类
@Table(name = "your_table_name") // 对应的数据库中表名称
public class SomeEntity {

@GeneratedValue(strategy = GenerationType.IDENTITY)
// 生成策略,这里配置为自增
@Column(name = "id") // 对应表中id这一列
@Id // 此属性为主键
int id;

@Column(name = "username") // 对应表中username这一列
String username;

@Column(name = "password") // 对应表中password这一列
String password;

@JoinColumn(name = "foreign_column_name") // 指定存储外键的字段名称
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) // 声明为一对一关系
// LAZY 懒加载(需要时才加载)
// cascade 级联操作
AccountDetail detail;
}

JPQL 自定义 SQL

@Repository
public interface AccountRepository extends JpaRepository<Account, Integer> {

@Transactional // DML操作需要事务环境,可以不在这里声明,但是调用时一定要处于事务环境下
@Modifying // 表示这是DML操作
/* 使用实体类 */
@Query("update Account set password = ?2 where id = ?1")
// 这里操作的是一个实体类对应的表,参数使用?代表,后面接第n个参数
/* 使用原生写法 */
@Query(value = "update users set password = :pwd where username = :name", nativeQuery = true)
// 使用原生SQL,和Mybatis一样,这里使用 :名称 表示参数,当然也可以继续用上面那种方式。
int updatePasswordByUsername(@Param("name") String username, //我们可以使用@Param指定名称
@Param("pwd") String newPassword);
}

MyBatisPlus

是国内开发的用于增强MyBatis的非侵入型框架。相当于JPA+MyBatis。

<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>

映射实体类,继承BaseMapper

@Data
@TableName("user") //对应的表名
public class User {
@TableId(type = IdType.AUTO) //对应的主键
int id;
@TableField("name") //对应的字段
String name;
@TableField("email")
String email;
@TableField("password")
String password;
}

@Mapper
public interface UserMapper extends BaseMapper<User> {
// 使用方式与JPA极其相似,同样是继承一个基础的模版Mapper
// 这个模版里面提供了预设的大量方法直接使用,跟JPA如出一辙
}

复杂条件Wrapper

QueryWrapper<User> wrapper = new QueryWrapper<>();    // 复杂查询可以使用QueryWrapper来完成
wrapper
.select("id", "name", "email", "password") // 可以自定义选择哪些字段
.ge("id", 2) // 选择判断id大于等于1的所有数据
.orderByDesc("id"); // 根据id字段进行降序排序
System.out.println(mapper.selectList(wrapper)); // Mapper同样支持使用QueryWrapper进行查询

打印输出

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

IService

@Service
public interface UserService extends IService<User> {
// 除了继承模版,我们也可以把它当成普通Service添加自己需要的方法
}
@Service // 需要继承ServiceImpl才能实现那些默认的CRUD方法
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}

根据数据库生成代码

<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
@Test
void contextLoads() {
FastAutoGenerator
.create(new DataSourceConfig.Builder(dataSource))
.globalConfig(builder -> {
builder.author("author"); // 作者信息,一会会变成注释
builder.commentDate("YY-MM-DD"); // 日期信息,一会会变成注释
builder.outputDir("src/main/java"); // 输出目录设置为当前项目的目录
})

.packageConfig(builder -> builder.parent("com.example"))
.strategyConfig(builder -> {
// 设置为所有Mapper添加@Mapper注解
builder
.mapperBuilder()
.mapperAnnotation(Mapper.class)
.build();
})
.execute();
}