Spring mvc配置消息转换器

配置消息转换器

配置FastJson转换器

  • 选择一个配置文件类实现WebMvcConfigurer

  • 重写configureMessageConverters方法注册添加消息转换器,需要配置UTF-8格式。

     public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
            FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
    //        FastJsonConfig fastJsonConfig = new FastJsonConfig();
            List<MediaType> fastMediaTypes = new ArrayList<>();
            fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
            converter.setSupportedMediaTypes(fastMediaTypes);
            converters.add(converter);
        }
        @Autowired
        public SpringMvcConfig(UserController u){
    
        }

钩子方法

父类定义一个模版方法,即方法中没有内容,但是有参数,子类重写方法,此时使用多态赋值父类,父类调用钩子方法,通过方法参数就能钓到子类运行后的值,本质就是地址里的值改变了,地址其实没有变,钩子里有个小参数诱饵但是经过执行后,钓到了大的鱼,即将其附上了其他值。对于spirng中就是容器实例化的自动注入,实现多态,然后钩子调用。

  • 父类,但是方法上加了@Bean 此时如果IOC容器中有子类实例,则会多态自动注入到this中, 通过System.out.println(this);以及通过一个Controller类自动注入实现类,然后输出地址,你会发现其实是一个地址,也就是此时this其实就是其容器里注册后子类实例,然后spirng启动后会扫描执行该方法,此时容器是没有该类实例,只有实现类实例。
public  class Student {
    private String name;
    private int age;

    @Bean
    public void beanTest(){
        List<Integer>ss =new ArrayList<>() ;
        this.hook(ss);
        //ss相对于鱼饵
        System.out.println(this);
        //此时ss变成了大鱼,因为里面有东西了。
        System.out.println("勾中了"+ss.toString());

    }

	//钩子方法
    public void hook(List<Integer> s){
        System.out.println(name);
    }
    //有参构造
    public Student(String name, int age){
        this.name = name;
        this.age = age;
    }



    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
  • 子类,类上加了Componet注解,告诉容器要创建实例,然后重写了钩子方法,同时s加上了1。

    @Component
    public class MyTest extends Student {
        private String name;
        private int age;
    
        public MyTest() {
            super("123",10);
            this.name ="ssss";
            this.age =30;
        }
    
        @Override
        public void hook(List<Integer> s) {
            s.add(1);
            System.out.println("重写了");
        }
    
    }
  • 输出结果

    image-20240930154947457

    而此时的自动注入的输出为:(具体代码不放了,应该都会)

    image-20240930155027186

    可以发现实现了钩子功能,钓上了1。这就是钩子方法,其实原理就是多态然后方法内值改了,不过记住前提地址不能变,否则达不到效果,因为spring的注解+IOC容器原理,所以我们会理解不了。

@EnableWebMvc注解

Read More

注解二

注解的解析

注解的解析

  • 需要解析那个对象的注解就加载那个对象,例如:解析类则获取Class对象(反射);
  • 常用方法:
    • isAnnotationPresent(Class<?> class);是否存在该注解;
    • getDeclaredAnnotation(Class<?> class); 获取注解对象(需要强转);
    • getDeclaredAnnotations();获取所有注解构成的数组;
    • 注解对象.属性(方法)获取属性值。

Read More

注解

注解

注解为特殊标记,用于告诉程序如何执行

自定义注解

public @interface a{
    public String name() default 默认值;//将方法作为属性。
    String value();//特殊属性,即默认属性,即如果就只有一个value属性,则使用注解时无需指定value,默认赋值给value,注:此时的只有一个value属性,不仅代表注解只有一个value,如果注解有多个属性,但是多个属性都有默认值的话,则value属性也是可以不用写(value有默认值也是可以)。
        
}

元注解

注解注解的注解😏,第一个注解为动词,后面两个为名词。

  • @Retention() 声明注解作用时机,即保留周期
    • RetentionPolicy枚举类
      • SOURCE 只作用源码阶段,字节码文件中不存在。
      • CLASS(默认值)存在于源码与class文件中,但是运行时消失。
      • RUNTIME 一直到运行时都存在。
  • @Target() 声明注解作用位置
    • ElementType 枚举类
      • TYPE 类,接口
      • FIELD, 成员变量
      • METHOD, 成员方法
      • PARAMETER, 方法参数
      • CONSTRUCTOR, 构造器
      • LOCAL_VARIABLE ,局部变量

Read More

丝线情

  红丝剪不断,金线系万千。烬心凝血弦,情深化柔绵。
  连星理不乱,丝线四象穿。星云汇金缕,引线刺心弦。

Read More

post

  学习java mysql的关闭资源方法中,学习到try catch with resource 方法,这个方法需要要求所释放资源类实现了AutoCloseable接口,代码介绍如下:

try(将需要关闭的资源语句写在这里){

    ......
}catch(错误){
}

  这个方法被常用取代try-catch finally,除了写作简洁外,还有一个就是它避免了错误覆盖,通过addSuppressed()方法将抑制的错误信息存储下来,后面通过getSuppressed()输出。
参考博客地址:深入理解 Java 中的 try with resources

Read More

java 反射

  反射看了这么多,可以简单认为是用于动态变化类的内容,避免写死,通过配置文件,来进行修改,可以这么说,如果使用new那么如果更新需要重写代码,但是如果用反射,则可以用配置文件就可以更新,无须修改代码与重新运行编译。

Read More

事务

