小辣椒

用处:一个注解完成大量的 get、set 操作

idea 安装 Lombok 插件,推荐用 properties 标签来管理更加规范

前 3 行比较通用,所以一起先写了,1,2 那个指定 maven 的解析方式,能避免环境不一样的错误

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
      <!--boot的版本如下-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starters</artifactId>
<version>2.1.3.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<lombok.version>1.18.4</lombok.version>
</properties>

<!-- 小辣椒依赖,就能直接使用@Slf4j注解了,不需要额外导入 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>

实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;


@Data //等于自动set、get下面的属性
@NoArgsConstructor //自动空构造
@AllArgsConstructor //全参构造,要是少参,得再建一个构造函数
public class Client {

private int userAcc;

private String userPwd;

}

单元测试

tip:springboot 中进行单元测试,不是很规范情况直接写版本就行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

<!--包含了junit4.12等测试框架,没有它无法调用springboot里的上下文中对象,正常引入它就对了-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<!--如果不调用项目中模块的东西,用它就行了 <scope>test</scope>仅限于测试代码运行时,compile是编译时-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>

在 test 文件夹–>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
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;

/**
* @Author Lucky友人a
* @Date 2023/7/19 -9:46
*/
@Slf4j //日志注解
@RunWith(SpringRunner.class) //获取上下文
@SpringBootTest //SpringBoot测试注解
public class TestWiring {
@Resource
private DeviceTopoService deviceTopoService; //如果只导入junit,将空指针

@Test
public void fun1() {
DeviceTopoEntity info = deviceTopoService.getById(1);
log.info(String.valueOf(info));
}
}

Fastjson2

选用 2 的版本,更加的好用

1
2
3
4
5
6
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.7</version>
</dependency>

前端:都采用 post 请求

1
2
3
4
5
6
7
8
9
10
11
export const loginM = (datas) => {
return request({
url: '/index/login',
method: 'post',
data: datas
})
}

loginM({ userAcc: this.username, userPwd: this.password }).then((res) => {...})


后端

1
2
3
4
5
6
7
8
9
10
import com.alibaba.fastjson2.JSONObject;     //核心导包

@PostMapping("/login")
public ResultVO loginHome(@RequestBody JSONObject obj) {
String userAcc = obj.getString("userAcc");
// List<String> ids = obj.getList("ids",String.class);
//// Date date = obj.getDate("date");
String userPwd = obj.getString("userPwd");
return indexService.login(userAcc, userPwd);
}

WebMvcConfigurer

后端的拦截器配置

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
package com.nwa.until;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
* @Author Lucky友人a
* @Date 2023/1/24 -17:50
*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Autowired
private CheckTokenInterceptor checkTokenInterceptor;

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(checkTokenInterceptor)
.addPathPatterns("/home/**") //这里添加拦截的
.excludePathPatterns("/index/**") //这里是排除的
.excludePathPatterns("/home/getLogList")
.excludePathPatterns("/swagger-ui/**")
.excludePathPatterns("/swagger2.html")
.excludePathPatterns("/doc.html");
}

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("doc.html")
.addResourceLocations("classpath:/META-INF/resources/");
}

}

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
 __                            __                         ______
/ | / | / \
$$ | __ __ _______ $$ | __ __ __ /$$$$$$ |
$$ | / | / | / |$$ | / |/ | / | $$ |__$$ |
$$ | $$ | $$ |/$$$$$$$/ $$ |_/$$/ $$ | $$ | $$ $$ |
$$ | $$ | $$ |$$ | $$ $$< $$ | $$ | $$$$$$$$ |
$$ |_____ $$ \__$$ |$$ \_____ $$$$$$ \ $$ \__$$ | $$ | $$ |
$$ |$$ $$/ $$ |$$ | $$ |$$ $$ | $$ | $$ |
$$$$$$$$/ $$$$$$/ $$$$$$$/ $$/ $$/ $$$$$$$ | $$/ $$/
/ \__$$ |
$$ $$/
$$$$$$/





