Fork me on GitHub

Mybatis-plus增删改查

Mybatis-plus增删改查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117

@Autowired
private UserMapper commonMapper;
@Autowired
private UserService commonService;
private final String id = "User_id";

@Operation(summary = "列表")
@PostMapping("/list")
public Result listUser() {
return Result.success("数据列表", commonService.list());
}

@Operation(summary = "存在")
@PostMapping("/exist")
public Result existUser(@RequestBody @Validated IdParam param) {
QueryWrapper<UserEntity> wrapper = new QueryWrapper<>();
wrapper.eq(id.toLowerCase(Locale.ROOT), param.getId());
long count = commonService.count(wrapper);
if (count == 0) return Result.success("ID不存在", false);
return Result.success("ID已存在", true);
}

@Operation(summary = "保存")
@PostMapping("/insert")
public Result insertUser(@RequestBody @Validated UserEntity param) {
QueryWrapper<UserEntity> wrapper = new QueryWrapper<>();
wrapper.eq(id.toLowerCase(Locale.ROOT), param.getUserId());
if (commonService.count(wrapper) != 0) return Result.failure("ID已存在", new Date());
if (commonService.save(param)) return Result.success("保存成功", new Date());
return Result.failure("保存失败", new Date());
}

@Operation(summary = "删除")
@PostMapping("/delete")
public Result deleteUser(@RequestBody @Validated IdParam param) {
QueryWrapper<UserEntity> wrapper = new QueryWrapper<>();
wrapper.eq(id.toLowerCase(Locale.ROOT), param.getId());
if (commonService.count(wrapper) == 0) return Result.failure("ID不存在", param.getId());
if (commonService.remove(wrapper)) return Result.success("删除成功", param.getId());
return Result.failure("删除失败", param.getId());
}

@Operation(summary = "修改")
@PostMapping("/update")
public Result updateUser(@RequestBody @Validated UserEntity param) {
QueryWrapper<UserEntity> wrapper = new QueryWrapper<>();
wrapper.eq(id.toLowerCase(Locale.ROOT), param.getUserId());
if (commonService.count(wrapper) == 0) return Result.failure("ID不存在", new Date());
if (commonService.updateById(param)) return Result.success("修改成功", new Date());
return Result.failure("修改失败", new Date());
}

@Operation(summary = "查询")
@PostMapping("/select")
public Result selectUser(@RequestBody @Validated IdParam param) {
QueryWrapper<UserEntity> wrapper = new QueryWrapper<>();
wrapper.eq(id.toLowerCase(Locale.ROOT), param.getId());
if (commonService.count(wrapper) == 0) return Result.failure("ID不存在", param.getId());
return Result.success(commonService.getOne(wrapper));
}


@Operation(summary = "查询byAcc")
@PostMapping("/selectByAcc/{param}")
public Result selectUserByAcc(@PathVariable @Validated String param) {
QueryWrapper<UserEntity> wrapper = new QueryWrapper<>();
wrapper.eq("user_acc", param);
if (commonService.count(wrapper) == 0) return Result.failure("ID不存在", param);
return Result.success(commonService.getOne(wrapper));
}


@Operation(summary = "列表分页")
@PostMapping("/listPage")
public Result listPageUser(@RequestParam Integer page, @RequestParam Integer pageSize) {
//分页参数
Page<UserEntity> rowPage = new Page(page, pageSize);
//queryWrapper组装查询where条件
LambdaQueryWrapper<UserEntity> queryWrapper = new LambdaQueryWrapper<>();
rowPage = commonMapper.selectPage(rowPage, queryWrapper);
return Result.success("数据列表", rowPage);
}

@Operation(summary = "导出数据")
@PostMapping("exportExcel")
public void exportExcelUser(HttpServletResponse response) throws IOException {
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
String fileName = URLEncoder.encode("轮播图", StandardCharsets.UTF_8).replaceAll("\\+", "%20");
List<UserEntity> list = commonService.list();
response.setHeader("Content-disposition", "attachment;filename*=" + fileName + ".xlsx");
EasyExcel.write(response.getOutputStream(), UserEntity.class).sheet("轮播图").doWrite(list);
}

