一、第一天

md5加密(maven导入版)

1
2
3
4
5
6
7
8
9
10
1. 导入md5(单程加密,不能复原)
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.2</version>
</dependency>

2. 使用
//将前端的数据进行md5处理再对比
password = DigestUtils.md5DigestAsHex(password.getBytes());

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
1. 在maven中导入knife4j
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
</dependency>

2. 在config文件中设置相关

2.1:设置静态资源映射

/**
* 设置静态资源映射
* @param registry
*/
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
log.info("开始静态资源映射");
registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}

2.2:生成接口文档(在启动springboot时间会显示)

/**
* 通过knife4j生成接口文档
* @return
*/
@Bean
public Docket docket() {
log.info("准备生成接口文档");
ApiInfo apiInfo = new ApiInfoBuilder()
.title("苍穹外卖项目接口文档")
.version("2.0")
.description("苍穹外卖项目接口文档")
.build();
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo)
.select()
.apis(RequestHandlerSelectors.basePackage("com.sky.controller"))
.paths(PathSelectors.any())
.build();
return docket;
}

2.3:使用
在浏览器中打开 http://localhost:8080/doc.html
一般用于后台测试接口



swagger的注解(在页面中显示相关注解)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<h1>1. @Api: 用在类上解释,例如解释Controller<h1>
例子:
@Api(tags = "员工相关接口") //swagger解释
public class EmployeeController {}

2. @ApiModel: 用在类上,一般解释实体类,如entity,DTO,VO

3.@ApiModelProperty: 用在属性上,一般用在实体类的具体参数

4.@ApiOperation: 用在方法上,如Controller的方法即这个方法的接口,说明方法的用途和作用如在
例子:
@ApiOperation(value = "员工登录") //说明方法用途的注解,配合Swagger
@PostMapping("/login")
public Result<EmployeeLoginVO> login{}




二、第二天


对象属性拷贝

1
2
3
4
5
6
7
1. 一般用在新增事件中,前端传来DTO类型数据,在新增时转为具体实体类

例子:
Category category = new Category();
//属性拷贝(第一个参数为要拷贝的对象,第二个参数为数据转入对象)
BeanUtils.copyProperties(categoryDTO, category);
//(categoryDTO --> category)

账号已存在情况动态处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1. 一般用在注册账号,若新增账号在数据库中已存在则返回字符串:"zhangsan"(可变,动态) + "用户名已存在"(静态)

2. 在全局处理异常时添加

例子:
@ExceptionHandler
public Result exceptionHandler(SQLIntegrityConstraintViolationException ex){
//账号已存在
String message = ex.getMessage();
if(message.contains("Duplicate entry")){
String[] split = message.split(" ");
String username = split[2];
//TODO 改为常量
String msg = username + "用户名已存在";
return Result.error(msg);
}
else {
return Result.error(MessageConstant.UNKNOWN_ERROR);
}
}

  1. 详细结果

拦截器添加id到线程,方便后续使用当前用户id


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
1. 拦截器设置

/**
* jwt令牌校验的拦截器
*/
@Component
@Slf4j
public class JwtTokenAdminInterceptor implements HandlerInterceptor {

@Autowired
private JwtProperties jwtProperties;

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//判断当前拦截到的是Controller的方法还是其他资源
if (!(handler instanceof HandlerMethod)) {
//当前拦截到的不是动态方法,直接放行
return true;
}

//1、从请求头中获取令牌
String token = request.getHeader(jwtProperties.getAdminTokenName());

//2、校验令牌
try {
log.info("jwt校验:{}", token);
Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);
Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());
log.info("当前员工id:", empId);
//当前登录用户id放入线程
BaseContext.setCurrentId(empId);
//3、通过,放行
return true;
} catch (Exception ex) {
//4、不通过,响应401状态码
response.setStatus(401);
return false;
}
}
}


2. BaseContext根据ThreadLocal完成(要获取直接调用BaseContext.getCurrentId())

