Spring基础(一)

原作者:https://blog.csdn.net/sujin_/article/details/78700158

  1. 什么是Spring?

Spring是一个轻量级的开源框架,是为解决企业应用开发的复杂性而创建的;它是一个容器框架,用来装javabeanjava对象),中间层框架(万能胶)可以起一个连接作用,比如说把Strutshibernate粘合在一起运用。简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。(Spring 核心就是IOC和AOP)

 

  1. Spring容器的简介

 

2.Spring 容器的实例化  

3.Spring容器的使用

4.Bean的实例化,初始化过程:https://www.cnblogs.com/fyx158497308/p/3977391.html

https://www.cnblogs.com/xrq730/p/6285358.html

5.Bean的命名

6.Bean的作用域:https://blog.csdn.net/qq_33800083/article/details/80166144

7.Bean的生命周期

8.Bean延迟实例化

9.制定Bean依赖关

      2. 什么是控制反转(IoC=Inversion of Control 或依赖注入DI=Dependency Injection)?

Spring容器最基本的接口是BeanFactory,他负责配置、创建、管理bean.他的子接口之一:ApplicationContext,也叫做spring的上下文。ApplicationContextBeanFactory的子接口,

web应用中,通常会用到XmlWebApplicationContextAnnotationCofigWebApplicationContext两个实现类。

    3.  实现SpringIoC

         在Spring当中定义和配置一个javabean

Bean的基本配置:

  1. id:在容器中查找Bean(对象)的id(唯一、且不能以/开头)
  2. classbean(对象)的完整类名
  3. name:在容器中查找Bean(对象)的名字(唯一、允许以/开头、允许多个值,多个值之间用逗号或空格隔开)
  4. scope:(singleton|prototype)默认是singleton
  5. singleton(单例模式):在每个Spring IoC容器中一个bean定义对应一个对象实
  6. prototype(原型模式/多例模式):一个bean(对象)定义对应多个对象实例
  7. abstract:将一个bean定义成抽象bean(抽象bean是不能实例化的),抽象类一定要定义成抽象bean,非抽象类也可以定义成抽象bean
  8. parent:指定一个父bean(必须要有继承关系才行)
  9. init-method:指定bean对象()的初始化方法
  10. 使用有参数构造方法创建javaBeanjava对象):constructor-arg

第一步:新建spring工程

第二步:创建Helloworld

package com.manning.readinglist;
public class HelloWorld {
    private String name;

    public HelloWorld() {
        super();
        System.out.println("new HelloWorld()");
    }

    public HelloWorld(String name) {
        super();
        this.name = name;
    }

