查看原文
其他

整合Redis,以及项目优雅的异常处理与返回结果封装

吕一明 MarkerHub 2022-11-04

小Hub领读:

继续弄我们的开源项目eblog,今天,内容比较简单,我们先来弄一下基础的东西,异常处理与返回结果封装类的编写。


项目名称:eblog

项目Git仓库:https://github.com/MarkerHub/eblog(给个star支持哈)

前几篇文章:

1、Github上最值得学习的Springboot开源博客项目!

2、小Hub手把手教你如何从0搭建一个开源项目架构


1. 优雅的异常处理

有时候不可避免服务器报错的情况,如果不配置异常处理机制,就会默认返回tomcat或者nginx的5XX页面,对普通用户来说,不太友好,用户也不懂什么情况。这时候需要我们程序员设计返回一个友好简单的页面给用户。

处理办法如下:通过使用@ControllerAdvice来进行统一异常处理,@ExceptionHandler(value = Exception.class)来指定捕获的Exception各个类型异常 ,这个异常的处理,是全局的,所有类似的异常,都会跑到这个地方处理。

  • com.example.common.exception.GlobalExceptionHandler

  • com.example.common.exception.HwException

步骤一、首先我们自定义一个异常HwException,需要继承RuntimeException,这样涉及到事务时候才会有回滚。HwException将作为我们系统catch到错误时候报出来的异常。

  1. public class HwException extends RuntimeException {


  2. private int code;


  3. public HwException() {}


  4. public HwException(int code) {

  5. this.code = code;

  6. }


  7. public HwException(String message) {

  8. super(message);

  9. }


  10. public HwException(int code, String message) {

  11. super(message);

  12. this.code = code;

  13. }


  14. public int getCode() {

  15. return code;

  16. }


  17. public void setCode(int code) {

  18. this.code = code;

  19. }

  20. }

步骤二、定义全局异常处理,@ControllerAdvice表示定义全局控制器异常处理,@ExceptionHandler表示针对性异常处理,可对每种异常针对性处理。

  1. @Slf4j

  2. @ControllerAdvice

  3. public class GlobalExceptionHandler {


  4. @ExceptionHandler(value = Exception.class)

  5. public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) {


  6. log.error("------------------>捕捉到全局异常", e);


  7. if(e instanceof HwException) {

  8. //...

  9. }


  10. ModelAndView mav = new ModelAndView();

  11. mav.addObject("exception", e);

  12. mav.addObject("message", e.getMessage());

  13. mav.addObject("url", req.getRequestURL());

  14. mav.setViewName("error");

  15. return mav;

  16. }


  17. @ExceptionHandler(value = HwException.class)

  18. @ResponseBody

  19. public Result jsonErrorHandler(HttpServletRequest req, HwException e) {

  20. return Result.fail(e.getMessage(), "some error data");

  21. }


  22. }

步骤三、定义异常error页面。打开layui页面,有个tips.ftl的页面比较符合我们的异常页面。可用于展示异常。

  • templates/error.ftl

  1. <#include "/inc/layout.ftl"/>


  2. <@layout "首页">


  3. <#include "/inc/header-panel.ftl" />


  4. <div class="layui-container fly-marginTop">

  5. <div class="fly-panel">

  6. <div class="fly-none">

  7. <h2><i class="iconfont icon-tishilian"></i></h2>

  8. <p>${message}</p>

  9. </div>

  10. </div>

  11. </div>


  12. </@layout>

2. 统一的结果返回封装(异步返回)

上面我们用到了一个Result的类,这个用于我们的异步统一返回的结果封装。一般来说,结果里面有几个要素必要的

  • 是否成功,可用code表示(如0表示成功,-1表示异常)

  • 结果消息

  • 结果数据