██╗ ██╗ ██╗ ██████╗██╗ ██╗██╗ ██╗ █████╗
██║ ██║ ██║██╔════╝██║ ██╔╝╚██╗ ██╔╝██╔══██╗
██║ ██║ ██║██║ █████╔╝ ╚████╔╝ ███████║
██║ ██║ ██║██║ ██╔═██╗ ╚██╔╝ ██╔══██║
███████╗╚██████╔╝╚██████╗██║ ██╗ ██║ ██║ ██║
╚══════╝ ╚═════╝ ╚═════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝

SpringBoot 分页器

依赖

1
2
3
4
5
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.0</version>
</dependency>

yml

1
2
3
spring:
main:
allow-circular-references: true

impl(有待优化,封装分页类)

1
2
3
4
5
6
7
8
9
10
11
@Override
public ResultVO getMyWeekList(String months, String id, int page, int limit) {
PageHelper.startPage(page, limit); //一般传过来1,100条
List<Client> clientS = adHomeMapper.getMyWeekList(months, id);
if (clientS != null) {
PageInfo<Client> goodsTbPageInfo = new PageInfo<>(clientS, 3);
int count = (int) goodsTbPageInfo.getTotal();
resultVO = new ResultVO(ResStatus.OK, "列表信息返回成功!", count, clientS);
}
return resultVO;
}

前端部分

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
    <el-table :data="
tableData.slice((currentPage - 1) * pageSize, currentPage * pageSize)
"
....
>.....
</el-table>
<div>
<div class="block"
style="margin-top: 15px">
<el-pagination align="center"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[1, 3, 5]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="tableData.length">
</el-pagination>
</div>
</div>



方法中:
handleSizeChange (val) {
console.log(`每页${val}条`)
this.currentPage = 1
this.pageSize = val
},
handleClick (row) {
console.log(row)
this.$data.drawe = true
this.$data.userObj = row
},
handleCurrentChange (val) {
console.log(`当前页:${val}`)
this.currentPage = val
},

data里return中
tableData: [],
currentPage: 1,
pageSize: 5,
total: '',

发起请求
getMonthsList () {
getMyWeekList({
months: this.findContent,
id: '',
page: 1,
limit: 100
}).then((resp) => {
this.$data.tableData = resp.data.data
})
},

Token

依赖

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.10.3</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>

工具类

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
package com.nwa.until;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
* @Author Lucky友人a
* @Date 2023/1/6 -16:15
*/

public class JWTUtils {
//设置过期时间
private static final long EXPIRE_DATE=30*610*100000;
//token秘钥
private static final String TOKEN_SECRET = "LuckyNWA666";

public static String token (String username, String password){
String token = "";
try {
//过期时间
Date date = new Date(System.currentTimeMillis()+EXPIRE_DATE);
//秘钥及加密算法
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
//设置头部信息
Map<String,Object> header = new HashMap<>();
header.put("typ","JWT");
header.put("alg","HS256");
//携带username,password信息,生成签名
token = JWT.create()
.withHeader(header)
.withClaim("username",username)
.withClaim("password",password).withExpiresAt(date)
.sign(algorithm);
}catch (Exception e){
e.printStackTrace();
return null;
}
return token;
}
public static boolean verify(String token){
/**
* @desc 验证token,通过返回true
* @create 2019/1/18/018 9:39
* @params [token]需要校验的串
**/
try {
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
JWTVerifier verifier = JWT.require(algorithm).build();
DecodedJWT jwt = verifier.verify(token);
return true;
}catch (Exception e){
e.printStackTrace();
return false;
}
}

}