    public void init() {
        System.out.println("init
().......");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

 

第三步:在xml中配置bean


       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
   
   
   
   
   
       
            zs
       

   

   
       
            zzz
       

   

第四步:写测试类

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class HelloWorldTest {
    public static void main(String[] args) {
        //
以前的写法
        HelloWorld helloWorld=new HelloWorld();
        helloWorld.setName("
张三");
        System.out.println("hello"+helloWorld.getName());
        //-------------------------------------------------------------
        //Spring
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("ApplicationContext.xml");
        HelloWorld a = (HelloWorld)applicationContext.getBean("a");
        System.out.println("
你好: "+a.getName());

        HelloWorld b = (HelloWorld)applicationContext.getBean("b");
        System.out.println("
你好: "+b.getName());

        HelloWorld c = (HelloWorld)applicationContext.getBean("c");
        System.out.println("
你好: "+c.getName());

        HelloWorld d = (HelloWorld)applicationContext.getBean("helloworld2");
        System.out.println("--------------------------------");
        System.out.println("
你好: "+d.getName());
    }
}

第五步:运行结果

Spring基础(一)_第1张图片


Spring 框架由6个定义好的模块组成:(六大模块,不同功能)

Spring基础(一)_第2张图片

  • 2.Spring 的主要功能有哪些?

    1.       Spring Core核心容器: Core封装包是框架的最基础部分,提供IOC和依赖注入特性。Springbean的方式组织和管理Java应用中的各个组件及其关系。Spring使用BeanFactory来产生和管理Bean,它是工厂模式的实现。BeanFactory使用控制反转(IoC)模式将应用的配置和依赖性规范与实际的应用程序代码分开。BeanFactory使用依赖注入的方式提供给组件依赖。

    2.      Spring Context: 构建于Core封装包基础上的 Context封装包,提供了一种框架式的对象访问方法,有些象JNDI注册器。Context封装包的特性得自于Beans封装包,并添加了对国际化(I18N)的支持(例如资源绑定),事件传播,资源装载的方式和Context的透明创建,比如说通过Servlet容器。

    3.  Spring DAO:  DAO (Data Access Object)提供了JDBC的抽象层,它可消除冗长的JDBC编码和解析数据库厂商特有的错误代码。 并且,JDBC封装包还提供了一种比编程性更好的声明性事务管理方法,不仅仅是实现了特定接口,而且对所有的POJOs(plain old Java objects)都适用。

    4.      Spring ORM: ORM 封装包提供了常用的“对象/关系”映射APIs的集成层。 其中包括JPA、JDO、Hibernate 和 iBatis 。利用ORM封装包,可以混合使用所有Spring提供的特性进行“对象/关系”映射,如前边提到的简单声明性事务管理。

    5.      Spring AOP: Spring的 AOP 封装包提供了符合AOP Alliance规范的面向方面的编程实现,让你可以定义,例如方法拦截器(method-interceptors)和切点(pointcuts),从逻辑上讲,从而减弱代码的功能耦合,清晰的被分离开。而且,利用source-level的元数据功能,还可以将各种行为信息合并到你的代码中。

    6.      Spring Web: Spring中的 Web 包提供了基础的针对Web开发的集成特性,例如多方文件上传,利用Servlet listeners进行IOC容器初始化和针对Web的ApplicationContext。当与WebWork或Struts一起使用Spring时,这个包使Spring可与其他框架结合。

    7.      Spring Web MVC: Spring中的MVC封装包提供了Web应用的Model-View-Controller(MVC)实现。Spring的MVC框架并不是仅仅提供一种传统的实现,它提供了一种清晰的分离模型,在领域模型代码和Web Form之间。并且,还可以借助Spring框架的其他特性

  • Instrumentation Spring的Instrumentation模块提供了为JVM添加代理(agent)的功能。具体来讲,它为Tomcat提供了一个织入代理,能够为Tomcat传递类文 件,就像这些文件是被类加载器加载的一样。

如果这听起来有点难以理解,不必对此过于担心。这个模块所提供的Instrumentation使用场景非常有限,在本书中,我们不会介绍该模块。

  • 测试 测试

鉴于开发者自测的重要性,Spring提供了测试模块以致力于Spring应用的测试。 通过该模块,你会发现Spring为使用JNDI、Servlet和Portlet编写单元测试提供了一系列的mock对象实现。对于集成测试,该模块为加载Spring 应用上下文中的bean集合以及与Spring上下文中的bean进行交互提供了支持。 在本书中,有很多的样例都是测试驱动的,将会使用到Spring所提供的测试功能。 


1.Spring降低Java开发复杂性所采用的的策略:

  • 基于POJO的轻量级和最小侵入性编程;
  • 通过依赖注入和面向接口实现松耦合;
  • 基于切面和惯例进行声明式编程;
  • 通过切面和模板减少样板式代码

 


二:  容器和Bean管理   

1.Spring容器的简介

在基于Spring的应用中,你的应用对象生存于Spring容器(container)中。如图所示,Spring容器负责创建对象,装配它们,配置它们并管理它们的整个生命周期,从生存到死亡(在这里,可能就是new到finalize())。

Spring基础(一)_第3张图片Spring基础(一)_第4张图片

2.Spring 容器的实例化  

3.Spring容器的使用

使用最多的spring容器就是ApplicationContext(Spring应用上下文beanFactory的接口之一)

  • Spring自带多种应用上下文,他们只是加载方式和路径不同
  • AnnotationConfigApplicationContext:从一个或多个基于Java的配置类中加载Spring应用上下文。
  • AnnotationConfigWebApplicationContext:从一个或多个基于Java的配置类中加载Spring Web应用上下文。
  • ClassPathXmlApplicationContext:从类路径下的一个或多个XML配置文件中加载上下文定义,把应用上下文的定义文件作为类资源。
  • FileSystemXmlapplicationcontext:从文件系统下的一个或多个XML配置文件中加载上下文定义。
  • XmlWebApplicationContext:从Web应用下的一个或多个XML配置文件中加载上下文定义。

4.Bean的实例化,初始化过程:

https://www.cnblogs.com/fyx158497308/p/3977391.html

https://www.cnblogs.com/xrq730/p/6285358.html

https://upload-images.jianshu.io/upload_images/1727685-c357395b8191b12e.png?imageMogr2/auto-orient/

https://upload-images.jianshu.io/upload_images/1727685-94ae490a0837bc57.png?imageMogr2/auto-orient/

  • 在调用ClassPathXmlApplicationContext之后首先将XML配置文件的位置保存到configLocations供后面解析使用
  • 创建beanFactory
  • 使用XMLReader解析XML配置文件,将其解析成需要的beanDefinition
  • 注册的实质就是以beanName为key,beanDefinition为value,将其放入HashMap

5.Bean的命名

6.Bean的作用域:https://blog.csdn.net/qq_33800083/article/details/80166144

7.Bean的生命周期

8.Bean延迟实例化

9.制定Bean依赖关


 三:容器的IOC应用       

  1. ICO概念

可以把IoC模式看做是工厂模式的升华,可以把IoC看作是一个大工厂,只不过这个大工厂里要生成的对象都是在XML文件中给出定义的,然后利用Java 的“反射”编程,根据XML中给出的类名生成相应的对象。从实现来看,IoC是把以前在工厂方法里写死的对象生成代码,改变为由XML文件来定义,也就是把工厂和对象生成这两者独立分隔开来,目的就是提高灵活性和可维护性。

IoC中最基本的Java技术就是“反射”编程。

2.      Setter注入

3.构造器装配

4.自动装配

 

第一部分:Spring基础

第二章、装配bean

  • 声明bean
  • 构造器注入和Setter方法注入
  • 装配bean
  • 控制bean的创建和销毁

Spring配置的可选方案

  • 在XML中进行显式配置。
  • 在Java中进行显式配置。
  • 隐式的bean发现机制和自动装配

Bean的装配方式:Spring中的bean都是单例,同一个实例可以注入到任意数量的其他bean当中。Spring 会拦截所有对同一个实例的调用,并确保直接返回该方法所创建的bean,而不是每次都对其进行实际的调用。

在XML中进行显式配置。

Xml启动扫描:

JavaConfig(配置代码)

@Configuration:注解表明这个类是一个配置类,该类应该包含了在Spring应用上下文中如何创建bean的细节。

@Bean

注入:1)引用创建bean的方法来进行装配,需要与被引用的bean声明在同一个配置类中

           2)通过参数引用,可以在不同的配置类中进行声明,甚至没有要求CompactDisc必须要在JavaConfig中声明

           3)通过setter方法来注入,或者其他任意方法进行注入

@Configuration表明该java类是一个配置类,等价于XML中的

@Bean等价于XML的标签

隐式的bean发现机制和自动装配(从两个角度来实现)

组件扫描(component scanning):Spring会自动发现应用上下文中所创建的bean。

自动装配(autowiring):Spring自动满足bean之间的依赖

***组件扫描***详解@ComponentScan和@Component********

@Component: 注解表明该类会作为组件类,并告知Spring要为这个类创建bean

** 不过,组件扫描默认是不启用的。我们还需要显式配置一下Spring,从而命令它去寻找带有@Component注解的类,并为其创建bean。

@ComponentScan注解,这个注解能够在Spring中启用组件扫描。

如果没有其他配置的话,@ComponentScan默认会扫描与配置类相同的包及所有子包,查找带有@Component注解的类,将其创建为bean。

通过XML的方案来启用组件扫描,元素

Spring支持将@Named(由Java依赖注入规范Java Dependency Injection提供)作为@Component注解的替代方案。两者之间有一些细微的差异,但是在大多数场景中,它们是可以互相替换的。

@ComponentScan("com.bean.soundSystem") //设置一个基础扫描包,以String类型表示,但是不安全not-safe,重构代码后报名可能会变

@ComponentScan(basePackages = {"com.bean.soundSystem","com.bean.soundSystem2"})设置多个基础扫描包

@ComponentScan(basePackageClasses = {SgtPeppers.class , SgtPeppers2.class})将扫描的包用包中所包含的类或接口来指定。

**可以使用空标记接口来制定要扫描的包,对重构更加友好

*****自动装配,使得spring自动满足bean依赖**@Autowired****

构造器上添加@Autowired注解

在setter方法上添加@Autowired 注解

@Autowired注解可以用在类的任何方法上。

不管是构造器、Setter方法还是其他的方法,Spring都会尝试满足方法参数上所声明的依赖。

@Autowired(required = false)

如果没有匹配的bean,那么在应用上下文创建的时候,Spring会抛出一个异常。为了避免异常的出现,你可以将@Autowired的required属 性设置为false。

@Inject注解来源于Java依赖注入规范,该规范同时还为我们定义了@Named注解。在自动装配中,Spring同时支持@Inject和@Autowired。尽管@Inject和@Autowired之间有着一些细微的差别,但是在大多数场景下,它们都是可以互相替换的。

导入和混合配置

在javaconfig中引用xml配置

@Import注解:

@ImportResource

在xml中引用springconfig

xml引入javaconfig

  xml引用其他xml配置

第三章、Bean的高级装配:主要知识点

Spring profile :

它可以理解为我们在Spring容器中所定义的Bean的逻辑组名称,只有当这些Profile被激活的时候,才会将Profile中所对应的Bean注册到Spring容器中。

  • 条件化的bean声明
  • 自动装配与歧义性
  • bean的作用域
  • Spring表达式语言

环境与profile:

简单来讲,profile就是一组配置,不同profile提供不同组合的配置,程序运行时可以选择使用哪些profile来适应环境。

例子:DATA Source管理:在不同环境中会有所不同,我们必须要有一种方法来配置DataSource,使 其在每种环境下都会选择最为合适的配置。

 JNDI管理的DATA Source更适合生产环境;

 在QA环境中可以选择完全不同的DATA Source配置为Commons DBCP连接池;

 在开发环境试用嵌入式数据库来进行自测;

解决方法一:在单独的配置类(或XML文件)中配置每个bean,然后在构建阶段(可能会使用Maven的profiles标签)确定要将哪一个配置编译 到可部署的应用中。但环境变更的构建可能会引入bug

解决方法二:使用Spring提供的解决方案,通过Profile配置,Spring可以在根据环境在运行阶段来决定bean的创建与否,先举例如下,主要从Profile bean的配置和激活来展开。

配置profile bean

SpringConfig中的配置 :@Profile("dev")

* @Profile被加载类级别上,如果dev profile没有被激活,那么类中对应的所有bean就不会被创建

* 如果当前是dev环境被激活了,被标记为其他的profile如@Profile("prod"),则不会创建相应的bean。没有指定profile的bean始终都会被创建,与激活哪个profile没有关系。

* @Profile不仅仅可以加载类级别上,还可以加载方法上

XML配置profile

* 通过元素的profile属性,在XML中配置profile bean。

* 可以在根元素中嵌套定义元素,而不是为每个环境都创建一个profile XML文件。这能够将所有的profile bean定义放到 同一个XML文件中,如下所示:

激活profile

* 激活需要依赖两个独立的属性spring.profiles.active和spring.profiles.default

* 如果spring.profile.active被赋值了,则spring.profile.default就不会起作用,如果spring.profie.active没有赋值,则使用默认的spring.profile.default设置的值。当然,如果两者都没有设置的话,则只会创建那些没有定义在pofile中的bean。

* 可以同时激活多个profile,这可以通过列出多个profile名称,并以逗号分隔来实现。

* 有多种方式来设置这两个属性:比如在web.xml中就是作为dispatcherServlet参数传值。

作为DispatcherServlet的初始化参数;

  1. 作为Web应用的上下文参数;
  2. 作为JNDI条目;
  3. 作为环境变量;
  4. 作为JVM的系统属性;
  5. 在集成测试类上,使用@ActiveProfiles注解设置

条件化的bean:

@Conditional:它可以用到带有@Bean注解的方法 上。如果给定的条件计算结果为true,就会创建这个bean,否则的话,这个bean会被忽略。

public interface Condition {

         boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);

}

 

设置给@Conditional的类可以是任意实现了Condition接口的类型。可以看出来,这个接口实现起来很简单直接,只需提 供matches()方法的实现即可。如果matches()方法返回true,那么就会创建带有@Conditional注解的bean。如果matches()方法返 回false,将不会创建这些bean。

         ConditionContext和AnnotatedTypeMetadata是两个接口

         *** ConditionContext ***

借助getRegistry()返回的BeanDefinitionRegistry检查bean定义;

借助getBeanFactory()返回的ConfigurableListableBeanFactory检查bean是否存在,甚至探查bean的属性;

借助getEnvironment()返回的Environment检查环境变量是否存在以及它的值是什么;

读取并探查getResourceLoader()返回的ResourceLoader所加载的资源;

借助getClassLoader()返回的ClassLoader加载并检查类是否存在

*** AnnotatedTypeMetadata ***

借助isAnnotated()方法,我们能够判断带有@Bean注解的方法是不是还有其他特定的注解。借助其他的那些方法,我们能够检 查@Bean注解的方法上其他注解的属性。

*** @Profile注解在4.0之后进行了重构,使其基于@Conditional和Condition实现。作为如何使 用@Conditional和Condition的例子。

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.TYPE, ElementType.METHOD})

@Documented

@Conditional(ProfileCondition.class)

public @interface Profile {

         String[] value();

}

@Profile本身也使用了@Conditional注解,并且引用ProfileCondition作为Condition实现。如下所示,ProfileCondition实现了Condition接口,并且在做出决策的过程中,考虑到 了ConditionContext和AnnotatedTypeMetadata中的多个因素 :

Spring基础(一)_第5张图片

** ProfileCondition通过AnnotatedTypeMetadata得到了用于@Profile注解的所有属性。借助该信息,它会明确地检 查value属性,该属性包含了bean的profile名称。然后,它根据通过ConditionContext得到的Environment来检查[借 助acceptsProfiles()方法]该profile是否处于激活状态。

         ** 可以模仿@Profile注解来自定义条件化注解

 

处理自动装配的歧义性:

标示首选的bean@primary

* 隐式装配:@Primary与@Component组合用在组件扫描的bean上

* JavaConfig显式装配:@Primary与@Bean组合用在Java配置的bean声明中。

         * XML显示装配:

限定自动装配的bean:使用限定符@Qalifier,可以与@Awtowire与@Inject协同使用,在注入时指定需要的bean

** 使用默认的beanId作为限定符

为@Qualifier注解所设置的参数就是想要注入的bean的ID。例:@Qualifier("iceCream")

@Qualifier("iceCream")所引用的bean要具有String类型的“iceCream”作为限定符。如 果没有指定其他的限定符的话,所有的bean都以bean的ID作为默认限定符。

缺点:与类名紧密耦合,不利于代码重构修改类名

** 创建自定义的限定符

         在bean声明上添加@Qualifier注解。

例如,与@Component组合使用:

@Qualifier("clod")

@Component

public class IceCream implements Dessert{

……

}

在这种情况下,cold限定符分配给了IceCreambean。因为它没有耦合类名,因此可以随意重构IceCream的类名,而不必担心会破坏自动装配。在注入的地方,只要引用cold限定符就可以了

@Qualifier("cold")

@Autowired

    public void setDessert (Dessert dessert){

        this. dessert = dessert;

    }

Java配置显式定义bean的时候,@Qualifier也可以与@Bean注解一起使用,为bean添加自己定义限定符:

@Qualifier("cold")

@Bean

    public Dessert iceCream(){

        return new IceCream();

    }

** 自定义限定符注解:

创建一个注解借助这个注解来表达bean需要限定的特性,该注解需要用@Qualifier来标注,通过在定义时添加@Qualifier注解来拥有@Qualifier注解的特性,使得该注解成为限定符注解。

定义多个限定符注解,来使用必要的限定符注解进行任意组合,从而将可选范围缩小到只有一个bean满足需求。相对于使用原始的@Qualifier并借助String类型来指定限定符,自定义的注解也更为类型安全。

3.4Bean的作用域

         Spring定义了多种作用域,可以基于这些作用域

创建bean:

  • 单例Singleton:在整个应用中只创建bean的一个实例
  • 原型Prototype:每次注入或者通过spring上下文获取的时候都会创建一个新的bean实例
  • 会话Session:在web应用中为每一个会话创建一个bean实例
  • 请求Request:在web应用中为每一个请求创建一个bean实例

单例是默认的作用域,但对于易变的类型并不适用,要选择其他的作用域需要使用@Scope注解

         @Scope可以与@Component和@Bean注解一起使用:

@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

使用ConfigurableBeanFactory类的SCOPE_PROTOTYPE常量设置了原型作用域。当然也可以使用@Scope("prototype"),但是使用SCOPE_PROTOTYPE常量更加安全并且不易出错。

         在XML显示配置时可以使用来设置原型作用域

         ** 使用会话和请求作用域

         代理模式,懒解析(设计模式)

         proxyMode属性:指定作用域代理

         proxyMode属性设置为ScopedProxyMode.INTERFACES,表明这个代理要实现ShoppingCart接口,并将调用委托给实现bean。 如果ShoppingCart是接口而不是类的话,这是可以的(也是最为理想的代理模式)。但如果ShoppingCart是一个具体的类的话,Spring 就没有办法创建基于接口的代理了。此时,它必须使用CGLib来生成基于类的代理。所以,如果bean类型是具体类的话,我们必须要将proxyMode属性设置为ScopedProxyMode.TARGET_CLASS,以此来表明要以生成目标类扩展的方式创建代理。                                                                                     Spring基础(一)_第6张图片

在xml中指定作用域代理:需要使用Spring aop命名空间的一个新元素

是与@Scope注解的ProxyMode属性功能相同的Spring xml 配置元素,它会告诉Spring为bean创建一个作用域代理。默认情况下,它会使用CGLib创建目标类的代理。但是我们也可以将proxy-target-class属性设置为false,进而要求它生成基于接口的代理:

以request为例,要启用他需要保证应用的“上下文”是web模式,例如XmlWebApplicationContext,其他情况下会抛出异常。然后"scope=request"的工作方式就是外部发起一个请求后,web层(servlet)启用一个线程来响应这个请求。到了业务层面我们需要指定一些bean来处理这个请求,当这些bean设定为request时,那么它仅仅用于这一次请求就抛弃。下一次请求出现时会创建一个新的实例。

所以不管是request、session、application还是websocket,实际上都是通过prototype模式创建的实例,也就是设计模式中的原型模式,虽然并不一定是教科书般的标准,但是在整个容器中他实现了原型的特性。

 

Spring表达式语言:避免硬编码值,运行时注入值

***属性占位符: 占位符的形式为使用“${ ... }”

         注入外部的值:

声明属性源

@PropertySource("classpath:application.properties")

通过Spring的Environment来检索属性。

@Configuration

@PropertySource("classpath:application.properties")

public class CDConfig {

    @Autowired

    Environment env;

    @Bean

    public CompactDisc sgtPeppers(){

        return new SgtPeppers(

               env.getProperty("disc.title"),

               env.getProperty("disc.artist","不知名作者")//设置默认值      

);

    }

}

                  没有配置文件,隐式声明的bean注入外部值时直接在构造器中使用@Value注解

SgtPeppers(@Value("${disc.title} ") String title,

@Value("${disc.artist} ") String artist){

        this.artist=artist;

        this.title=title;

    }

                  XML注入外部值

        

 

*** 深入学习Spring的Environment

属性相关

获取属性值的方法并不唯一:getProperty有四个重载的变形形式

String getProperty(String key);

    String getProperty(String key, String defaultValue);

    T getProperty(String key, Class targetType);

T getProperty(String key, Class targetType, T defaultValue);

例:env.getProperty("db.connection.count",Integer.class,30);

         getRequiredProperty()获取的属性必须定义,否则抛出出IllegalStateException异常

         用Environment的containsProperty()方法:检查属性是否存在

         属性解析为类用getPropertyAsClass()方法:

env.getPropertyAsClass("disc.class",CompactDisc.class);

检查哪些profile处于激活状态:

String[] getActiveProfiles():返回激活profile名称的数组;

String[] getDefaultProfiles():返回默认profile名称的数组;

boolean acceptsProfiles(String... profiles):如果environment支持给定profile的话,就返回true。

***解析属性占位符

         使用占位符必须先配置:PropertyPlaceHolderConfigurer bean或者

PropertySourcesPlaceHolderConfigurer bean(推介使用,可以给予environment及其属性源来解析占位符)

                   在JavaConfig中配置

@Bean

    public PropertySourcesPlaceholderConfigurer placeholderConfigurer(){

        return new PropertySourcesPlaceholderConfigurer();

    }

在XML中配置:Spring context命名空间中的元素将会为你生成PropertySourcesPlaceholderConfigurer bean:

****解析外部属性能够将值的处理推迟到运行时,但是它的关注点在于根据名称解析来自于Spring

Environment和属性源的属性。而Spring表达 式语言提供了一种更通用的方式在运行时计算所要注入的值。

***Spring表达式(SEL,使用spring表达式语言进行装配)表达式要放在 “#{ ... }”之中

 

        

JAVA注解详解:https://blog.csdn.net/sw5131899/article/details/54947192

java中元注解有四个: @Retention @Target @Document @Inherited;

@Retention:注解的保留位置

@Retention(RetentionPolicy.SOURCE)  //注解仅存在于源码中,在class字节码文件中不包含

@Retention(RetentionPolicy.CLASS)     // 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得,

@Retention(RetentionPolicy.RUNTIME)  // 注解会在class字节码文件中存在,在运行时可以通过反射获取到

@Target:注解的作用目标

        @Target(ElementType.TYPE) //接口、类、枚举、注解

        @Target(ElementType.FIELD) //字段、枚举的常量

        @Target(ElementType.METHOD) //方法

        @Target(ElementType.PARAMETER) //方法参数

        @Target(ElementType.CONSTRUCTOR) //构造函数

        @Target(ElementType.LOCAL_VARIABLE)//局部变量

        @Target(ElementType.ANNOTATION_TYPE)//注解

        @Target(ElementType.PACKAGE) ///包

    @Document:说明该注解将被包含在javadoc中

@Inherited:说明子类可以继承父类中的该注解


第四章、面向切面的Spring

AOP还需要再学习

面向切面编程:分离横切关注点(散布于应用多处的功能,如日志、安全和事务管理)与业务逻辑

面向切面编程的基本原理

通过POJO创建切面

使用@AspectJ注解

为AspectJ切面注入依赖:横切关注点被模块化为特殊的类,这些类称为切面

优点:1)每个关注点都集中在一个地方分散在代码各处;

