【探花交友】day02—完善个人信息

我会带着你远行 2024-03-24 16:02 176阅读 0赞

目录

1、完善用户信息

1.1、阿里云OSS

1.2、百度人脸识别

1.3、保存用户信息

1.4、上传用户头像

2、用户信息管理

2.1、查询用户资料

2.2、更新用户资料

3、统一token处理

3.1、代码存在的问题

3.2、解决方案

3.3、代码实现

4、统一异常处理

4.1、解决方案

4.2、代码实现

1、完善用户信息

用户在首次登录时需要完善个人信息,包括性别、昵称、生日、城市、头像等。其中,头像数据需要做图片上传,这里采用阿里云的OSS服务作为我们的图片服务器,并且对头像要做人脸识别,非人脸照片不得上传。

122830beba8f4ed2a2d2a80eb82ffc28.png

  • 首次登录时(手机号码不存在),需要创建用户存入数据库中
  • 客户端检测首次登录需要完善用户信息

    • 填写用户基本信息
    • 上传用户头像(需要人脸认证)

1.1、阿里云OSS

实现图片上传服务,需要有存储的支持,那么我们的解决方案将以下几种:

  1. 直接将图片保存到服务的硬盘(springmvc将的文件上传)

    1. 优点:开发便捷,成本低
    2. 缺点:扩容困难
  2. 使用分布式文件系统进行存储

    1. 优点:容易实现扩容
    2. 缺点:开发复杂度稍大(有成熟的产品可以使用,比如:FastDFS)
  3. 使用第三方的存储服务

    1. 优点:开发简单,拥有强大功能,免维护
    2. 缺点:付费

在本套课程中选用阿里云的OSS服务进行图片存储。

fbc48613d1c045ab88ccbc71afd6e933.png

1.1.1、概述

对象存储服务(Object Storage Service,OSS)是一种海量、安全、低成本、高可靠的云存储服务,适合存放任意类型的文件。容量和处理能力弹性扩展,多种存储类型供选择,全面优化存储成本。

地址:对象存储 OSS_云存储服务_企业数据管理_存储-阿里云

bb3fb60c9b0245b083bdaa73ff566fa4.png

1.1.2、账号申请

购买服务

使用第三方服务最大的缺点就是需要付费,下面,我们看下如何购买开通服务。7d7fffab5d254b168e0badf33190053b.png

f938859b27de4964b10412622e1a380a.png

购买下行流量包: (不购买也可以使用,按照流量付费)a95395d4008f4322954ab8a4975d20c8.png

说明:OSS的上行流量是免费的,但是下行流量是需要购买的。

创建Bucket

使用OSS,首先需要创建Bucket,Bucket翻译成中文是水桶的意思,把存储的图片资源看做是水,想要盛水必须得有桶,就是这个意思了。

进入控制台,阿里云登录 - 欢迎登录阿里云,安全稳定的云计算服务平台

28571e13d77b4cd0b9a7b337a9409518.png

选择Bucket后,即可看到对应的信息,如:url、消耗流量等 :

17d91b684bdc4303a2faef45eb512ec3.png

文件管理:

8dad567dee914316982384ff5882996b.png

查看文件:

229e89e10f3341a4b159e62917492bef.png

1.1.3、抽取模板工具

和发送短信类似,阿里云OSS也是采用自定义工具的形式进行封装

OssProperties

tanhua-autoconfig创建配置类

  1. @Data
  2. @ConfigurationProperties(prefix = "tanhua.oss")
  3. public class OssProperties {
  4. private String accessKey;
  5. private String secret;
  6. private String bucketName;
  7. private String url; //域名
  8. private String endpoint;
  9. }

OssTemplate

tanhua-autoconfig创建模板对象

  1. package com.tanhua.autoconfig.template;
  2. import com.aliyun.oss.OSS;
  3. import com.aliyun.oss.OSSClientBuilder;
  4. import com.tanhua.autoconfig.properties.OssProperties;
  5. import java.io.InputStream;
  6. import java.text.SimpleDateFormat;
  7. import java.util.Date;
  8. import java.util.UUID;
  9. public class OssTemplate {
  10. private OssProperties properties;
  11. public OssTemplate(OssProperties properties) {
  12. this.properties = properties;
  13. }
  14. /**
  15. * 文件上传
  16. * 1:文件名称
  17. * 2:输入流
  18. */
  19. public String upload(String filename, InputStream is) {
  20. //3、拼写图片路径
  21. filename = new SimpleDateFormat("yyyy/MM/dd").format(new Date())
  22. +"/"+ UUID.randomUUID().toString() + filename.substring(filename.lastIndexOf("."));
  23. // yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
  24. String endpoint = properties.getEndpoint();
  25. // 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
  26. String accessKeyId = properties.getAccessKey();
  27. String accessKeySecret = properties.getSecret();
  28. // 创建OSSClient实例。
  29. OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId,accessKeySecret);
  30. // 填写Byte数组。
  31. // 填写Bucket名称和Object完整路径。Object完整路径中不能包含Bucket名称。
  32. ossClient.putObject(properties.getBucketName(), filename, is);
  33. // 关闭OSSClient。
  34. ossClient.shutdown();
  35. String url = properties.getUrl() +"/" + filename;
  36. return url;
  37. }
  38. }