@Operation(summary = "导入数据")
@PostMapping("/importExcel")
public Result importExcelUser(MultipartFile file) {
try {
//获取文件的输入流
InputStream inputStream = file.getInputStream();
List<UserEntity> list = EasyExcel.read(inputStream) //调用read方法
//注册自定义监听器,字段校验可以在监听器内实现
//.registerReadListener(new UserListener())
.head(UserEntity.class) //对应导入的实体类
.sheet(0) //导入数据的sheet页编号,0代表第一个sheet页,如果不填,则会导入所有sheet页的数据
.headRowNumber(1) //列表头行数,1代表列表头有1行,第二行开始为数据行
.doReadSync();//开始读Excel,返回一个List<T>集合,继续后续入库操作
//模拟导入数据库操作
for (UserEntity entity : list) {
commonService.saveOrUpdate(entity);
}
return Result.success("导入成功", new Date());
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}

Springboot工程常用依赖

Springboot工程常用依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<!--   mysql     -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>8.0.32</scope>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--参数校验-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>8.0.0.Final</version>
</dependency>
<!--swagger3-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>4.1.0</version>
</dependency>
<!--mybatis-plus-->
<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>
<!--freemarker模板-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.32</version>
</dependency>
<!-- 导出excel -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.2.1</version>
</dependency>

Spring Boot中Excel数据导入导出的高效实现

Spring Boot中Excel数据导入导出的高效实现

摘要

在企业级应用中,Excel文件的导入导出是一个常见的需求。本文将介绍如何在Spring Boot项目中使用EasyExcel库实现Excel文件的导入导出功能。我们将通过实际的代码示例,展示如何读取和写入Excel文件,以及如何通过自定义监听器来增强数据处理的灵活性。

1. 依赖添加

首先,我们需要在项目的pom.xml文件中添加EasyExcel的依赖。

1
2
3
4
5
6
<!-- 导出excel -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.2.1</version>
</dependency>

2. 自定义监听器(可选)

为了增强数据处理的灵活性,我们可以创建一个自定义监听器来校验Excel文件中的数据。例如,我们可以校验用户名称是否重复,或者数据格式是否正确。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.xiaohe.uploadimage.entity.User;

/**
* 自定义监听器,对下载的excel中的数据进行校验
*/

public class UserListener extends AnalysisEventListener {

List<String> names = new ArrayList<>();

/**
* 每解析一行,回调该方法
*
* @param data
* @param context
*/
@Override
public void invoke(Object data, AnalysisContext context) {
//校验名称
String name = ((User) data).getU_name();
// if (StrUtil.isBlank(name)) {
// throw new RuntimeException(String.format("第%s行名称为空,请核实", context.readRowHolder().getRowIndex() + 1));
// }
if (names.contains(name)) {
throw new RuntimeException(String.format("第%s行名称已重复,请核实", context.readRowHolder().getRowIndex() + 1));
} else {
names.add(name);
}
}

/**
* 出现异常回调
*
* @param exception
* @param context
* @throws Exception
*/
@Override
public void onException(Exception exception, AnalysisContext context) throws Exception {
if (exception instanceof ExcelDataConvertException) {
/**从0开始计算*/
int columnIndex = ((ExcelDataConvertException) exception).getColumnIndex() + 1;
int rowIndex = ((ExcelDataConvertException) exception).getRowIndex() + 1;
String message = "第" + rowIndex + "行,第" + columnIndex + "列" + "数据格式有误,请核实";
throw new RuntimeException(message);
} else if (exception instanceof RuntimeException) {
throw exception;
} else {
super.onException(exception, context);
}
}

/**
* 解析完,全部回调
*
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
//解析完,全部回调逻辑实现
names.clear();
}
}

3. 实体类定义

我们需要定义一个实体类来映射Excel文件中的列。使用@ExcelProperty注解来指定Excel列的名称。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

// ... 其他代码 ...

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class User {
// ... 实体类属性和注解 ...
@ExcelProperty("账号")
private String u_acc;
@ExcelProperty("密码")
private String u_pwd;
@ExcelProperty("姓名")
private String u_name;
@ExcelProperty("性别")
private String u_sex;
@ColumnWidth(20)
@DateTimeFormat("yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd")
@ExcelProperty("生日")
private Date u_birth;
@ExcelProperty("角色")
private String u_ide;
@ExcelProperty("状态")
private int u_statues;
@ColumnWidth(20)
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ExcelProperty("创建日期")
private Date u_create_time;
}

4. 控制层实现

导出数据

在控制器中,我们提供一个接口来导出Excel文件。EasyExcel提供了便捷的API来生成Excel文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import com.alibaba.excel.EasyExcel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

// ... 其他代码 ...

@RestController
public class ExcelController {

@Autowired
private ExcelMapper excelMapper;

@GetMapping("user")
public List<User> user() {
return excelMapper.selectUserAll();
}

/**
* 导出数据
*/
@GetMapping("exportExcel")
public void exportData(HttpServletResponse response) throws IOException {
// ... 导出数据代码 ...
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
String fileName = URLEncoder.encode("用户表", StandardCharsets.UTF_8).replaceAll("\\+", "%20");
List<User> users = excelMapper.selectUserAll();
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
EasyExcel.write(response.getOutputStream(), User.class).sheet("用户表").doWrite(users);
}
}

导入数据

同样地,我们提供一个接口来处理Excel文件的导入。通过EasyExcel的读取功能,我们可以将Excel文件中的数据转换为Java对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import com.alibaba.excel.EasyExcel;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

// ... 其他代码 ...

@RestController
public class ExcelController {
/**
* 导入数据
*/
@PostMapping("/importExcel")
public Integer importData(MultipartFile file) {
try {
//获取文件的输入流
InputStream inputStream = file.getInputStream();
List<User> lst = EasyExcel.read(inputStream) //调用read方法
//注册自定义监听器,字段校验可以在监听器内实现
.registerReadListener(new UserListener())
.head(User.class) //对应导入的实体类
.sheet(0) //导入数据的sheet页编号,0代表第一个sheet页,如果不填,则会导入所有sheet页的数据
.headRowNumber(1) //列表头行数,1代表列表头有1行,第二行开始为数据行
.doReadSync(); //开始读Excel,返回一个List<T>集合,继续后续入库操作
//模拟导入数据库操作
for (User user : lst) {
Date date = user.getU_birth();
String form = String.format("%tF", date);
System.out.println(form);
}
return 1;
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
}

🎉 结语

通过本文的介绍,我们学习了如何在Spring Boot项目中使用EasyExcel库来实现Excel文件的导入导出。自定义监听器的引入使得数据处理更加灵活,能够应对各种复杂的业务需求。EasyExcel的简单易用和强大的功能,使得Excel文件处理变得高效和便捷。在实际开发中,开发者可以根据项目需求,选择合适的库来实现Excel文件的处理。

感谢你的访问,期待与你在技术的道路上相遇!👋🌟🚀

Spring Boot 3项目集成Swagger3教程

Spring Boot 3项目集成Swagger3教程

Swagger是一个用于设计、构建、记录和使用RESTful web服务的开源软件框架。Swagger 3(OpenAPI 3.0)提供了更加强大和灵活的API文档生成能力。本教程将指导您如何在Spring Boot 3项目中集成Swagger3,并使用Knife4j作为UI界面。

1. 添加依赖

首先,您需要在项目的pom.xml文件中添加Swagger3的依赖。同时,为了确保依赖能够正确下载,您可以添加阿里云的Maven镜像仓库。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    <!--swagger3-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>4.1.0</version>
</dependency>


<repositories>
<!--阿里云镜像-->
<repository>
<id>alimaven</id>
<name>aliyun maven</name>
<url>https://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>

2. 配置Swagger

在Spring Boot项目中创建一个配置类SwaggerConfig,并添加Swagger的配置信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import io.swagger.v3.oas.models.ExternalDocumentation;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SwaggerConfig {
@Bean
public OpenAPI springShopOpenAPI() {
return new OpenAPI()
.info(new Info().title("标题")
.contact(new Contact())
.description("我的API文档")
.version("v1")
.license(new License().name("Apache 2.0").url("http://springdoc.org")))
.externalDocs(new ExternalDocumentation()
.description("外部文档")
.url("https://springshop.wiki.github.org/docs"));
}
}


3. 实体类和控制层注解

在您的实体类和控制层中使用Swagger注解来描述API。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// 实体类注解示例
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.util.Date;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@Schema(name = "Employee", description = "$!{table.comment}")
public class Emp {
@ExcelProperty("ID")
@Schema(description = "ID")
private int id;
@ExcelProperty("用户名")
@Schema(description = "用户名")
private String names;
@ExcelProperty("工资")
@Schema(description = "工资")
private double salary;
@ExcelProperty("生日")
@Schema(description = "生日")
private Date birthday;
@ColumnWidth(20)
@ExcelProperty("头像")
@Schema(description = "头像")
private String photo;

// @ColumnWidth(20)
// @DateTimeFormat("yyyy-MM-dd HH:mm:ss")
// @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
// @ExcelProperty("创建日期")
// private Date u_create_time;
}


// 控制层注解示例
import io.swagger.v3.oas.annotations.Operation;

@Operation(summary = "获取所有员工信息")
@GetMapping("/selectAll")
public List<Emp> selectAll() {
// ...
}

4. 通用返回结果封装

创建一个通用的返回结果类,用于统一API的响应格式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

@Builder(toBuilder = true)
@AllArgsConstructor
@Setter
@Getter
@Slf4j
public class Result<T> {
/**
* 提示信息
*/
@Schema(description = "提示信息")
private String message;
/**
* 是否成功
*/
@Schema(description = "是否成功")
private boolean success;
/**
* 返回状态码
*/
@Schema(description = "返回状态码")
private Integer code;
/**
* 数据
*/
@Schema(description = "数据")
private T data;

public Result() {
}

public static Result success() {
Result Result = new Result();
Result.setSuccess(Boolean.TRUE);
Result.setCode(ResultCode.SUCCESS.getCode());
Result.setMessage(ResultCode.SUCCESS.getMsg());
return Result;
}

public static Result success(String msg) {
Result Result = new Result();
Result.setMessage(msg);
Result.setSuccess(Boolean.TRUE);
Result.setCode(ResultCode.SUCCESS.getCode());
return Result;
}

public static Result success(Object data) {
Result Result = new Result();
Result.setData(data);
Result.setSuccess(Boolean.TRUE);
Result.setCode(ResultCode.SUCCESS.getCode());
Result.setMessage(ResultCode.SUCCESS.getMsg());
return Result;
}

/**
* 返回失败 消息
*
* @return Result
*/
public static Result failure() {
Result Result = new Result();
Result.setSuccess(Boolean.FALSE);
Result.setCode(ResultCode.FAILURE.getCode());
Result.setMessage(ResultCode.FAILURE.getMsg());
return Result;
}

/**
* 返回失败 消息
*
* @param msg 失败信息
* @return Result
*/
public static Result failure(String msg) {
Result Result = new Result();
Result.setSuccess(Boolean.FALSE);
Result.setCode(ResultCode.FAILURE.getCode());
Result.setMessage(msg);
return Result;
}

public static Result failure(Integer code, String msg) {
Result Result = new Result();
Result.setSuccess(Boolean.FALSE);
Result.setCode(code);
Result.setMessage(msg);
return Result;
}


public static Result failure(String msg, ResultCode exceptionCode) {
Result Result = new Result();
Result.setMessage(msg);
Result.setSuccess(Boolean.FALSE);
Result.setCode(exceptionCode.getCode());
Result.setData(exceptionCode.getMsg());
return Result;
}

/**
* 返回失败 消息
*
* @param exceptionCode 错误信息枚举
* @return Result
*/
public static Result failure(ResultCode exceptionCode) {
Result Result = new Result();
Result.setSuccess(Boolean.FALSE);
Result.setCode(exceptionCode.getCode());
Result.setMessage(exceptionCode.getMsg());
return Result;
}

/**
* 返回失败 消息
*
* @param exceptionCode 错误信息枚举
* @param msg 自定义错误提示信息
* @return Result
*/
public static Result failure(ResultCode exceptionCode, String msg) {
Result Result = new Result();
Result.setMessage(msg);
Result.setSuccess(Boolean.FALSE);
Result.setCode(exceptionCode.getCode());
return Result;
}

}

5. 注解说明

Swagger3的注解与Swagger2有所不同,以下是一些常用注解的对照表:

Swagger2注解 Swagger3注解 注解位置
@Api @Tag(name = “接口类描述”) Controller类上
@ApiOperation @Operation(summary = “接口方法描述”) Controller方法上
@ApiImplicitParams @Parameters Controller方法上
@ApiImplicitParam @Parameter(description = “参数描述”) Controller方法上
@ApiParam @Parameter(description = “参数描述”) 方法参数上
@ApiIgnore @Parameter(hidden = true) 或 @Operation(hidden = true) -
@ApiModel @Schema DTO类上
@ApiModelProperty @Schema DTO属性上

6. 访问Swagger UI

启动您的Spring Boot应用后,您可以通过以下地址访问Swagger UI:

1
2
http://localhost:8080/doc.html
http://localhost:8080/swagger-ui/index.html

在这里,您可以查看API文档,测试API接口,并获取相关信息。

Springboot工程常用配置

Springboot工程常用配置

yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
server:
port: 9090

spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/db_crud?serverTimezone=GMT%2b8
username: root
password: password

mybatis:
mapper-locations: classpath:mapper/*.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl


#mybatis-plus:
# mapper-locations: classpath*:/dao/**/*Dao.xml
# configuration:
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl


xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.springboot.mapper.BooksMapper">

<select id="list" resultType="com.example.springboot.entity.Books">
select *
from sys_books;
</select>

<select id="selectPage" resultType="com.example.springboot.entity.User">
select *
from sys_books limit #{pageNum},#{pageSize};
</select>

<select id="selectTotal" resultType="java.lang.Integer">
select count(*)
from sys_books
</select>


</mapper>

thymeleaf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#关闭thymeleaf模板缓存
spring:
thymeleaf:
cache: false
prefix: classpath:/templates/ #指定模板位置
suffix: .html #指定后缀名
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/ssmbuild?characterEncoding=UTF-8
username: root
password: password
web:
resources:
static-locations: classpath:/static/,file:${photo.file.dir} #暴露哪些资源可以通过项目名访问

mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.xuda.springboot.pojo
#Mybatis配置

#日志配置
logging:
level:
root: info
com.xuda: debug

#指定文件上传的位置
photo:
file:
dir: D:\__easyProjects__\IntelliJ_IDEA\SpringBootStudy\photo

React基本使用第二版

React基本使用第二版

1.安装

1.网页下载

1
npm i react react-dom

2.全局安装脚手架

1
npm i -g create-react-app

2.创建项目

1.直接创建项目

1
npx create-react-app my-app

2.npm创建项目

1
npx create-react-app my-app --use-npm

3.脚手架创建项目

1
create-react-app my-app

3.运行、构建、测试、打包、

1
2
3
4
5
6
7
npm start

npm run build

npm test

npm run eject

4.项目结构

一、node_modules(依赖目录)

二、public(公共资源目录)

三、src(源文件目录)

​ 1.index.js(项目的入口文件)

​ 2.app.js(从入口文件出获取到的app实例文件)

​ // 需要手动创建

​ 3.api目录

​ 4.assets目录

​ 5.components目录

​ 6.config目录

​ 7.utils目录

​ 8.views目录

5.快捷键

1
2
3
4
5
6
7
8
9
// 1.rfc --- 快速生成页面框架代码

import React from 'react'

export default function Layout() {
return (
<div>Layout</div>
)
}

6.配置eslint

在package中,可以先把eslint配置的这段代码删掉,以免不必要的报错。

1
2
3
4
5
6
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},

7. 安装和引入antd

1
2
3
4
5
6
7
1.全局
npm install antd-init -g

antd-init

2.项目
npm install antd --save
1
2
3
4
5
6
7
8
9
//index.js
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import "antd/dist/reset.css";
import App from "./App";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);

8. 使用antd组件

[antd官网]: https://ant.design/components/button-cn “antd”

7. 安装react-router-dom

1
npm install react-router-dom

9.配置路由

react项目的入口文件为index.js,我一般把路由直接写在app.js中,也可以新建一个router文件夹下写。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//app.js
import "./App.css";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Layout from "./views/Layout/Layout";
import Login from "./views/Login/Login";
import Sale from "./views/Sale/Sale";
import Detail from "./views/Detail/Detail";
import User from "./views/User/User";
import Role from "./views/Role/Role";
import Room from "./views/Room/Room";
import Type from "./views/Type/Type";

function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Login />}></Route>
<Route path="/layout" element={<Layout />}>
<Route path="sale" element={<Sale />}></Route>
<Route path="detail" element={<Detail />}></Route>
<Route path="role" element={<Role />}></Route>
<Route path="user" element={<User />}></Route>
<Route path="room" element={<Room />}></Route>
<Route path="type" element={<Type />}></Route>
</Route>
</Routes>
</BrowserRouter>
);
}

