码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • Spring 编程常见问题之三(专栏学习笔记)


    spring 扩展中间件列表

    Spring Data Commons
    Spring Data JPA
    Spring Data KeyValue
    Spring Data LDAP
    Spring Data MongoDB
    Spring Data Redis
    Spring Data REST
    Spring Data for Apache Cassandra
    Spring Data for Apache Geode
    Spring Data for Apache Solr
    Spring Data for Pivotal GemFire
    Spring Data Couchbase (community module)
    Spring Data Elasticsearch (community module)
    Spring Data Neo4j (community module)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    Spring Data Redis

    RedisTemplate、 stringRedisTemplate 读 写不能混用,混用无法读到别人的数据

    原因:
    RedisTemplate 使用的是jdk序列化
    stringRedisTemplate 使用的 StringRedisSerializer

    public class StringRedisSerializer implements RedisSerializer {
       private final Charset charset;
       @Override
       public byte[] serialize(@Nullable String string) {
          return (string == null ? null : string.getBytes(charset));
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    public class JdkSerializationRedisSerializer implements RedisSerializer {  
       @Override
       public byte[] serialize(@Nullable Object object) {
          if (object == null) {
             return SerializationUtils.EMPTY_ARRAY;
          }
          try {
             return serializer.convert(object);
          } catch (Exception ex) {
             throw new SerializationException("Cannot serialize", ex);
          }
       }
    }
    
    public interface Serializer {
        void serialize(T var1, OutputStream var2) throws IOException;
    
        default byte[] serializeToByteArray(T object) throws IOException {
            ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
            this.serialize(object, out);
            return out.toByteArray();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    spring 事务

    Spring Data 事务管理包

    Spring 事务管理包含两种配置方式

    1. 第一种是使用 XML 进行模糊匹配,绑定事务管理;
    2. 第二种是使用注解,这种方式可以对每个需要进行事务处理的方法进行单独配置,你只需要添加上 @Transactional,然后在注解内添加属性配置即可。

    1. Spring 支持声明式事务机制,它通过在方法上加上 @Transactional,表明该方法需要事务支持。于是,在加载的时候,根据 @Transactional 中的属性,决定对该事务采取什么样的策略;
    2. @Transactional 对 private 方法不生效,所以我们应该把需要支持事务的方法声明为 public 类型;
    3. Spring 处理事务的时候,默认只对 RuntimeException 和 Error 回滚,不会对 Exception 回滚,如果有特殊需要,需要额外声明,例如指明 Transactional 的属性 rollbackFor 为 Exception.class。

    事务处理

    TransactionAspectSupport.invokeWithinTransaction():

    
    protected Object invokeWithinTransaction(Method method, @Nullable Class targetClass,
          final InvocationCallback invocation) throws Throwable {
     
       TransactionAttributeSource tas = getTransactionAttributeSource();
       final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
       final PlatformTransactionManager tm = determineTransactionManager(txAttr);
       final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
       if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
          // 是否需要创建一个事务
          TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
          Object retVal = null;
          try {
             // 调用具体的业务方法
             retVal = invocation.proceedWithInvocation();
          }
          catch (Throwable ex) {
             // 当发生异常时进行处理
             completeTransactionAfterThrowing(txInfo, ex);
             throw ex;
          }
          finally {
             cleanupTransactionInfo(txInfo);
          }
          // 正常返回时提交事务
          commitTransactionAfterReturning(txInfo);
          return retVal;
       }
       //......省略非关键代码.....
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    1. 检查是否需要创建事务;
    2. 调用具体的业务方法进行处理;
    3. 提交事务;
    4. 处理异常。

    spring rest template 使用post提交表单,参数应该为MultiValueMap 而非HashMap

    错误示例,content 为application/json

    
    RestTemplate template = new RestTemplate();
    Map paramMap = new HashMap();
    paramMap.put("para1", "001");
    paramMap.put("para2", "002");
    
    String url = "http://localhost:8080/hi";
    String result = template.postForObject(url, paramMap, String.class);
    System.out.println(result);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    正确示例,content 为application/x-www-form-urlencoded;

    //错误:
    //Map paramMap = new HashMap();
    //paramMap.put("para1", "001");
    //paramMap.put("para2", "002");
    
    //修正代码:
    MultiValueMap paramMap = new LinkedMultiValueMap();
    paramMap.add("para1", "001");
    paramMap.add("para2", "002");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    原因:
    根据当前要提交的 Body 内容,遍历当前支持的所有编解码器,如果找到合适的编解码器,就使用它来完成 Body 的转化。

    1. 先遍历了AbstractJackson2HttpMessageConverter#canWrite: 判断HashMap是能够json序列化的就走了json序列化方式作为body
    2. 如果使用MultiValueMap,则会走表单消息的转化器,FormHttpMessageConverter#canWrite:
    public boolean canWrite(Class clazz, @Nullable MediaType mediaType) {
       if (!MultiValueMap.class.isAssignableFrom(clazz)) {
          return false;
       }
       if (mediaType == null || MediaType.ALL.equals(mediaType)) {
          return true;
       }
       for (MediaType supportedMediaType : getSupportedMediaTypes()) {
          if (supportedMediaType.isCompatibleWith(mediaType)) {
             return true;
          }
       }
       return false;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    解决get请求中,查询参数含特殊字符的问题

    RestTemplate restTemplate = new RestTemplate();
    UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("http://localhost:8080/hi");
    builder.queryParam("para1", "开发测试 001");
    URI url = builder.encode().build().toUri();
    ResponseEntity forEntity = restTemplate.getForEntity(url, String.class);
    System.out.println(forEntity.getBody());
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    spring boot 的基础加载路径

    classpath:META-INF/resources
    classpath:resources
    classpath:static
    classpath:public
    src/main/webapp
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    java中如何将嵌套循环性能提高500倍
    好用的 JS 脚本
    Qt-OpenCV学习笔记--图像的腐蚀--erode()
    SSO单点登录
    【芯片设计- RTL 数字逻辑设计入门 5 -- RTL 全加器实现及验证】
    keras fit_generator 增加并行度问题 use_multiprocessing
    【iOS】JSONModel的基本使用
    mysql锁机制
    Java抽象类和接口
    Git版本控制工具
  • 原文地址:https://blog.csdn.net/hesiyuanlx/article/details/126729616
    • 最新文章
    • 沪漂五周年了:我越来越迷茫了
      Agentic Skill Routing 实战:别再把所有 Skill 塞进 AI Agent 上下文
      MySQL-Seconds_behind_master的精度误差
      [MAF预定义ChatClient中间件-03]CachingChatClient——利用缓存省钱省时间
      AI的至暗历史:从万众期待到被政府撤资,AI的两次死亡徘徊
      Agent OS :五种驯服不确定性的范式
      PortSwigger SQL注入LAB11
      数据库即时编译JIT
      [Begin]AI Learn Data Day 0
      深度学习进阶(二十七)现代 LLM 的核心架构设计其二:SwiGLU
    • 热门文章
    • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
      奉劝各位学弟学妹们,该打造你的技术影响力了!
      五年了,我在 CSDN 的两个一百万。
      Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
      面试官都震惊,你这网络基础可以啊!
      你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
      心情不好的时候,用 Python 画棵樱花树送给自己吧
      通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
      13 万字 C 语言从入门到精通保姆级教程2021 年版
      10行代码集2000张美女图,Python爬虫120例,再上征途
    小工具 小游戏
    Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1

    京公网安备 11010502049817号