Springboot integrates redis, mybatis-plus and websocket exception framework code encapsulation

In the process of software development, a well-encapsulated, concise and elegant Family Bucket framework can greatly improve the work efficiency of developers, while also reducing the complexity of the code and making it easier to maintain in the future. The source code involved in this article is at the end of the article, with a download link.

The encapsulated framework involved in this article can be directly used for project development.

What elements do we need to consider when integrating software development frameworks:

1. What technologies are used?

2. Processing of exception information

3. When printing logs, it is best to print sql logs with parameters (sql with parameters in non-question mark form). This framework prints sql with parameters to facilitate debugging.

4. The interface returns the data format encapsulation (look down on some garbage encapsulation)

This blog post is mainly divided into five parts, including the use of websocket, the use of mybatis-plus, the use of redis, how to use exception information, and log printing (the focus is on printing SQL statements with parameters to facilitate development and debugging)

1. Integration of Websockt
1. Initialization configuration
@Configuration
public class WebSocketConfig {
    /**
     * Will automatically register the Websocket endpoint declared using the @ServerEndpoint annotation
     * Please note that if you use a separate servlet container,
     * Instead of using springboot's built-in container directly,
     * Just don't inject ServerEndpointExporter, because it will be provided and managed by the container itself.
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}
2. The server receives messages
@Slf4j
@Component
@ServerEndpoint(value = "/websocket")
public class WebsocketGet {

    /**
     * Connect events and add comments
     * @param session
     */
    @OnOpen
    public void onOpen(Session session) {
        String orderId = WebsocketSend.getParam(WebsocketSend.sessionKey, session);
        log.info("Websocket connection has been opened, the current orderId is:" + orderId);
        //Add to session mapping relationship
        WebsocketSend.addSession(orderId, session);
        //Test sending message
        WebsocketSend.sendMessage(orderId, WsResultVo.success("Congratulations, the connection has been established"));
    }
    /**
     * 1. websocker (2) receives messages uploaded by client users
     * @param session
     */
    @OnMessage
    public void onMessage(Session session, String message) {
        log.info("Websocket message received:" + message);
    }
    /**
     * Connect events and add comments
     * User disconnects link
     *
     * @param session
     */
    @OnClose
    public void onClose(Session session) {
        String orderId = WebsocketSend.getParam(WebsocketSend.sessionKey, session);
        //Delete mapping relationship
        WebsocketSend.removeSession(orderId);
    }