export default App;
1
2
3
4
5
6
7
8
9
//index.js
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import "antd/dist/reset.css";
import App from "./App";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);

10.二级页面路由和重定向

1
2
3
4
5
6
7
8
9
10
11
// 1.在需要跳转的
import { Outlet } from "react-router-dom";

// 2.在需要路由的地方写上Outlet标签
<Outlet></Outlet>

// 3.使用如下生命周期钩子函数将页面在渲染前跳转到重定向位置
useEffect(() => {
setCurrent("1-1");
navigate("/layout/sale");
}, []);

11.页面跳转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 1.在需要跳转的页面导入如下,跳转到二级页面时一般配合使用。
import { useNavigate, Outlet } from "react-router-dom";

// 2.对方法进行适当改造,方便使用。
let navigate = useNavigate();

// 3.编写跳转页面的方法,跳转页面。
const clickMenu = (e) => {
setCurrent(e.key);
switch (e.key) {
case "1-1":
navigate("/layout/sale");
break;
case "1-2":
navigate("/layout/detail");
break;
case "2-1":
navigate("/layout/role");
break;
case "2-2":
navigate("/layout/user");
break;
}
};

// 方法触发位置在这里
<Menu
theme="dark"
mode="inline"
defaultSelectedKeys={["1-1"]}
items={asideMenu}
onClick={clickMenu}
selectedKeys={current}
/>