TanhuaAutoConfiguration

TanhuaAutoConfiguration加入配置

  1. @EnableConfigurationProperties({
  2. SmsProperties.class,
  3. OssProperties.class
  4. })
  5. public class TanhuaAutoConfiguration {
  6. @Bean
  7. public SmsTemplate smsTemplate(SmsProperties properties) {
  8. return new SmsTemplate(properties);
  9. }
  10. @Bean
  11. public OssTemplate ossTemplate(OssProperties properties) {
  12. return new OssTemplate(properties);
  13. }
  14. }

1.1.4、测试

tanhua-app-server加入配置内容,并测试

  1. tanhua:
  2. oss:
  3. accessKey: LTAI4GKgob9vZ53k2SZdyAC7
  4. secret: LHLBvXmILRoyw0niRSBuXBZewQ30la
  5. endpoint: oss-cn-beijing.aliyuncs.com
  6. bucketName: tanhua001
  7. url: https://tanhua001.oss-cn-beijing.aliyuncs.com/

编写测试类

  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest(classes = AppServerApplication.class)
  3. public class OssTest {
  4. @Autowired
  5. private OssTemplate template;
  6. @Test
  7. public void testTemplateUpload() throws FileNotFoundException {
  8. String path = "C:\\Users\\lemon\\Desktop\\课程资源\\02-完善用户信息\\03-资料\\2.jpg";
  9. FileInputStream inputStream = new FileInputStream(new File(path));
  10. String imageUrl = template.upload(path, inputStream);
  11. System.out.println(imageUrl);
  12. }
  13. }

1.2、百度人脸识别

人脸识别(Face Recognition)基于图像或视频中的人脸检测、分析和比对技术,提供对您已获授权前提下的私有数据的人脸检测与属性分析、人脸对比、人脸搜索、活体检测等能力。灵活应用于金融、泛安防、零售等行业场景,满足身份核验、人脸考勤、闸机通行等业务需求

1.2.1、概述

地址:人脸识别_人脸识别_准确率99.99%_免费试用-百度AI开放平台

72cf91d1abaa42e5b6775631758f9147.png

1.2.2、账号申请

账号登录注册

百度云AI支持百度账号登录,也可以支持云账号。按需注册即可

ca39affdbeb4430dab2451c6dec02d60.png

创建应用

按需创建应用

cd8dd63eb4b94c8699f386a5d696e54e.png

1.2.3、抽取模板工具

AipFaceProperties

  1. @Data
  2. @ConfigurationProperties("tanhua.aip")
  3. public class AipFaceProperties {
  4. private String appId;
  5. private String apiKey;
  6. private String secretKey;
  7. @Bean
  8. public AipFace aipFace() {
  9. AipFace client = new AipFace(appId, apiKey, secretKey);
  10. // 可选:设置网络连接参数
  11. client.setConnectionTimeoutInMillis(2000);
  12. client.setSocketTimeoutInMillis(60000);
  13. return client;
  14. }
  15. }

AipFaceTemplate

  1. package com.tanhua.autoconfig.template;
  2. import com.baidu.aip.face.AipFace;
  3. import org.json.JSONObject;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import java.util.HashMap;
  6. public class AipFaceTemplate {
  7. @Autowired
  8. private AipFace client;
  9. /**
  10. * 检测图片中是否包含人脸
  11. * true:包含
  12. * false:不包含
  13. */
  14. public boolean detect(String imageUrl) {
  15. // 调用接口
  16. String imageType = "URL";
  17. HashMap<String, String> options = new HashMap<String, String>();
  18. options.put("face_field", "age");
  19. options.put("max_face_num", "2");
  20. options.put("face_type", "LIVE");
  21. options.put("liveness_control", "LOW");
  22. // 人脸检测
  23. JSONObject res = client.detect(imageUrl, imageType, options);
  24. System.out.println(res.toString(2));
  25. Integer error_code = (Integer) res.get("error_code");
  26. return error_code == 0;
  27. }
  28. }

