记录一下碰到的问题

1. Arrays.asList() 以及 list.subList() 方法生成的数组无法修改

public class Test {

    public static void main(String[] args) {
        List<String> list = Arrays.asList("a","b","c");
        list.add("d");
    }
    
}

/*
结果:
Exception in thread "main" java.lang.UnsupportedOperationException
	at java.util.AbstractList.add(AbstractList.java:148)
	at java.util.AbstractList.add(AbstractList.java:108)
	at jvm.Test.main(Test.java:14)
*/

产生原因: Arrays.asList()方法生成的list对象的Class类型为Arrays类中的内部类,仅支持查询,不支持修改。subList方法同理,ArrayList的subList方法生成的对象为SubList.

2.Redisson锁释放时必须由持有锁的线程释放,否则会产生异常

    public void test() {
        RLock lock = redissonClient.getFairLock("LOCK");
        try {
            boolean success = lock.tryLock(10,30,TimeUnit.SECONDS);
            if (success) {
                // do your business
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

产生原因: 见java/util/concurrent/locks/Lock.java的unlock方法注释

    /**
     * Releases the lock.
     *
     * <p><b>Implementation Considerations</b>
     *
     * <p>A {@code Lock} implementation will usually impose
     * restrictions on which thread can release a lock (typically only the
     * holder of the lock can release it) and may throw
     * an (unchecked) exception if the restriction is violated.
     * Any restrictions and the exception
     * type must be documented by that {@code Lock} implementation.
     */
    void unlock();

3.RocketMQ顺序消费异常会阻塞当前队列消费,必须尽快处理

4.Mybatis Plus 多数据源下,开启事务会导致数据源无法切换

产生原因:开启事务会导致提前获取数据源,如果在事务中切换数据源则无法生效。如果业务上存在这种场景,建议将更新操作放到最后一起更新,让事务的粒度最细

5.MybatisPlus使用乐观锁必须判断SQL执行结果影响数量是否不为0,并加上重试机制,否则会导致更新失败

6.ServletRequest的getParameter方法会影响getReader或getInputStream方法,导致后者为空,尤其是参数在请求体中的情况

产生原因:多个WebFilter同时存在,其中一个使用了getParameter方法,导致后续获取请求数据时为空。可以看ServletRequest.getParameter的注释

    /**
     * Returns the value of a request parameter as a <code>String</code>, or <code>null</code> if the parameter does not
     * exist. Request parameters are extra information sent with the request. For HTTP servlets, parameters are
     * contained in the query string or posted form data.
     *
     * <p>
     * You should only use this method when you are sure the parameter has only one value. If the parameter might have
     * more than one value, use {@link #getParameterValues}.
     *
     * <p>
     * If you use this method with a multivalued parameter, the value returned is equal to the first value in the array
     * returned by <code>getParameterValues</code>.
     *
     * <p>
     * If the parameter data was sent in the request body, such as occurs with an HTTP POST request, then reading the
     * body directly via {@link #getInputStream} or {@link #getReader} can interfere with the execution of this method.
     *
     * @param name a <code>String</code> specifying the name of the parameter
     *
     * @return a <code>String</code> representing the single value of the parameter
     *
     * @see #getParameterValues
     */
    public String getParameter(String name);

7.Spring事务注解对this调用的方法无效,需要注入自己,或者使用别的方法让事务生效

产生原因:Spring事务管理本质上是通过AOP实现的,最关键的是代理对象,而this指代的是本类对象,并不是代理对象,所有this调用的方法不会被Spring事务管理

8.在使用stream生成map的时候,除非确认key是唯一的,否则需要提供一个mergeFunction用来避免产生冲突

9.Spring容器中通过Bean的类型去获取Class名称时,不一定能够拿到原始的Class对象名称,由于SpringAOP会为SpringBean生成代理对象,所以拿到的可能是代理类的类对象

解决方法:可以通过Spring提供的AopUtils.getTargetClass()方法来获取原始类对象

文章作者: YeYu
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 YeYu的个人博客
Java 日常
喜欢就支持一下吧
打赏
微信 微信
支付宝 支付宝