12.hooks

[Hooks]: https://zh-hans.react.dev/reference/react “React Hook”

React基本使用

React基本使用

1.安装

1.网页下载

1
npm i react react-dom

2.全局安装脚手架

1
npm i -g create-react-app

2.创建项目

1.直接创建项目

1
npx create-react-app my-app

2.npm创建项目

1
npx create-react-app my-app --use-npm

3.脚手架创建项目

1
create-react-app my-app

3.运行、构建、测试、打包、

1
2
3
4
5
6
7
npm start

npm run build

npm test

npm run eject

4.快速开始

1
2
import React from 'react';
import ReactDom from 'react-dom';

5. 安装antd,创建项目

1
2
3
4
5
6
7
1.全局
npm install antd-init -g

antd-init

2.项目
npm install antd --save

6. 安装react-router-dom

1
npm install react-router-dom
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//index.js
import Router from './router';
//router/index.js
import App from '../App';
import List from "../pages/List/List.jsx";
import Edit from "../pages/Edit/Edit.jsx";
import Means from "../pages/Means/Means.jsx";
import Login from "../pages/Login/Login.jsx";
import Register from "../pages/Register/Register.jsx";
import { BrowserRouter as BaseRouter, Routes, Route } from "react-router-dom";

const Router = () => (
<BaseRouter>
<Routes>
<Route path="/" element={<App />}>
<Route path="/list" element={<List />}></Route>
<Route path="/edit" element={<Edit />}></Route>
<Route path="/means" element={<Means />}></Route>
</Route>
<Route path="/login" element={<Login />}></Route>
<Route path="/register" element={<Register />}></Route>
</Routes>
</BaseRouter>
);
export default Router