1.2.4、测试

tanhua-app-server加入百度AI的配置信息

  1. tanhua:
  2. aip:
  3. appId: 27469915
  4. apiKey: sHiKW8u382xONufrmu0dHKdv
  5. secretKey: YsrzV2EVDRROdlZRAxDoTWGDH5L5cNrF

编写单元测试类

  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest(classes = AppServerApplication.class)
  3. public class FaceTest {
  4. @Autowired
  5. private AipFaceTemplate template;
  6. @Test
  7. public void detectFace() {
  8. String image = "https://tanhua001.oss-cn-beijing.aliyuncs.com/2021/04/19/a3824a45-70e3-4655-8106-a1e1be009a5e.jpg";
  9. boolean detect = template.detect(image);
  10. }
  11. }

1.3、保存用户信息

1.3.1、接口文档

8a13844d97ed4634a464bb32ea1da69e.png

YAPI接口地址:http://192.168.136.160:3000/project/19/interface/api/88

1.3.2、需求分析

数据库表

tb_user_info(用户基本资料表)

d222b606d1f3422d800f3d6af50b6166.png

  • 用户表和用户信息表是一对一的关系,两者采用主键关联的形式配置
  • 主键关联:用户表主键和用户资料表主键要保持一致(如:用户表id=1,此用户的资料表id=1)

执行流程

  1. 手机端发送请求到消费者
  2. 消费者构造数据,调用提供者
  3. 消费者完成业务处理,操作数据库

c07dd447cc1d475689f78099f46dc408.png

1.3.3、代码实现

UserInfo实体类

  1. @Data
  2. @NoArgsConstructor
  3. @AllArgsConstructor
  4. public class UserInfo implements Serializable {
  5. /**
  6. * 由于userinfo表和user表之间是一对一关系
  7. * userInfo的id来源于user表的id
  8. */
  9. @TableId(type= IdType.INPUT)
  10. private Long id; //用户id
  11. private String nickname; //昵称
  12. private String avatar; //用户头像
  13. private String birthday; //生日
  14. private String gender; //性别
  15. private Integer age; //年龄
  16. private String city; //城市
  17. private String income; //收入
  18. private String education; //学历
  19. private String profession; //行业
  20. private Integer marriage; //婚姻状态
  21. private String tags; //用户标签:多个用逗号分隔
  22. private String coverPic; // 封面图片
  23. private Date created;
  24. private Date updated;
  25. //用户状态,1为正常,2为冻结
  26. @TableField(exist = false)
  27. private String userStatus = "1";
  28. }

UserController

  1. @RestController
  2. @RequestMapping("/user")
  3. public class UserController {
  4. @Autowired
  5. private UserInfoService userInfoService;
  6. /**
  7. * 保存用户信息
  8. * UserInfo
  9. * 请求头中携带token
  10. */
  11. @PostMapping("/loginReginfo")
  12. public ResponseEntity loginReginfo(@RequestBody UserInfo userInfo,
  13. @RequestHeader("Authorization") String token) {
  14. //1、解析token
  15. Claims claims = JwtUtils.getClaims(token);
  16. Integer id = (Integer) claims.get("id");
  17. //2、向userinfo中设置用户id
  18. userInfo.setId(Long.valueOf(id));
  19. //3、调用service
  20. userInfoService.save(userInfo);
  21. return ResponseEntity.ok(null);
  22. }
  23. }

UserInfoService

  1. @Service
  2. public class UserInfoService {
  3. @DubboReference
  4. private UserInfoApi userInfoApi;
  5. public void save(UserInfo userInfo) {
  6. userInfoApi.save(userInfo);
  7. }
  8. }

UserInfoApi

  1. public interface UserInfoApi {
  2. public void save(UserInfo userInfo);
  3. }

UserInfoApiImpl

  1. @DubboService
  2. public class UserInfoApiImpl implements UserInfoApi {
  3. @Autowired
  4. private UserInfoMapper userInfoMapper;
  5. @Override
  6. public void save(UserInfo userInfo) {
  7. userInfoMapper.insert(userInfo);
  8. }
  9. }

UserInfoMapper

  1. public interface UserInfoMapper extends BaseMapper<UserInfo> {
  2. }

1.4、上传用户头像

1.4.1、需求分析