    /**
     * Handle user live connection exceptions
     *
     * @param session
     * @param throwable
     */
    @OnError
    public void onError(Session session, Throwable throwable) {
        try {
            if (session.isOpen()) {
                session.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        throwable.printStackTrace();
    }
}
3. Send message to client
/**
 * Websocket tool class
 * Record the current online link and operate the link
 */
public class WebsocketSend {
    /**
     * Log information
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(WebsocketSend.class);
    /**
     * Record the current online Session
     */
    private static final Map<String, Session> ONLINE_SESSION = new ConcurrentHashMap<>();
    public static final String sessionKey = "orderId";

    /**
     * Add session
     *
     * @param userId
     * @param session
     */
    public static void addSession(String userId, Session session) {
        //Only one user's session link is allowed here. Multiple connections from one user are considered invalid by us.
        ONLINE_SESSION.putIfAbsent(userId, session);
    }

    /**
     * Close session
     *
     * @param userId
     */
    public static void removeSession(String userId) {
        ONLINE_SESSION.remove(userId);
    }

    /**
     * Push messages to a single user
     *
     * @param session
     * @param message
     */
    public static void sendMessage(Session session, String message) {
        if (session == null) {
            return;
        }

        // Synchronize
        RemoteEndpoint.Async async = session.getAsyncRemote();
        async.sendText(message);
    }

    /**
     * Send message to everyone online
     *
     * @param message
     */
    public static void sendMessageForAll(String message) {
        //jdk8 new method
        ONLINE_SESSION.forEach((sessionId, session) -> {
            if (session.isOpen()) {
                sendMessage(session, message);
            }
        });
    }

    /**
     * Send message based on user ID
     *
     * @param result
     */
    public static void sendMessage(String sessionId, WsResultVo result) {
        sendMessage(sessionId, JSON.toJSONString(result));
    }

    /**
     * Send message based on user ID
     *
     * @param message
     */
    public static void sendMessage(String sessionId, String message) {
        Session session = ONLINE_SESSION.get(sessionId);
        //Determine whether the user's session exists and whether it is still online
        if (session == null || !session.isOpen()) {
            return;
        }
        sendMessage(session, message);
    }

    /**
     * Get Session based on ID
     *
     * @param sessionId
     */
    public static Session getSession(String sessionId) {
        Session session = ONLINE_SESSION.get(sessionId);
        return session;
    }

    /**
     * Get the parameters in the session based on the passed key
     * @param key
     * @param session
     * @return
     */
    public static String getParam(String key, Session session) {
        Map map = session.getRequestParameterMap();
        Object userId1 = map.get(key);
        if (userId1 == null) {
            return null;
        }

        String s = userId1.toString();
        s = s.replaceAll("\[", "").replaceAll("]", "");

        if (!StringUtils.isEmpty(s)) {
            return s;
        }
        return null;
    }

}
4, websocket test (we use apifox software for the client and download it from Baidu)

First start the server, run ServerApplication.java, then apifox, click to connect to the server, as shown in the screenshot below

Click [Connect] to request the address: ws://127.0.0.1:8080/ck/websocket?orderId=123456. Note that the parameter orderId is required.

(1) The client apifox sends a message to the server

(2) The server sends a message to the client and opens the swagger address: http://localhost:8080/ck/swagger-ui.html

The backend interface is called through swagger, the backend receives the interface request, and then sends a message to the websocket client.

2. Integration of Mybatis-plus
1. Initialization configuration
@Configuration
@MapperScan("com.ck.server.web.mapper")
public class MybatisPlusConfig {
    /**
     * Add paging plugin
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));//If you configure multiple plug-ins, remember to add pagination last
        //interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); If there are multiple data sources, you do not need to match the specific type. Otherwise, it is recommended to match the specific DbType.
        return interceptor;
    }
}
2. Use of interfaces

Open swagger address: http://localhost:8080/ck/swagger-ui.html

3. Add, delete, check and save mybatis-pluse

controller part

@GetMapping("/mybatis-plus/getPage")
    @ApiOperation("2. Mybatis-plus query (1) paging query")
    public PageBeanVo<User> getPage(UserParam param) {
        PageBeanVo pageBeanVo = userService.getPage(param);
        return pageBeanVo;
    }

    @PostMapping("/mybatis-plus/save")
    @ApiOperation("2. Mybatis-plus query (2) save")
    public ResultInfoVo save(String name,Integer age,String email) {
        User user = new User();
        user.setName(name);
        user.setAge(age);
        user.setEmail(email);
        userService.save(user);
        return new ResultInfoVo();
    }

    @GetMapping("/mybatis-plus/getById")
    @ApiOperation("2. Mybatis-plus query (3) query based on id")
    public ResultInfoVo<User> getById(Integer id) {
        User user = userService.getById(id);
        return new ResultInfoVo(user);
    }

    @DeleteMapping("/mybatis-plus/deleteById")
    @ApiOperation("2. Mybatis-plus query (4) Delete according to id")
    public ResultInfoVo<User> deleteById(Integer id) {
         userService.deleteById(id);
        return new ResultInfoVo();
    }

service part

@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
    /**
     * Query based on id
     * @param id
     * @return
     */
    public User getById(Integer id){
        return userMapper.selectById(id);
    }
    /**
     * Paging query
     * @param param
     * @return
     */
    public PageBeanVo<User> getPage(UserParam param){
        IPage<User> page = userMapper.getPage(param);
        System.out.println(page);
        return new PageBeanVo(page.getTotal(),page.getRecords());
    }
    /**
     * Guaranteed
     * @param user
     */
    @Transactional
    public void save(User user){
        userMapper.insert(user);
    }
    /**
     * Guaranteed
     * @param id
     */
    @Transactional
    public void deleteById(Integer id){
        userMapper.deleteById(id);
    }
}

mapper part

public interface UserMapper extends BaseMapper<User> {
    /**
     * Paging query
     * @param pageParam
     * @return
     */
    IPage<User> getPage(IPage pageParam);
}

The xml part corresponding to the mapper

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ck.server.web.mapper.UserMapper">
    <select id="getPage" resultType="com.ck.server.web.model.User">
        SELECT * FROM user WHERE 1=1
        <if test="id!= null and id!= ''">
            and id =#{id}
        </if>
        <if test="name!= null and name!= ''">
            and name like concat('%',#{name},'%')
        </if>
    </select>
</mapper>

Here is a screenshot of the paging query:

3. redis integration
1. Initialization configuration
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Serializable> redisTemplate(LettuceConnectionFactory connectionFactory) {
RedisTemplate<String, Serializable> redisTemplate = new RedisTemplate<>();
// redisTemplate.setKeySerializer(new StringRedisSerializer());
// redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
RedisSerializer stringSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);

redisTemplate.setKeySerializer(stringSerializer);
redisTemplate.setHashKeySerializer(stringSerializer);

redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setConnectionFactory(connectionFactory);
return redisTemplate;
}
}
2. Use of redis
@PostMapping("/redis/redisSave")
    @ApiOperation("3. Redis cache (1) saved to redis")
    public ResultInfoVo<User> redisSave(String key,String value) {
        redisService.addString(key,value);
        return new ResultInfoVo();
    }

