• Springboot集成redis和mybatis-plus及websocket异常框架代码封装


    软件开发过程中,一款封装完善简洁大气的全家桶框架,能大大提升开发人员的工作效率,同时还能降低代码的复杂程序,也便于后期方便维护。本文所涉及源代码在文章最后,有下载链接。

    本文章所涉及封装的框架,可直接用于项目开发

    在集成软件开发框架时,我们需要考虑哪些要素:

    1、用哪些技术

    2、异常信息的处理

    3、日志的打印,最好是能带参数打印sql日志(非问号形式的带参sql),本框架就是带参数打印sql,方便调试

    4、接口返回数据格式的封装(瞧不起一些垃圾封装)

    本博文主要分五大块讲解,分别为websocket的使用、mybatis-plus的使用、redis的使用、异常信息怎么使用、日志打印(重点是带参数打印sql语句,方便开发调式)

    一、Websockt的集成
    1、初始化配置
    1. @Configuration
    2. public class WebSocketConfig {
    3. /**
    4. * 会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint
    5. * 要注意,如果使用独立的servlet容器,
    6. * 而不是直接使用springboot的内置容器,
    7. * 就不要注入ServerEndpointExporter,因为它将由容器自己提供和管理。
    8. */
    9. @Bean
    10. public ServerEndpointExporter serverEndpointExporter() {
    11. return new ServerEndpointExporter();
    12. }
    13. }
    2、服务端收消息
    1. @Slf4j
    2. @Component
    3. @ServerEndpoint(value = "/websocket")
    4. public class WebsocketGet {
    5. /**
    6. * 连接事件,加入注解
    7. * @param session
    8. */
    9. @OnOpen
    10. public void onOpen(Session session) {
    11. String orderId = WebsocketSend.getParam(WebsocketSend.sessionKey, session);
    12. log.info("Websocket连接已打开,当前orderId为:"+orderId);
    13. // 添加到session的映射关系中
    14. WebsocketSend.addSession(orderId, session);
    15. //测试发送消息
    16. WebsocketSend.sendMessage(orderId, WsResultVo.success("恭喜,已建立连接"));
    17. }
    18. /**
    19. * 一、websocker (2)接收到客户端用户上传的消息
    20. * @param session
    21. */
    22. @OnMessage
    23. public void onMessage(Session session, String message) {
    24. log.info("收到Websocket消息:"+message);
    25. }
    26. /**
    27. * 连接事件,加入注解
    28. * 用户断开链接
    29. *
    30. * @param session
    31. */
    32. @OnClose
    33. public void onClose(Session session) {
    34. String orderId = WebsocketSend.getParam(WebsocketSend.sessionKey, session);
    35. // 删除映射关系
    36. WebsocketSend.removeSession(orderId);
    37. }
    38. /**
    39. * 处理用户活连接异常
    40. *
    41. * @param session
    42. * @param throwable
    43. */
    44. @OnError
    45. public void onError(Session session, Throwable throwable) {
    46. try {
    47. if (session.isOpen()) {
    48. session.close();
    49. }
    50. } catch (IOException e) {
    51. e.printStackTrace();
    52. }
    53. throwable.printStackTrace();
    54. }
    55. }
    3、向客户端发送消息
    1. /**
    2. * Websocket工具类
    3. * 记录当前在线的链接对链接进行操作
    4. */
    5. public class WebsocketSend {
    6. /**
    7. * 日志信息
    8. */
    9. private static final Logger LOGGER = LoggerFactory.getLogger(WebsocketSend.class);
    10. /**
    11. * 记录当前在线的Session
    12. */
    13. private static final Map<String, Session> ONLINE_SESSION = new ConcurrentHashMap<>();
    14. public static final String sessionKey = "orderId";
    15. /**
    16. * 添加session
    17. *
    18. * @param userId
    19. * @param session
    20. */
    21. public static void addSession(String userId, Session session) {
    22. // 此处只允许一个用户的session链接。一个用户的多个连接,我们视为无效。
    23. ONLINE_SESSION.putIfAbsent(userId, session);
    24. }
    25. /**
    26. * 关闭session
    27. *
    28. * @param userId
    29. */
    30. public static void removeSession(String userId) {
    31. ONLINE_SESSION.remove(userId);
    32. }
    33. /**
    34. * 给单个用户推送消息
    35. *
    36. * @param session
    37. * @param message
    38. */
    39. public static void sendMessage(Session session, String message) {
    40. if (session == null) {
    41. return;
    42. }
    43. // 同步
    44. RemoteEndpoint.Async async = session.getAsyncRemote();
    45. async.sendText(message);
    46. }
    47. /**
    48. * 向所有在线人发送消息
    49. *
    50. * @param message
    51. */
    52. public static void sendMessageForAll(String message) {
    53. //jdk8 新方法
    54. ONLINE_SESSION.forEach((sessionId, session) -> {
    55. if (session.isOpen()) {
    56. sendMessage(session, message);
    57. }
    58. });
    59. }
    60. /**
    61. * 根据用户ID发送消息
    62. *
    63. * @param result
    64. */
    65. public static void sendMessage(String sessionId, WsResultVo result) {
    66. sendMessage(sessionId, JSON.toJSONString(result));
    67. }
    68. /**
    69. * 根据用户ID发送消息
    70. *
    71. * @param message
    72. */
    73. public static void sendMessage(String sessionId, String message) {
    74. Session session = ONLINE_SESSION.get(sessionId);
    75. //判断是否存在该用户的session,判断是否还在线
    76. if (session == null || !session.isOpen()) {
    77. return;
    78. }
    79. sendMessage(session, message);
    80. }
    81. /**
    82. * 根据ID获取Session
    83. *
    84. * @param sessionId
    85. */
    86. public static Session getSession(String sessionId) {
    87. Session session = ONLINE_SESSION.get(sessionId);
    88. return session;
    89. }
    90. /**
    91. * 根据传过来的key获取session中的参数
    92. * @param key
    93. * @param session
    94. * @return
    95. */
    96. public static String getParam(String key, Session session) {
    97. Map map = session.getRequestParameterMap();
    98. Object userId1 = map.get(key);
    99. if (userId1 == null) {
    100. return null;
    101. }
    102. String s = userId1.toString();
    103. s = s.replaceAll("\\[", "").replaceAll("]", "");
    104. if (!StringUtils.isEmpty(s)) {
    105. return s;
    106. }
    107. return null;
    108. }
    109. }
    4,websocket测试(客户端我们用apifox软件,自行百度下载)

    先启动服务端,运行ServerApplication.java,然后apifox,点击连接服务器,如下截图

    点击【连接】请求地址:ws://127.0.0.1:8080/ck/websocket?orderId=123456,注意参数orderId必填

    (1)客户端apifox向服务端发送消息

    (2)服务器端向客户端发送消息,打开swagger地址:http://localhost:8080/ck/swagger-ui.html

    通过swagger调用后端接口,后端收到接口请求,再向websocket客户端发送消息

    二、Mybatis-plus的集成
    1、初始化配置
    1. @Configuration
    2. @MapperScan("com.ck.server.web.mapper")
    3. public class MybatisPlusConfig {
    4. /**
    5. * 添加分页插件
    6. */
    7. @Bean
    8. public MybatisPlusInterceptor mybatisPlusInterceptor() {
    9. MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    10. interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));//如果配置多个插件,切记分页最后添加
    11. //interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); 如果有多数据源可以不配具体类型 否则都建议配上具体的DbType
    12. return interceptor;
    13. }
    14. }
    2、接口的使用

     打开swagger地址:http://localhost:8080/ck/swagger-ui.html

    3、mybatis-pluse的增、删、查、保存

    controller部分

    1. @GetMapping("/mybatis-plus/getPage")
    2. @ApiOperation("二、Mybatis-plus查询(1)分页查询")
    3. public PageBeanVo<User> getPage(UserParam param) {
    4. PageBeanVo pageBeanVo = userService.getPage(param);
    5. return pageBeanVo;
    6. }
    7. @PostMapping("/mybatis-plus/save")
    8. @ApiOperation("二、Mybatis-plus查询(2)保存")
    9. public ResultInfoVo save(String name,Integer age,String email) {
    10. User user = new User();
    11. user.setName(name);
    12. user.setAge(age);
    13. user.setEmail(email);
    14. userService.save(user);
    15. return new ResultInfoVo();
    16. }
    17. @GetMapping("/mybatis-plus/getById")
    18. @ApiOperation("二、Mybatis-plus查询(3)根据id查询")
    19. public ResultInfoVo<User> getById(Integer id) {
    20. User user = userService.getById(id);
    21. return new ResultInfoVo(user);
    22. }
    23. @DeleteMapping("/mybatis-plus/deleteById")
    24. @ApiOperation("二、Mybatis-plus查询(4)根据id删除")
    25. public ResultInfoVo<User> deleteById(Integer id) {
    26. userService.deleteById(id);
    27. return new ResultInfoVo();
    28. }

    service部分

    1. @Service
    2. public class UserService {
    3. @Autowired
    4. private UserMapper userMapper;
    5. /**
    6. * 根据id查询
    7. * @param id
    8. * @return
    9. */
    10. public User getById(Integer id){
    11. return userMapper.selectById(id);
    12. }
    13. /**
    14. * 分页查询
    15. * @param param
    16. * @return
    17. */
    18. public PageBeanVo<User> getPage(UserParam param){
    19. IPage<User> page = userMapper.getPage(param);
    20. System.out.println(page);
    21. return new PageBeanVo(page.getTotal(),page.getRecords());
    22. }
    23. /**
    24. * 保付
    25. * @param user
    26. */
    27. @Transactional
    28. public void save(User user){
    29. userMapper.insert(user);
    30. }
    31. /**
    32. * 保付
    33. * @param id
    34. */
    35. @Transactional
    36. public void deleteById(Integer id){
    37. userMapper.deleteById(id);
    38. }
    39. }

    mapper部分

    1. public interface UserMapper extends BaseMapper<User> {
    2. /**
    3. * 分页查询
    4. * @param pageParam
    5. * @return
    6. */
    7. IPage<User> getPage(IPage pageParam);
    8. }

    mapper对应的xml的部分

    1. "1.0" encoding="UTF-8"?>
    2. mapper
    3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    5. <mapper namespace="com.ck.server.web.mapper.UserMapper">
    6. <select id="getPage" resultType="com.ck.server.web.model.User">
    7. SELECT * FROM user WHERE 1=1
    8. <if test="id!= null and id!= ''">
    9. and id =#{id}
    10. if>
    11. <if test="name!= null and name!= ''">
    12. and name like concat('%',#{name},'%')
    13. if>
    14. select>
    15. mapper>

    来个分页查询的截图:

    三、redis集成
    1、初始化配置
    1. @Configuration
    2. public class RedisConfig {
    3. @Bean
    4. public RedisTemplate<String, Serializable> redisTemplate(LettuceConnectionFactory connectionFactory) {
    5. RedisTemplate<String, Serializable> redisTemplate = new RedisTemplate<>();
    6. // redisTemplate.setKeySerializer(new StringRedisSerializer());
    7. // redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
    8. RedisSerializer stringSerializer = new StringRedisSerializer();
    9. Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
    10. ObjectMapper om = new ObjectMapper();
    11. om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    12. om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    13. jackson2JsonRedisSerializer.setObjectMapper(om);
    14. redisTemplate.setKeySerializer(stringSerializer);
    15. redisTemplate.setHashKeySerializer(stringSerializer);
    16. redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
    17. redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
    18. redisTemplate.setConnectionFactory(connectionFactory);
    19. return redisTemplate;
    20. }
    21. }
    2、redis的使用
    1. @PostMapping("/redis/redisSave")
    2. @ApiOperation("三、redis缓存(1)保存到redis")
    3. public ResultInfoVo<User> redisSave(String key,String value) {
    4. redisService.addString(key,value);
    5. return new ResultInfoVo();
    6. }
    7. @GetMapping("/redis/redisFind")
    8. @ApiOperation("三、redis缓存(2)查询redis")
    9. public ResultInfoVo<User> redisFind(String key) {
    10. String value = redisService.getString(key);
    11. return new ResultInfoVo(value);
    12. }

    3、保存和查询截图

    四、异常信息

    异常信息结构和接口数据返回的数据结构是一致的

    如接口返回的结构如下

    1、封装对象
    1. @ToString
    2. @ApiModel()
    3. public class ResultInfoVo<T> {
    4. public static final String SUCCESS="success";
    5. public static final String FAILED="failed";
    6. @ApiModelProperty(value = "业务code:成功为success,失败为其它业务,如roleIdIsNull")
    7. private String code="success";//业务code 成功为 success 失败为 其它业务编号,如paramIsNull
    8. @ApiModelProperty(value = "描述信息")
    9. private String message="处理成功";//描述信息
    10. @ApiModelProperty(value = "业务数据")
    11. public T data;//页数据
    12. public ResultInfoVo(){}
    13. public ResultInfoVo(T data) {
    14. this.data = data;
    15. }
    16. public ResultInfoVo(String message,T data) {
    17. this.message = message;
    18. this.data = data;
    19. }
    20. public ResultInfoVo(String code, String message) {
    21. this.code = code;
    22. this.message = message;
    23. }
    24. public ResultInfoVo( String code, String message, T data) {
    25. this.code = code;
    26. this.message = message;
    27. this.data = data;
    28. }
    29. }

    异常信息返回的对象

    1. public class CKException extends RuntimeException {
    2. private Log logger = LogFactory.getLog(getClass());
    3. @ApiModelProperty(value = "业务code:成都为success,失败为其它业务,如roleIdIsNull")
    4. private String code;//业务错误码
    5. @ApiModelProperty(value = "描述信息")
    6. private String message;//错误详情
    7. @ApiModelProperty(value = "其它数据")
    8. private Object data;//其它数据
    9. public CKException(String code, String message) {
    10. this.code = code;
    11. this.message = message;
    12. this.data=data;
    13. }
    14. public CKException(String code, String message, Object data) {
    15. this.code = code;
    16. this.message = message;
    17. this.data=data;
    18. }
    19. }

    2、使用:

    五、接口返回数据格式的封装
    1. package com.ck.server.web.model.vo;
    2. import io.swagger.annotations.ApiModel;
    3. import io.swagger.annotations.ApiModelProperty;
    4. import lombok.ToString;
    5. /**
    6. * Created by Administrator on 2018/7/2.
    7. */
    8. @ToString
    9. @ApiModel()
    10. public class ResultInfoVo<T> {
    11. public static final String SUCCESS="success";
    12. public static final String FAILED="failed";
    13. @ApiModelProperty(value = "业务code:成功为success,失败为其它业务,如roleIdIsNull")
    14. private String code="success";//业务code 成功为 success 失败为 其它业务编号,如paramIsNull
    15. @ApiModelProperty(value = "描述信息")
    16. private String message="处理成功";//描述信息
    17. @ApiModelProperty(value = "业务数据")
    18. public T data;//页数据
    19. public ResultInfoVo(){}
    20. public ResultInfoVo(T data) {
    21. this.data = data;
    22. }
    23. public ResultInfoVo(String message,T data) {
    24. this.message = message;
    25. this.data = data;
    26. }
    27. public ResultInfoVo(String code, String message) {
    28. this.code = code;
    29. this.message = message;
    30. }
    31. public ResultInfoVo( String code, String message, T data) {
    32. this.code = code;
    33. this.message = message;
    34. this.data = data;
    35. }
    36. public String getCode() {
    37. return code;
    38. }
    39. public void setCode(String code) {
    40. this.code = code;
    41. }
    42. public String getMessage() {
    43. return message;
    44. }
    45. public void setMessage(String message) {
    46. this.message = message;
    47. }
    48. public T getData() {
    49. return data;
    50. }
    51. public void setData(T data) {
    52. this.data = data;
    53. }
    54. }
    六、源代码下载:

    链接:https://pan.baidu.com/s/16snuaL2X3oPelNm6uSMv4Q?pwd=dy7p 
    提取码:dy7p

  • 相关阅读:
    Python在地球科学领域中的数据处理、科学计算、数学建模、数据挖掘和数据可视化
    备战秋招--基础模块
    晨控CK-GW06系列网关与汇川可编程控制器MOSBUSTCP通讯手册
    2023年中国禽流感疫苗产量、需求量及市场规模分析[图]
    WordArt Designer:基于用户驱动与大语言模型的艺术字生成
    嵌入式Linux中内存管理详解分析
    ASTM D4434/D4434M-2021 PVC屋面板检测
    SpringMvc 如何同时支持 Jsp 和 Json 接口?
    sprinboot打包jar后读取不到/resource/data/ip2region.xdb的文件.
    2.AUTOSAR SWC设计概述
  • 原文地址:https://blog.csdn.net/hekf2010/article/details/134299410