接口文档896ec9c456a24ec389b9ad594c80ac92.png

YAPI地址:http://192.168.136.160:3000/project/19/interface/api/91

文件上传采用POST传递,mvc中经过文件解析器转化为MultipartFile对象处理

后续请求中,请求headr中都有Authorization参数。

执行流程

3b7d44b5912945de95e816f13a98b66f.png

1.4.2、代码实现

UserControler

  1. /**
  2. * 上传用户头像
  3. * @return
  4. */
  5. @PostMapping("/loginReginfo/head")
  6. public ResponseEntity head(MultipartFile headPhoto,@RequestHeader("Authorization") String token) throws IOException {
  7. //1、判断token是合法
  8. boolean verifyToken = JwtUtils.verifyToken(token);
  9. if(!verifyToken){
  10. return ResponseEntity.status(401).body(null);
  11. }
  12. //2、向userinfo中设置用户id
  13. Claims claims = JwtUtils.getClaims(token);
  14. Integer id = (Integer) claims.get("id");
  15. //3、调用service
  16. userInfoService.updateHead(headPhoto,id);
  17. return ResponseEntity.ok(null);
  18. }

UserInfoService

  1. //更新用户头像
  2. public void updateHead(MultipartFile headPhoto, Long id) throws IOException {
  3. //1、将图片上传到阿里云oss
  4. String imageUrl = ossTemplate.upload(headPhoto.getOriginalFilename(), headPhoto.getInputStream());
  5. //2、调用百度云判断是否包含人脸
  6. boolean detect = aipFaceTemplate.detect(imageUrl);
  7. //2.1 如果不包含人脸,抛出异常
  8. if(!detect) {
  9. throw new RuntimeException();
  10. }else{
  11. //2.2 包含人脸,调用API更新
  12. UserInfo userInfo = new UserInfo();
  13. userInfo.setId(id);
  14. userInfo.setAvatar(imageUrl);
  15. userInfoApi.update(userInfo);
  16. }
  17. }

UserInfoApi

  1. public void update(UserInfo userInfo);

UserInfoApiImpl

  1. @Override
  2. public void update(UserInfo userInfo) {
  3. userInfoMapper.updateById(userInfo);
  4. }

2、用户信息管理

2.1、查询用户资料

2.1.1、接口文档

7303073ec4834a779525236eed8875a2.png

YAPI地址:http://192.168.136.160:3000/project/19/interface/api/265

参数userID: 用户id,当不传递时,查询当前用户的资料信息

2.1.2、代码实现

UserInfoVo

  1. @Data
  2. @NoArgsConstructor
  3. @AllArgsConstructor
  4. public class UserInfoVo implements Serializable {
  5. private Long id; //用户id
  6. private String nickname; //昵称
  7. private String avatar; //用户头像
  8. private String birthday; //生日
  9. private String gender; //性别
  10. private String age; //年龄
  11. private String city; //城市
  12. private String income; //收入
  13. private String education; //学历
  14. private String profession; //行业
  15. private Integer marriage; //婚姻状态
  16. }

UsersController

  1. @RestController
  2. @RequestMapping("/users")
  3. public class UsersControler {
  4. @Autowired
  5. private UserInfoService userInfoService;
  6. /**
  7. * 查询用户资料
  8. */
  9. @GetMapping
  10. public ResponseEntity users(Long userID,@RequestHeader("Authorization") String token) {
  11. if(userID == null) {
  12. Claims claims = JwtUtils.getClaims(token);
  13. Integer id = (Integer) claims.get("id");
  14. userID = Long.valueOf(id);
  15. }
  16. UserInfoVo userInfo = userInfoService.findById(userID);
  17. return ResponseEntity.ok(userInfo);
  18. }
  19. }

UserInfoService

  1. //根据id查寻
  2. public UserInfoVo findById(Long id) {
  3. UserInfo userInfo = userInfoApi.findById(id);
  4. UserInfoVo vo = new UserInfoVo();
  5. BeanUtils.copyProperties(userInfo,vo); //copy同名同类型的属性
  6. if(userInfo.getAge() != null) {
  7. vo.setAge(userInfo.getAge().toString());
  8. }
  9. return vo;
  10. }

UserInfoApiImpl

  1. @Override
  2. public UserInfo findById(Long id) {
  3. return userInfoMapper.selectById(id);
  4. }

2.2、更新用户资料

2.2.1、接口文档

06f667268e7949728e1f602f30495ef8.png

YAPI地址:http://192.168.136.160:3000/project/19/interface/api/259

