SpringBoot2 核心知识点浓缩

约定优于配置,这是Spring Boot的主导思想

配置

配置的优先级从高到低:

  • 命令行参数
  • 来自java:comp/env的JNDI属性
  • Java系统属性(System.getProterties())
  • 操作系统环境变量
  • RandomValuePropertySource配置的random.*属性值
  • jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件
  • jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件
  • spring.config.location 这个功能见下文补充
  • jar包外部的application.properties或application.yml(不带spring.profile)配置文件
  • jar包内部的application.properties或application.yml(不带spring.profile)配置文件
  • @Configuration注解类上的@PropertySource
  • 通过SpringApplication.setDefaultProperties指定的默认属性

补充:
–spring.config.location=C:/application.properties
–spring.config.location=classpath:/bootstrap.properties
这个配置只能用在命令行里,主要用来运维已经打包好了的程序

Spring

Spring最成功的是其提出的理念,而不是技术本身。控制反转(IoC)&面向切面编程(AOP)

Spring IoC容器是一个管理Bean的容器,Spring要求所有的IoC容器都需要实现接口BeanFactory,他是一个顶级容器接口

ApplicationContext

ApplicationContext是BeanFactory的子接口之一,在Spring的体系中BeanFactory和ApplicationContext是最为重要的接口设计。

@Configuration && @Compent

@Configuration代表这是一个Java配置文件,Spring的容器会根据它来生成IoC容器去装配Bean;

@Configuration和@Compent有什么区别。@Component 注解并没有通过 cglib 来代理@Bean 方法的调用,因此像下面这样配置时,就是两个不同的 country。

@Bean

@Bean(name=”user”)可用在成员变量或成员方法上,它代表将成员变量(或成员方法返回的POJO)装配到IoC容器中。

@Bean属性name定义这个Bean的名称,若没定义,这以成员变量名(或成员方法名)为Bean名称。

通过@Bean注入Spring IoC容器中,是一件很麻烦的事情,你可以通过@Component和@ComponentScan两个注解用来装配你的Bean

@ComponentScan

加入了@ComponentScan,它会进行扫描,但是它指挥扫描当前类所在的包及其子包。可以在此注解中配置excludeFilters 去过滤哪些类不需要加载到IoC容器

basePackages定义扫描的包名,在没有定义的情况下,它只会扫描当前包和其子包下的路径。当然,你也通过可以过basePackageClassses定义扫描的类

@Primary

告诉IoC容器,当发现了有多个同样类型的B时,请优先使用当前类进行注入

@Autowired

它会根据类型找到对应的Bean,如果对应类型的Bean不是唯一的,那么它会一句其属性名称和Bean的名称进行匹配。如果还无法匹配,则会报错

它除了可以标注属性哎,还可以标注方法

默认情况下,就是不带参数的构造方法下实现依赖注入。但事实上,有些类只有带有参数的构造方法,你可以用@Autowired标注在参数上,以达到目的:

public Persion(@Autowired @Qualifier(“doy”) Animal animal)

@从配置文件取值

@Value。从配置文件取值,成员变量上使用@Value(“${database.username}”)

这里有个高级写法,你可以用Spring EL 表达式

上面这种写法便捷,但是下面开发中最好用下面的注解

@ConfigurationProperties(“database”)

@Conditional条件装配Bean

@Conditional(DatabaseTestConditinal.class),依据这类判断是否要装配当前类

DatabaseTestConditinal需要实现Condition接口

Bean的作用域

  • singleton 默认值,IoC容器中单例
  • prototype 每当从IoC中取出,则创建一个新的Bean
  • session HTTP会话
  • application web工程生命周期
  • request Web单次请求
  • globalSession 在整个全局http session中

@Profile

依据运行环境动态加载到IoC容器

AOP

只要按照一定的规则,我就可以将你的代码织入事先约定的流程中

AOP也是一种约定流程的编程

AOP术语:

  • 连接点
  • 切点
  • 通知
  • 目标对象
  • 引入
  • 织入
  • 切面

AOP只能对方法进行拦截

环绕通知(Around)是所有通知中最强大的

@DeclareParents,它的作用是引入新的类来增强服务,比如给UserService包装下,增加表单提交校验

从通知中获取参数:

@Before("pointCut() && args(user)")
public void beforeParam(JoinPoint point, User user)