           2)服务模块更简洁,只需关注核心功能的业务代码

AOP术语:

  1. 通知(advice):切面的工作被称为通知,做什么及何时做
  2. 前置通知(Before):在目标方法被调用之前调用通知功能;
  3. 后置通知(After):在目标方法完成之后调用通知,此时不会关心方法的输出是什么;
  4. 返回通知(After-returning):在目标方法成功执行之后调用通知;
  5. 异常通知(After-throwing):在目标方法抛出异常后调用通知;
  6. 环绕通知(Around):包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为
  7. 切点(pointcut):切点的定义会匹配通知所要织入的一个或多个连接点。定义通知何处
  8. 连接点(join point):连接点是在应用执行过程中能够插入切面的一个点
  9. 切面(Aspect):切面是通知和切点的结合,知道是什么和何时何处
  10. 引入(Inteoduction):引入允许我们向现有的类添加新方法或属性
  11. 织入(Weaving):把切面应用到目标对象并创建新的代理对象的过程。

         在对象的生命周期中有多个点可以织入

编译期:切面在目标类编译时被织入。这种方式需要特殊的编译器。AspectJ的织入编译器就是以这种方式织入切面的。

类加载期:切面在目标类加载到JVM时被织入。这种方式需要特殊的类加载器(ClassLoader),它可以在目标类被引入应用之前增 强该目标类的字节码。AspectJ 5的加载时织入(load-time weaving,LTW)就支持以这种方式织入切面。

运行期:切面在应用运行的某个时刻被织入。一般情况下,在织入切面时,AOP容器会为目标对象动态地创建一个代理对象。Spring AOP就是以这种方式织入切面的。                                                              Spring基础(一)_第7张图片

 

Spring AOP(基于动态代理)

Spring提供 了4种类型的AOP支持:

基于代理的经典Spring AOP;

纯POJO切面;

@AspectJ注解驱动的切面;

注入式AspectJ切面(适用于Spring各版本)

** 前三种都是Spring AOP实现的变体,Spring AOP构建在动态代理基础之上,因此,Spring对AOP的支持局限于方法拦截。

借助Spring的aop命名空间(XML配置)

注解驱动的AOP

定义切点(使用AspectJ的切点表达式语言)

         Spring AOP只支持AspectJ切点指示器的一个子集,在Spring中尝试使用AspectJ其他指示器时,将会抛出IllegalArgument-Exception异常

         Spring引入新的bean()指示器

***创建切面类

         @Aspect:表明这是一个切面类,AspectJ自动代理会为使用@Aspect注解的bean创建一个代理

         @Pointcut(“切点表达式”):定义命名的切点

         @Before @After @Around @AfterReturning @AfterThrowing :五种通知方式

     装配切面类

***启动自动代理

         JavaConfig在配置类的类级别上使用@EnableAspectJAutoProxy启用自动代理功能

使用XML的aop命名空间

***创建环绕通知:ProceedingJoinPoint的proceed()方法。

         接受ProceedingJoinPoint作为参数,该对象必须要有。

***处理通知中的参数

***通过注解引入新功能

         1)创建切面类,添加@DeclareParents注解:为对象添加新方法

@DeclareParents(value ="com.Performance+",defaultImpl=DefaultEncoreable.class)

public static Encoreable encoreable;

value属性指定了哪种类型的bean要引入该接口。在本例中,也就是所有实现Performance的类型。(标记符后面的加号表示是Performance的所有子类型,而不是Performance本身。)

defaultImpl属性指定了为引入功能提供实现的类。在这里,我们指定的是DefaultEncoreable提供实现。

@DeclareParents注解所标注的静态属性指明了要引入了接口。在这里,我们所引入的是Encoreable接口

2)在Spring中将该切面类声明为一个bean

* Spring的自动代理机制获取到切面类bean的声明,当Spring发现一个bean使用了@Aspect注解时,Spring就会创建一个代理,然后将调用委托给被代理的bean或被引入的实现,这取决于调用的方法属于被代理的bean还是属于被引入的接口。

*** Spring XML配置中声明切面:借用Spring 的aop命名空间

AOP配置元素及用途

定义AOP通知器

定义AOP后置通知(不管被通知的方法是否执行成功)

定义AOP返回通知

定义AOP异常通知

定义AOP环绕通知

定义一个切面

启用@AspectJ注解驱动的切面

定义一个AOP前置通知

顶层的AOP配置元素。大多数的元素必须包含在元素内

以透明的方式为被通知的对象引入额外的接口,添加新功能

定义一个切点

XML中通过切面引入新功能

implement-interface="com.Encoreable"

types-matching="com.Performance"

delegate-ref="defaultEncoreable"/>

***注入AspectJ

使用factory-method来调用asepctOf() 

Spring 的IOC和AOP

https://www.jianshu.com/p/40d0a6ad21d2


第二部分:SpringWeb

构建Spring Web应用程序

映射请求到Spring控制器

透明地绑定表单参数

 

一、跟踪SpringMVC请求

请求从离开浏览器开始到获取响应返回,它会经历好多站,在每站都会留下一些信息同时也会带上其他信息。图5.1 展示了请求使用Spring MVC所经历的所有站点。                                                                          Spring基础(一)_第8张图片

 

二、搭建SpringMVC (简单搭建,近运行控制器)

1.      配置DispatcherServlet

         Web.xml替代方式:扩展AbstractAnnotationConfigDispatcherServletInitializer类;

DispatcherServlet启动时创建Spring应用上下文:加载包含web组件的bean

ContextLoaderListener创建另外的应用上下文,加载应用中的其他bean,如:驱动应用后端的中间层和数据层组件

2.  启动springMVC

         1)启用注解驱动的springMVC : @EnableWebMvc

         2)编写基本控制器:@Controller @RequestMapping

         3) 使用mockmvc测试控制器

         4) 定义类级别的请求处理:将@RequestMapping加到类上@RequestMapping接受一个String类型的数组

         5)传递模型数据到视图中

3.处理查询参数

查询参数(Query Parameter)@RequestParam(value="max" ,defaultValue= "10") long max

路径变量(Path Variable)@PathVariable

** 在理想情况下,要识别的资源应该通过URL路径进行标示,而不是通过查询参数。从面向资源的角度来看,对“/spittles/12345”发起GET请求要优于对“/spittles/show?spittle_id=12345”发起请求。前者能够识别出要查询的资源,而后者描述的是带有参数的一个操作——本质上是通过HTTP发 起的RPC。

处理表单:表单参数(Form Parameter)  POST请求

return "redirect:/spitter/"+spitter.getUserName;

当InternalResourceViewResolver看到视图格式中的“redirect:”前缀时,它就知道要将其解析为重定向的规则,而不是视图的名称。本例中,它将会重定向到用户基本信息的页面。例如,如果Spitter.username属性的值为“jbauer”,那么视图将会重定向 到“/spitter/jbauer”。

校验表单

* 使用Spring对Java校验API(Java Validation API,又称JSR-303)的支持

         * 比如Hibernate Validator,在类路径下包含相关依赖包即可

* Java校验API定义了多个注解,这些注解可以放到属性上,从而限制这些属性的值。所有的注解都位于javax.validation.constraints包中。

注  解        描  述

@AssertFalse  所注解的元素必须是Boolean类型,并且值为false

@AssertTrue   所注解的元素必须是Boolean类型,并且值为true

@DecimalMax   所注解的元素必须是数字,并且它的值要小于或等于给定的BigDecimalString

@DecimalMin   所注解的元素必须是数字,并且它的值要大于或等于给定的BigDecimalString值

@Digits        所注解的元素必须是数字,并且它的值必须有指定的位数

@Future        所注解的元素的值必须是一个将来的日期

@Max           所注解的元素必须是数字,并且它的值要小于或等于给定的值

@Min           所注解的元素必须是数字,并且它的值要大于或等于给定的值

@NotNull       所注解元素的值必须不能为null

@Null          所注解元素的值必须为null

@Past          所注解的元素的值必须是一个已过去的日期

@Pattern       所注解的元素的值必须匹配给定的正则表达式

@Size          所注解的元素的值必须是String、集合或数组,并且它的长度要符合给定的范围

添加校验注解

启用校验功能:

在controller层方法的要校验的参数上添加@Valid注解,并传入一个Errors对象来检查校验失败(Errors参数要紧跟在带有@Valid注解的参数后面)

方法中首先调用Errors的hasErrors方法检查是否有错误

if (errors.hasErrors())
    return "errors";

SpringMVC的高级技术

将DispatcherServlet配置到web.xml中

自定义DispatcherServlet:对Abstract-AnnotationConfigDispatcherServletInitializer类的其他方法进行重载,以实现额外的配置

必须重载的三个方法

public class SpittrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override

//将一个或多个路径映射到DispatcherServlet上。
    protected Class[] getRootConfigClasses() {
        return new Class[] {RootConfig.class};
    }
    //指定配置位置

@Override
    protected Class[] getServletConfigClasses() {
        return new Class[] {WebConfig.class};
    }
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

@Override
protected void customizeRegistration(ServletRegistration.Dynamic registration){
    registration.setMultipartConfig(new      

MultipartConfigElement("/tmp/spittr/uploads")); //处理multipart请求和文件上传
}

}

***借助customizeRegistration()方法中的ServletRegistration.Dynamic,我们能够完成多项任务,包括通过调用setLoadOnStartup()设置load-on-startup优先级,通过setInitParameter()设置初始化参数,通过调 用setMultipartConfig()配置Servlet 3.0对multipart的支持。在前面的样例中,我们设置了对multipart的支持,将上传文件的临时存储目录设置在“/tmp/spittr/uploads”中。

添加其他的servlet和filter

添加其他的servlet和filter,只需创建一个新的初始化器就可以了。最简单的方式就是实现Spring的WebApplicationInitializer接口。

JavaConfig

@Override
public void onStartup(ServletContext servletContext) throws ServletException{
    //注册servlet
    Registration.Dynamic myServlet = servletContext.addServlet("myServlet",MyServlet.class);
    //映射servlet
    myServlet.addMapping("/custom/*");
}
  //注册filter
@Override
public void onStartup(ServletContext servletContext) throws ServletException{
    javax.servlet.FilterRegistration.Dynamic filter=
            servletContext.addFilter("myFilter",MyFilter.class);
    filter.addMappingForUrlPatterns(null,false,"/customs/*");
}

在webxml中声明DispatcherServlet:

典型的Spring MVC应用中,我们会需要DispatcherServlet和Context-LoaderListener。AbstractAnnotationConfigDispatcherServletInitializer会自动注册它们,但是如果需要在web.xml中注册的 话,那就需要我们自己来完成这项任务了。



    contextClass
   
        org.springframework.web.context.support.AnnotationConfigWebApplicationContext
   




    contextConfigLocation
    /WEB-INF/spring/root-context.xml



   
        org.springframework.web.context.ContextLoaderListener
   




    appServlet
   
        org.springframework.web.servlet.DispatcherServlet
   

   
        contextConfigLocation
        /WEB-INF/spring/appServlet/servlet-context.xml
   

    1



    appServlet
    /

 

*********处理mutilpart形式数据:使用SpringMVC实现文件上传

  1. 配置multipart 解析器,通过它来告诉DispatcherServlet该如何读取multipart请求。

