前言

最近在学习怎么做一个项目,记录一下一些经常用到的类。

结果类的封装

定义状态码

状态码的定义需要与前端进行约定,这里就定义最简单的两个状态码,成功和失败。

1
2
3
4
5
6
public interface ResultCode {
// 成功
public static Integer SUCCESS = 20000;
// 失败
public static Integer ERROR = 20001;
}

结果类的封装

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
// 使用lombok偷懒,不使用lombok就自己定义get和set方法
@Data
public class Result {
// 是否成功
private Boolean success;
// 返回状态码
private Integer code;
// 返回的信息
private String message;
// 返回的数据
private Map<String, Object> data = new HashMap<String, Object>();

// 私有构造方法,使用静态方法居多,就不公开构造方法了
private Result(){}

// 操作成功时的默认返回值
public static Result ok() {
Result result = new Result();
result.setSuccess(true);
result.setCode(ResultCode.SUCCESS);
result.setMessage("操作成功");
return result;
}

// 操作失败的默认返回值
public static Result error() {
Result result = new Result();
result.setSuccess(false);
result.setCode(ResultCode.ERROR);
result.setMessage("操作失败");
return result;
}

// 使用链式编程进行封装
public Result success(Boolean success) {
this.setSuccess(success);
return this;
}
public Result message(String message) {
this.setMessage(message);
return this;
}
public Result code(Integer code) {
this.setCode(code);
return this;
}
public Result data(String key,Object value) {
this.data.put(key, value);
return this;
}

}

使用结果类

这里使用mybatis-plus来测试一下返回的结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@RestController
public class EduTeacherController {

@Autowired
private CourseService courseService;

// 返回查询到的数据
@GetMapping("findAll")
public Result findAllCourse() {
List<Course> list = courseService.list(null);
if(list == null) {
return Result.error().message("没有查询到任何数据");
} else {
return Result.ok().data("courseList",list);
}
}
}

可以看到成功后的结果。

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
{
"success": true,
"code": 20000,
"message": "操作成功",
"data": {
"courseList": [
{
"id": "1272143086562152450",
"title": "语文",
"gmtCreate": "2020-06-14 20:25:22",
"gmtModified": "2020-06-15 20:29:19"
},
{
"id": "1272143133739683841",
"title": "数学",
"gmtCreate": "2020-06-14 20:25:33",
"gmtModified": "2020-06-15 20:29:33"
},
{
"id": "1272143217621569537",
"title": "英语",
"gmtCreate": "2020-06-14 20:25:53",
"gmtModified": "2020-06-15 20:29:05"
}
]
}
}

返回这样的JSON数据,前端就能更好的使用接口得到的数据,而且统一结果类后,所有的controller的返回值都使用这个结果类返回,从而规范返回的结果。

自定义全局异常类

定义一个异常类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* @ClassName TestException
* @Descriprtion 自定义异常,继承RuntimeException异常类
* @Author yww
**/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class TestException extends RuntimeException{

private Integer code;

private String msg;

}

设置异常处理

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
/**
* @ClassName GlobalExceptionHandler
* @Descriprtion 统一异常处理类
* @Author yww
**/

@ControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(Exception.class)
@ResponseBody
public Result error(Exception e) {
e.printStackTrace();
return Result.error().message("执行全局异常处理!");
}

@ExceptionHandler(TestException.class)
@ResponseBody
public Result error(schoolException e) {
log.error(e.getMsg());
e.printStackTrace();
return Result.error().code(e.getCode()).message(e.getMsg());
}

}

处理逻辑,从小到大。 即出现TestException就会优先使用第二个方法处理异常。 出现了其他的异常,就会使用大一级的异常。

测试

写一个测试类来测试一下。

1
2
3
4
5
@Test
public void run() {
// 自定义返回结果码和异常信息
throw new TestException(20001, "出现TestException异常");
}
1
TestException(code=20001, msg=出现TestException异常)

这样返回异常信息给前端,前端就能展示给用户,从而用户就知道怎样的操作是不合理的了。

MD5加密

用户的密码一般都会进行加密后在存储到数据库当中,所以一般用到MD5这种加密算法。

这种加密算法最大的特点就是不可逆,只能加密不能解密。

这是挺简单的一种加密算法了,之后还可以考虑加盐和哈希散列,进行更复杂的加密手段。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Md5Utils {
public static String encrypt(String strSrc) {
try {
char hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
'9', 'a', 'b', 'c', 'd', 'e', 'f' };
byte[] bytes = strSrc.getBytes();
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(bytes);
bytes = md.digest();
int j = bytes.length;
char[] chars = new char[j * 2];
int k = 0;
for (int i = 0; i < bytes.length; i++) {
byte b = bytes[i];
chars[k++] = hexChars[b >>> 4 & 0xf];
chars[k++] = hexChars[b & 0xf];
}
return new String(chars);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
throw new RuntimeException("MD5加密出错+" + e);
}
}
}

Redis配置类

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
/**
* @ClassName RedisConfig
* @Descriprtion Redis的配置类
* @Author yww
**/
@EnableCaching
@Configuration
public class RedisConfig extends CachingConfigurationSelector {

/**
* 自定义RedisTemplate
* @param factory Redis工厂
* @return RedisTemplate
*/
@Bean
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
// 连接工厂
template.setConnectionFactory(redisConnectionFactory);
// JSON序列化的配置
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance ,
ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
jackson2JsonRedisSerializer.setObjectMapper(om);

// String的序列化
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value采用Jackson的JSON序列化
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value采用Jackson的JSON序列化
template.setHashValueSerializer(jackson2JsonRedisSerializer);

template.afterPropertiesSet();

return template;
}

/**
* 缓存管理
* @param factory Redis连接工厂
* @return CacheManager
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance ,
ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
jackson2JsonRedisSerializer.setObjectMapper(om);
// 配置序列化(解决乱码的问题),过期时间600秒
RedisCacheConfiguration config =
RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(600))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager.builder(factory).cacheDefaults(config).build();
return cacheManager;
}

}