拦截调用

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
package com.nwa.until;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.nwa.bean.ResultVO;
import io.jsonwebtoken.*;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
* @Author Lucky友人a
* @Date 2023/1/24 -17:36
*/
@Component
public class CheckTokenInterceptor implements HandlerInterceptor {


@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
// String token = request.getParameter("token");//这个是通过请求里面带token参数来传的,默认请求头传的
String method = request.getMethod();//这里请求是options 这里有3次握手,预检机制
if ("OPTIONS".equalsIgnoreCase(method)) {
return true;//放行
}
String token = request.getHeader("token");
System.out.println("进入拦截器");
System.out.println("token的值是" + token);
if (token == null) {
ResultVO resultVO = new ResultVO(ResStatus.FAIL, "请先登录", null);
doResponse(response, resultVO);

} else {
try {
//验证token
//如果token正确,有效期内则这正常执行,否则抛出异常
boolean verify = JWTUtils.verify(token);
return verify;
} catch (ExpiredJwtException e) {
ResultVO resultVO = new ResultVO(ResStatus.FAIL, "登录过期", null);
doResponse(response, resultVO);
} catch (UnsupportedJwtException e) {
ResultVO resultVO = new ResultVO(ResStatus.FAIL, "token不合法", null);
doResponse(response, resultVO);
} catch (Exception e) {
ResultVO resultVO = new ResultVO(ResStatus.FAIL, "请先登录", null);
doResponse(response, resultVO);
}
}
return false;
}

private void doResponse(HttpServletResponse response, ResultVO resultVO) throws IOException {
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
PrintWriter out = response.getWriter();
String s = new ObjectMapper().writeValueAsString(resultVO);
out.println(s);
out.flush();
out.close();
}
}


登录成功时候
String token = JWTUtils.token(acc, pwd);
client.setToken(token);

前端 request 中带上请求头

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
登录后记得保存;
window.sessionStorage.setItem("token", data.token);
接下去每次访问接口携带;
request.interceptors.request.use(
(config) => {
// 在发送请求之前做些什么
// 比如判断是否有token
config.headers.token = window.sessionStorage.getItem("token");

return config;
},
function (error) {
return Promise.reject(error);
}
);

Md5

没有加盐可以被破解,需优化

1
2
3
4
5
<!--md5依赖-->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>

工具类

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
package com.nwa.until;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
* @Author Lucky友人a
* @Date 2023/1/25 -16:09
*/