public class BaseContext {

public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();

public static void setCurrentId(Long id) {
threadLocal.set(id);
}

public static Long getCurrentId() {
return threadLocal.get();
}

public static void removeCurrentId() {
threadLocal.remove();
}

}

pageHelper进行分页查询

1
2
3
4
5
6
1. 开启分页功能(需要传入第几页和页面大小的参数)
PageHelper.startPage(categoryPageQueryDTO.getPage(),categoryPageQueryDTO.getPageSize());
//下一条sql进行分页,自动加入limit关键字分页
Page<Category> page = categoryMapper.pageQuery(categoryPageQueryDTO);

2. pageHelper根据线程,自动为sql语句添加limit实现分页功能

前端传入的数据获取

1
2
3
4
5
6
7
8
9
10
11
12
13
1. Json格式,在controller层通过@requestbody注解获取

public Result<String> save(@RequestBody CategoryDTO categoryDTO){}


2. Path参数,在controller层通过@PathVariable注解获取。并且前端axios时URL是/url/{...}
@PostMapping("/status/{status}")
public Result<String> startOrStop(@PathVariable("status") Integer status){}


3. Query 参数,直接获取
public Result<List<Category>> list(Integer type){}

三、第三天

自定义注解,实现公共字段填充

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
1. 声明注解

/**
* 自定义注解
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
//数据库操作类型(update,insert)
OperationType value();
}

1.2 数据库操作类型,用在上面

/**
* 数据库操作类型
*/
public enum OperationType {

/**
* 更新操作
*/
UPDATE,

/**
* 插入操作
*/
INSERT

}
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
2. 切入面
2.1: 切入点
/**
* 切入点
*/
@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
public void autoFillPointCut(){}

2.2:前置通知,通知中给公共词条进行复制
@Before("autoFillPointCut()")
public void autoFill(JoinPoint joinPoint){
log.info("开始给公共词条进行填充");

//获取当前被拦截方法上的数据库操作类
MethodSignature signature = (MethodSignature) joinPoint.getSignature(); //方法签名对象
AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class); //获取方法上的注解对象
OperationType operationType = autoFill.value(); //获取操作类型(insert,update)

//获取被拦截的参数:实体对象
Object[] args = joinPoint.getArgs();
if(args == null || args.length == 0){
return;
}

Object entity = args[0]; //约定,自动填充的实体类放在mapper层的第一个参数

//反射赋值

//准备赋值的数据
LocalDateTime now = LocalDateTime.now();
Long currentId = BaseContext.getCurrentId(); //创建者id