所以可得到封装如下:

  • com.example.common.lang.Result

  1. @Data

  2. public class Result implements Serializable {


  3. private String code;

  4. private String msg;

  5. private Object data;


  6. public static Result succ(Object data) {

  7. Result m = new Result();

  8. m.setCode("0");

  9. m.setData(data);

  10. m.setMsg("操作成功");

  11. return m;

  12. }


  13. public static Result succ(String mess, Object data) {

  14. Result m = new Result();

  15. m.setCode("0");

  16. m.setData(data);

  17. m.setMsg(mess);


  18. return m;

  19. }


  20. public static Result fail(String mess) {

  21. Result m = new Result();

  22. m.setCode("-1");

  23. m.setData(null);

  24. m.setMsg(mess);


  25. return m;

  26. }


  27. public static Result fail(String mess, Object data) {

  28. Result m = new Result();

  29. m.setCode("-1");

  30. m.setData(data);

  31. m.setMsg(mess);


  32. return m;

  33. }

  34. }


3、集成redis

在redis课程中,我们演示过redis的主从、还有哨兵配置,高可用的redis集群中,可以帮我们完成主库下线,从库自动切换的功能。

集成到springboot中

第一步、导入redis的pom包

  1. <!--redis-->

  2. <dependency>

  3. <groupId>org.springframework.boot</groupId>

  4. <artifactId>spring-boot-starter-data-redis</artifactId>

  5. </dependency>

第二步、配置redis的连接信息

  1. spring:

  2. redis:

  3. sentinel:

  4. master: mymaster

  5. nodes: 47.106.38.101:26379,47.106.38.101:26380

以上的两个redis是我自己的阿里云上配置,大家可以用,也可以自己配置一个。 致此,redis已经集成到我们的springboot项目中了。

以上是哨兵的配置,如果单机redis的话,配置也简单:

  1. spring:

  2. redis:

  3. host: localhost

  4. port: 6379

第三步、为了让我们的存到redis中的缓存数据能更加容易看懂,这里换一种序列化方式,默认的是jdk的序列化方式,这里选用jackson2JsonRedisSerializer。只需要重写redisTemplate操作模板的生成方式即可。新建一个config包,放在这个包下。

  1. @Configuration

  2. public class RedisConfiguration {

  3. @Bean

  4. public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {

  5. RedisTemplate<Object, Object> template = new RedisTemplate();

  6. template.setConnectionFactory(redisConnectionFactory);

  7. Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);

  8. jackson2JsonRedisSerializer.setObjectMapper(new ObjectMapper());

  9. template.setKeySerializer(jackson2JsonRedisSerializer);

  10. template.setValueSerializer(jackson2JsonRedisSerializer);

  11. return template;

  12. }

  13. }

第四步、使用redisTemplate操作数据相对比较麻烦,我们使用一个util封装类,让我们操作redis更加方便。放在utils包下 RedisUtil.java(https://uploader.shimo.im/f/HTgtITdNfuklQepB.java)

至此,能操作redis的工具类和配置我们已经集成进来。后面我们需要用到缓存注解的时候我们再单独说明。

集成redis之后可以使用的地方又很多,比如我们的侧边栏热议功能,还有我们的缓存注解Cacheable等。但是使用了redis的缓存注解,你会发现不能给注解设定一个缓存过期时间,为了解决这个问题,我们引入redission。

首先开启一下我们的缓存注解功能,添加一个配置WebMvcConfig 。加上开启注解@EnableCaching。如下:

  1. @EnableCaching

  2. @Configuration

  3. publicclassWebMvcConfig{

  4. }

接下来,引入redission,其实很简单,首先引入jar包:

  1. <!-- redission -->

  2. <dependency>

  3. <groupId>org.redisson</groupId>

  4. <artifactId>redisson-spring-boot-starter</artifactId>

  5. <version>3.10.6</version>

  6. </dependency>

因为redission其实也有引入spring-boot-starter-data-redis包,所以配置redis的属性其实和引入redis是一样的的,因此,引入了jar包之后,我们就可以使用redission功能了,比如做分布式锁、给缓存注解一个过期时间等 ok、关于 redis模块就说到这里,下面我们去填充一下首页的数据先。

(完)

MarkerHub文章索引:

https://github.com/MarkerHub/JavaIndex


【项目相关文章】

1、Github上最值得学习的Springboot开源博客项目!

2、小Hub手把手教你如何从0搭建一个开源项目架构




 给eblog一个star,感谢支持哈

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存