借助MultipartResolver策略接口的实现类来解析multipart请求中的内容。从Spring 3.1开始,Spring内置了两个MultipartResolver的实现供我们选择:

  1. CommonsMultipartResolver:使用Jakarta Commons FileUpload解析multipart请求;
  2.  StandardServletMultipartResolver:依赖于Servlet 3.0对multipart请求的支持(始于Spring 3.1)。它使用Servlet所提供的功能支持,并不需要依赖任何其他的项目,比CommonsMultipartResolver更优。
  3. 例:使用StandardServletMultipartResolver兼容3.0的无参构造器

第一步:将StandardServletMultipartResolver声明为bean

@Bean
public MultipartResolver multipartResolver()throws IOException {
    return new StandardServletMultipartResolver();
}

第二步:在Servlet中指定multipart的配置。(写入的文件临时路径,限制上传文件大小等)

使用servlet初始化类的方式来配置DispatcherServlet,初始化类已经实现了WebApplicationInitializer

public void onStartup(ServletContext servletContext) throws ServletException{

 DispatcherServlet ds=new DispatcherServlet();

 //注册servlet

 ServletRegistration.Dynamic myServlet = servletContext.addServlet("myServlet",ds);

 //映射servlet

 myServlet.addMapping("/custom/*");

 //设置临时路径

myServlet.setMultipartConfig(new MultipartConfigElement("tmp/spittr/upload"));

}

配置DispatcherServlet的Servlet初始化类继承了Abstract AnnotationConfigDispatcherServletInitializer或AbstractDispatcher-ServletInitializer

protected void customizeRegistration(ServletRegistration.Dynamic registration){

        registration.setMultipartConfig(new MultipartConfigElement("/tmp/spittr/uploads"));

}//重载customizeRegistration()方法

只有一个参数的MultipartConfigElement构造器,这个参数指定的是文件系统中的一个绝对目录,上传文件 将会临时写入该目录中。

  1. 除了临时路径的位置,其他的构造器所能接受的参数有:

*上传文件的最大容量(以字节为单位)。默认是没有限制的。

*整个multipart请求的最大容量(以字节为单位),不会关心有多少个part以及每个part的大小。默认是没有限制的。

*在上传的过程中,如果文件大小达到了一个指定最大容量(以字节为单位),将会写入到临时文件路径中。默认值为0,也就是所有上传 的文件都会写入到磁盘上。

  1. 例:限制文件的大小不超过2MB,整个请求不超过4MB,所有的文件写到磁盘中。下面的代码使 用MultipartConfigElement设置了这些临界值:

protected void customizeRegistration(ServletRegistration.Dynamic registration){

        registration.setMultipartConfig(new

                MultipartConfigElement(

                //参数:location,maxFileSize,maxRequestSize,FileSizeThreshold

                        "/tmp/spittr/uploads",2097152,4194304,0

        ));

}

使用web.xml配置MultipartConfigElement,可以使用中的元素, 如下所示:的默认值与MultipartConfigElement相同。与MultipartConfigElement一样,必须要配置的 是

        appServlet

       

            org.springframework.web.servlet.DispatcherServlet

       

        1

       

            /tmp/spittr/uploads

            2097152

            4194304

       

 

配置3.0以前的MutilpartResolver

将CommonsMultipartResolver声明为Spring bean

@Bean

    public MultipartResolver commonsMultiPartResolver() throws IOException{

        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();

         multipartResolver.setUploadTempDir(/spittr/uploads/);

         multipartResolver.setMaxUploadSize(2097152);

         multipartResolver.setMaxInMemorySize(0);

        return multipartResolver;

}

 

修改html,

标签将enctype属性设置为multipart/form-data,这会告诉浏览器以multipart数据的形式提交表单,而不是以表单数据的 形式进行提交。在multipart中,每个输入域都会对应一个part。

**编写controller处理mutilpart请求

方式一:添加byte数组参数,为其添加@RequestPart注解

@RequestMapping(value = "/add",method = RequestMethod.POST)

    public String addSpitter(

            @RequestPart("profilePicture") byte[]  profilePicture,

            @Valid  Spitter spitter , Errors errors){

     ……

}

 

         方式二:接受MultiPartFile对象:

         Spring提供MultiPartFile接口,MultipartFile提供了获取上传文件byte的方式,还能获得原始的文件名、大小以及内 容类型。它还提供了一个InputStream用来将文件数据以流的方式进行读取。还提供了一个便利的transferTo()方法,它能够帮助我们将上传的文件写入到文件系统中。

        

public String addSpitter(

            @RequestPart("profilePicture")  MultipartFile profilePicture,

            @Valid  Spitter spitter , Errors errors) throws IOException{

        //将上传的图片文件写到文件系统

        profilePicture.transferTo(new File("/spittr/data"+profilePicture.getOriginalFilename()));

}

         方式三:将MultipartFile保存到Amazon S3中

         Spring 3.0容器中javax.servlet.http.Part替代MultipartFile

public String addSpitter(

            @RequestPart("profilePicture")  Part profilePicture,

            @Valid  Spitter spitter , Errors errors) throws IOException{

        //将上传的图片文件写到文件系统

        profilePicture.transferTo(new File("/spittr/data"+profilePicture.getOriginalFilename()));

}

***如果在编写控制器方法的时候,通过Part参数的形式接受文件上传,那么就没有必要配置MultipartResolver了。只有使用MultipartFile的时候,我们才需要MultipartResolver。

 

处理异常:Spring提供多种方式将异常转换为servlet响应

  1. 特定的Spring异常将会自动映射为指定的HTTP状态码;(由Spring自身抛出)
  2. 异常上可以添加@ResponseStatus注解,从而将其映射为某一个HTTP状态码;
  3. 在方法上可以添加@ExceptionHandler注解,使其用来处理异常。

将异常映射为某一个HTTP状态码:(在方法上添加异常,SpittleNotFound自定义异常)

@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "SpittleNotFound")

编写异常处理的方法

         在处理请求的controller中直接处理异常

catch (DuplicateSpittleException de){
    return "errer/duplicate";
}

         使用@ExceptionHandler注解,能处理同一个控制器中所有处理器方法所抛出的异常。

@ExceptionHandler(DuplicateSpittleException.class)
public String handlerDuplicateException(){
    return "error/duplicate";
}

为控制器添加通知,使用@ControllerAdvice:这个类会包含一个或多个如下类型的方法:

  1. @ExceptionHandler注解标注的方法;
  2. @InitBinder注解标注的方法;
  3. @ModelAttribute注解标注的方法。

@ControllerAdvice将所有的@ExceptionHandler方法收集到一个类中,这样所有控制器的异常就能在一个地方进行一致的处理

@ControllerAdvice
public class AppWideExceptionHandler  {
    @ExceptionHandler
    public String duplicateExceptionHandler(){
        return "error/duplicate";
    }
}

 

***跨重定向请求传递数据

从发起重定向的方法传递数据给处理重定向方法中:

  1. 使用URL模板以路径变量和/或查询参数的形式传递数据;

username作为占位符填充到了URL模板中,而不是直接连接到重定向String中,所以username中所有的不安全字符都会进行转义。

@RequestMapping(value = "/register",method = POST)
public String ProcessRegistration(Spitter spitter, Model model){
    model.addAttribute("userName",spitter.getUserName());
    model.addAttribute("spitterId",spitter.getUserId());
    return "redirect:/register/{userName}";
    //得到的重定向URL路径将会是“/spitter/habuma? spitterId=42”。
}

 

  1. 通过flash属性发送数据。

使用Spring提供的RedirectAttributes(Model的子接口)来设置flash属性;在重定向执行之前,所有的flash属性都会复制到会话中。在重定向后,存在会话中的flash属性会被取出,并从会话转移到模型之中。处理重定向的方法就能从模型中访问Spitter对象了,就像获取其他的模型对象一样。

@RequestMapping(value = "/register",method = POST)
public String ProcessRegistration(Spitter spitter, RedirectAttributes model){
    model.addAttribute("userName",spitter.getUserName());
    //spitter作为key,Spitter对象作为值。也可以不设置key,根据值类型自动推断
    model.addFlashAttribute("spitter",spitter);
    return "redirect:/register/{userName}";
}


Servlet

https://blog.csdn.net/lunatic_xian/article/details/53040941

https://www.cnblogs.com/whgk/p/6399262.html

https://blog.csdn.net/x_iya/article/details/80210497

Spring基础(一)_第9张图片

  1. Servlet:生命周期

         Init();   service();  destroy();

  1. ServletConfig:

在应用初始化的时候,Web容器在创建Servlet对象时会自动将web.xml中的servlet配置这些初始化参数封装到ServletConfig对象中,并在调用servlet 的init方法时,将ServletConfig对象传递给servlet。所以我们可以通过ServletConfig对象就可以得到当前servlet的初始化参数信息。

  1. ServletContext:

Servlet的应用上下文

         功能:tomcat为每个web项目都创建一个ServletContext实例,tomcat在启动时创建,服务器关闭时销毁,在一个web项目中共享数据,管理web项目资源,为整个web配置公共信息等,通俗点讲,就是一个web项目,就存在一个ServletContext实例,每个Servlet读可以访问到它。

Spring基础(一)_第10张图片

 

 

Spring基础(一)_第11张图片


Web安全:

Spring Security:

  1. Spring Securuty的11个模块:
  1. ACL 支持通过访问控制列表(access control list,ACL)为域对象提供安全性
  2. 切面(Aspects) 一个很小的模块,当使用Spring Security注解时,会使用基于AspectJ的切面,而不是使用标准的Spring AOP
  3. CAS客户端(CAS Client) 提供与Jasig的中心认证服务(Central Authentication Serv ice,CAS)进行集成的功能配置(Configuration)包含通过XML和Java配置Spring Security的功能支持
  4. 核心(Core) 提供Spring Security基本库
  5. 加密(Cryptography) 提供了加密和密码编码的功能
  6. LDAP 支持基于LDAP进行认证
  7. OpenID 支持使用OpenID进行集中式认证
  8. Remoting 提供了对Spring Remoting的支持
  9. 标签库(Tag Library) Spring Security的JSP标签库
  10. Web 提供了Spring Security基于Filter的Web安全性支持
  1. 过滤web请求,配置filter:DelegatingFilterProxy
  2. 启用web security :

