Spring框架进阶 - Spring Boot(二)

Spring Boot启动配置原理

  • main方法程序运行入口,分为两步
  • 1.创建SpringApplication对象
    • 调用initialize方法创建对象
      • 保存主配置类
      • 判断当前是否为web应用
      • 从类路径下找到META‐INF/spring.factories配置的所有ApplicationContextInitializer并保存起来
      • 从类路径下找到ETA‐INF/spring.factories配置的所有ApplicationListener
      • 从多个配置类获取有main方法的主程序类
  • 2.运行run方法
    • 从类路径下找到META‐INF/spring.factories配置获取SpringApplicationRunListeners
    • 回调所有的SpringApplicationRunListener.starting()方法
    • 封装命令行参数
    • 准备环境并回调所有监听器SpringApplicationRunListener.environmentPrepared()环境准备完成
    • 创建ApplicationContext,决定创建web的ioc还是普通的ioc
    • 准备上下文环境prepareContext():将environment保存到ioc中
      • applyInitializers():回调之前保存的所有的ApplicationContextInitializer.initialize(),回调所有的SpringApplicationRunListener的contextPrepared()
      • 加载主配置类定义信息
      • 运行完成以后回调所有的SpringApplicationRunListener.contextLoaded()
    • 刷新容器refreshContext(context),ioc容器创建完成
      • 扫描加载所有容器中的组件
      • 包括从META-INF/spring.factories中获取的所有EnableAutoConfiguration组件
    • afterRefresh(context, applicationArguments)从ioc容器中获取所有的ApplicationRunnerCommandLineRunner进行回调
    • listeners.finished(context, null)所有的SpringApplicationRunListener回调finished方法
    • 返回启动的ioc容器

自定义场景启动器starters

  • 模式
    • 编写启动器用来做依赖导入,启动器模块是一个空 JAR 文件,仅提供辅助性依赖管理,这些依赖可能用于自动
      装配或者其他类库
    • 编写自动配置模块,启动器依赖自动配置模块,使用只需要引入启动器
  • 步骤
    • 启动器模块
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.gc.starter</groupId>
    <artifactId>gc-spring-boot-starter</artifactId>
    <version>1.0-SNAPSHOT</version>
    <!--启动器-->
    <dependencies>
    	<!--引入自动配置模块-->
    	<dependency>
    		<groupId>com.gc.starter</groupId>
    		<artifactId>gc-spring-boot-starter-autoconfigurer</artifactId>
    		<version>0.0.1-SNAPSHOT</version>
    	</dependency>
    </dependencies>
    
    • 自动配置模块
    <?xml version="1.0" encoding="UTF‐8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema‐instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven‐4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.gc.starter</groupId>
    <artifactId>gc‐spring‐boot‐starter‐autoconfigurer</artifactId>
    <version>0.0.1‐SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>gc‐spring‐boot‐starter‐autoconfigurer</name>
    <description>Demo project for Spring Boot</description>
    <parent>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-starter-parent</artifactId>
    	<version>1.5.10.RELEASE</version>
    	<relativePath/>
    </parent>
    <properties>
    	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    	<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    	<java.version>1.8</java.version>
    </properties>
    <dependencies>
    	<dependency>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter</artifactId>
    	</dependency>
    </dependencies>
    </project>
    
    • 设置场景
    package com.gc.starter;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    @ConfigurationProperties(prefix = "Spring.hello")
    public class HelloProperties {
    	private String prefix;
    	private String suffix;
    	public String getPrefix() {
    		return prefix;
    	}
    	public void setPrefix(String prefix) {
    		this.prefix = prefix;
    	}
    	public String getSuffix() {
    		return suffix;
    	}
    	public void setSuffix(String suffix) {
    		this.suffix = suffix;
    	}
    }
    
    package com.gc.starter;
    public class HelloService {
    	HelloProperties helloProperties;
    	public HelloProperties getHelloProperties() {
    		return helloProperties;
    	}
    	public void setHelloProperties(HelloProperties helloProperties) {
    		this.helloProperties = helloProperties;
    	}
    	public String sayHellSpring(String name){
    		return helloProperties.getPrefix()+"‐" +name + helloProperties.getSuffix();
    	}
    }
    
    package com.gc.starter;
    @Configuration
    @ConditionalOnWebApplication //web应用才生效
    @EnableConfigurationProperties(HelloProperties.class)
    public class HelloServiceAutoConfiguration {
    	@Autowired
    	HelloProperties helloProperties;
    	@Bean
    	public HelloService helloService(){
    		HelloService service = new HelloService();
    		service.setHelloProperties(helloProperties);
    		return service;
    	}
    }
    