2.2.2、代码实现

UsersController

  1. /**
  2. * 更新用户资料
  3. * @return
  4. */
  5. @PutMapping
  6. public ResponseEntity updateUserInfo(@RequestBody UserInfo userInfo,@RequestHeader("Authorization") String token){
  7. //1、判断token是否合法
  8. boolean verifyToken = JwtUtils.verifyToken(token);
  9. if(!verifyToken){
  10. return ResponseEntity.status(401).body(null);
  11. }
  12. //2、获取用户id
  13. Claims claims = JwtUtils.getClaims(token);
  14. Integer id = (Integer) claims.get("id");
  15. //3、设置用户id
  16. userInfo.setId(Long.valueOf(id));
  17. userInfoService.update(userInfo);
  18. return ResponseEntity.ok(null);
  19. }

UserInfoService

  1. //更新
  2. public void update(UserInfo userInfo) {
  3. userInfoApi.update(userInfo);
  4. }

UserInfoApiImpl

  1. @Override
  2. public void update(UserInfo userInfo) {
  3. userInfoMapper.updateById(userInfo);
  4. }

3、统一token处理

3.1、代码存在的问题

3.2、解决方案

基于ThreadLocal + 拦截器的形式统一处理

a5c4701b20474a1faf6226c272370c7f.png

拦截器(Interceptor)

  • 是一种动态拦截方法调用的机制;
  • 类似于Servlet 开发中的过滤器Filter,用于对处理器进行前置处理和后置处理。

68fdfcdffb6946698c1d55b36a346f15.png

ThreadLocal

  • 线程内部的存储类,赋予了线程存储数据的能力。
  • 线程内调用的方法都可以从ThreadLocal中获取同一个对象。
  • 多个线程中ThreadLocal数据相互隔离

Threadlocal使用方法很简单

  1. ThreadLocal<T> threadLocal = new ThreadLocal<T>();
  2. threadLocal.set() //将数据绑定到当前线程
  3. threadLocal.get() //从当前线程中获取数据

3.3、代码实现

3.3.1、ThreadLocal工具类

定义ThreadLocal工具类,仅需要调用set方法即可将数据存入ThreadLocal中

  1. /**
  2. * 工具类:实现向threadlocal存储数据的方法
  3. */
  4. public class UserHolder {
  5. private static ThreadLocal<User> tl = new ThreadLocal<>();
  6. //将用户对象,存入Threadlocal
  7. public static void set(User user) {
  8. tl.set(user);
  9. }
  10. //从当前线程,获取用户对象
  11. public static User get() {
  12. return tl.get();
  13. }
  14. //从当前线程,获取用户对象的id
  15. public static Long getUserId() {
  16. return tl.get().getId();
  17. }
  18. //从当前线程,获取用户对象的手机号码
  19. public static String getMobile() {
  20. return tl.get().getMobile();
  21. }
  22. }

3.3.2、定义拦截器

定义拦截器,在前置拦截方法preHandle中解析token并验证有效性,如果失效返回状态码401。如果有效,解析User对象,存入ThreadLocal中

  1. public class TokenInterceptor implements HandlerInterceptor {
  2. @Override
  3. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  4. //1、获取请求头
  5. String token = request.getHeader("Authorization");
  6. //2、使用工具类,判断token是否有效
  7. boolean verifyToken = JwtUtils.verifyToken(token);
  8. //3、如果token失效,返回状态码401,拦截
  9. if(!verifyToken) {
  10. response.setStatus(401);
  11. return false;
  12. }
  13. //4、如果token正常可用,放行
  14. //解析token,获取id和手机号码,构造User对象,存入Threadlocal
  15. Claims claims = JwtUtils.getClaims(token);
  16. String mobile = (String) claims.get("mobile");
  17. Integer id = (Integer) claims.get("id");
  18. User user = new User();
  19. user.setId(Long.valueOf(id));
  20. user.setMobile(mobile);
  21. UserHolder.set(user);
  22. return true;
  23. }
  24. }

3.3.3、注册拦截器

拦截器需要注册到MVC容器中

  1. @Configuration
  2. public class WebConfig implements WebMvcConfigurer {
  3. @Override
  4. public void addInterceptors(InterceptorRegistry registry) {
  5. registry.addInterceptor(new TokenInterceptor())
  6. .addPathPatterns("/**")
  7. .excludePathPatterns(new String[]{"/user/login","/user/loginVerification"});
  8. }
  9. }

3.3.4、测试