Spring Security必须配置在一个实现了WebSecurityConfigurer的bean中,或者(简单起见)扩展WebSecurityConfigurerAdapter。

@EnableWebSecurity

使用springMVC开发的程序@EnableWebMvcSecurity

  1. 指定Web安全的细节:

重载WebSecurityConfigurerAdapter的configure()方法

configure(WebSecurity) 通过重载,配置Spring Security的Filter链

configure(HttpSecurity) 通过重载,配置如何通过拦截器保护请求

configure(AuthenticationManagerBuilder) 通过重载,配置user-detail用户存储服务

 

  1. 配置用户存储:protected void configure(AuthenticationManagerBuilder auth) throws Exception{  …   }

内存

关系型数据库

LDAP

自定义用户服务

  1. 拦截请求:protected void configure(HttpSecurity http) throws Exception{   …   }

定义如何保护路径的方法

  1. access(String) 如果给定的SpEL表达式计算结果为true,就允许访问
  2. anonymous() 允许匿名用户访问
  3. authenticated() 允许认证过的用户访问
  4. denyAll() 无条件拒绝所有访问
  5. fullyAuthenticated() 如果用户是完整认证的话(不是通过Remember-me功能认证的),就允许访问
  6. hasAnyAuthority(String...) 如果用户具备给定权限中的某一个的话,就允许访问
  7. hasAnyRole(String...) 如果用户具备给定角色中的某一个的话,就允许访问
  8. hasAuthority(String) 如果用户具备给定权限的话,就允许访问
  9. hasIpAddress(String) 如果请求来自给定IP地址的话,就允许访问
  10. hasRole(String) 如果用户具备给定角色的话,就允许访问
  11. not() 对其他访问方法的结果求反
  12. permitAll() 无条件允许访问
  13. rememberMe() 如果用户是通过Remember-me功能认证的,就允许访问

**这些规则会按照给定的顺序发挥作用。所以,很重要的一点就是将最为具体的请求路径放在前面,而最不具体的路径(如anyRequest())放在最后面。如果不这样做的话,那不具体的路径配置将会覆盖掉更为具体的路径配置。

  1. 使用SPEL进行安全保护:Spring Secucurity通过一些安全性相关的表达式扩展了Spring表达式语言。
  2. 强制的安全通道:在配置中添加requiresChannel()方法自动将选定的URL重定向到HTTPS上。对不需要HTTPS传送的可以使用requiresInsecure()方法声明为通过HTTP传送。
  3. 防止跨站请求伪造:Spring Security通过一个同步token的方式来实现CSRF防护的功能。默认启用。

Spring Security 简化了将token放到请求的属性中这一任务。

标签的action属性添加Thymeleaf命名空间前缀,就会自动生成一个“_csrf”隐藏域:      

JSP :

;

在配置中禁用spring security的csrf防护功能:csrf().disable()

  1. 启用http basic

在configure()方法所传入的HttpSecurity对象上调用httpBasic()即可                                 

  1. 启用remember me功能:在configure()方法所传入 的HttpSecurity对象上调用rememberMe()即可。默认情况下,这个功能是在cookie中存储一个session完成的。存储在cookie中的token包含用户名、密码、过期时间和一个私钥——在写入cookie前都进行了MD5哈希。
  2. 添加退出功能

在configure()中调用logout()方法配置退出行为: logoutSuccessUrl()表明在退出成功之后,浏览器重定向的URL。调用logoutUrl重写LougoutFilter的默认拦截路径。

 

保护视图:

  1. Spring Security的JSP标签库:只包含三个标签

如果用户通过访问控制列表授予了指定的权限,那么渲染该标签体中的内容

渲染当前用户认证对象的详细信息

如果用户被授予了特定的权限或者SpEL表达式的计算结果为true,那么渲染该标签体中的内容

  1.  
  2.  

 

 

第三部分:后端中的spring

第十章:Spring JDBC:Spring基础(一)_第12张图片

遵循“面向接口编程原则”

  1. Spring提供平台无关的持久化异常,均继承自DataAccessException,这是一个非检查型异常,没有必要捕获Spring抛出的数据访问异常。因为触发异常的很多问题不能在catch代码块中修复。
  2. Spring数据访问模板(模板方法模式)

为多种持久化框架提供支持,Spring所支持的大多数持久化功能都依赖数据源。

  1. 配置数据源,在spring上下文配置数据源bean的多种方式,包括:
  1. 通过JDBC驱动程序定义的数据源;

DriverManagerDataSource

SimpleDriverDataSource

SingleConnectionDataSource:

  1. 通过JNDI查找的数据源;

位于jee命名空间下的元素可以用于检索JNDI中的任何对象(包括数据源)并将其作为Spring的bean。


   

                   使用java配置可以借助JndiObjectFactoryBean从JNDI中查找DataSource

  1. 连接池的数据源。如下开源实现