//根据不同的操作类型,为对应的属性赋值
//添加操作
if(operationType == OperationType.INSERT){
try {
Method setCreateTime = entity.getClass().getDeclaredMethod("setCreateTime",LocalDateTime.class);
Method setCreateUser = entity.getClass().getDeclaredMethod("setCreateUser",Long.class);
Method setUpdateTime = entity.getClass().getDeclaredMethod("setUpdateTime",LocalDateTime.class);
Method setUpdateUser= entity.getClass().getDeclaredMethod("setUpdateUser",Long.class);

//反射为对象赋值
setCreateTime.invoke(entity,now);
setCreateUser.invoke(entity,currentId);
setUpdateTime.invoke(entity,now);
setUpdateUser.invoke(entity,currentId);

} catch (Exception e) {
throw new RuntimeException(e);
}
} else if (operationType == OperationType.UPDATE) {
try {
Method setUpdateTime = entity.getClass().getDeclaredMethod("setUpdateTime",LocalDateTime.class);
Method setUpdateUser= entity.getClass().getDeclaredMethod("setUpdateUser",Long.class);

//反射为对象赋值
setUpdateTime.invoke(entity,now);
setUpdateUser.invoke(entity,currentId);

} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

1
2
3
4
5
6
7
8
9
10
3. 在mapper中使用
/**
* 插入数据
* @param category
*/
@Insert("insert into category(type, name, sort, status, create_time, update_time, create_user, update_user)" +
" VALUES" +
" (#{type}, #{name}, #{sort}, #{status}, #{createTime}, #{updateTime}, #{createUser}, #{updateUser})")
@AutoFill(value = OperationType.INSERT)
void insert(Category category);

阿里云环境变量配置(应该)

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
1.配置环境变量
1.1:开发环境配置(application-dev.yml
alioss:
endpoint: oss-cn-hangzhou.aliyuncs.com
access-key-id: LTAI5tQZnPXD6Rik8wCrwqR4
access-key-secret: zLNPJPqlZF079cbepAPzlkREWr35u9
bucket-name: spike1666cangqiong

1.2:application.yml
alioss:
endpoint: ${sky.alioss.endpoint}
access-key-id: ${sky.alioss.access-key-id}
access-key-secret: ${sky.alioss.access-key-secret}
bucket-name: ${sky.alioss.bucket-name}

2.配置类创建阿里云上传文件工具
2.1:configuration
@Slf4j
@Configuration
public class OssConfiguration {

@Bean
@ConditionalOnMissingBean
public AliOssUtil aliOssUtil(AliOssProperties aliOssProperties){
log.info("开始创建阿里云文件上传工具类: {}",aliOssProperties);
return new AliOssUtil(aliOssProperties.getEndpoint(),
aliOssProperties.getAccessKeyId(),
aliOssProperties.getAccessKeySecret(),
aliOssProperties.getBucketName());
}
}

2.2:properties
@Component
@ConfigurationProperties(prefix = "sky.alioss") //自动获取阿里的环境变量
@Data
public class AliOssProperties {

private String endpoint;
private String accessKeyId;
private String accessKeySecret;
private String bucketName;

}

3. CommonController中使用

@RestController
@RequestMapping("/admin/common")
@Api(tags = "公共相关接口")
@Slf4j
public class CommonController {
@Autowired
AliOssUtil aliOssUtil;

@PostMapping("/upload")
@ApiOperation("文件上传")
public Result upload(MultipartFile file){
log.info("文件上传: {}",file);
try {
//原始文件名
String originalFilename = file.getOriginalFilename();
//后缀
String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
//新文件名
String objectName = UUID.randomUUID().toString() + extension;

//文件请求路径
String filePath = aliOssUtil.upload(file.getBytes(), objectName);
return Result.success(filePath);
} catch (IOException e) {
//TODO常量
log.error("文件上传失败: {}",e);
}
return null;
}
}

Mapper主键返回

1
2
3
4
5
6
Mapper.Xml中使用

<insert id="addDish" useGeneratedKeys="true" keyProperty="id"> //在这里
insert into dish (name, category_id, price,image,description,create_time,update_time,create_user,update_user,status)
values (#{name},#{categoryId},#{price},#{image},#{description},#{createTime},#{updateTime},#{createUser},#{updateUser},#{status})
</insert>

Mapper列表上传减少sql服务器压力

1
2
3
4
5
6
7
8
Mapper.Xml中使用

<insert id="addFlavor">
insert into dish_flavor (dish_id, name, value) VALUES
<foreach collection="list" item="s" separator=",">
(#{s.dishId},#{s.name},#{s.value})
</foreach>
</insert>

Mapper逻辑外键查询

1
2
3
4
5
6
7
8
9
10
11
Mapper.Xml中使用

<select id="pageQuery" resultType="com.sky.vo.DishVO">
select d.*, c.name as categoryName from dish d left outer join category c on d.category_id = c.id
<where>
<if test="categoryId != null and categoryId != ''"> //逻辑外键
and d.category_id = #{categoryId}
</if>
</where>
order by d.create_time desc
</select>

五、第五天

SpringDataRedis

1
2
3
4
5
6
1. maven导入
<!-- Spring data Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2. Configration

@Configuration
@Slf4j
public class RedisConfiguration {

@Bean //注入redis链接工厂
public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory){
RedisTemplate redisTemplate = new RedisTemplate<>();
//设置redis连接工厂对象
redisTemplate.setConnectionFactory(redisConnectionFactory);
//设置redis key序列化器
redisTemplate.setKeySerializer(new StringRedisSerializer()); //字符串类型序列化器

return redisTemplate;
}
}

SpringDataRedis基本用法

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
152
153
154
155
156
157
3. 使用RedisTemplate
3.1: 测试类
package com.sky.test;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.connection.DataType;
import org.springframework.data.redis.core.*;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

//(注释防止内存滥用)
@SpringBootTest
public class SpringDataRedisTest {
//包结构一致才能自动注入(com.sky.test)
@Autowired
private RedisTemplate redisTemplate;

@Test
public void setRedisTemplate(){
System.out.println(redisTemplate);
//五种对象
ListOperations listOperations = redisTemplate.opsForList();
ValueOperations valueOperations = redisTemplate.opsForValue();
HashOperations hashOperations = redisTemplate.opsForHash();
SetOperations setOperations = redisTemplate.opsForSet();
ZSetOperations zSetOperations = redisTemplate.opsForZSet();

}

@Test
public void testString(){
//插入 set
redisTemplate.opsForValue().set("city","背景");
String city = (String) redisTemplate.opsForValue().get("city");
System.out.println(city);
//设置过期时间
redisTemplate.opsForValue().set("code","123456",3, TimeUnit.MINUTES);
//不存在则设置
redisTemplate.opsForValue().setIfAbsent("lock","1");
redisTemplate.opsForValue().setIfAbsent("lock","2");
}

/**
* Hash数据类型
*/
@Test
public void testHash(){
//操作对象
HashOperations hashOperations = redisTemplate.opsForHash();
//hset, hget, hdel, hkeys, hvals
hashOperations.put("100","name","tom");
hashOperations.put("100","age","20");

String name = (String) hashOperations.get("100", "name");
System.out.println("name: "+name);

//获取所有字段
Set keys = hashOperations.keys("100");
System.out.println("keys: "+keys);
//所有value
List values = hashOperations.values("100");
System.out.println("values: "+values);
hashOperations.delete("100","age");

}

/**
* 列表类型数据
*/
@Test
public void testList(){
//lpush lrange rpop llen
ListOperations listOperations = redisTemplate.opsForList();
//添加
listOperations.leftPushAll("mylist","a","b","c");
listOperations.leftPush("mylist","d");

List mylist = listOperations.range("mylist", 0, -1);
System.out.println(mylist);
//删除
listOperations.rightPop("mylist");

Long size = listOperations.size("mylist");
System.out.println(size);
}

/**
* 集合数据
*/
@Test
public void testSet(){
//sadd smembers scard sinter sunion srem
SetOperations setOperations = redisTemplate.opsForSet();

setOperations.add("set1","a","b","c","d");
setOperations.add("set2","a","b","x","y");

Set members = setOperations.members("set1");
System.out.println(members);

Long size = setOperations.size("set1");
System.out.println(size);
//集合的交集
Set intersect = setOperations.intersect("set1", "set2");
System.out.println(intersect);
//并集
Set union = setOperations.union("set1", "set2");
System.out.println(union);
//删除元素
setOperations.remove("set1","a","b");
}

/**
* 操作有序集合类型的数据
*/
@Test
public void testZset(){
//zadd zrange zincrby zrem
ZSetOperations zSetOperations = redisTemplate.opsForZSet();
//添加
zSetOperations.add("zset1","a",10);
zSetOperations.add("zset1","b",12);
zSetOperations.add("zset1","c",9);
//查询范围内的元素
Set zset1 = zSetOperations.range("zset1", 0, -1);
System.out.println(zset1);
//为元素加指定元素(9+10)
zSetOperations.incrementScore("zset1","c",10);
//删除
zSetOperations.remove("zset1","a","b");
}

/**
* 通用命令操作
*/
@Test
public void testCommon(){
//keys exists type del
//获得所有key
Set keys = redisTemplate.keys("*");
System.out.println(keys);
//查询是否存在当前key
Boolean name = redisTemplate.hasKey("name");
Boolean set1 = redisTemplate.hasKey("set1");
//所有key的类型
for (Object key : keys) {
DataType type = redisTemplate.type(key);
System.out.println(type.name());
}
//删除指定key
redisTemplate.delete("mylist");
}

}

SpringDataRedis控制层用法

1
2
3
4
5
6
1. 自动导入
@Autowired
RedisTemplate redisTemplate;

2. 使用与基本方法相同

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
1. 客户端接口
/**
* 通过knife4j生成接口文档
* @return
*/
@Bean
public Docket docket() {
log.info("准备生成接口文档");
ApiInfo apiInfo = new ApiInfoBuilder()
.title("苍穹外卖项目接口文档")
.version("2.0")
.description("苍穹外卖项目接口文档")
.build();
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.groupName("客户端接口")
.apiInfo(apiInfo)
.select()
.apis(RequestHandlerSelectors.basePackage("com.sky.controller"))
.paths(PathSelectors.any())
.build();
return docket;
}

2. 用户端接口
/**
* 通过knife4j生成接口文档
* @return
*/
@Bean
public Docket docket1() {
log.info("准备生成接口文档");
ApiInfo apiInfo = new ApiInfoBuilder()
.title("苍穹外卖项目接口文档")
.version("2.0")
.description("苍穹外卖项目接口文档")
.build();
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.groupName("用户端接口")
.apiInfo(apiInfo)
.select()
.apis(RequestHandlerSelectors.basePackage("com.sky.controller.user"))
.paths(PathSelectors.any())
.build();
return docket;
}

六. 第六天

Java向小程序发送请求(用于获取微信小程序用户的信息)

1. maven导入(阿里云导入时一并导入)

1
2
3
4
5
6
1. maven导入(阿里云导入时一并导入)
<dependency>
<groupId>org.apach.httpcomponets</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>

2. 工具类创建

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
152
153
154
155
156
157
158
159
160
161
2. 工具类创建
package com.sky.utils;

/**
* Http工具类
*/
public class HttpClientUtil {

static final int TIMEOUT_MSEC = 5 * 1000;

/**
* 发送GET方式请求
* @param url
* @param paramMap
* @return
*/
public static String doGet(String url,Map<String,String> paramMap){
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();

String result = "";
CloseableHttpResponse response = null;

try{
URIBuilder builder = new URIBuilder(url);
if(paramMap != null){
for (String key : paramMap.keySet()) {
builder.addParameter(key,paramMap.get(key));
}
}
URI uri = builder.build();

//创建GET请求
HttpGet httpGet = new HttpGet(uri);

//发送请求
response = httpClient.execute(httpGet);

//判断响应状态
if(response.getStatusLine().getStatusCode() == 200){
result = EntityUtils.toString(response.getEntity(),"UTF-8");
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
response.close();
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}

return result;
}

/**
* 发送POST方式请求
* @param url
* @param paramMap
* @return
* @throws IOException
*/
public static String doPost(String url, Map<String, String> paramMap) throws IOException {
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String resultString = "";

try {
// 创建Http Post请求
HttpPost httpPost = new HttpPost(url);

// 创建参数列表
if (paramMap != null) {
List<NameValuePair> paramList = new ArrayList();
for (Map.Entry<String, String> param : paramMap.entrySet()) {
paramList.add(new BasicNameValuePair(param.getKey(), param.getValue()));
}
// 模拟表单
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);
httpPost.setEntity(entity);
}

httpPost.setConfig(builderRequestConfig());

// 执行http请求
response = httpClient.execute(httpPost);

resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
} catch (Exception e) {
throw e;
} finally {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}

return resultString;
}

/**
* 发送POST方式请求
* @param url
* @param paramMap
* @return
* @throws IOException
*/
public static String doPost4Json(String url, Map<String, String> paramMap) throws IOException {
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String resultString = "";

try {
// 创建Http Post请求
HttpPost httpPost = new HttpPost(url);

if (paramMap != null) {
//构造json格式数据
JSONObject jsonObject = new JSONObject();
for (Map.Entry<String, String> param : paramMap.entrySet()) {
jsonObject.put(param.getKey(),param.getValue());
}
StringEntity entity = new StringEntity(jsonObject.toString(),"utf-8");
//设置请求编码
entity.setContentEncoding("utf-8");
//设置数据类型
entity.setContentType("application/json");
httpPost.setEntity(entity);
}

httpPost.setConfig(builderRequestConfig());

// 执行http请求
response = httpClient.execute(httpPost);

resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
} catch (Exception e) {
throw e;
} finally {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}

return resultString;
}
private static RequestConfig builderRequestConfig() {
return RequestConfig.custom()
.setConnectTimeout(TIMEOUT_MSEC)
.setConnectionRequestTimeout(TIMEOUT_MSEC)
.setSocketTimeout(TIMEOUT_MSEC).build();
}

}

微信小程序使用案例

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

@Service
public class UserServiceImpl implements UserService {

public static final String WX_LOGIN = "https://api.weixin.qq.com/sns/jscode2session";

@Autowired
WeChatProperties weChatProperties;

@Autowired
UserMapper userMapper;

@Override
public User wxlogin(UserLoginDTO dto) {
//调取接口服务获取当前用户的openid
Map<String , String> map = new HashMap<>();
map.put("appid",weChatProperties.getAppid());
map.put("secret",weChatProperties.getSecret());
map.put("js_code",dto.getCode());
map.put("grant_type","authorization_code");
//http工具类
String json = HttpClientUtil.doGet(WX_LOGIN,map);

JSONObject jsonObject = JSON.parseObject(json);
String openid = jsonObject.getString("openid");

//判断openid是否存在,空则表示登录失败
if (openid == null){
throw new LoginFailedException(MessageConstant.LOGIN_FAILED);
}

//判断是否为新用户
User user = userMapper.getByOpenid(openid);

//如果是新用户则自动注册
if (user == null){
user = User.builder()
.openid(openid)
.createTime(LocalDateTime.now())
.build();
userMapper.insert(user);
}

return user;
}
}

微信小程序需要导入的配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1. 开发配置(dev)
wechat:
appid: wxa4efcf2378f09b26
secret: 2e04cfec4701d51e688ca7d910a3e76e

2. 使用配置(jwt配合令牌验证,appid是小程序id)
sky:
jwt:
#微信相关配置
user-secret-key: itheima
user-token-name: authentication
user-ttl: 7200000
wechat:
appid: ${sky.wechat.appid}
secret: ${sky.wechat.secret}

七. 第七天

SpringCatche

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1. maven导入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring - boot - starter - cache</artifactId>
<version>2.7.3</version>
</dependency>

2. 使用方法
@EnableCaching 开启缓存注解功能,通常加在启动类上(application)
@Cacheable 在方法执行前先查询缓存中是否有数据,如果有数据,则直接返回缓存数据;如果没有缓存数据,调用方法并将方法返回值放到缓存中
@CachePut 将方法的返回值放到缓存中
@CacheEvict 将一条或多条数据从缓存中删除

3. 例子(修改菜品删除全部缓存)
@CacheEvict(value = "Dish" , allEntries = true) //删除全部缓存
@GetMapping("/{id}")
@ApiOperation("修改菜品数据回显")
public Result<DishVO> getById(@PathVariable Long id){
DishVO dishVO = new DishVO();
dishVO = dishService.getById(id);
return Result.success(dishVO);
}

八.第八天

开启事务注解

1
2
@Transactional  //开启事务
开启事务后,一个数据库操作报错全部返回。