7. 暴露webpack

1
2
3
4
5
git add .

git commit -m '解包前'

npm run eject

8. 配置less

webpack.config.js
查找sasaModuleRegex

1
2
3
4
5
6
7
8
9
{
test:/\.less$/,
use:getStyleLoaders(
{
//暂不配置
},
'less-loader'
),
},
1
npm install less-loader

9.使用antd组件

https://ant.design/components/button-cn

Gsap基本使用

Gsap基本使用

1. 下载

1
2
// power shell
npm i gsap

2.导入

1
2
//main.js
import { gsap } from "gsap";

3.编写配置文件

1
2
3
4
5
6
7
8
9
// vue.config.js
const path = require('path');

module.exports = {
chainWebpack: config => {
config.resolve.alias.set('gsap', path.resolve(__dirname, 'node_modules', 'gsap')); // 设置GSAP别名
}
};

4.使用gsap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { gsap } from "gsap";

export const flow =()=>{
gsap.set(".flow",{
y:"-20px",
});
gsap.to(".form", {
y: '0',
duration: 1,
repeat: -1,
yoyo: true,
ease: "power1.inOut"
});
}

5.全部代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
<template>
<view class="main">
<view class="flow form">
<input type="text" placeholder="账号" v-model="user.acc">
<input type="text" placeholder="密码" v-model="user.pwd">
<button size="mini" type="default" @click="loginIn">登录</button>
<button size="mini" type="default" @click="reset">取消</button>
</view>
<view class="dots">
<view class="dot"></view>
<view class="dot"></view>
<view class="dot"></view>
</view>