Spring 采用了JDK和CGLIB,对于JDK而言,它要求被代理的目标对象必须拥有接口,而对于CGLIB则不做要求。因此,在默认情况下,Spring会依照这样的一条规则处理即当你需要使用AOP的类拥有接口时,它会用JDK动态代理,否则以CGLIB运行

多个切面的存在,可通过@Order控制顺序。(是不是很想典型的责任链模式?)

很关键的一个知识点:类自身的调用,而不是代理对象去调用,那么就不会产生AOP

@JbdcTemplate

这是Spring框架提供的,准确来说,JdbcTemplate这种方式也不算成功,在实际工作中还是比较少使用的。用的更多的是Hibernate和MyBatis

JPA(java persistence api,java持久化API),定义了对象关系映射(ORM)以及实体对象持久化的标准接口

Spring Boot中JPA是依靠Hibernate才得以实现

你可以通过@Convert设定实体类字段使用的定义转换器(常见的,用来解决枚举转换器)

@Spring事务管理器

事务管理器的顶层接口PlatformTransactionManager

当你依赖mybatis-spring-boot-starter后,它会自动创建一个DataSource-TransactionManager对象作为事务管理对象

当你依赖spring-boot-starter-data-jpa后,它会自动创建一个JpaTransactionManager对象作为事务管理对象

事务机制中有最重要的两个配置项,隔离级别和传播行为,可通过配置文件声明

NESTED隔离级别,它是一个如果子方法回滚而当前事务不回滚的方法~~

注意:并发情况下又要保证事务一致性,需要通过其他手段实现

Redis

Redis 是基于内存的,所以运行速度很快,大约是关系数据库几倍到几十倍的速度

Redis 自身数据类型比较少,命令功能也比较有限,运算能力一直不强,所以 Redis 在2.6版本之后开始增加 Lua 语言的支持

在java 中 Redis 的驱动存在很多种,目前比较广泛使用的是 Jedis,其他还有Lettuce、Jredis和Srp(后两个在Spring中已经被标注了@Deprecated)。项目开发中我们会引入spring-boot-starter-daat-redis(版本2.x),它会依赖Lettuce的 Redis 客户端驱动,我们需要排除掉,手动添加 Jedis

java配置文件RedisConfig来创建,通过redisTemplate.opsXXXXX来操作不同的数据类型

关于事物。通常的命令组合是watch multi exec。watch是监控key,multi是开始事务,开始事务后,所有的命令不会马上执行,而是存放到一个队列中!没执行!

默认情况下,Redis 命令时一条条发送给 Redis 服务器执行的。在很多情况下并不是 Redis 性能不佳,而是网络传输的速度造成瓶颈,使用流水线后就可以大幅度地在需要执行很多命令时提升 Redis 的性能

流水线可以提升大约10倍的速度,它十分适合大数据量的执行,使用过程需要注意:

  • 如果过多的命令执行返回的结果都保存到整个list中,显然会造成内存消耗过大,尤其在那些高并发的网站中就很容易造成JVM内存溢出的异常,这个时候应该考虑使用迭代的方法执行 Redis 命令
  • 与事务一样,使用流水线的过程中,所有的命令也只是进入队列而没有执行,所以执行的命令返回值为空!一定注意了!

你也可以订阅监听 Redis 的消息发布,通过RedisMessageListenerContainer,这个设计中,Topic是渠道

关于消息这块的开发测试,你用登录 Redis 客户端,使用 publish topic1 msg 来模拟发布,也可以使用 redisTemplate.convertAndSend(channel, message)