public class MD5Utils {
public static String md5(String pwd) {
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");

md5.update(pwd.getBytes());
return new BigInteger(1, md5.digest()).toString(16);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
}

比较简单,等以后再完善

1
2
3
String md5Pwd = MD5Utils.md5(pwd);
(pwdD.equals(md5Pwd))

代码生成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!-- 下面一键生成代码的依赖,在加个配置类很方便,感觉比MybatisX插件好用,有头部注释-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.30</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.4.3.4</version>
</dependency>

工具类,修改配置即可使用

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
package com.nwa.until;

import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

import java.util.Collections;

/**
* @Author Lucky友人a
* @Date 2023/4/18 -15:28
*/

public class CodeGenerator {
public static void main(String[] args) {
FastAutoGenerator.create("jdbc:mysql://127.0.0.1:3306/weeklydb?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC", "root", "123456")
.globalConfig(builder -> {
builder.author("luckyNwa") // 设置作者
.enableSwagger() // 开启 swagger 模式
.fileOverride() // 覆盖已生成文件
.outputDir(System.getProperty("user.dir") + "/src/main/java"); // 指定输出目录
})
// 全局配置
.packageConfig(builder -> {
builder.parent("com.nwa") // 设置父包名
.moduleName("") // 设置父包模块名
.pathInfo(Collections.singletonMap(OutputFile.mapperXml, System.getProperty("user.dir") + "/src/main/resources/mapper")); // 设置mapperXml生成路径
})
//策略配置
.strategyConfig(builder -> {
builder.addInclude("tb_weeks") // 设置需要生成的表名
.addTablePrefix("tb_", "sys_"); // 设置过滤表前缀
})
.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
}
}

Aop

springboot 中的自定义注解加上 aop

1
2
3
4
5
<!--        日志处理依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

自定义注解类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.nwa.aop;

import java.lang.annotation.*;

//自定义注解类
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLog {
String operationType() default ""; //操作人

String operationName() default ""; //操作名称

String value() default ""; //状态
}

切面类

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
package com.nwa.aop;


import com.nwa.bean.Client;
import com.nwa.service.impl.SysLogService;
import com.nwa.until.ClientInfoUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;


@Slf4j
@Aspect //切面
@Component
public class SysLogA { //切面类
@Resource
private SysLogService sysLogService;

@Pointcut("execution(* com.nwa.controller.IndexController.*(..))") //切点
public void logPointCut() {
}

@After("logPointCut()") //后置加强
public void logTest(JoinPoint joinPoint) throws Exception {

HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
// HttpSession session = request.getSession();


String browser = ClientInfoUtil.getBrowserInfo(request); //获取浏览器名称
String os = ClientInfoUtil.getOperatingSystem(request); //获取操作系统
//
// String userName = (String) session.getAttribute("userName");
// if(userName==null){
// userName="lucky";
// }
//
// String userId = (String) session.getAttribute("userId");
// if(userId==null){
// userId="2727";
// }

String ip = ClientInfoUtil.getIP(request); //获取ip

try {
// String targetName = joinPoint.getTarget().getClass().getName();
// String methodName = joinPoint.getSignature().getName();
// Object[] arguments = joinPoint.getArgs();

//获取自定义注解里面的值
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
SysLog sysLog = method.getAnnotation(SysLog.class);
String operationType = sysLog.operationType();
String operationName = sysLog.operationName();

//*========存进数据库=========*//
Client client1 = new Client();
client1.setCreateBy(operationType);
// client1.setLogMethod((targetName + "." + methodName + "()") + "." + operationType);
client1.setRequestIp(ip);
// client1.setLogCreateBy(userName);
client1.setLogTip(operationName);
client1.setLogSys(os);
client1.setLogBrowser(browser);
client1.setCreateDate(new Date());
//保存数据库
sysLogService.save(client1);

} catch (Exception e) {
//记录本地异常日志
log.error("==后置通知异常==");
log.error("异常信息:{}------" + e.getMessage());
throw e;
}

}
}


接着只需要去Con那边对应的方法上面加入即可
@SysLog(operationType = "admin", operationName = "登录成功", value = "200") //自定义注解来获取日志

Swagger

接着这个下面 2 个主题也同样是 api 生成

正常 1-2 依赖就能用了,为了好看加了 3 的依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!--  api文档需要的依赖  -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>1.9.6</version>
</dependency>

工具类

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
package com.nwa.until;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;
import java.util.List;

/**
* @Author Lucky友人a
* @Date 2023/1/15 -20:06
*/
@Configuration
@EnableSwagger2 //添加依赖这个才有,下面端口去配置里指定
//访问的地址 http://localhost:9999/swagger-ui.html
//如果添加ui插件。 http://localhost:9999/doc.html
public class SwaggerConfig {
@Bean
public Docket docket() {
// ApiInfoBuilder apiInfoBuilder = new ApiInfoBuilder();
// apiInfoBuilder.title("小维的后端接口说明")
// .description("此文档详细说明了小维前后端项目端口规范...").version("v1.0")
// .contact(new Contact("luckyNWA","www.nwa.com","1656213092@qq.com"));
//
// ApiInfo apiInfo = apiInfoBuilder.build();
// //指定文档中的封面信息;版本作者等
// Docket docket = new Docket(DocumentationType.SWAGGER_2) //指定文档风格
// .apiInfo(apiInfo).select()
// .apis(RequestHandlerSelectors.basePackage("com.nwa.controller"))//扫描这个包下所有接口
// .paths(PathSelectors.any())//PathSelectors.regx("/user/")//正则只要user下的接口
// .build();
//
// return docket;
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.nwa.controller"))//扫描这个包下所有接口
//加了ApiOperation注解的类,才生成接口文档
// .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
//包下的类,才生成接口文档
//.apis(RequestHandlerSelectors.basePackage("io.sysssc.controller"))
// .paths(PathSelectors.any())
.build()
.securitySchemes(security()); //主要关注点--统一填写一次token

}


private ApiInfo apiInfo() {
Contact luckyNWA = new Contact("luckyNWA", "www.nwa.com", "1656213092@qq.com");
return new ApiInfo(
"小维的API接口说明",
"此文档详细说明了小维前后端项目端口规范",
"v1.0",
"www.nwa.com",
luckyNWA,
"apache 2.0",
"www.nwa.com",
new ArrayList()
);
}

private List<ApiKey> security() {
ArrayList<ApiKey> list = new ArrayList<>();
list.add(new ApiKey("token", "token", "header"));
return list;


}

}

other

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
控制层中
可以在类上面加 @Api(value = "提供了后台主页面的各种接口", tags = "后台主页面接口") //这是swagger里类的描述
可以在方法上面加
@ApiOperation("修改密码")//这是swagger里方法的描述
@ApiImplicitParams({
@ApiImplicitParam(dataType = "string", name = "userAcc", value = "账号", required = true),
@ApiImplicitParam(dataType = "string", name = "newPassword", value = "新密码", required = true),
@ApiImplicitParam(dataType = "string", name = "newPassword", value = "老密码", required = true),
})//这里是swagger里面的属性描述
@PutMapping("/modifyPwd") //符合RESTFUL接口风格,别用RequsetMapping

实体类中
可以在类上面加 @ApiModel(value = "周报里面的实体", description = "封装的周报对象")//文档响应的类说明
可以在属性上面加 @ApiModelProperty("用户id") //文档属性的说明

knife4j

依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.5</version>
</parent>




<!--swagger的依赖-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>2.0.9</version>
</dependency>

YML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
knife4j:
# 开启增强配置
enable: true
#开启生产环境屏蔽
production: false
# 开启Swagger的Basic认证功能,默认是false
basic:
enable: false
# Basic认证用户名
username: test
# Basic认证密码
password: 123
setting:
enableSearch: false # 开启搜索功能
enableHomeCustom: true #开启自定义主页
homeCustomLocation: classpath:markdown/home.md #地址

去 resources–>新建 markdown—>home.md

1
2
3
4
5
6
7
昵称:Lucky 小 a

职业:全栈开发工程师

博客地址:http://luckynwa.top

联系邮箱:1656213092@qq.com

Knife4jConfiguration

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
package com.nwa.config;

import com.github.xiaoymin.knife4j.spring.extension.OpenApiExtensionResolver;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;

import java.util.List;

import static com.github.xiaoymin.knife4j.core.util.CollectionUtils.newArrayList;

/**
* knife4j配置
*
* @author luckyNwa
* @date 2023/10/17
*///教程地址:https://segmentfault.com/a/1190000041143413#item-6-12
@Configuration
@AllArgsConstructor
@EnableSwagger2WebMvc
public class Knife4jConfiguration {
private final OpenApiExtensionResolver openApiExtensionResolver;//全构造注解加他等于引入这个对象

@Bean
public Docket createRestApi() {
//创建Docket对象,指定文档类型为OpenAPI 3.0
return new Docket(DocumentationType.SWAGGER_2)
//配置API信息
.apiInfo(apiInfo())
//配置扫描路径
.select()
//扫描所有@ApiOperation注解的类
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
//扫描指定包下的类
//.apis(RequestHandlerSelectors.basePackage("com.nwa.modules.lucky.controller"))
//扫描所有路径
.paths(PathSelectors.any())
//创建
.build()
//添加扩展
//.extensions(openApiExtensionResolver.buildExtensions("Lucky"))
//添加设置自定义主页这个
.extensions(openApiExtensionResolver.buildSettingExtensions())
//自定义时间格式
// .directModelSubstitute(java.util.Date.class, String.class)
//添加安全认证
.securitySchemes(security());
}

private List<ApiKey> security() {
//添加ApiKey认证
return newArrayList(new ApiKey("Token", "token", "header"));
}

private ApiInfo apiInfo() {
//配置API信息
Contact luckyNWA = new Contact("luckyNWA", "http://luckynwa.top", "1656213092@qq.com");
return new ApiInfoBuilder()
.title("小维的API接口说明")
.description("多个应用系统之间的身份验证和访问控制的接口")
.termsOfServiceUrl("http://luckynwa.top")
.version("1.0").contact(luckyNWA).license("apache 2.0")
.build();
}


}