<view class="bg-container"></view>
</view>
</template>

<script>
import {
flow,
showMessage
} from '../../gsap/index.js'
import {
$login
} from '../../api/index.js'
export default {
data() {
return {
user: {
acc: '',
pwd: '',
}
}
},
mounted() {
flow();
},
methods: {
async loginIn() {
if (this.user.acc.length <= 0 || this.user.pwd.length <= 0) {
showMessage('请输入账号或密码...');
return;
}
let data = await $login(this.user);
if (data.length >= 1) {
uni.setStorage({
key: 'account',
data: this.user.acc,
success: (res) => {
console.log('记录登录+1');
}
})
uni.navigateTo({
url: '/pages/index/index',
animationType: 'slide-in-right'
})
} else {
showMessage('账号或密码错误...');
}
},
reset() {
this.user.acc = '';
this.user.pwd = '';
}
},
onLoad() {
uni.getStorage({
key: 'account',
success: (res) => {
if (res.data.length >= 0) {
uni.navigateTo({
url: '/pages/index/index',
animationType: 'slide-in-right'
})
}
}
})
},
}
</script>

<style scoped>
* {
--hei: 40px;
}

.main {
width: 100vw;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}

.form {
width: 70%;
height: 300px;
border-radius: 10px;
border: 4px solid orange;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding: 30px;
box-shadow: 0px 3px 10px 2px #fff;
}