    @GetMapping("/redis/redisFind")
    @ApiOperation("3. redis cache (2) query redis")
    public ResultInfoVo<User> redisFind(String key) {
        String value = redisService.getString(key);
        return new ResultInfoVo(value);
    }

3. Save and query screenshots

4. Abnormal information

The exception information structure is consistent with the data structure returned by the interface data.

For example, the structure returned by the interface is as follows

1. Encapsulation object
@ToString
@ApiModel()
public class ResultInfoVo<T> {

    public static final String SUCCESS="success";
    public static final String FAILED="failed";

    @ApiModelProperty(value = "Business code: success is success, failure is other services, such as roleIdIsNull")
    private String code="success";//The business code is success for success and other business numbers for failure, such as paramIsNull
    @ApiModelProperty(value = "Description information")
    private String message="Processing successfully";//Description information
    @ApiModelProperty(value = "Business Data")
    public T data; //Page data


    public ResultInfoVo(){}

    public ResultInfoVo(T data) {
        this.data = data;
    }

    public ResultInfoVo(String message,T data) {
        this.message = message;
        this.data = data;
    }

    public ResultInfoVo(String code, String message) {
        this.code = code;
        this.message = message;
    }

    public ResultInfoVo(String code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }
}

Object returned by exception information

public class CKException extends RuntimeException {
    private Log logger = LogFactory.getLog(getClass());
    @ApiModelProperty(value = "Business code: Chengdu is success, failure is other services, such as roleIdIsNull")
    private String code; //Business error code
    @ApiModelProperty(value = "Description information")
    private String message;//error details
    @ApiModelProperty(value = "Other data")
    private Object data;//Other data


    public CKException(String code, String message) {
        this.code = code;
        this.message = message;
        this.data=data;
    }


    public CKException(String code, String message, Object data) {
        this.code = code;
        this.message = message;
        this.data=data;
    }
}

2. Use:

5. Encapsulation of interface return data format
package com.ck.server.web.model.vo;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.ToString;

/**
 * Created by Administrator on 2018/7/2.
 */
@ToString
@ApiModel()
public class ResultInfoVo<T> {

    public static final String SUCCESS="success";
    public static final String FAILED="failed";

    @ApiModelProperty(value = "Business code: success is success, failure is other services, such as roleIdIsNull")
    private String code="success";//The business code is success for success and other business numbers for failure, such as paramIsNull
    @ApiModelProperty(value = "Description information")
    private String message="Processing successfully";//Description information
    @ApiModelProperty(value = "Business Data")
    public T data; //Page data


    public ResultInfoVo(){}

    public ResultInfoVo(T data) {
        this.data = data;
    }

    public ResultInfoVo(String message,T data) {
        this.message = message;
        this.data = data;
    }

    public ResultInfoVo(String code, String message) {
        this.code = code;
        this.message = message;
    }

    public ResultInfoVo(String code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}
6. Source code download:

Link: https://pan.baidu.com/s/16snuaL2X3oPelNm6uSMv4Q?pwd=dy7p
Extraction code: dy7p