  事务是数据库管理系统执行过程中的一个逻辑单位,由有限个数据库操作序列组成。
  事务四个特性:

1.原子性(Atomicity):事务作为一个整体被执行,包含其中的全部数据操作,要么全部执行,要么全部不执行,即回滚到执行前状态。
2.一致性(Consistency):事务应确保数据库状态从一个一致状态转变为另一个一致状态。一致状态是数据库中的数据应与数据库的定义一致,换句话说就是满足完整性约束。
3.隔离性(Isolation):多个事务并发执行时,一个事务的执行不影响其他事务执行,换句话说,每个事务只有自己执行的效果,没含带其他事务,具有独立性,最后,不同事务先后提交并执行后,最终呈现出来的效果是串行的。
3.持久性(Durability):已被提交的事务对数据库的修改应该是永久改变的。

  隔离性最简单的实现方式就是各个事务都串行执行了,如果前面的事务还没有执行完毕,后面的事务就都等待。但是这样的实现方式很明显并发效率不高,并不适合在实际环境中使用。为了解决上述问题,实现不同程度的并发控制,SQL的标准制定者提出了不同的隔离级别:未提交读、提交读、可重复读、序列化读。

1. 未提交读(READ UNCOMMITTED)
    最低级的的隔离级别,可以读取未提交事务的数据。
2. 提交读(READ COMMITTED)
    一个事务只能看见已经提交的事务所做的改变,大多数数据库系统的默认隔离级别(但不是MYSQL默认的)。
3. 可重复读(REPEATABLE READ)
    事务A在读到一条数据之后,此时事务B对该数据进行了修改并提交,那么事务A再读该数据,读到的还是原来的内容,可以说上了一个修改锁。
4. 可串行化(SERIALIZABLE)
    最高级别隔离,强制事务串行执行,时间消耗大,导致超市现象和锁竞争,一般不用该级别,而是采用乐观锁与悲观锁。

  较低的隔离级别能够提高效率,但是却会导致很多问题,常见的4个问题如下:

1.脏读
    脏读发生于未提交读级别,事务A读取事务B的修改的数据,但是事务B提交前回滚,即撤回操作,此时事务A读取的数据为无用数据,出现了脏读,脏读就是读取脏的数据(垃圾数据)。
2. 不可重复读问题(对于列说)
    不可重复读问题是说事务两次读取的数据不一致,发生于并发事务中,事务A第一次读取数据,随后,事务B修改数据的某一列,此时提交后,数据修改,此时事务A又再次读取数据,此时读取数据的某一列不一致,从而产生不可重复读问题。
3. 幻读问题(对于行说)
    幻读问题是说事务第一次读的数据与第二次读的数据数量不一致,从而产生幻觉的问题,事务A第一次读取数据,此时事务B增加或删减了一行数据后,此时事务A再次读取数据时产生了两者不一致的幻觉。
4. 丢失更新问题
    丢失更新问题是说事务A的更新被事务B的修改覆盖,从而丢失了更新,丢失问题分为两种,第一种为回滚丢失更新,在事务A执行更新时,事务B执行更新并提交,但是事务A最后回滚撤销,进而回滚到事务开始状态,此时事务B的更新也会被覆盖,第二种为提交覆盖数据更新,事务A的提交修改了期间事务B的更新的数据,从而导致了事务B更新消失,因为丢失更新1比较严重,所以数据库本身不允许这一类丢失更新的发生。

  对于不同隔离等级会出现的问题汇总如下:

隔离级别 脏读 不可重复读 幻读 丢失更新1 丢失更新2
未提交读 发生 发生 发生 不发生 发生
提交读 不发生 发生 发生 不发生 发生
可重复读 不发生 不发生 发生 不发生 不发生
可串行化 不发生 不发生 不发生 不发生 不发生

  前面说了乐观锁与悲观锁,但是这里要强调乐观锁与悲观锁是思想,不是具体实现,那些具体锁可以根据思想划分为乐观锁或悲观锁。乐观锁又叫乐观并发控制(OCC),悲观锁又叫悲观并发控制(PCC)。
  乐观锁是认为外界对数据的操作一般是不会发生冲突的,因此在操作过程不会进行加锁,而是当提交的时候才会进行检测加锁,数据库的乐观锁,并不是利用数据库本身的锁去实现的,可能是利用某种实现逻辑去实现做到乐观锁的思想。
  悲观锁是认为外界对数据的操作默认是会发生冲突的,所以在数据操作的整个过程都会处于加锁状态,保证同一时间只有一个线程可以访问到数据,通常利用数据库本身提供的锁机制去实现。
  乐观锁使用逻辑进行上锁,一般基于CAS思想进行设计,CAS思想是通过对比旧期望值a(在操作前进行读取,并进行赋值)与需要进行最终修改时读取值b进行比较,如果一致,则表明在此期间没有人进行修改,可以进行操作,而如果不一致,说明在此期间已经有人进行了修改,不执行更新,基于此思想数据库有两种方式:

Read More

无题

  天上星,光如故,地上人,难长明;天无情,天长存,人有情,难长留。
  天星四象华光旧,地人万代久难明。天道冷情长青存,人世喜乐不长留。灰云尽染靛青布,半生雨露半若晴;浮生微醒乐逍遥,万气归源吟我心。

Read More