*Apache Commons DBCP (http://jakarta.apache.org/commons/dbcp);

*c3p0 (http://sourceforge.net/projects/c3p0/) ;

*BoneCP (http://jolbox.com/)

      destroy-method="close">
   
   
   
   

  1. 使用jdbc命名空间配置嵌入式数据库
  2. 使用profile选择数据源
  1.  

 

第十一章:使用对象-关系映射持久化数据

持久化层更复杂的特性:

  1. 延迟加载
  2. 预先抓取
  3. 级联

Spring对ORM框架的支持和集成及附加服务

  1. 支持集成Spring声明式事务;
  2. 透明的异常处理;
  3. 线程安全的、轻量级的模板类;
  4. DAO支持类;
  5. 资源管理。
  1. Sring中集成hibernate

声明hibernate seesion工厂:org.hibernate.Session接口提供了基本的数据访问功能,保存、更新、删除及从数据库加载对象的功能。

通过Hibernate的Session接口,应用程序的Repository能够满足所有的持久化需求。 获取Hibernate Session对象的标准方式是借助于Hibernate SessionFactory接口的实现类。Session Factory主要负责hibernate Session 的打开关闭以及管理。

构建不依赖于spring的hibernate代码

 

  1. Spring 与Java 持久化API(JPA)

配置实体管理工厂(实体管理器工厂由对应的spring工厂bean创建)

 

LocalEntityManagerFactoryBean生成应用程序管理类型的EntityManager-Factory; LocalContainerEntityManagerFactoryBean生成容器管理类型的Entity-ManagerFactory。

  1. 配置应用程序管理类型的JPA:大部分配置信息来源于persistence.xml(位于类路径下的META-INF目录),作用是定义一个或多个持久化单元(< persistence-unit >),识别持久化单元中的实体类

在Spring上下文中声明LocalEntityManagerFactoryBean

  1. 使用容器管理类型的JPA:用@Bean注解,直接用LocalContainerEntity-ManagerFactoryBean来配置容器管理类型的JPA
  2. 从JNDI获取实体管理工厂
  3. 编写基于JPA的repository:@PersistenceUnit

*EntityManager并不是线程安全的

         何借助@PersistentContext注解为JpaSpitterRepository设置EntityManager,将EntityManager的代理注入到Repository中:@PersistenceContext

***@PersistenceUnit和@PersistenceContext不是spring的注解,是由JPA规范提供的,因此要配置Spring的PersistenceAnnotationBeanPostProcessor

***将PersistenceExceptionTranslationPostProcessor,作为一个bean装配到Spring中,使用@Repository注解可以抛出spring体系下的异常。

  1. 借助spring data JPA实现自动化的Repository

借助spring data ,以接口的形式创建repository;

从一组接口中挑选一个进行扩展:

//JpaRepository进行了参数化,所以它就能知道这是一个用来持久化Pizza对象的Repository,并且Pizza的ID类型为Long

//继承18个进行持久化操作的通用方法

         让spring来创建repository的实现:在XML配置中启用spring data JPA


         JAVA配置中启用@EnableJpaRepositories(basepackage=””)

 

为Spring data JPA编写自定义查询方法;

(1)通过属性名和关键字构建repository方法签名,让spring data JPA自动实现查询方法

Spring基础(一)_第13张图片

***要查询的对象类型是通过如何参数化JpaRepository接口来确定的,而不是方法名称中的主题。

***断言可指定比较操作符

(2)声明自定义查询:@Query

(3)混合自定义的功能:使用被注入的EntityManager来完成预期目标;将编写的实现类与repository接口关联起来的是基于借口名称。RepositoryImpl对应Repository接口(Impl类不需要直接继承Repository接口)

         指定后缀:在配置@EnableJpa-Repositories的时候,设置repositoryImplementationPostfix属性;或者在XML中配置

 

本章内容:

为MongoDB和Neo4j编写Repository 为多种数据存储形式持久化数据 组合使用Spring和Redis

 

12.3使用redis操作key-value数据

使用redis模板来完成redis数据库的存取

  1. 连接到redis:redis连接工厂会生成到redis数据库服务器的连接;spring data redis为四种redis客户端实现提供了连接工厂:

JedisConnectionFactory;

JredisConnectionFactory;

LettuceConnectionFactory;

SrpConnectionFactory;

将连接工厂配置为spring中的bean

  1. 使用redis Template:Spring Redis Template 提供连个模板

Redis Template :极大化简redis访问,可持久化各种类型的k-v,并不局限于字节数组。

StringRedisTemplate:扩展自RedisTemplate 只关注String类型。

通过RedisTemplate(和StringRedisTemplate)调用子接口的提供的数据条目操作:

  1. opsForValue() ValueOperations 操作具有简单值的条目
  2. opsForList() ListOperations 操作具有list值的条目
  3. opsForSet() SetOperations 操作具有set值的条目
  4. opsForZSet() ZSetOperations 操作具有ZSet值(排序的set)的条目
  5. opsForHash() HashOperations 操作具有hash值的条目
  6. boundValueOps(K) BoundValueOperations 以绑定指定key的方式,操作具有简单值的条目
  7. boundListOps(K) BoundListOperations 以绑定指定key的方式,操作具有list值的条目
  8. boundSetOps(K) BoundSetOperations 以绑定指定key的方式,操作具有set值的条目
  9. boundZSet(K) BoundZSetOperations 以绑定指定key的方式,操作具有ZSet值(排序的set)的条目boundHashOps(K) BoundHashOperations 以绑定指定key的方式,操作具有hash值的条

 

  1. 使用k-v的序列化器
  1. GenericToStringSerializer:使用Spring转换服务进行序列化;
  2. JacksonJsonRedisSerializer:使用Jackson 1,将对象序列化为JSON;
  3. Jackson2JsonRedisSerializer:使用Jackson 2,将对象序列化为JSON;
  4. JdkSerializationRedisSerializer:使用Java序列化;
  5. OxmSerializer:使用Spring O/X映射的编排器和解排器(marshaler和unmarshaler)实现序列化,用于XML序列化;
  6. StringRedisSerializer:序列化String类型的key和value

 

 

 

第十三章:缓存数据,spring对缓存功能提供声明式支持,对多种流行缓存实现了进行集成。

启用声明式缓存

使用Ehcache、Redis、和Gemfire实现缓存功能

注解驱动的缓存

  1. spring对缓存的支持:

注解驱动的缓存

XML声明的缓存

**启用注解驱动的缓存

Javaconfig:

@EnableCaching //启用注解驱动的缓存

//声明缓存管理器
@Bean
public CacheManager cacheManager(){
    return  new ConcurrentMapCacheManager();
}

 

XML:




 

***@EnableCaching和的工作方式是相同的。它们都会创建一个切面(aspect)并触发 Spring缓存注解的切点(pointcut)。根据所使用的注解以及缓存的状态,这个切面会从缓存中获取数据,将数据添加到缓存之中或者从缓存中移除某个值。

  1. 配置缓存处理器:

spring内置五个缓存管理器

  1. SimpleCacheManager
  2. NoOpCacheManager
  3. ConcurrentMapCacheManager
  4. CompositeCacheManager
  5. EhCacheCacheManager

Spring Data提供两个缓存管理器

  1. RedisCacheManager(来自于Spring Data Redis项目)
  2. GemfireCacheManager(来自于Spring Data GemFire项目)
  1. 使用Eache缓存

 

  1. 使用Redis缓存

Redis缓存管理器bean:RedisCachemanager

Redis连接工厂bean:JedisConnectionFactory

RedisTemplate bean:RedisTemplate

  1. 使用多个缓存管理器:

CompositeCacheManager要通过一个或多个缓存管理器来进行配置,它会迭代这些

缓存管理器,以查找之前所缓存的值。

配置完缓存管理器就可以在bean方法上应用缓存规则了。

  1. 为方法添加注解以支持缓存

Spring提供了四个注解来声明缓存规则

@Cacheable表明Spring在调用方法之前,首先应该在缓存中查找方法的返回值。如果这个值能够找到,就会返回缓存的值。否则的话,这个方法就会被调用,返回值会放到缓存之中

@CachePut 表明Spring应该将方法的返回值放到缓存中。在方法的调用前并不会检查缓存,方法始终都会被调用

@CacheEvict 表明Spring应该在缓存中清除一个或多个条目

@Caching 这是一个分组的注解,能够同时应用多个其他的缓存注解

  1. 填充缓存

@Cacheable和@CachePut注解都可以填充缓存

  1. value String[] 要使用的缓存名称
  2. condition String SpEL表达式,值是false的话,不会将缓存应用到方法调用上
  3. key String SpEL表达式,用来计算自定义的缓存key
  4. unless String SpEL表达式,如果得到的值是true的话,返回值不会放到缓存之中
  1. 自定义缓存key

Spring提供多个用来定义缓存规则的SpEL扩展

#root.args 传递给缓存方法的参数,形式为数组

#root.caches 该方法执行时所对应的缓存,形式为数组

#root.target 目标对象

#root.targetClass 目标对象的类,是#root.target.class的简写形式

#root.method 缓存方法

#root.methodName 缓存方法的名字,是#root.method.name的简写形式

#result 方法调用的返回值(不能用在@Cacheable注解上)

#Argument 任意的方法参数名(如#argName)或参数索引(如#a0或#p0

  1. 条件化缓存:unless和condition

 

  1. 移除缓存条目:@CacheEvict
  1. value String [] 要使用的缓存名称
  2. key String SpEL表达式,用来计算自定义的缓存key
  3. condition String SpEL表达式,如果得到的值是false的话,缓存不会应用到方法调用上
  4. allEntries b oolean 如果为true的话,特定缓存的所有条目都会被移除掉
  5. beforeInvocation b oolean 如果为true的话,在方法调用之前移除条目。如果为false(默认值)的话,在方法成功调用之后再移除条目

***  与@Cacheable和@CachePut不同,@CacheEvict能够应用在返回值为void的方法上,而@Cacheable和@CachePut需要非void回值,它将会作为放在缓存中的条目。而CacheEvict只是将条目从缓存中移除,因此它可以放在任意的方法上,甚至void方法。

  1. 使用XML声明缓存

Spring的cache命名空间提供了使用XML声明缓存规则的方法,因为缓存是一种面向切面的行为,因此cache命名空间会与Spring的aop命名空间结合起来使用,用来声明缓存所应用的切点在哪里。  

Spring的cache命名空间所提供的以XML方式配置缓存规则的元素

  1. 启用注解驱动的缓存。等同于Java配置中的@EnableCaching
  2. 定义缓存通知(adv ice)。结合,将通知应用到切点上
  3. 在缓存通知中,定义一组特定的缓存规则
  4. 指明某个方法要进行缓存。等同于@Cacheable注解
  5. 指明某个方法要填充缓存,但不会考虑缓存中是否已有匹配的值。等同于@CachePut注解
  6. 指明某个方法要从缓存中移除一个或多个条目,等同于@CacheEvict注解
  1. 例子


           pointcut="execution(*com.springinaction.pizza.dao.JpaPizzaRepository.*(..))"/>



   
   
       
       
       
   





 

 

第十四章:保护方法应用

  1. 保护方法调用
  2. 使用表达式定义安全规则
  3. 创建安全表达式计算器
  1. 使用注解保护方法
  1. Spring Security提供三种工不同的安全注解
  2. Spring Security自带的@Secured注解;
  3. JSR-250的@RolesAllowed注解;
  4. 表达式驱动的注解,包括@PreAuthorize、@PostAuthorize、@PreFilter和@PostFilter
  1. 使用@Security限制方法调用(Spring的特定注解)

启用基于注解的方法安全性,在配置类上使用@EnableGlobalMethodSecurity注解,且配置类扩展GlobalMethodSecurityConfiguration,能够为方法级别的安全性提供更精细的配置。

@EnableMethodSecurityConfiguration的securedEnabled属性值为true的话,将会创建一个切点,这样Spring Security切面就会包装带有@Secured注解的方法。

           ***@Secured注解会使用一个String数组作为参数。每个String值是一个权限,调用这个方法至少需要具备其中的一个权限。通

  1. 在Spring Security中使用JSR-250的@RolesAllowed注解;

@RolesAllowed是Java标准注解

将@EnableGlobalMethodSecurity的jsr250Enabled属性设置为true,以开启此注解功能(与securedEnable注解风格可以同时启用):这样带有@RolesAllowed注解的方法都会被SpringSecurity的方法包装起来。

***@Security和@RolesAllowed只能根据用户有没有授予特定的权限来限制方法的调用。在判断方式是否执行方面,无法使用其他的因素。

  1. 使用表达式实现方法级别的安全

Spring Security3.0提供的4个新的注解

**表述方法的访问规则

@PreAuthorize 在方法调用之前,基于表达式的计算结果来限制对方法的访问

@PostAuthorize 允许方法调用,但是如果表达式计算结果为false,将抛出一个安全性异常

**过滤方法的输入输出

@PostFilter 允许方法调用,但必须按照表达式来过滤方法的结果

@PreFilter 允许方法调用,但必须在进入方法之前过滤输入值

 

  1. 定义许可计算器,简化SpEL表达式

编写自定义许可计算器,实现Spring Security的PermissionEvaluator接口,需要实现两个不同的hasPermission()方法,一个hasPermission()方法把要评估的对象作为第二个参数。第二个hasPermission()方法在只有目标对象的ID可以得到的时候才有用,并将ID作为Serializable传入第二个参数。

将许可计算器注册到Spring Security中:重载GlobalMethodSecurityConfiguration的createExceptionHandler方法。

@EnableGlobalMethodSecurity(securedEnabled = true)
public class SpringSecurityConfig extends GlobalMethodSecurityConfiguration {
    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler(){
        DefaultMethodSecurityExpressionHandler expressionHandler=
                new DefaultMethodSecurityExpressionHandler();
        expressionHandler.setPermissionEvaluator(
                new PizzaPermissionEvaluator()
        );
        return  expressionHandler;
    }
}

         **现在,我们不管在任何地方的表达式中使用hasPermission()来保护方法,都会调用PizzaPermissionEvaluator来决定用户是否有权限调用方法。

 

 

第四部分:spring集成

第十六章:使用Spring MVC创建REST API

  1. 编写处理REST资源的控制器
  2. 以XML、JSON及其他格式来表述资源
  3. 使用REST资源
  1. Spring支持以下方式来创建REST资源:
  1. 控制器可以处理所有的HTTP方法,包含四个主要的REST方法:GET、PUT、DELETE以及POST。Spring 3.2及以上版本还支持PATCH 方法;
  2. 借助@PathVariable注解,控制器能够处理参数化的URL(将变量输入作为URL的一部分);
  3. 借助Spring的视图和视图解析器,资源能够以多种方式进行表述,包括将模型数据渲染为XML、JSON、Atom以及RSS的View实现;
  4. 可以使用ContentNegotiatingViewResolver来选择最适合客户端的表述;
  5. 借助@ResponseBody注解和各种HttpMethodConverter实现,能够替换基于视图的渲染方式;
  6. 类似地,@RequestBody注解以及HttpMethodConverter实现可以将传入的HTTP数据转化为传入控制器处理方法的Java对象;
  7. 借助RestTemplate,Spring应用能够方便地使用REST资源。
  1. Spring将资源的java表述形式转换为发送给客户端的表述形式:
  1. 内容协商(Cntent negotiation):选择一个视图,他能够将模型渲染为呈现给客户端的表述形式;

Spring的ContentNegotiatingViewResolver解析器:

  1. 确定请求的媒体类型 :首先查看URL的文件扩展名;

如果根据文件扩展名不能得到任何媒体类型的话,那就会考虑请求中的Accept头部信息;

扩展名和Accet都不包含的话,使用“/”作为默认的内容类型,这就意味着客户端必须要接收服务器发送的任何形式的表述。

  1. 找到适合请求媒体类型的最佳视图:

ContentNegotiatingViewResolver要求其他的视图解析器将逻辑视图名解析为视图。解析得到的每个视图都会放到一个列表中。这个 列表装配完成后,ContentNegotiatingViewResolver会循环客户端请求的所有媒体类型,在候选的视图中查找能够产生对应内容类型 的视图。第一个匹配的视图会用来渲染模型。

  1. 借助Content-NegotiationManager影响媒体类型的选择

有三种配置ContentNegotiationManager的方法:

        1. 直接声明一个ContentNegotiationManager类型的bean;
        2. 通过ContentNegotiationManagerFactoryBean间接创建bean;
        3. 重载WebMvcConfigurerAdapter的configureContentNegotiation()方法

优点:在Spring MVC之上构建了REST资源表述层,控制器代码无需修改。相同的一 套控制器方法能够为面向人类的用户产生HTML内容,也能针对不是人类的客户端产生JSON或XML。

  1. 消息转换器(Message conversion):将控制其产生的数据转换为服务于客户端的表述形式。

@ResponseBody注解会告知spring将返回的对象作为资源发送给客户端,并将其转化为客户端额可接受的资源表述形式;。更具体地讲,DispatcherServlet将会考虑到请求中Accept头部信息,并查找能够为客户端提供所需表述形式的消息转换器。

@RequestBody也会告诉Spring查找一个消息转换器,将来自客户端的资源表数转换为对象。

@RestControllar注解Spring会为该处理器的所有处理方法应用消息转换功能。

  1. 提供资源之外的其他信息:
    1. 发送错误信息到客户端:使用ResponseEntity:包含响应头信息、状态码、负载,并且ResponseEntity还包含了@ResponseBody的语义;

借助@ExceptionHandler和@ResponseStatus避免使用ResponseEntity

    1. 在响应中设置头部信息:使用ResponseEntity
  1. 编写Rest客户端

了解RestTemplate的操作:对四个 主要HTTP方法的支持(也就是GET、PUT、DELETE和POST)

  1. delete() 在特定的URL上对资源执行HTTP DELETE操作
  2. exchange() 在URL上执行特定的HTTP方法,返回包含对象的ResponseEntity,这个对象是从响应体中映射得到的
  3. execute() 在URL上执行特定的HTTP方法,返回一个从响应体映射得到的对象
  4. getForEntity() 发送一个HTTP GET请求,返回的ResponseEntity包含了响应体所映射成的对象
  5. getForObject() 发送一个HTTP GET请求,返回的请求体将映射为一个对象
  6. headForHeaders() 发送HTTP HEAD请求,返回包含特定资源URL的HTTP头
  7. optionsForAllow() 发送HTTP OPTIONS请求,返回对特定URL的A llow头信息
  8. postForEntity() POST数据到一个URL,返回包含一个对象的ResponseEntity,这个对象是从响应体中映射得到的
  9. postForLocation() POST数据到一个URL,返回新创建资源的URL
  10. postForObject() POST数据到一个URL,返回根据响应体匹配形成的对象
  11. put() PUT资源到特定的URL

***以上的大多数操作都以三种方法的形式进行了重载: 一个使用java.net.URI作为URL格式,不支持参数化URL; 一个使用String作为URL格式,并使用Map指明URL参数; 一个使用String作为URL格式,并使用可变参数列表指明URL参数。

 

第17章 Spring消息

  1. 异步消息简介
  2. 基于JMS的消息功能
  3. 使用Spring和AMQP发送消息
  4. 消息驱动的POJO
  1. 使用JMS发送消息
  1. 在Spring中搭建消息代理:ActiveMQ做消息代理

创建连接工厂;声明ActiveMQ消息目的地(队列和主题两种目的地);均可以使用方式声明或ActiveMQ命名空间

  1. 使用JMS模板:JMSTemplate可以创建连接、获得会话以及发送和接收消息,JmsTemplate代表发送者来负责处理发送消息的复杂过程。如果在使用JmsTemplate时抛出JMSException异常,JmsTemplate将捕获该异常,然后抛出一个非检查型异常,该异常是Spring自带的JmsException异常的子类。

***使用JmsTemplate接收消息是同步的

  1. 创建消息驱动的POJO

创建异步接收和处理消息的消息驱动POJO

配置消息监听器容器和消息监听器(使用spring的jms命名空间):将处理器声明为bean;将这个bean声明为消息监听器;

  1. 使用基于消息的RPC

导出基于JMS的服务:JmsInvokerServiceExporte

  1. AMQP(RabbitMQ)

 

同步消息和异步消息优缺点对比:

同步通信意味着等待。当客户端调用远程服务的方法时,它必须等待远程方法结束后才能继续执行。如果客户端与远程服务频繁通信, 或者远程服务响应很慢,就会对客户端应用的性能带来负面影响。

客户端通过服务接口与远程服务相耦合。如果服务的接口发生变化,此服务的所有客户端都需要做相应的改变。

客户端与远程服务的位置耦合。客户端必须配置服务的网络位置,这样它才知道如何与远程服务进行交互。如果网络拓扑进行调整,客 户端也需要重新配置新的网络位置。

客户端与服务的可用性相耦合。如果远程服务不可用,客户端实际上也无法正常运行。

异步通信的优点:与服务端解耦,未绑定方法名称。

不需要等待消息被处理

 

ActiveMQ作为消息代理:

  1. 配置连接工厂连接到消息代理(借助JMS连接工厂)——
  2. 通过brokenURL指定消息代理的位置;
  3. 配置消息最终发送的目的地(主题/队列)——必须使用特定性消息代理实现类来配置目的地。

使用Spring 的JMS模板 JMSTemplate

 

Dubbo:基于java的轻量级RPC(remote procedure call远程过程调用)框架

https://www.iteye.com/blog/manzhizhen-2314514

https://blog.csdn.net/qq_30051265/article/details/83749983


第六章:渲染web视图:

配置视图解析器:解析jstl视图

Javaconfig:

@Bean
public ViewResolver viewRseolver(){
    InternalRieso。urceViewResolver resolver = new InternalResourceViewResolver();
    resolver.setPrefix("/WEB-INF/views/");
    resolver.setSuffix(".jsp");

//解析jstl;
    resolver.setViewClass(org.springframework.web.servlet.view.JstlView.class);
    return resolver;
}

Webxml:

       

       

使用Spring的JSP库

Spring的通用标签库

国际化

配置Tiles视图解析器:

1.首先,配置TilesConfigurer来解析Tile定义。JavaConfig

@Bean
public TilesConfigurer tilesConfigurer(){
    TilesConfigurer tiles=new TilesConfigurer();
    tiles.setDefinitions(  //指定tile定义的位置
            new String[]{"WEB-INF/layout/tiles.xmnl"});
    tiles.setCheckRefresh(true);   //启用刷新功能
    return tiles;
}

2.接下来,配置TilesViewResolver

@Bean
public ViewResolver viewResolver(){
    return new TilesViewResolver();
}

*** TilesConfigurer会加载Tile定义并与Apache Tiles协作, 而TilesViewRe-solver会将逻辑视图名称解析为引用Tile定义的视图。它是通过查找与逻辑视图名称相匹配的Tile定义实现该功能的。

使用Thymeleaf:

配置Thymeleaf视图解析器:启用Thymeleaf与Spring集成的bean

ThymeleafViewResolver:将逻辑视图名称解析为Thymeleaf模板视图; 视图解析器

SpringTemplateEngine:处理模板并渲染结果;模板引擎

TemplateResolver:加载Thymeleaf模板。模板解析器

 

 

Spring Web Flow:管理web应用页面流程

在spring中配置web flow

  1. 配置Spring Web Flow 所需的bean 和组件

流程执行器

流程注册表

处理流程请求

  1. Web流程三元素:状态、转移、数据

状态类型:视图、决策、行为状态、子流程状态

 

流程数据作用域:Conversation;Flow;Request;Flash;View

你可能感兴趣的:(Spring)