button {
color: white;
width: 100%;
height: var(--hei);
line-height: var(--hei);
margin: 10px 0;
background-color: orange;
border: none;
}

button:active {
color: white;
background-color: rgba(255, 165, 0, .4);
}

input {
width: 100%;
font-size: 14px;
height: var(--hei);
margin: 10px 0;
border: 2px solid orange;
padding: 0 10px;
border-radius: 6px;
}

.dots {
width: 40%;
height: 20px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
}

.dot {
width: 20px;
height: 20px;
background-color: orange;
border-radius: 50%;
}
</style>

Git基本使用

Git 创建仓库

1
2
3
4
5
6
git init
git init newrepo 初始化后,会在 newrepo 目录下会出现一个名为 .git 的目录,所有 Git 需要的数据和资源都存放在这个目录中。
git add \*.p
git add README
git commit -m '初始化项目版本'
如果当前目录下有几个文件想要纳入版本控制,需要先用 git add 命令告诉 Git 开始对这些文件进行跟踪,然后提交:

git clone

1
2
3
4
5
6
7
repo:Git 仓库。
git clone <repo> <directory>
directory:本地目录。
git clone git://github.com/schacon/grit.git
执行该命令后,会在当前目录下创建一个名为 grit 的目录,其中包含一个 .git 的目录,用于保存下载下来的所有版本记录。
git clone git://github.com/schacon/grit.git mygrit
如果要自己定义要新建的项目目录名称,可以在上面的命令末尾指定新的名字

配置

1
2
3
4
5
6
7
git config -e  
针对当前仓库
git config -e --global
针对系统上所有仓库
git config --global user.name "runoob"
git config --global user.email test@runoob.com
设置提交代码时的用户信息,如果去掉 --global 参数只对当前仓库有效。

一个简单的操作步骤:

1
2
3
4
5
6
git init
初始化仓库。
git add .
添加文件到暂存区。
git commit
将暂存区内容添加到仓库中。

创建仓库命令

git init 初始化仓库
git clone 拷贝一份远程仓库,也就是下载一个项目。

提交与修改

1
2
3
4
5
6
7
git add 添加文件到暂存区
git status 查看仓库当前的状态,显示有变更的文件。
git diff 比较文件的不同,即暂存区和工作区的差异。
git commit 提交暂存区到本地仓库。
git reset 回退版本。
git rm 将文件从暂存区和工作区中删除。
git mv 移动或重命名工作区文件。

提交日志

1
2
git log 查看历史提交记录
git blame <file> 以列表形式查看指定文件的历史修改记录

远程操作

1
2
3
4
git remote 查看当前的远程库
git fetch 从远程获取代码库
git pull 下载远程代码并合并
git push 上传远程代码并合并

Git 分支管理

1
2
3
4
5
6
git branch
没有参数时,git branch 会列出你在本地的分支。
git branch (branchname) 创建分支
git branch -d (branchname) 删除分支
git checkout (branchname) 切换分支
git merge 合并分支