Spring Boot与缓存

JSR107缓存规范
  • Java Caching定义了5个核心接口,分别是CachingProvider, CacheManager, Cache, Entry 和 Expiry
    • CachingProvider(缓存提供者)定义了创建、配置、获取、管理和控制多个CacheManager。一个应用可以在运行期访问多个CachingProvider。
    • CacheManager(缓存管理器)定义了创建、配置、获取、管理和控制多个唯一命名的Cache,这些Cache存在于CacheManager的上下文中。一个CacheManager仅被一个CachingProvider所拥有。
    • Cache(缓存)是一个类似Map的数据结构并临时存储以Key为索引的值。一个Cache仅被一个CacheManager所拥有。
    • Entry(接口)是一个存储在Cache中的key-value对
    • Expiry(有效期):每一个存储在Cache中的条目有一个定义的有效期。一旦超过这个时间,条目为过期的状态。一旦过期,条目将不可访问、更新和删除。缓存有效期可以通过ExpiryPolicy设置
  • 使用JSR107需要导入如下包
<dependency>
    <groupId>javax.cache</groupId>
    <artifactId>cache-api</artifactId>
</dependency>
Spring缓存抽象
  • Spring从3.1开始定义了org.springframework.cache.Cache和org.springframework.cache.CacheManager接口来统一不同的缓存技术,并支持使用JCache(JSR-107)注解简化开发
    • Cache接口为缓存的组件规范定义,包含缓存的各种操作集合
    • Cache接口下Spring提供了各种xxxCache的实现;如RedisCache,EhCacheCache , ConcurrentMapCache等
    • 核心思想:当我们在调用一个缓存方法时会把该方法参数和返回结果作为一个键值对存放在缓存中,等到下次利用同样的参数来调用该方法时将不再执行该方法,而是直接从缓存中获取结果进行返回。所以在使用Spring Cache的时候我们要保证我们缓存的方法对于相同的方法参数要有相同的返回结果
    • 使用Spring缓存抽象需注意两点
      • 确定方法需要被缓存以及他们的缓存策略
      • 从缓存中读取之前缓存存储的数据
    • 使用Spring缓存抽象需做两方面的事
      • 声明某些方法使用缓存
      • 配置Spring对Cache的支持
    • Spring对Cache的支持也有基于注解和基于XML配置两种方式
  • 重要概念
    • 对于一个支持缓存的方法,Spring会在其被调用后将其返回值缓存起来,以保证下次利用同样的参数来执行该方法时可以直接从缓存中获取结果,而不需要再次执行该方法
    • Spring在缓存方法的返回值时是以键值对进行缓存的,值就是方法的返回结果,至于键的话,Spring又支持两种策略,默认策略和自定义策略
    • 当一个支持缓存的方法在对象内部被调用时是不会触发缓存功能的
    • keyGenerator:缓存数据时key生成策略
    • serialize:缓存数据时value序列化策略
  • 基于注解配置
    • @EnableCaching:开启基于注解的缓存
    • @Cacheable
      • 可以标记在一个方法上,也可以标记在一个类上。当标记在一个方法上时表示该方法是支持缓存的,当标记在一个类上时则表示该类所有的方法都是支持缓存的
      • 属性value:指定Cache名称,必须指定,其表示当前方法的返回值是会被缓存在哪个Cache上的,对应Cache的名称。其可以是一个Cache也可以是多个Cache,当需要指定多个Cache时其是一个数组
      • 属性key:指定Spring缓存方法的返回结果时对应的key,支持SpringEL表达式
        • 当没有指定该属性时,Spring将使用默认策略生成key,默认的key生成策略是通过KeyGenerator生成的
          • 如果方法没有参数,则使用0作为key
          • 如果只有一个参数的话则使用该参数作为key
          • 如果参数多余一个的话则使用所有参数的hashCode作为key
        • 自定义策略:通过Spring的EL表达式来指定我们的key,EL表达式可以使用方法参数及它们对应的属性,使用方法参数时我们可以直接使用“#参数名”或者“#p参数index”
        • Spring还为我们提供了一个root对象可以用来生成key
          • methodName:当前方法名(例:#root.methodName)
          • method:当前方法(例:#root.method.name)
          • target:当前被调用的对象(例:#root.target)
          • targetClass:当前被调用的对象的class(例:#root.targetClass)
          • args:当前方法参数组成的数组(例:#root.args[0])
          • caches:当前被调用的方法使用的Cache(例:#root.caches[0].name)
      • 属性condition:用于缓存一个方法的部分返回结果,默认为空,表示将缓存所有的调用情形。其值是通过SpringEL表达式来指定的,当为true时表示进行缓存处理;当为false时表示不进行缓存处理,即每次调用该方法时该方法都会执行一次
    • @CachePut:更新缓存
      • 标注在类上和方法上,表示支持缓存功能
      • 与@Cacheable不同的是使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中
      • 属性跟@Cacheable是一样的
      • 属性unless:否定缓存,当unless指定的条件为true,该方法的返回值就不会被缓存
      • 属性CacheManager:指定缓存管理器
    • @CacheEvict:清空缓存
      • 标注在类上和方法上,当标记在一个类上时表示其中所有的方法的执行都会触发缓存的清除操作
      • 属性value:表示清除操作是发生在哪些Cache上的
      • 属性key:表示需要清除的是哪个key
      • 属性condition:表示清除操作发生的条件
      • 属性allEntries:默认为false,表示不删除指定缓存中的所有key的缓存数据
      • 属性beforeInvocation:默认为false,表示缓存的清除在方法之后执行
    • @Caching
      • 在一个方法或者类上同时指定多个Spring Cache相关的注解
      • 其拥有三个属性:cacheable、put和evict,分别用于指定@Cacheable、@CachePut和@CacheEvict
    • @CacheConfig
      • 标注在类上,用于抽取一个类中所有缓存注解的公共配置(属性)
  • 基于XML配置
    • 在cache命名空间下定义了一个cache:advice元素用来定义一个对于Cache的advice,其需要指定一个cache-manager属性,默认为cacheManager
    • cache:advice下面可以指定多个cache:caching元素,其有点类似于使用注解时的@Caching注解
    • cache:caching元素下又可以指定cache:cacheable、cache:cache-put和cache:cache-evict元素,它们类似于使用注解时的@Cacheable、@CachePut和@CacheEvict
    <cache:advice id="cacheAdvice" cache-manager="cacheManager">
    	<cache:caching cache="users">
    		<cache:cacheable method="findById" key="#p0"/>
    		<cache:cacheable method="find" key="#user.id"/>
    		<cache:cache-evict method="deleteAll" all-entries="true"/>
    	</cache:caching>
    </cache:advice>
    
    • 有了cache:advice之后,我们还需要引入aop命名空间,然后通过aop:config指定定义好的cacheAdvice要应用在哪些pointcut上
    <aop:config proxy-target-class="false">
    	<aop:advisor advice-ref="cacheAdvice" pointcut="execution(* com.xxx.UserService.*(..))"/>
    </aop:config>
    
    • CacheManager是Spring定义的一个用来管理Cache的接口。Spring自身已经为我们提供了两种CacheManager的实现,一种是基于Java API的ConcurrentMap,另一种是基于第三方Cache实现——Ehcache
    //基于ConcurrentMap的配置
    <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
    	<property name="caches">
    		 <set>
    		 	<bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="xxx"/>
    		 </set>
    	</property>
    </bean>
    // 基于Ehcache的配置
    <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cache-manager-ref="ehcacheManager"/>
    <bean id="ehcacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:config-location="ehcache-spring.xml"/>
    //上面的配置使用了一个Spring提供的EhCacheCacheManager来生成一个Spring的CacheManager,其接收一个Ehcache的CacheManager,因为真正用来存入缓存数据的还是Ehcache。Ehcache的CacheManager是通过Spring提供的EhCacheManagerFactoryBean来生成的,其可以通过指定ehcache的配置文件位置来生成一个Ehcache的CacheManager。若未指定则将按照Ehcache的默认规则取classpath根路径下的ehcache.xml文件,若该文件也不存在,则获取Ehcache对应jar包中的ehcache-failsafe.xml文件作为配置文件
    
整合redis实现缓存
  • 引入spring-boot-starter-data-redis
  • application.yml配置redis连接地址
  • 使用RedisTemplate操作redis
    • redisTemplate.opsForValue();//操作字符串
    • redisTemplate.opsForHash();//操作hash
    • redisTemplate.opsForList();//操作list
    • redisTemplate.opsForSet();//操作set
    • redisTemplate.opsForZSet();//操作有序set
  • 配置缓存、CacheManagerCustomizers
  • 测试使用缓存、切换缓存、 CompositeCacheManager

Spring Boot与消息

消息概述
  • 在大多数应用中,可以通过消息服务中间件来提升系统的异步通信、扩展解耦和流量削峰等能力
  • 当消息发送者发送消息后,将由消息代理接管,消息代理保证消息传递到指定目的地
  • 消息队列主要有两种形式的目的地
    • 队列(queue):点对点消息通信(point-to-point):消息发送者发送消息,消息代理将其送入一个队列中,消息接收者从队列中获取消息,消息被读取后被移出队列。注意:每一个消息只能从一个发送者发送到达唯一一个接收者
    • 主题(topic):发布(publish)/订阅(subscribe)消息通信:发送者(发布者)发送消息到主题,多个接收者(订阅者)监听(订阅)这个主题,那么接收者(订阅者)就会在消息到达时同时收到消息
  • 点对点式
    • 消息发送者发送消息,消息代理将其放入一个队列中,消息接收者从队列中获取消息内容,消息读取后被移出队列
    • 消息只有唯一的发送者和接受者,但并不是说只能有一个接收者
  • 发布订阅式
    • 发送者(发布者)发送消息到主题,多个接收者(订阅者)监听(订阅)这个主题,那么就会在消息到达时同时收到消息
  • JMS(Java Message Service):JAVA 消息服务–基于 JVM 消息代理的规范。ActiveMQ、HornetMQ 是 JMS 的实现
  • AMQP(Advanced Message Queuing Protocol):高级消息队列协议,也是一个消息代理的规范,兼容 JMS,RabbitMQ是 AMQP 的实现
RabbitMQ
  • 简介:RabbitMQ 是一个由 erlang 开发的 AMQP 的开源实现
  • 核心概念
    • Message:消息,消息是不具名的,它由消息头和消息体组成。消息体是不透明的,而消息头则由一系列的可选属性组成,这些属性包括 routing-key(路由键)、priority(相对于其他消息的优先权)、delivery-mode(指出该消息可能需要持久性存储)等
    • Publisher:消息的生产者,也是一个向交换器发布消息的客户端应用程序
    • Exchange:交换器,用来接收生产者发送的消息并将这些消息路由给服务器中的队列
    • Queue:消息队列,用来保存消息直到发送给消费者一个消息可投入一个或多个队列
    • Binding:绑定,用于关联消息队列和交换器。一个绑定就是基于路由键将交换器和消息队列连接起来的路由规则,所以可以将交换器理解成一个由绑定构成的路由表。Exchange 和 Queue 之间的绑定可以多对多的
    • Connection:网络连接,比如一个 TCP 连接
    • Channel:信道,多路复用连接中的一条独立的双向数据流通道。信道是建立在真实的 TCP 连接内的虚拟连接,AMQP 的命令都是通过信道发送出去的。因为建立和销毁一条 TCP 连接开销太大,所以使用信道来复用 TCP 连接
    • Consumer:消息的消费者,表示一个从消息队列中取得消息的客户端应用程序
    • Virtual Host:虚拟主机,表示一批交换器、消息队列和相关对象。虚拟主机是共享相同的身份认证和加密环境的独立服务器域。每个 vhost 本质就是一个 mini 版的 RabbitMQ 服务器,拥有自己的队列、交换器、绑定和权限机制。vhost 是 AMQP 概念的基础,必须在连接时指定,RabbitMQ 默认的 vhost 是/
    • Broker:消息队列服务器实体
      消息
RabbitMQ运行机制
  • AMQP 中消息的路由过程和 Java 开发者熟悉的 JMS 存在一些差别,AMQP 中增加了 Exchange 和 Binding 的角色。生产者把消息发布到 Exchange 上,消息最终到达队列并被消费者接收,而 Binding 决定交换器的消息应该发送到那个队列
    RabbitMQ运行机制
  • Exchange 类型
    • Exchange分发消息时根据类型的不同分发策略有区别,目前共四种类型:direct、fanout、topic、headers(性能较差,几乎不用)
    • direct:消息中的路由键(routing key)如果和 Binding 中的 binding key 一致, 交换器就将消息发到对应的队列中。路由键与队列名完全匹配,如果一个队列绑定到交换机要求路由键为“dog”,则只转发 routing key 标记为“dog”的消息,不会转发“dog.puppy”,也不会转发“dog.guard”等等。它是完全匹配、单播的模式
    • fanout:每个发到 fanout 类型交换器的消息都会分到所有绑定的队列上去。fanout 交换器不处理路由键,只是简单的将队列绑定到交换器上,每个发送到交换器的消息都会被转发到与该交换器绑定的所有队列上。很像子网广播,每台子网内的主机都获得了一份复制的消息。fanout 类型转发消息是最快的
    • topic:topic 交换器通过模式匹配分配消息的路由键属性,将路由键和某个模式进行匹配,此时队列需要绑定到一个模式上。它将路由键和绑定键的字符串切分成单词,这些单词之间用点隔开。它同样也会识别两个通配符:符号“#”和符号“*”。#匹配0个或多个单词,*匹配一个单词
Spring Boot 使用 RabbitMQ
  • 引入 spring-boot-starter-amqp(创建 Spring Boot 项目并选中 RabbitMQ 模块)
    • RabbitAutoConfiguration 自动配置了连接工厂 rabbitConnectionFactory
    • RabbitProperties 封装了 RabbitMQ 的配置
    • AmqpAdmin : RabbitMQ 系统管理功能组件,创建和删除 Queue,Exchange,Binding
    • RabbitTemplate :给 RabbitMQ 发送和接受消息
  • application.properties配置RabbitMQ
    spring.rabbitmq.host=xx.xx.xx.xx
    spring.rabbitmq.virtual-host=/
    spring.rabbitmq.username=guest
    spring.rabbitmq.password=guest
    
  • 测试
    • 使用 AmqpAdmin 创建 Exchange、队列和相应的 Bindings
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class SpringRabbitmqApplicationTests {
    @Autowired
    AmqpAdmin amqpAdmin;
    	@Test
        public void contextLoads() {
            amqpAdmin.declareExchange(new DirectExchange("test-direct-exchange"));
            System.out.println("创建了一个 direct 类型的 exchange");
            amqpAdmin.declareQueue(new Queue("test-queue"));
            System.out.println("创建了一个队列");
            amqpAdmin.declareBinding(new Binding("test-queue", Binding.DestinationType.QUEUE, "test-direct-exchange", "test-routingkey", null));
            System.out.println("添加了绑定,路由键为 test-routingkey");
        }
    }
    
    • 使用 RabbitTemplate 发送和接收消息
    @Autowired
    RabbitTemplate rabbitTemplate;
    @Test
    public void sendMsg() {
    	rabbitTemplate.convertAndSend("test-direct-exchange","test-routingkey", "hello world");
    	
    }
    @Test
    public void receiveMsg() {
    	String msg = (String)rabbitTemplate.receiveAndConvert("test-queue");
    	System.out.println(msg);
    }
    @Test
    public void sendObject() {
    
    	rabbitTemplate.convertAndSend("test-direct-exchange","test-routingkey", new Book("红楼梦", "曹雪芹"));
    }
    
    private static class Book implements Serializable {
    	private String name;
    	private String author;
    
    	public String getName() {
        	return name;
    	}
    
    	public void setName(String name) {
        	this.name = name;
    	}
    
        public Book(String name, String author) {
            this.name = name;
            this.author = author;
        }
    
        public String getAuthor() {
    
            return author;
        }
    
        public void setAuthor(String author) {
            this.author = author;
        }
    }
    
    • 监听消息
    //@RabbitListener 监听消息队列的内容;首先用@EnableRabbit 开启基于注解的 RabbitMQ 模式
    @EnableRabbit
    @SpringBootApplication
    public class SpringRabbitmqApplication {
    	public static void main(String[] args) {
        	SpringApplication.run(SpringRabbitmqApplication.class, args);
    	}
    }
    //监听
    @RabbitListener(queues = "test-queue")
    public void msgListener(Book book) {
        System.out.println(book.getAuthor());
    }
    

Spring Boot与检索

  • 我们的应用经常需要添加检索功能,开源的 ElasticSearch 是目前全文搜索引擎的首选,可以快速的存储、搜索和分析海量数据,Spring Boot通过整合Spring Data ElasticSearch为我们提供了非常便捷的检索功能支持
  • Elasticsearch是一个分布式搜索服务,提供Restful API,底层基于Lucene,采用多shard(分片)的方式保证数据安全,并且提供自动resharding的功能,github等大型的站点也是采用了ElasticSearch作为其搜索服务
Restful
  • Restful是一种资源定位及资源操作的风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制
  • 使用POST、DELETE、PUT、PATCH、GET对资源进行添加、 删除、修改、局部修改、查询操作
http://localhost/users GET方式提交查询全部用户
http://localhost/users/{id} GET方式提交查询指定id的员工
http://localhost/users POST方式提交增加用户
http://localhost/users/{id} PUT方式提交修改指定id用户的全部信息
http://localhost/users/{id} PATCH方式提交修改指定id用户的部分信息
http://localhost/users/{id} DELETE方式提交修改指定id用户的部分信息
  • DELETE、PUT、PATCH都是POST模拟的,表单提交为POST,需要一个隐藏域 _method=“提交方式”
  • 后端需要一个角色(Filter),获取提交方式和_method数据,告知后端是什么提交方式
  • 使用注解@RequestMapping(“item/{id}”)声明请求的url
  • 使用@PathVariable() Integer id获取url上的数据,若id和形参名称一致@PathVariable不用指定名称
    • @PathVariable是获取url上数据的,@RequestParam获取请求参数的(包括post表单提交)
ElasticSearch开源的搜索引擎
  • 使用docker下载ElasticSearch
docker run -e ES_JAVA_OPTS="-Xms256m -Xmx256m" -d -p 9200:9200 -p 9300:9300 --name es1 4f7e4c61f09d
  • Elasticsearch相关使用和用法
    • Elasticsearch 是面向文档的,意味着它存储整个对象或文档,Elasticsearch 不仅存储文档,而且索引每个文档的内容使之可以被检索
    • 在 Elasticsearch 中,是对文档进行索引、检索、排序和过滤,而不是对行列数据。这是一种完全不同的思考数据的方式,也是 Elasticsearch 能支持复杂全文检索的原因
    • 在 Elasticsearch 中,每一条数据保存为一个文档,它有唯一的索引、类型,且包含属性,数据默认使用JSON来存储
    • JSON编辑
      • Elasticsearch 使用 JavaScript Object Notation 或者 JSON 作为文档的序列化格式。JSON 序列化被大多数编程语言所支持,并且已经成为 NoSQL 领域的标准格式。 它简单、简洁、易于阅读
    • ES集群
      • 一个 Elasticsearch 集群可以包含多个索引,相应的每个索引可以包含多个类型 ,不同的类型存储着多个文档 ,每个文档又有多个属性
    • 要向ES中添加文档,只需要发送一个PUT请求,请求路径中包含文档的索引和类型,消息体中包含文档数据即可
    • 要从ES中获得文档,只需要发送get请求以及文档的位置即可
    • 删除只需要发送DELETE请求
    • 判断某个文档是否存在,可以发送HEAD请求,根据状态码判断该文档是否存在,状态码是200说明文档存在,状态码是404说明不存在
SpringBoot整合ElasticSearch
  • SpringBoot支持两种技术来和ES交互,默认是使用springdata整合ES的.也支持使用jest操作ES
  • 使用springdata整合ES
    • 引入spring-boot-starter-data-elasticsearch(创建 Spring Boot 项目并选中 Web模块 和 ElasticSearch模块)
    • 安装Spring Data 对应版本的ElasticSearch
    • application.yml配置节点名称和节点通信端口
    spring:
    	data:
    		elasticsearch:
    			cluster-name: elasticsearch   # 节点名称
    			cluster-nodes: 192.168.124.127:9300  # 节点间进行通信的端口
    
    • Spring Boot自动配置的ElasticsearchRepository、ElasticsearchTemplate都可操作ES
      • 编写一个ElasticSearchRepository接口的子接口
      public interface BookRepository extends ElasticsearchRepository<Book,Integer> {
      	//Book指是要存储的数据的类型,Integer是主键的类型
      	//也可以在接口中编写自定义的方法,具体的方法的命名可以参照官方文档
      	public List<Book> findBookByBookNameLike(String bookName);
      }
      
      • 编写实体类
      @Document(indexName = "gc" , type = "book")
      public class Book {
      	private Integer id;
      	private String author;
      	private String bookName;
      }
      
      • 测试
      @Autowired
      BookRepository bookRepository;
      @Test
      public void test02(){
      Book book = new Book();
      	book.setId(1);
      	book.setAuthor("作者");
      	book.setBookName("书名");
      	bookRepository.index(book);//更多方法参考官方文档
      }
      
  • 使用jest整合ES
    • 引入依赖
    <dependency>
    	<groupId>io.searchbox</groupId>
    	<artifactId>jest</artifactId>
    	<version>5.3.3</version>
    </dependency>
    
    • application.yml配置主机和端口
    spring:
      elasticsearch:
        jest:
          uris: http://192.168.124.127:9200
    
    • 测试
    @Autowired
    JestClient jestClient;
    @Test
    public void contextLoads() throws IOException {
    	//给ES中索引 (保存) 一个文档
    	Article article = new Article();
    	article.setId(1);
    	// 构建索引
    	Index index = new Index.Builder(article).index("book").type("new").build();
    	//执行
    	jestClient.execute(index);
    }
    

Spring Boot与任务

异步任务
  • 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的;但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在Spring 3.x之后,就已经内置了@Async来完美解决这个问题
  • @EnableAysnc:开启异步,标注在主程序类上
  • @Async:标注在方法上,告诉spring这是一个异步的方法
定时任务
  • Spring为我们提供了异步执行任务调度的方式提供了TaskExecutor、TaskScheduler接口
  • @EnableScheduling:开启定时任务,标注在主程序类上
  • @Scheduled:标注在方法上,告诉spring这是一个定时的方法
    • cron属性=“cron表达式” //指明执行时机
表达式字段允许值允许字符
0-59, - * /
0-59, - * /
0-23, - * /
日期1-31, - * ? / L W C
月份1-12, - * /
星期0-7或SUN-SAT 0,7是SUN, - * ? / L C #
  • 特殊字符
特殊字符含义
,枚举
  • | 区间
  • | 任意
    / | 步长
    ? | 日/星期冲突匹配
    L | 最后
    W | 工作日
    c | 和calendar联系后计算过的值
    /# | 星期,4#2,第2个星期四
邮件任务
  • 需引入spring-boot-starter-mail
  • Springboot 自动配置MailSenderAutoConfiguration
  • 定义MailProperties内容,配置在application.yml中
spring.mail.username=1287221322@qq.com
#授权码
spring.mail.password=keoszgbsssddbaad
spring.mail.host=smtp.qq.com
spring.mail.properties.mail.smtp.ssl.enable=true
  • 自动装配JavaMailSender
  • 测试
@Autowired
JavaMailSenderImpl javaMailSender;
@Test
public void contextLoads() {
    SimpleMailMessage msg = new SimpleMailMessage();
    //邮件设置
    msg.setSubject("标题");
    msg.setText("内容");
    msg.setTo("接收邮箱");
    msg.setFrom("发送邮箱");
    javaMailSender.send(msg);
}
@Test
public void test1() throws MessagingException {
    //创建复杂邮件
    MimeMessage msg = javaMailSender.createMimeMessage();
    //上传文件
    MimeMessageHelper helper = new MimeMessageHelper(msg,true);
    //邮件设置
    helper.setSubject("标题");
    helper.setText("内容");
    helper.setTo("接收邮箱");
    helper.setFrom("发送邮箱");
    //上传文件
    helper.addAttachment("319898.jpg",new File("D:\\Tools\\319898.jpg"));
    javaMailSender.send(msg);
}

Spring Boot与安全

  • Spring Security是针对Spring项目的安全框架,也是Spring Boot底层安全模块默认的技术选型。他可以实现强大的web安全控制。对于安全控制,我们仅需引入spring-boot-starter-security模块,进行少量的配置,即可实现强大的安全管理
    • WebSecurityConfigurerAdapter接口:自定义Security策略
    • AuthenticationManagerBuilder接口:自定义认证策略
    • @EnableWebSecurity:开启WebSecurity模式
  • Spring Security 的两个目标是“认证”和“授权”
    • 认证”(Authentication),是建立一个他声明的主体的过程(一个“主体”一般是指用户,设备或一些可以在你的应用程序中执行动作的其他系统)
    • “授权”(Authorization)指确定一个主体是否允许在你的应用程序执行一个动作的过程。为了抵达需要授权的店,主体的身份已经有认证过程建立
  • Web&安全
    • 登陆/注销 HttpSecurity配置登陆、注销功能
    • Thymeleaf提供的SpringSecurity标签支持
      • 需要引入thymeleaf-extras-springsecurity4
      • sec:authentication=“name”获得当前用户的用户名
      • sec:authorize=“hasRole(‘ADMIN’)”当前用户必须拥有ADMIN权限时才会显示标签内容
    • remember me
      • 表单添加remember-me的checkbox
      • 配置启用remember-me功能
    • CSRF跨站请求伪造:HttpSecurity启用csrf功能,会为表单添加_csrf的值,提交携带来预防CSRF

Spring Boot与开发热部署(自动部署)

  • 模板引擎实现热部署
    • 在Spring Boot中开发情况下禁用模板引擎的cache 页面模板改变ctrl+F9,可以重新编译当前页面并生效
  • Spring LoadedSpring
    • 官方提供的热部署程序,实现修改类文件的热部署 下载Spring Loaded
    • 添加运行时参数; -javaagent:C:/springloaded-1.2.5.RELEASE.jar –noverify
  • JRebel
    • 安装插件使用即可
  • Spring Boot Devtools
// 引入依赖
<dependency>  
       <groupId>org.springframework.boot</groupId>  
       <artifactId>spring-boot-devtools</artifactId>
       <optional>true</optional>
</dependency>

Spring Boot与监控管理

  • Spring Boot Actuator 提供了运行状态监控的功能,ctuator 监控数据可以通过阻止REST远程 shell 和 JMX 方式获得
  • 通过执行器端点,可监控应用程序并与之交互。Spring Boot包含许多内置端点,也允许添加自己的端点
  • 可以启用或禁用某个端点,控制是否创建端点并且其bean存在于应用程序上下文中。要进行远程访问,还必须通过JMX或HTTP公开端点 ,大多数应用程序选择HTTP,其中端点的ID以及前缀/actuator 映射到URL
  • 步骤
    • 添加依赖spring-boot-starter-actuator
    • 配置
    server.port=8009
    management.server.port=8083
    #开放所有页面节点  默认只开启了health、info两个节点
    management.endpoints.web.exposure.include=*
    #actuator端口
    #修改访问路径  2.0之前默认是/   2.0默认是 /actuator  可以通过这个属性值修改
    #management.endpoints.web.base-path: /actuator
    #显示健康具体信息  默认不会显示详细信息
    management.endpoint.health.show-details:ALWAYS
    
    • 访问http://localhost:8083/actuator
    • 可进行shutdown(POST 提交,此端点默认关闭,除了shutdown请求为post,其他的皆为GET请求)
  • 监控和管理端点
端点名描述
autoconfig所有自动配置信息
auditevents审计事件
beans所有Bean的信息
configprops所有配置属性
dump线程状态信息
env当前环境信息
health应用健康状况
info当前应用信息
metrics应用的各项指标
mappings应用@RequestMapping映射路径
shutdown关闭当前应用(默认关闭)
trace追踪信息(最新的http请求)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值