Public account: MarkerHub (pay attention to get more project resources)

Eblog codebase: github.com/markerhub/e…

Eblog project video: www.bilibili.com/video/BV1ri…


Development Document Catalog:

(Eblog) 1. Set up the project architecture and initialized the home page

(EBLOG) 2. Integrate Redis and project elegant exception handling and return result encapsulation

(eblog) 3, using Redis zset ordered set to achieve a hot feature of the week

(EBLOG) 4, customize Freemaker label to achieve blog homepage data filling

(Eblog) 5, blog classification filling, login registration logic

(EBLOG) 6. Set up blog publishing collection and user center

(eblog) 7, message asynchronous notification, details adjustment

8. Blog search engine development and background selection

(Eblog) 9. Instant group chat development, chat history, etc


Front and back end separation project vueblog please click here: super detailed! 4 hours to develop a SpringBoot+ Vue front and back separated blog project!!


1. Elegant exception handling

Sometimes the inevitable server error, if the exception handling mechanism is not configured, the default will return tomcat or nginx 5XX page, for ordinary users, not very friendly, users do not understand what the situation. At this time we need programmers to design a friendly and simple page to return to the user.

The treatment is as follows: ExceptionHandler(value = exception.class) is used to specify each type of Exception to be caught. This Exception is handled globally. All of these exceptions, they run to this place.

  • com.example.common.exception.GlobalExceptionHandler

  • com.example.common.exception.HwException

Step 1: First, we define a HwException and need to inherit RuntimeException, so that the transaction will be involved in the rollback. HwException will be reported when our system catches an error.

public class HwException extends RuntimeException {
    private int code;
    public HwException() {}
    public HwException(int code) {
        this.code = code;
    }
    public HwException(String message) {
        super(message);
    }
    public HwException(int code, String message) {
        super(message);
        this.code = code;
    }
    public int getCode() {
        return code;
    }
    public void setCode(int code) { this.code = code; }}Copy the code

Step 2. Define the global exception handling. @ControllerAdvice indicates the global controller exception handling, and @ExceptionHandler indicates the specific exception handling.

@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(value = Exception.class)
    public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) {
        log.error("------------------> Global exception caught", e);
        if(e instanceof HwException) {
            //...
        }
        ModelAndView mav = new ModelAndView();
        mav.addObject("exception", e);
        mav.addObject("message", e.getMessage());
        mav.addObject("url", req.getRequestURL());
        mav.setViewName("error");
        return mav;
    }
    @ExceptionHandler(value = HwException.class)
    @ResponseBody
    public Result jsonErrorHandler(HttpServletRequest req, HwException e) {
        return Result.fail(e.getMessage(), "some error data"); }}Copy the code

Step 3. Define the error page. When I open the Layui page, there is a tips. FTL page that matches our exception page. Can be used to display exceptions.

  • templates/error.ftl
<#include "/inc/layout.ftl"/>
<@layout "Home page">
    <#include "/inc/header-panel.ftl" />
    <div class="layui-container fly-marginTop">
        <div class="fly-panel">
            <div class="fly-none">
                <h2><i class="iconfont icon-tishilian"></i></h2>
                <p>${message}</p>
            </div>
        </div>
    </div>
</@layout>

Copy the code

2. Uniform result return encapsulation (asynchronous return)

Above we used a Result class that encapsulates the Result returned by our asynchronous uniform. In general, there are several elements necessary for a result

  • Code can be used to indicate success (for example, 0 indicates success and -1 indicates exception).

  • Result message

  • The resulting data

Therefore, encapsulation can be obtained as follows:

  • com.example.common.lang.Result
@Data
public class Result implements Serializable {
    private String code;
    private String msg;
    private Object data;
    public static Result succ(Object data) {
        Result m = new Result();
        m.setCode("0");
        m.setData(data);
        m.setMsg("Operation successful");
        return m;
    }
    public static Result succ(String mess, Object data) {
        Result m = new Result();
        m.setCode("0");
        m.setData(data);
        m.setMsg(mess);
        return m;
    }
    public static Result fail(String mess) {
        Result m = new Result();
        m.setCode("1");
        m.setData(null);
        m.setMsg(mess);
        return m;
    }
    public static Result fail(String mess, Object data) {
        Result m = new Result();
        m.setCode("1");
        m.setData(data);
        m.setMsg(mess);
        returnm; }}Copy the code

3. Integrate Redis

In the Redis course, we have demonstrated the master/slave and Sentinel configuration of Redis. In the highly available Redis cluster, it can help us complete the main library offline and automatic switch between the secondary libraries.

Integrate into SpringBoot

First, import the POM package of Redis

<! --redis--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>Copy the code

Step 2: Configure redis connection information

Spring: redis: sentinel: master: mymaster nodes: 47.106.38.101:26379,47.106. 38.101:26380Copy the code

The above two Redis is my own Ali cloud configuration, you can use, you can also configure a. As such, Redis has been integrated into our SpringBoot project.

The above is the sentinel configuration, if the single redis, the configuration is also simple:

spring:
  redis:
    host: localhost
    port: 6379

Copy the code

The third step, in order to let us to redis cache data can be easier to understand, in here, in a way of serialization, the default is JDK serialization way, choose jackson2JsonRedisSerializer here. You just need to override how the redisTemplate action template is generated. Create a new config package and place it under it.

@Configuration
public class RedisConfiguration {
    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        RedisTemplate<Object, Object> template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        jackson2JsonRedisSerializer.setObjectMapper(new ObjectMapper());
        template.setKeySerializer(jackson2JsonRedisSerializer);
        template.setValueSerializer(jackson2JsonRedisSerializer);
        returntemplate; }}Copy the code

The fourth step, using redisTemplate to manipulate data is relatively troublesome, we use an util wrapper class, which makes it more convenient to operate redis. Under the utils package RedisUtil. Java (uploader. Shimo. Im/f/HTgtITdNf…

At this point, we have integrated the utility classes and configurations that can operate Redis. We will explain this separately later when we need to use cached annotations.

There are a lot of things you can use with redis, like our sidebar hot talk feature and our Cacheable annotation. However, with Redis cache annotations, you will find that you cannot set a cache expiration time for annotations. To solve this problem, we introduced Redission.

Start with our caching annotations and add a configuration WebMvcConfig. Plus the enable annotation @enablecaching. As follows:

@EnableCaching
@Configuration
publicclassWebMvcConfig{
}

Copy the code

Next, introduce redission, which is actually very simple, first introduce JAR package:

<! -- redission --> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson-spring-boot-starter</artifactId> The < version > 3.10.6 < / version > < / dependency >Copy the code

Redission also introduces the spring-boot-starter-data-redis package, so configuring redis properties is the same as importing redis. Therefore, after importing jar packages, We can use redission functions, such as make distributed lock, to cache annotation an expiration time, etc. Ok, about redis module said here, let’s go to fill the home page data first.

(after)

MarkerHub Article Index:

Github.com/MarkerHub/J…