Git 查看提交历史

1
2
3
4
5
6
git log 查看历史提交记录。
git log --oneline 查看历史记录的简洁的版本
git log --reverse --oneline 逆向显示所有日志
git log --author=Linus --oneline -5 Git 源码中 Linus 提交的部分。
git log --oneline --before={3.weeks.ago} --after={2010-04-18} --no-merges 指定日期、隐藏合并提交
git blame <file> 查看指定文件的历史修改记录。

Git 标签

1
2
3
git tag -a v1.0 创建带注解的标签
git tag 查看所有标签
git tag -a <tagname> -m "com 标签" 指定标签信息

Git 远程仓库

1
2
3
git remote add [shortname] [url] 添加一个新的远程仓库
ssh-keygen -t rsa -C "youremail@example.com" 生成 SSH Key
ssh -T git@github.com 验证是否成功

推送到 GitHub 仓库

1
2
3
4
5
6
7
8
9
10
mkdir runoob-git-test # 创建测试目录
cd runoob-git-test/ # 进入测试目录
echo "# 菜鸟教程 Git 测试" >> README.md # 创建 README.md 文件并写入内容
ls #查看目录下的文件
git init # 初始化
git add README.md # 添加文件
git commit -m "添加 README.md 文件" # 提交并备注信息

git remote add origin git@github.com:tianqixin/runoob-git-test.git
git push -u origin master # 提交到 Github

查看当前的远程库

1
2
git remote 查看当前配置有哪些远程仓库
git remote -v 别名的实际链接地址

提取远程仓库

1
2
git fetch 从远程仓库下载新分支与数据
git merge 从远端仓库提取数据并尝试合并到当前分支

常用

登录

1
2
git config --global user.name "xiaohe"
git config --global user.email "2109664977@qq.com"

连接

1
2
3
ssh-keygen -t rsa -C "2109664977@qq.com"
ssh-keygen -t ed25519 -C "2109664977@qq.com"
ssh -T git@gitee.com

添加远程仓库

1
2
3
git remote add [shortname] [url]
git remote add test https://gitee.com/bestwishes0203/login.git
ssh-keygen -t rsa -C "2109664977@qq.com"

提交

1
2
3
4
5
6
7
8
9
10
git init - 初始化仓库。
git add . - 添加文件到暂存区。
git commit - 将暂存区内容添加到仓库中。
git commit -m "提交说明"
git commit -m "第一次提交"
git pull
git push -u https://gitee.com/bestwishes0203/login.git master
git log
git checkout 版本号
git checkout master

分支

1
2
3
git branch
git branch dev
git checkout dev

合并分支

1
2
3
4
5
6
git add .
git commit -m "fenzhi"
git checkout master
git pull
git merge dev
git push

Docker基本使用

Docker基本使用

安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
更新源
yum update

yum install -y yum-utils device-mapper-persistent-data lvm2

yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

yum install -y docker-ce

docker -v

配置docker加速
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://zpthq4nu.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

cat /etc/docker/daemon.json

常用命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
开启
systemctl start docker

查看状态
systemctl status docker

关闭
systemctl stop docker

重启
restart docker

开机自启
systemctl enable docker

镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
查看镜像
docker images

搜索镜像
docker search redis

下载最后版本的镜像
docker pull redis

查找就像版本网址
--hub.docker.com

下载指定版本镜像
docker pull redis:5.0

删除指定镜像
docker rmi id

删除指定版本镜像
docker rmi redis:5.0

查看所有id
docker images -q

删除所有镜像
docker rmi `docker images -q`

容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
创建容器 前台运行
docker run -it --name=c1 centos:7 /bin/bash

退出
exit

查看正在运行的容器
docker ps

查看容器
docker ps -a

创建容器 后台运行
docker run -id --name=c2 centos:7

进入容器
docker exec -it c2 /bin/bash

删除容器
docker rm c1

查看所有容器
docker ps -aq

删除所有容器
docker rm `docker ps -aq`

查看容器信息
docker inspect c1

数据卷

1
2
3
4
5
6
7
8
将 /root/data 绑定到容器 /root/data_container
docker run -it --name=c3 -v /root/data:/root/data_container centos:7 /bin/bash






  • Copyrights © 2022-2024 何福海
  • 访问人数: | 浏览次数:

请我喝杯奶茶吧~

支付宝
微信