修改UsersController方法,从ThreadLoca中获取用户数据

  1. /**
  2. * 查询用户资料
  3. */
  4. @GetMapping
  5. public ResponseEntity users(Long userID) {
  6. if(userID == null) {
  7. userID = UserHolder.getUserId();
  8. }
  9. UserInfoVo userInfo = userInfoService.findById(userID);
  10. return ResponseEntity.ok(userInfo);
  11. }

4、统一异常处理

软件开发过程中,不可避免的是需要处理各种异常,常见的形式就是逐层向上抛出,web层进行处理。使用try {…} catch {…}很方便就能对异常做到业务处理

  1. 冗余代码多,影响代码可读性
  2. 异常处理和业务代码耦合

4.1、解决方案

SpringMVC提供了一套解决全局异常的处理方案,可以在代码无侵入的前提下完成异常处理。遵循逐层抛出,异常处理器统一处理的思路

ea19c69996454f10bb11f2fd001dae54.png

4.2、代码实现

项目中可能存在不可预知的各种异常,如:空指针,数组越界等。针对这类异常,可以直接在异常处理器中统一处理;

还有一类是可预知的错误,如图片不合法,验证码错误等等。这类错误也可以理解为业务异常,可以通过自定义异常类来处理;

4.2.1、业务异常对象

为了方便操作,将一些常见的业务错误封装到ErrorResult对象中

  1. @Data
  2. @NoArgsConstructor
  3. @AllArgsConstructor
  4. @Builder
  5. public class ErrorResult {
  6. private String errCode = "999999";
  7. private String errMessage;
  8. public static ErrorResult error() {
  9. return ErrorResult.builder().errCode("999999").errMessage("系统异常稍后再试").build();
  10. }
  11. public static ErrorResult fail() {
  12. return ErrorResult.builder().errCode("000001").errMessage("发送验证码失败").build();
  13. }
  14. public static ErrorResult loginError() {
  15. return ErrorResult.builder().errCode("000002").errMessage("验证码失效").build();
  16. }
  17. public static ErrorResult faceError() {
  18. return ErrorResult.builder().errCode("000003").errMessage("图片非人像,请重新上传!").build();
  19. }
  20. public static ErrorResult mobileError() {
  21. return ErrorResult.builder().errCode("000004").errMessage("手机号码已注册").build();
  22. }
  23. public static ErrorResult contentError() {
  24. return ErrorResult.builder().errCode("000005").errMessage("动态内容为空").build();
  25. }
  26. public static ErrorResult likeError() {
  27. return ErrorResult.builder().errCode("000006").errMessage("用户已点赞").build();
  28. }
  29. public static ErrorResult disLikeError() {
  30. return ErrorResult.builder().errCode("000007").errMessage("用户未点赞").build();
  31. }
  32. public static ErrorResult loveError() {
  33. return ErrorResult.builder().errCode("000008").errMessage("用户已喜欢").build();
  34. }
  35. public static ErrorResult disloveError() {
  36. return ErrorResult.builder().errCode("000009").errMessage("用户未喜欢").build();
  37. }
  38. }

4.2.2 业务异常类

自定义业务异常类,针对业务错误之间抛出业务异常即可

  1. /**
  2. * 自定义异常类
  3. */
  4. @Data
  5. public class BusinessException extends RuntimeException {
  6. private ErrorResult errorResult;
  7. public BusinessException(ErrorResult errorResult) {
  8. super(errorResult.getErrMessage());
  9. this.errorResult = errorResult;
  10. }
  11. }

4.2.3、异常处理器

  1. /**
  2. * 自定义统一异常处理
  3. * 1、通过注解,声明异常处理类
  4. * 2、编写方法,在方法内部处理异常,构造响应数据
  5. * 3、方法上编写注解,指定此方法可以处理的异常类型
  6. */
  7. @ControllerAdvice
  8. public class ExceptionAdvice {
  9. //处理业务异常
  10. @ExceptionHandler(BusinessException.class)
  11. public ResponseEntity handlerException(BusinessException be) {
  12. be.printStackTrace();
  13. ErrorResult errorResult = be.getErrorResult();
  14. return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResult);
  15. }
  16. //处理不可预知的异常
  17. @ExceptionHandler(Exception.class)
  18. public ResponseEntity handlerException1(Exception be) {
  19. be.printStackTrace();
  20. return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ErrorResult.error());
  21. }
  22. }

发表评论

表情:
评论列表 (有 0 条评论,176人围观)

还没有评论,来说两句吧...

相关阅读