码农知识堂 - 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
  • 相关阅读:
    Python课设-学生信息管理系统
    学习 nginx 你需要知道的内容
    benchmark
    数据库、数据仓库相关
    结合scss实现黑白主题切换
    PLS-00172 string literal too long ORA-06550 字段太长插入不进去数据库
    【高通camera hal bug分析】高通自带相机镜像问题
    PHP 使用 Guzzle 执行 HTTP 请求
    vue3 和 vue2 区别,面试简答
    分布式篇---第五篇
  • 原文地址:https://blog.csdn.net/hesiyuanlx/article/details/126729616
    • 最新文章
    • 攻防演习之三天拿下官网站群
      数据安全治理学习——前期安全规划和安全管理体系建设
      企业安全 | 企业内一次钓鱼演练准备过程
      内网渗透测试 | Kerberos协议及其部分攻击手法
      0day的产生 | 不懂代码的"代码审计"
      安装scrcpy-client模块av模块异常,环境问题解决方案
      leetcode hot100【LeetCode 279. 完全平方数】java实现
      OpenWrt下安装Mosquitto
      AnatoMask论文汇总
      【AI日记】24.11.01 LangChain、openai api和github copilot
    • 热门文章
    • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
      奉劝各位学弟学妹们,该打造你的技术影响力了!
      五年了,我在 CSDN 的两个一百万。
      Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
      面试官都震惊,你这网络基础可以啊!
      你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
      心情不好的时候,用 Python 画棵樱花树送给自己吧
      通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
      13 万字 C 语言从入门到精通保姆级教程2021 年版
      10行代码集2000张美女图,Python爬虫120例,再上征途
    Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
    正则表达式工具 cron表达式工具 密码生成工具

    京公网安备 11010502049817号