如果你要给你的网站dao层设置缓存,可以通过mybatis的二级缓存机制来整合redis使用,也可以单独使用spring提供的redis的切面,关键配置:

  • spring.cache.cache-names=redisCache
  • 在dao层getUser方法上添加@Cacheable(value=”redisCache”, key=”‘redis_user_’+ #id”)。关于key的语法去官网查吧

MongoDB

一个十分接近于关系数据库的NoSQL,它允许我们使用JPA编程

SpringMVC

学习mvc首先要学习基于mvc的分层思想,mvc的巨大成功在于它的理念

这套体系下,我们以前都是 easyui+jstl 开发前端代码

关于返回

标注了@ResponseBody,所以控制器返回的结果就会转化为JSON数据集

在用户控制器中导出PDF数据:View view = new PdfView(exportService())

@ResponseBody,解析器MappingJackson2HttpMessageConverter

重定向,返回结果string,return 写 redirect:/user/show。怎么传递java对象?此方法入场加入RedirctAttributes rs,在return前些rs.addFlashAttribute(“user”, user)。show方法入参写User user即可

@RequestHeader获取请求头参数

关于请求

有时候,前端的命名规则和后端不同,你可以通过@RequestParam(value="sex", required=true\false)将其对应起来

数组参数的话,逗号隔开就行了

@RequestBody 可以直接对应前端的JSON消息

通过URL传递参数,后台@GetMapping("/{id}")

获取格式化参数,@DateTimeFormat\@NumberFormat

一对一转换器(Converter),StringToUserConverter implements Converter<String, User>

集合和数组转换(GennericConverter),底层还是一对一转换器

数据验证环节, Spring Boot 会引入关于Hibernate Validator 机制来支持 JSR-303验证规范

@InitBinger,作用是在执行控制器方法前,处理器会先执行被此注解标注的方法

支持文件上传,MultiportHttpServletRequest,注意配置文件,限制文件大小、上传的默认路径、多部件文件请求(multipart)

客户端请求 RestTemplate

restTmpl.getForObject(“/user/{id}”, User.class, id)

restTmpl.getForObject(“/user/{id}/{sex}”, User.class, paramsMap)

ResponseEntity res = restTmpl.postForEntity(“user”, User.class),可获取返回header等

@Async异步线程池

@Async标记在方法上,可使它变成异步

但你还需要在项目中添加@EnableAsync注解,激活异步功能

通常我们都喜欢把@EnableAsync添加到Application类的头部,不过我建议还是新建一个AsyncConfig类!

AsyncConfig添加@EnableAsync、@Configuration两个注解,实现AsyncConfigurer接口,重写getAsyncExecutor定义线程池相关参数,内部可定义线程池的实现类、核心线程数、线程池最大线程数、线程队列最大线程数,在return前initialize()初始化

@Scheduled定时任务

需要使用@EnableScheduling开启定时任务

Websocket

不是所有的浏览器都支持WebSocket协议,一些旧版本的浏览器并不能支持WebSocket协议,因此还需要去兼容这些浏览器。为此,我们可以引入STOMP(WebSocket的子协议),通过它即可兼容那些不支持Websocket的浏览器

如何开启STOMP,新增配置类,添加@EnableWebSocketMessageBroker,实现WebSocketMessageBrokerConfigurer接口

WebFlux

Spring 5 新框架,Spring Boot 2.X开始支持

Spring WebFlux 需要的使能够支持Servlet3.1+的容器,如tomcat、jetty、undertow,而在java异步编程领域,使用的最多的使 Netty ,所以在Spring Booot对Spring Webflux的starter中默认依赖于 Netty 库

在WebFlux中,存在两种开发方式:1、类似于Spring MVC;2、函数功能性编程

高并发开发

提出了乐观锁、悲观锁和使用了Redis等多种方案

悲观锁(也称 独占锁、排他锁,关键词:排队)

数据库在事务执行过程中,会锁定查询出来的数据,其他的事务将不能再对其进行读写,这样就避免了数据的不一致。单个请求处理完毕,才会释放这所,其他请求需要逐个排队得到锁!

很明显,性能是最大问题,效率太低了!

乐观锁

乐观锁是一种不适用数据库锁的机制,并且不会造成线程的阻塞,只是采用了多版本号的机制来实现。因为版本的冲突造成了请求失败的概率剧增,素以这时往往需要通过重入的机制将请求失败的概率降低。但是,多次的重入会带来过多的SQL问题。为了解决这问题,我们可以考虑使用按时间戳或限制重入次数的办法。

乐观锁是一个比较复杂的问题。

Redis下的高并发

这块内容可以查看我的博客redis高并发开发 ~

1、Redis响应高并发用户的请求,注意,这一步并不涉及任何数据库的操作,而只是涉及Redis。因为Redis性能比数据库要快很多(上面我们提及过)

2、redis本身的存储是不稳定的,所以需要及时将数据保存到数据库中。这里将会启用定时任务去查找Redis保存的购买信息,将它们保存到数据库中


转载请注明来源。 欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。 可以在下面评论区评论,也可以邮件至 sharlot2050@foxmail.com。

文章标题:SpringBoot2 核心知识点浓缩

字数:3.3k

本文作者:夏来风

发布时间:2020-07-06, 22:08:36

原始链接:http://www.demo1024.com/blog/java-springboot2/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。