SpringBoot

SpringBoot

一.Spring回顾

1.基本概念

1.1.SpringBoot介绍

Spring Boot是其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。

1.2…JavaConfig基本概念

Spring注解式编程也叫JavaConfig,即通过一个Java类来配置Spring,或者说把以前xml中配置的内容搬到了一个Java类中,这个类就是Spring的配置类,和以前的XML有相同的作用。

2.Spring回顾

2.1.IOC基本概念

控制反转,我们不需要手工去管理Bean,而是将Bean的创建,初始化,销毁等等工作全部交给Spring管理 。解放我们的工作量。

2.2.DI基本概念

依赖注入,既然Bean的管理交给了Spring,那么Bean之间的依赖关系也需要Spring去维护,DI指定就是Bean与Bean之间的依赖注入。

2.3.AOP基本概念

面向切面编程实现 ,可以看做是对面向对象的补充,面向切面指的是把多个Bean看成一个面,使用横切技术可以让功能(业务)作用于多个Bean , 使用AOP可以实现程序代码的解耦,公共代码的统一抽取和封装等等。Aop的原理是动态代理。

2.4.XML配置IOC
  • 操作步骤
1.创建项目
2.导入依赖
3.创建applicationContext.xml
4.创建一个简单的类 MyBean
5.把这类在 applicationContext.xml 配置成Bean
6.编写测试类:让Spring加载applicationContext.xml 配置文件,获取容器  - ClassPathXmlApplicationContext
7.获取MyBean
  • 创建项目

  • 导入Spring依赖

<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.12.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>RELEASE</version>
        </dependency>
    </dependencies>
  • 创建一个MyBean
public class MyBean {
}
  • 创建xml配置文件,配置Bean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">

    <bean id="myBean" class="cn.chenxin._01_xml_ioc.MyBean"></bean>

</beans>
  • 测试
public class XmlTest {

    @Test
    public void testMyBean(){
        //6.编写测试类:让Spring加载applicationContext.xml 配置文件,获取容器
        //针对于classpath下的xml配置的 Spring容器上下文对象
        ClassPathXmlApplicationContext classPathXmlApplicationContext =
                new ClassPathXmlApplicationContext("applicationContext.xml");

        //7.获取MyBean
        MyBean bean = classPathXmlApplicationContext.getBean(MyBean.class);
        System.out.println(bean);
    }
}

二.注解方式配置IOC

1.操作步骤

1.创建新的包
2.创建一个类作为Spring的配置类
3.创建一个普通的类作为bean(MyBean)
4.在配置类中,配置Bean
5.编写测试:加载配置类 ,获取容器 ,获取MyBean

2.代码演示

2.1.创建一个类作为Bean
public class MyBean {
}
2.2.创建Spring的配置类
/**
 * Spring的配置类 相当于是:applicationContext.xml
 * @Configuration :Spring的配置标签,标记改类是Spring的配置类
 */
@Configuration
public class ApplicationConfig {
}
2.3…在配置类中定义Bean
/**
 * Spring的配置类 相当于是:applicationContext.xml
 * @Configuration :Spring的配置标签,标记改类是Spring的配置类
 */
@Configuration
public class ApplicationConfig {

    /**
     * @Bean : Spring的bean的定义标签 ,标记方法返回的对象交给Spring容器管理
     */
    @Bean
    public MyBean myBean(){
        return new MyBean();
    }

}
2.4…测试

加载配置类,获取容器,获取MyBean

@Test
    public void test(){
        //加载配置文件,拿到Spring容器
        ApplicationContext applicationContext = 
        			new AnnotationConfigApplicationContext(ApplicationConfig.class);

        //通过容器获取Mybaean
        MyBean bean = applicationContext.getBean(MyBean.class);
        System.out.println(bean);
    }

三.ComponentScan自动扫描

@ComponentScan是ioc组件自动扫描,相当于是 <context:component-scan base-package=* 默认扫描当前包及其子包 中打了 @Service , @Controller , @Component , @Repository其中一个注解的 类自动交给Spring管理;也可以通过 basePackages 属性指定扫描的包路径。

1.操作步骤

1.创建配置类
2.创建一个普通类作为Spring的Bean
3.要交给Spring管理的类上贴标签: @Service ,  @Controller , @Component , @Repository
4.在配置类上贴 @ComponentScan标签
5.编写测试
注意:使用了IOC扫描,那么就不要再使用方法的方式定义Bean了

2.代码演示

1.准备MyBean帖@Component
@Component
public class MyBean {
}
2.创建配置类,帖@ComponentScan
@Configuration
//@ComponentScans
@ComponentScan("包名")
public class ApplicationConfig {
}

注意:如果使用了自动扫描 ,那么配置类中就不要去配置@Bean

3.编写测试类

同上一个案例一样…省略…

4.其他属性介绍
  • ComponentScan.lazyInit :懒初始化

  • ComponentScan.Filter[] includeFilters :包含

  • ComponentScan.excludeFilters :排除

四.Bean的详解

1.Bean的属性介绍

我们以前使用Spring使用xml进行配置,如下:

 <bean id="myBean"
          name="myBean2"
          init-method=""
          destroy-method=""
          lazy-init="false"
          scope="prototype"
          class="cn.chenxin._01_xml_ioc.MyBean">
        ...
    </bean>

那么在JavaCong中如何配置Bean的各种属性?

1.1.Bean的id
  • 那么在JavaCong中,方法名就是Bean的id
1.2.Bean的name
  • 可以通过 @Bean标签的name属性指定
1.3.生命周期方法
  • init-method初始方法: @Bean(initMethod = “”) 指定

  • destroy-method销毁方法:@Bean(destroyMethod = “”)指定

1.4.Bean的Scope
  • 单利多利,通过 @Scope(“prototype”)指定
1.5.懒初始化:
  • lazy-init="false"懒初始化: 通过标签 @Lazy(value=false) 指定

2.代码演示

1.1.配置MyBean
@Configuration
public class ApplicationConfig {

    /**
     * bean的id :就是方法的名字“myBean”
     * bean的name: 通过 @Bean(name = "myBean") 指定
     *  init-method初始方法: @Bean(initMethod = "") 指定
     *  destroy-method销毁方法:@Bean(destroyMethod = "")指定
     *  lazy-init="false"懒初始化: 通过标签 @Lazy(value=false) 指定
     *  scope="singleton"单例: 通过 @Scope(value="singleton")指定
     */
    @Bean(name = "myBean",initMethod = "init",destroyMethod = "destroy")
    //@Lazy(value=false)
    //@Scope(value="singleton")
    public MyBean myBean(){
        MyBean myBean = new MyBean();
        return myBean;
    }
}
1.2.定义initdestroy方法
public class MyBean {

    public void init(){
        System.out.println("啊,我被创建啦....");
    }

    public void destroy(){
        System.out.println("啊,我被销毁啦....");
    }

}
1.3.Spring的Test

上面的案例中我们的是使用的Junit的测试 ,在很多场景下Junit测试不能满足我们的需求,比如Junit测试会导致Bean的销毁方法没办办法正常管理,所以我们需要用到Spring的测试。

  • 导入Spring测试包
 <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-test</artifactId>
     <version>4.3.12.RELEASE</version>
</dependency>
  • 编写测试类
//使用Spring的Test ,不要直接用Junit的Test
//@ContextConfiguration(classes = ApplicationConfig.class) :加载Spring的配置类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ApplicationConfig.class)
public class JavaConfigTest {

    @Autowired
    private MyBean myBean;

    @Test
    public void testMyBean() throws Exception{
        System.out.println(myBean);
    }
}

需要注意:

使用了Spring的测试之后,就不要再使用new AnnotationConfigApplicationContext这种方式了

@ContextConfiguration标签后面跟的是配置类的字节码

五.依赖注入

我们以前使用Spring使用xml进行配置,我们除了定义Bean而外还会给Bean进行依赖对象的注入,如下:

 <bean id="myBean"
         ...
          class="cn.chenxin._01_xml_ioc.MyBean">
        <property name="username" value="zs" />
        <property name="OtherBean" ref="OtherBean" />
    </bean>

1.操作步骤

1.创建MyBean类,MyBean中有OtherBean字段
2.创建OtherBean类
3.定义MyBean
4.定义OtherBean
5.把OtherBean设置给MyBean
6.测试

2.代码演示

2.1.创建MyBean
public class MyBean {

    private String username;

    private OtherBean otherBean;
    ...getter,setter...
2.2.创建OtherBean
public class OtherBean {
}
2.2.配置MyBean,注入OtherBean
  • 方式一:直接通过调方法的方式注入OtherBean
@Configuration
public class ApplicationConfig {

    //@Autowired
    //private OtherBean otherBean2;

    /**
     * 需求:给MyBean注入OtherBean
     * 1.MyBean 需要通过容器获得
     * 2.OtherBean 也需要通过容器获得
     * 3.通过容器直接拿到的OtherBean要和通过MyBean拿到的OtherBean是同一个
     */
    @Bean
    public MyBean myBean(){
        MyBean myBean = new MyBean();
        //注入普通值
        myBean.setUsername("我是MyBean");

        //方式一:调用方法 , 通过掉OtherBean方法的方式获取OtherBean,
        myBean.setOtherBean(otherBean());

        return myBean;
    }

	//定义OtherBean
    @Bean
    public OtherBean otherBean(){
        return new OtherBean();
    }
}
  • 方式二:直接参数传入OtherBean
@Configuration
public class ApplicationConfig {

    //@Autowired
    //private OtherBean otherBean2;

    /**
     * 需求:给MyBean注入OtherBean
     * 1.MyBean 需要通过容器获得
     * 2.OtherBean 也需要通过容器获得
     * 3.通过容器直接拿到的OtherBean要和通过MyBean拿到的OtherBean是同一个
     */
    @Bean
    public MyBean myBean(OtherBean otherBean){
        MyBean myBean = new MyBean();
        //注入普通值
        myBean.setUsername("我是MyBean");

        //方式一:调用方法 , 通过掉OtherBean方法的方式获取OtherBean,
        myBean.setOtherBean(otherBean);

        return myBean;
    }

	//定义OtherBean
    @Bean
    public OtherBean otherBean(){
        return new OtherBean();
    }
}
2.3.测试
//使用Spring的Test ,不要直接用Junit的Test
//@ContextConfiguration(classes = ApplicationConfig.class) :加载Spring的配置类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ApplicationConfig.class)
public class JavaConfigTest {

    @Autowired
    private MyBean myBean;

    @Autowired
    private OtherBean otherBean;

    @Test
    public void testMyBean() throws Exception{
        System.out.println(myBean);
        System.out.println(myBean.getOtherBean());
        System.out.println(otherBean);
    }
}

注意:如果MyBean是通过贴@Component标签的方式来定义的,那么注入OtherBean通过@Autowired就可以了。

六.条件Conditional

Conditional用来对某些组件是否注册做条件限制,比如:Conditional注解帖在bean的定义方法上来判断,如果不满足条件就不会定义bean

案例演示:创建一个Bean,如果操作系统的环境是Windows ,那就创建,否则不创建

1.准备工作

1.建包
2.建类MyBean
3.建配置类
4.配置类,配置MyBean
5.给MyBean加上条件:如果操作系统的环境是Windows ,那就创建
6.测试

2.代码演示

省略掉一些不重要的步骤…

2.1.在Bean的定义方法帖@Conditional
@Configuration
public class ApplicationConfig {

    //定义条件:如果操作系统的环境是Windows ,那就创建,否则不创建
    // @Conditional(value = MyBeanCondition.class):
    //给Bean的定义加上条件,这个标签也可以打在类上面
    //value属性指向的是条件类
    @Bean
    @Conditional(value = MyBeanCondition.class)
    public MyBean myBean(){
        return new MyBean();
    }
}
2.2.定义条件类
//定义MyBean的条件类,MyBean是否能定义,通过该类的  matches 方法返回的boolean决定的
public class MyBeanCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //环境对象
        Environment environment = context.getEnvironment();
        //操作系统名字
        String os = environment.getProperty("os.name");
        if(os.equals("Windows 10")){
            return true;
        }
        return false;
    }
}
2.3.测试

根据条件类中matches方法的boolean值观察测试类中是否能注入MyBean

//使用Spring的Test ,不要直接用Junit的Test
//@ContextConfiguration(classes = ApplicationConfig.class) :加载Spring的配置类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ApplicationConfig.class)
public class JavaConfigTest {

    @Autowired
    private MyBean myBean;

    @Test
    public void testMyBean() throws Exception{
        System.out.println(myBean);
    }
}

七.@Import导入

@Import标签,可以有用来实现配置类之间的导入,如同 “ 导入配置 , 当然还可以通过导入ImportSelector,以及导入ImportBeanDefinitionRegistrar的方式注册Bean。

1.导入配置Configuration

演示案例:创建两个配置类,一个配置类 ApplicationConfig 配置MyBean,另一个配置类 OtherConfig 配置OtherBean,使用@Improt把两个配置类导入在一起,并且MyBean中的OtherBean要有值

1.操作步骤
1.创建两个配置类 `ApplicationConfig`  ,`OtherConfig`
2.创建两个普通类 `MyBean` ,`OtherBean` 
3.ApplicationConfig配置MyBean , MyBean只要注入OtherBean的值
4.OtherConfig配置`OtherBean`
5.@Improt导入配置类在一起
6.测试
2.代码演示
  • 创建MyBean,OtherBean
public class MyBean {
    private OtherBean otherBean;

    public OtherBean getOtherBean() {
        return otherBean;
    }

    public void setOtherBean(OtherBean otherBean) {
        this.otherBean = otherBean;
    }
}
  • 创建配置类OtherConfig,定义OtherBean
//第二个配置类
@Configuration
public class OtherConfig {

    @Bean
    public OtherBean otherBean(){
        return new OtherBean();
    }
}

  • 创建ApplicationConfig导入OtherConfig
//主配置类
//@Import(OtherConfig.class): 导入另外一个配置类
@Configuration
@Import(OtherConfig.class)
public class ApplicationConfig {

    @Bean
    public MyBean myBean(OtherBean otherBean){
        MyBean myBean = new MyBean();
        myBean.setOtherBean(otherBean);
        return myBean;
    }
}

  • 测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ApplicationConfig.class)
public class JavaConfigTest {

    @Autowired
    private MyBean myBean;

    @Autowired
    private OtherBean otherBean;

    @Test
    public void testMyBean() throws Exception{
        System.out.println(myBean);
        System.out.println(myBean.getOtherBean());
        System.out.println(otherBean);
    }
}
  • 分析图

    mark

2.导入ImportSelector

ImportSelector接口的作用是选择导入那些类,其中的方法 selectImports 就是用来返回要导入的类的class,

我们需要定义一个类,去实现 ImportSelector接口,复写selectImports 方法,返回我们要导入的类的字节码的字符串数组,然后把我们的类,交给@Import标签。

演示案例:在上面导入配置类的案例上做拓展 ,通过ImportSelector去导入MyBean和OtherBean。@Import标签去导入 ImportSelector的实现类。

1.操作步骤
1.创建mybean ,和OtherBean
2.创建主配置类
3.定义类 MyImportSelector 实现 ImportSelector
4.主配置类通过@Import(MyImportSelector.class)
5.测试
2.代码演示

省略到一些简单的步骤….

  • 定义MyImportSelector
//定义导入选择器
public class MyImportSelector implements ImportSelector {

    //返回要导入的类的字节码
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"cn.chenxin._08_import_selector.MyBean",
                "cn.chenxin._08_import_selector.OtherBean"};
    }
}

  • 定义配置类,导入选择器
@Configuration
@Import(value = MyImportSelector.class)
public class ApplicationConfig {
}
  • 测试
//使用Spring的Test ,不要直接用Junit的Test
//@ContextConfiguration(classes = ApplicationConfig.class) :加载Spring的配置类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ApplicationConfig.class)
public class JavaConfigTest {

    @Autowired
    private MyBean myBean;

    @Autowired
    private OtherBean otherBean;

    @Test
    public void testMyBean() throws Exception{
        System.out.println(myBean);
        System.out.println(otherBean);
    }
}

mark

3.导入ImportBeanDefinitionRegistrar

ImportBeanDefinitionRegistrar导入Bean的注册器,其中的registerBeanDefinitions方法提供了一个BeanDefinitionRegistry参数可以用来注册Bean

演示案例:定义MyBean,通过ImportBeanDefinitionRegistrar的方式来注册MyBean到Spring容器。

1.操作步骤
1.创建MyBean
2.创建导入注册器: MyImportBeanDefinitionRegistrar
3.创建配置类
4.测试
2.代码演示
  • 创建MyBean
public class MyBean {
}
  • 定义 ImportBeanDefinitionRegistrar
//Bean注册器
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    //BeanDefinitionRegistry:bean的注册器,可以注册Bean
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
                                        BeanDefinitionRegistry registry) {

        //参数:bean的名字  ,Bean的定义对象  BeanDefinition
        RootBeanDefinition myBeanDefinition = new RootBeanDefinition(MyBean.class);
        registry.registerBeanDefinition("myBean",myBeanDefinition);

    }
}
  • 定义配置类
@Configuration
@Import(MyImportBeanDefinitionRegistrar.class)	//导入bean注册器
public class ApplicationConfig{
    
}
  • 测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ApplicationConfig.class)
public class JavaConfigTest {

    @Autowired
    private MyBean myBean;

    @Test
    public void testMyBean() throws Exception{
        System.out.println(myBean);
    }
}

mark

八.SpringBoot入门

1.HelloWorld程序

使用Spring创建有一个简单Web程序,通过浏览器访问 http://localhost:8080 能够返回“hello world”信息

1.1.创建普通jar工程,导入依赖
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.5.RELEASE</version>
</parent>
...
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
1.2.创建配置类
@SpringBootApplication
public class ApplicationConfig {

    public static void main(String[] args) {
        SpringApplication.run(ApplicationConfig.class);
    }
}
1.3.编写Controller
@Controller
public class Example {

	@RequestMapping("/")
	@ResponseBody
	String home() {
		return "Hello World!";
	}
}
1.4.启动测试

启动main方法 ,浏览器访问:http://localhost:8080

2.HelloWorld分析

2.1.spring-boot-starter-parent

SpringBoot的父工程,通过dependencyManagement标签帮我们管理了很多的基础jar包,我们如果要使用SpringBoot父工程管理起来的Jar包,需要在子模块的dependencies中导入,版本号不用写交给父模块管理

2.2.spring-boot-starter-web

spring-boot-starter-web:继承与SpringBoot的父工程 spring-boot-starter-parent
这个Jar包在继承web(SpringMvc) ,它把web所需要的的所有的jar到给你导入进来,包括
spring相关包,springmvc相关保,日志相关包,json相关包,tomcat相关包等等都搞进来了。

2.3.RestController

该标签是@Controller和@ResponseBody标签的组合标签,同时拥有两者的能力。

2.4.@EnableAutoConfiguration

开启自动配置,就是SpringBoot帮我们自动配置如:前端控制器,视图解析器,等等。自动配置原理如下:

mark

1.@EnableAutoConfiguration上使用@Import导入了一个AutoConfigurationImportSelector 选择器

这里的导入选择器的作用就是去加载“自动配置”的类,注册到Spring容器中。

//省略....
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
//省略....

2.AutoConfigurationImportSelector的selectImports方法中返回一些自动配置类的全限定名的数组

selectImports方法返回的数组就是“自动配置”的全限定名的数组,这些配置类最终会注册到Spring容器中,主要跟踪getCandidateConfigurations方法

public class AutoConfigurationImportSelector
		implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,
		BeanFactoryAware, EnvironmentAware, Ordered {

	//...省略...
	@Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
		//...省略...
		List<String> configurations = getCandidateConfigurations(annotationMetadata,
				attributes);
		//...省略...
		return StringUtils.toStringArray(configurations);
	}

3.getCandidateConfigurations方法使用 SpringFactoriesLoader去 META-INF/spring.factories 文件中加载自动配置类

所有classpath中的jar包中的META-INF/spring.factories都会被尝试扫描

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
                                                  AnnotationAttributes attributes) {
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
        getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
    Assert.notEmpty(configurations,
                    "No auto configuration classes found in META-INF/spring.factories. If you "
                    + "are using a custom packaging, make sure that file is correct.");
    return configurations;
}


4.我们去 spring-boot-autoconfigure:2.0.5.RELEASE(这个是SpringBoot的自动配置包) 找到这个文件spring.factories 文件,里面有个很多的自动配置类如下:

#省略....
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\

我这里主要截取了我们常用的几个自动配置

  • DataSourceAutoConfiguration : 连接池的自动配置
  • ThymeleafAutoConfiguration :模板引擎自动配置
  • DispatcherServletAutoConfiguration : 前端控制器自动配置
  • HttpEncodingAutoConfiguration: 编码过滤器自动配置
  • MultipartAutoConfiguration:文件上传自动配置
  • WebMvcAutoConfiguration : SpringMvc自动配置,如视图解析器

5.我们打开DispatcherServletAutoConfiguration 看一下前端控制器是如何配置的

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass(DispatcherServlet.class)
@AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)
@EnableConfigurationProperties(ServerProperties.class)
public class DispatcherServletAutoConfiguration {
       //省略很多代码......
    
    @Configuration
	@Conditional(DefaultDispatcherServletCondition.class)
	@ConditionalOnClass(ServletRegistration.class)
	@EnableConfigurationProperties(WebMvcProperties.class)
	protected static class DispatcherServletConfiguration {

		private final WebMvcProperties webMvcProperties;
        
        //省略很多代码......
        @Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
        public DispatcherServlet dispatcherServlet() {
            DispatcherServlet dispatcherServlet = new DispatcherServlet();
            dispatcherServlet.setDispatchOptionsRequest(
                this.webMvcProperties.isDispatchOptionsRequest());
            dispatcherServlet.setDispatchTraceRequest(
                this.webMvcProperties.isDispatchTraceRequest());
            dispatcherServlet.setThrowExceptionIfNoHandlerFound(
                this.webMvcProperties.isThrowExceptionIfNoHandlerFound());
            return dispatcherServlet;
        }

这里看起来比较繁杂,我们调关键信息就可以了,这里可以看到,DispatcherServletAutoConfiguration 载入了一个WebMvcProperties ,其实这个对象就是用来从yml配置中读取DispatcherServlet的自定义配置项的,然后以WebMvcProperties 配置为基础,以Bean的方式配置了 DispatcherServlet。也就是说以前在web.xml中配置的前段控制器:org.springframework.web.servlet.DispatcherServlet ,现在在SpringBoot中的配置方式是一个Bean.

其他的自动配置类和以上类似:

编码过滤器:...HttpEncodingAutoConfiguration#characterEncodingFilter()

文件上传解析器:...MultipartAutoConfiguration#multipartResolver()

视图解析器:..WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter#defaultViewResolver()
2.5.SpringApplication.run
这个run方法在启动SpringBoot应用,大概的启动流程:

1.加载,启动监听器
2.准备环境,参数等
3.打印Banner
4.创建容器 , 初始化容器
5.刷新容器 (前,刷新,后):注册Bean,初始化Bean , 加载配置类,解析配置,做自动配置
6.打包项目到内嵌Tomcat中
7.启动Tomcat
2.6.为什么项目打包方式是jar

SpringBoot的项目,默认的打包方式就是jar

打包方式 pom/jar/war

  • pom:父工程的打包方式,用来管理依赖的 springboot-demo.pom
  • jar:普通的java工程,用来打jar包 , springboot-demo.jar
  • war: web工程 ,用来打war包 ,springboot-demo.war
2.7.@SpringBootApplication

@SpringBootApplication : 是一个组合标签,包括了下面三个标签:

  • @SpringBootConfiguration :
    • @Configuration :Spring的配置标签
  • @EnableAutoConfiguration : 开启SpringBoot自动配置标签
  • @ComponentScan :IOC组件自动扫描标签
2.8.dependencyManagement

这个标签是用来管理jar的,这个标签只是在声明jar包,子项目是用不了这个标签里面的jar包
如果子项目非得使用父项目的 dependencyManagement 里面的jar,得在子项目导入jar包,版本号不要了写,使用父项目的版本号,这样可以实现版本号的统一管理。

2.9.dependencies

如果在父工程的dependencies里面有jar包 ,那么这些jar包默认会被子项目给继承直接使用。

如何选择:如果所有的子项目都要用到的jar包 ,放到父工程的 dependencies ,如果只是部分子项目用到的jar包,放到 dependencyManagement 里面。

3.SpringBoot的特点

3.1.使用注解配置,无需xml(简单粗暴)

3.2.快速搭建,开发

3.3.简化的maven

3.4.方便的和三方框架集成

3.5.内嵌tomcat,部署简单

3.6.内置健康检查,监控等

3.7.自动配置,让配置更加简单

九.SpringBoot基本使用

1.项目结构

1.1.项目结构说明

.SpringBoot项目结构默认是Java项目结构,打包方式为Jar

src
	--main
		--java
		--resources
			--static		//静态资源目录
			--templates		//模板页面目录,如:jsp ,ftl
			--application.properties/application.yml	//默认配置文件

注意:如果么有使用默认的配置文件名需要在配置类上使用 @PropertySource("classpath:redis.properties") 方式导入配置文件。

1.2.SpringBoot在多模块项目中搭建方式

mark

study-springboot-parent	
pom.xml  //自己在父项目,继承SpringBoot,用来管理jar包 , 打包方式 pom
	- springboot-base	//子项目 ,继承自己在父项目,打包方式为 jar
    - 其他子项目

mark

2.独立运行

当项目上线时SpringBoot项目需要有独立在运行方式,不能以来IDEA工具运行,这时候就需要打包独立运行。

1.导入打包插件
<build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
2.打包项目

mark

打包命令会把jar打包到target目录

3.运行项目
java -jar xxx.jar

3.热部署

SpringBoot项目可以使用JRebel作为热部署,当然SpringBoot提供了一个热部署的工具包,导入工具包依赖后,在项目中修改了代码需要编译一下代码,即可以重启的方式实现热部署。

1.导入依赖
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-devtools</artifactId>
 </dependency>
2.编译代码

使用 ctrl + F9 编译代码,为了方便也可以吧编译功能配置成 ctrl + s

4.SpringBoot配置

SpringBoot可以使用application.properties作为默认的配置文件,这种传统的配置方式可以使用起来并不是特别美观,SpringBoot另外也提供application.yml的方式来进行配置,YAML以数据为中心,比json、xml等更适合做配置文件,看起来更加美观。

4.1.YML基础语法
  • k:(空格)v:表示一对键值对(空格必须有)
  • 以空格的缩进来控制层级关系;只要是左对齐的一列数据,都是同一个层级的
  • 属性和值也是大小写敏感;
4.2.值的写法
  • 普通值:数字,字符串,布尔
#字符串默认不用加上单引号或者双引号;

#"":双引号;不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思

name:   "zhangsan \n lisi"  #输出;zhangsan 换行  lisi

#'':单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据

name:   'zhangsan \n lisi' #输出;zhangsan \n  lisi
  • k: v:在下一行来写对象的属性和值的关系;注意缩进
对象还是k: v的方式

friends:
    lastName: zhangsan
	age: 20

行内写法:

friends: {lastName: zhangsan,age: 18}
  • 数组(List、Set)
#用- 值表示数组中的一个元素

pets: 
  - cat
  - dog
  - pig
 
#行内写法

pets: [cat,dog,pig]
4.3.案例:端口配置

使用yml配置服务端口 : 创建 application.yml 配置文件,内容如下:

server:
	port: 8080  #端口配置

十.SpringBoot读取配置

把配置文件中的配置项读取到代码中使用是常见的开发方式,那么在SpringBoot中如何实现呢?SpringBoot提供了两种方式:1.@Value标签适合用来读取单个配置 , 2.@ConfigurationProperties标签适合用来将一堆配置绑定配置对象。

1.@Value取单个配置

1.1.配置文件
application:
  name: springboot-demo
1.2.绑定配置的对象
@Controller
public class HelloController {

    //@Value :从配置文件中取值   SPEL
    @Value("${application.name}")
    private String applicationName ;
  • ${}:Spring表达式 SPEL , 当SpringBoot启动的时候,加载配置文件到Spring环境对象中
  • ${application.name} :会去环境对象中匹配名字到 application.name的配置项目
  • @Value :会把找到的值,赋值给 applicationName 字段

2@ConfigurationProperties绑定配置到对象

@Value用来读取单个配置项目比较方便,但是如果配置项目比较多就需要写很多@Value标签,这时候我们可以使用@ConfigurationProperties(prefix = "前缀")来实现多个配置项到对象的绑定。

@ConfigurationProperties(prefix = "前缀") 自动的根据前缀从配置中过滤出配置项目,然后根据当前对象的字段名进行同名匹配,自动赋值。

2.1.在类上使用

一种用法:@Component+ @ConfigurationProperties打在类上面 , 这里以员工举例:

  • 配置文件
employeeconfig:
  id: 1
  username: zs
  password: "000000"
  • .绑定配置到对象
@ConfigurationProperties(prefix = "employeeconfig")
@Component
public class EmployeeConfig {
    private Long id;
    private String username;
    private String password;
    ...getter,setter...
}
2.2.在Bean的方法上使用

二种用法:@Bean +@ConfigurationProperties打在bean的定义方法上面

  • 配置文件
deptconfig:
  id: 1
  name: "教学部"
  num: "110"
  • 配置绑定到对象
public class DeptConfig{
    private Long id;
    private String name;
    private String num;
    ..getter,setter,...
}

//主配置类
@SpringBootApplication
public class ApplicationConfig
{

    @Bean
    @ConfigurationProperties(prefix = "deptconfig")
    public DeptConfig deptConfig(){
        return new DeptConfig();
    }
	...main...
}
2.3.测试

在Controller中注入 对象进行打印即可

十一.多环境配置切换

1.为什么要多环境配置

在生产级别的项目中我们会有多套配置环境 ,如:“开发环境” , “测试环境” , “生产环境” 等等 ,在开发到上线的过程中,环境的切换会导致配置文件内容的频繁修改,如果切换环境所需要修改的配置项目比较的,那么对于开发,或者运维人员来说工作量就太大了,SpringBoot的多环境配置可以轻松的解决此问题。方案是针对不同的环境做不同的配置,做多套配置(多个配置文件),在切换环境的时候只需要切换不同的配置文件即可。SpringBoot提供了两种配置方式:1.单文件配置多套环境, 2.多文件配置多套环境,如下图:

mark

2.单文件配置多环境

2.1.创建配置文件

resource/application.yml

2.2.配置内容

多套配置环境通过 — 进行切分 , 通过使用 spring.profiles.active来激活某一个环境配置 ,通过spring.profiles来指定配置的名字

#主配置
spring:
  profiles:
    active: test	#激活(选择)环境test
---
#开发环境配置
spring:
  profiles: dev		#指定环境名字dev
server:
  port: 9999
---
#测试环境配置
spring:
  profiles: test	#指定环境名字test
server:
  port: 8888

提示:这里有两套配置 ,通过spring.profiles指定配置的名字 , 通过 spring.profiles.acitve指定使用哪一套配置。

3.多文件配置多环境

通过配置文件的名字来识别环境

2.1.开发环境配置

创建配置文件 resources/application-dev.yml

server:
  port: 9999
2.2.测试环境配置

创建配置文件 resources/application-test.yml

server:
  port: 8888
2.3.主配置文件

创建配置文件 resources/application.yml

spring:
  profiles:
    active: test 
    #根据文件名字配置 application-dev.properties

SpringBoot启动的时候会默认加载 application.yml 配置文件 ,通过spring.profiles.active=test 找到 application-test.yml 配置文件,加载其内容。如果要使用application-dev.yml配置文件只需要把spring.profiles.active=test修改为spring.profiles.active=dev即可。

4.外部激活配置

4.1.命令行激活配置 - 推荐

如果项目已经打成jar包,我们要启动需要指定不同的配置环境,可以通过如下命令进行激活:

java -jar spring-boot-02-config-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev
4.2.虚拟机参数激活配置 - 知道就行

启动器的vm项加入配置参数:

-Dspring.profiles.active=dev

十二.SpringBoot测试

后续的学习过程中,每次都要写controller来访问测试比较麻烦,其他我们可以通过springboot的测试直接测试。就和原来不用启动tomcat一样测试 , 在SpringBoot中提供了@SpringBootTest(classes=配置类)注解来加载配置类,配合@RunWith(SpringRunner.class)标签一起完成测试功能。

1.使用SpringBoot测试

1.1.导入依赖
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
</dependency>
1.2.编写测试类
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ApplicationConfig.class)//要告诉它在哪儿加载Spring配置类
public class TempTest {
    
	@Test
	public void test() throws Exception {
		System.out.println("如果能打印说明测试成功...");
		
	}
}

@SpringBootTest(classes = ApplicationConfig.class) :SpringBoot测试标签,指向配置类的字节码

十三.日志的使用

日志框架的一个非常重要的组件 , 日志可以用来调试程序,跟踪代码执行情况,日志的级别可以区分不同的日志类型,可以将日志输出到控制台,或者文件,方便程序员查看系统的执行状况,和错误信息。并且可以根据日志的级别做不同内容的输出,这些优点是System.out.print做不到的。

1.打印日志

1.1.使用Logger打印日志
//日志打印
@RestController
public class LogDemoController {

    //日志打印器
    private Logger log = LoggerFactory.getLogger(LogDemoController.class);

    @RequestMapping("/log-test")
    public void logTest(){
        //System.out.println("我是一个日志...");
        //日志级别: trace -> debug ->  info  -> ,warn -> error

        if(log.isTraceEnabled()){
            log.trace("我是trace日志....");
        }
//        if(log.isDebugEnabled()){
//            log.debug("我是debug日志....");
//        }
        log.debug("我是debug日志....");
        log.info("我是info日志....");
        log.warn("我是warn日志....");
        log.error("我是error日志....");
    }
}

注意:SpringBoot默认开启的日志级别是 “info”

1.2.结合Lombok插件打印日志
  • IDEA安装Lombok插件

mark

  • 导入Lombok依赖包
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.16.10</version>
    <scope>provided</scope>
</dependency>
  • 使用@Slf4j打印日志
//日志打印
@RestController
@Slf4j
public class LogDemoController {

    //日志打印器
    //private Logger log = LoggerFactory.getLogger(LogDemoController.class);

    @RequestMapping("/log-test")
    public void logTest(){
        //System.out.println("我是一个日志...");
        //日志级别: trace -> debug ->  info  -> ,warn -> error

        if(log.isTraceEnabled()){
            log.trace("我是trace日志....");
        }
//        if(log.isDebugEnabled()){
//            log.debug("我是debug日志....");
//        }
        log.debug("我是debug日志....");
        log.info("我是info日志....");
        log.warn("我是warn日志....");
        log.error("我是error日志....");
    }
}

2.日志的配置

1.1.使用默认配置
logging:
  level:
    root: info #全局配置日志级别:trace
    cn:
      chenxin: trace  #指定 cn.chenxin包下面的日志级别用 trace
  file: log/springboot.log  #输出到日志文件
  pattern:
    console: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n" #日志格式
1.2.使用logback-spring.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- 定义常量 : 日志格式 -->
    <property name="CONSOLE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} ----> [%thread] ---> %-5level %logger{50} - %msg%n"/>

    <!--ConsoleAppender 用于在屏幕上输出日志-->
    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <!--定义控制台输出格式-->
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <!-- 设置字符集 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!--打印到文件-->
    <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">

        <file>logs/springboot.log</file>

        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>logs/springboot-%d{yyyyMMdd}-%i.log.gz</fileNamePattern>
            <maxFileSize>1KB</maxFileSize>
            <maxHistory>30</maxHistory>
            <!--总上限大小-->
            <totalSizeCap>5GB</totalSizeCap>
        </rollingPolicy>
        <!--定义控制台输出格式-->
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <!-- 设置字符集 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>


    <!--root是默认的logger 这里设定输出级别是debug-->
    <root level="info">
        <!--定义了两个appender,日志会通过往这两个appender里面写-->
        <appender-ref ref="stdout"/>
        <appender-ref ref="file"/>
    </root>

    <!--如果没有设置 additivity="false" ,就会导致一条日志在控制台输出两次的情况-->
    <!--additivity表示要不要使用rootLogger配置的appender进行输出-->
    <logger name="cn.chenxin" level="error" additivity="false">
        <appender-ref ref="stdout"/>
        <appender-ref ref="file"/>
    </logger>

</configuration>

十四.SpringBoot集成WEB

1.模板引擎

1.1.模板引擎的原理

模板引擎可以看做是一种文件(内容)合成技术,我们可以使用某种模板引擎(Freemarker),使用填充数据,对模板进行合并可以输出响应的文件 , 如: model(数据) + ftl (模板文件) = html(合并成html) ,举例(JSP):

模板文件

  • /WEB-INF/views/user.jsp
....
欢迎登陆 ${username}    <!-- el,jstl表达式-->
....
  • controller
...
model.addAttribute("username","王大锤");  //model就是填充的数据
return "user.jsp";
  • 视图解析器

视图解析器负责 把 model数据 和 jsp模板文件 进行合并成html (${username} + "王大锤" ) ,输出给浏览器

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/views/"/>
    <property name="suffix" value=".jsp"/>
</bean>
1.2.常见的模板引擎

JSP、Thymeleaf 3、Velocity 1.7、Freemarker 2.3.23

2.集成Thymeleaf

2.1.导入依赖
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
2.2.创建模板

创建文件: resources/templates/hello.html

<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>成功!</h1>
    <!--使用语法th:text 将div里面的文本内容设置为 -->

    <div th:text="${msg}">这是显示欢迎信息</div>
</body>
</html>
2.3.编写controller
@Controller
public class HelloController {
    @RequestMapping("/index")
    public String hello(Model model){
        model.addAttribute("msg","后面有人,认真听课" );
        return "hello";
    }
}

思考?为什么我们没有对Thymeleaf做任何配置就能使用?

2.4.Thymeleaf的自动配置原理
1.Thymeleaf配置

application.yml中可以对Thymeleaf的配置做调整,但是不是必须,建议不要配置,默认的配置足够用。

#spring:
#  thymeleaf:
#    enabled: true
#    cache: false
#    encoding: utf-8
#    suffix: .html
#    prefix:
#    servlet:
#      content-type: text/html
2.Thymeleaf自动配置原理
  • Thymeleaf通过 @ConfigurationProperties把yml中的配置读取到 ThymeleafProperties 对象中
@ConfigurationProperties(prefix = "spring.thymeleaf")	//读取spring.thymeleaf配置
public class ThymeleafProperties {

	private static final Charset DEFAULT_ENCODING = StandardCharsets.UTF_8;

	public static final String DEFAULT_PREFIX = "classpath:/templates/";

	public static final String DEFAULT_SUFFIX = ".html";

	private boolean checkTemplate = true;

	private boolean checkTemplateLocation = true;

	//默认前缀
	private String prefix = DEFAULT_PREFIX;

    //默认后缀
	private String suffix = DEFAULT_SUFFIX;

	private Charset encoding = DEFAULT_ENCODING;
    //...省略...
  • ThymeleafAutoConfiguration 自动配置类使用 ThymeleafProperties 作为基础配置对Thymeleaf做自动配置,如视图解析器的自动配置如下:
@Configuration
//载入 ThymeleafProperties配置对象
@EnableConfigurationProperties(ThymeleafProperties.class)
@ConditionalOnClass(TemplateMode.class)
@AutoConfigureAfter({ WebMvcAutoConfiguration.class, WebFluxAutoConfiguration.class })
public class ThymeleafAutoConfiguration {
    //省略...
    //配置视图解析器
    @Bean
    @ConditionalOnMissingBean(name = "thymeleafViewResolver")
    public ThymeleafViewResolver thymeleafViewResolver() {
        ThymeleafViewResolver resolver = new ThymeleafViewResolver();
        ...
        return resolver;
    }
    //省略...
2.5.Thymeleaf的语法

省略…

2.静态资源

2.1.静态资源目录

resource/static

2.2.webjars

某些js组件已经被打包成jar包,通过maven导入jar包就可以使用。下面以jquery举例: http://www.webjars.org/

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t1ICp1kJ-1584465560649)(C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20200317101752532.png)]

  • 导入jquery依赖
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>jquery</artifactId>
    <version>3.4.1</version>
</dependency>
  • 导入jquery的js
<script src="/webjars/jquery/3.4.1/jquery.js"></script>
<!-- 测试 -->
 <script>
 	alert($);
 </script>
2.3.默认首页

在resources下放置名字index.html的页面默认为首页如:resources/index.html

2.4.网页图标

在resources下放置名字为favicon.ico的图标如: resources/favicon.ico

3.SpringBoot中的MVC配置

在SpringBoot中提供了 WebMvcConfigurer 接口来针对SpringMvc做自定义的配置,比如针对于拦截器,就可以通过WebMvcConfigurer 接口中的addInterceptors方法的InterceptorRegistry拦截器注册器来注册。

3.1.配置拦截器
  • 定义拦截器
//拦截器登录检查
@Component
@Slf4j
public class LoginCheckInterceptor implements HandlerInterceptor {

    //在controller方法调用前,先执行该方法:preHandle
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        String requestURI = request.getRequestURI();

        log.info("拦截器执行了,URI:"+requestURI);
        return true;
    }
}

  • 注册拦截器

创建拦截器配之类: config/WebConfig

//针对于web的配置
//WebMvcConfigurer:针对于springmvc配置的接口
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private LoginCheckInterceptor loginCheckInterceptor;

    //注册拦截器的方法 : InterceptorRegistry ,是注册拦截器的
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //注册具体的拦截器
        registry.addInterceptor(loginCheckInterceptor) //new LoginCheckInterceptor()
                //拦截器所有的请求
                .addPathPatterns("/**")
                //排除资源
                .excludePathPatterns("/static/**",
                        "/webjars/**",
                        "/login",
                        "/regist",
                        "/css/**",
                        "/js/**",
                        "/html/**",
                        "/images/**");
    }
}
3.2.添加视图控制器
  • 视图控制器可以将某个url请求直接定位到某个资源,不用通过controller转发。在WebConfig配置中添加代码:
//针对于web的配置
//WebMvcConfigurer:针对于springmvc配置的接口
@Configuration
public class WebConfig implements WebMvcConfigurer {
    
	@Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/xx").setViewName("hello2.html");
    }
    //...省略....
}

当访问/xx 定位到 templates/hello2.html

  • 填写模板文件 resources/templates/hello2.html
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="webjars/jquery/3.4.1/jquery.js"></script>
    <!--<script>-->
        <!--alert($);-->
    <!--</script>-->
</head>
<body>
    <h1>成功!</h1>

    <!--使用语法th:text 将div里面的文本内容设置为 -->
    <!--<div >第一个DIV:${msg}</div>-->

    <div>这是hello2.html</div>

</body>
</html>

十五.集成MyBatis

MyBatis的集成是集成项目必须要做的工作 , 在集成MyBatis之前需要先集成DataSource,SpringBoot中提供了DataSource自动集成方案,让配置更简单,针对于MyBatis的集成也只需要简单几步配置即可。

1.操作步骤

1.导入依赖
2.配置DataSource
3.完成基本组件创建:domain ,mapper映射器,mapper.xml映射文件,service,table
4.配置MyBatis
5.测试

1.集成DataSource

1.1.导入依赖

这里我们把连接池,mysql驱动,以及MyBatis包都导入进来,连接池选择阿里的Druid

<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.20</version>
</dependency>
<!-- mysql 数据库驱动. -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.1.1</version>
</dependency>
2.2.手动配置方式 - 不推荐
  • 手动配置四个属性
  jdbc:
    username: root
    password: 123456
    url: jdbc:mysql:///ssm
    driver-class-name: com.mysql.jdbc.Driver
  • 配置类中定义DataSource
@Bean
@ConfigurationProperties(prefix = "jdbc")
public DataSource dataSource(){
    DruidDataSource dataSource = new DruidDataSource();
    return dataSource ;
}
2.3.自动配置方式 - 推荐

application.yml配置:

#配置 druid 的 dataSource
spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql:///crm
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
2.4.DataSource自动配置原理

1.DataSourceProperties通过 @ConfigurationProperties(prefix = "spring.datasource") 读取yml配置中的DataSource配置项

@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {
    //省略
    private Class<? extends DataSource> type;

	/**
	 * Fully qualified name of the JDBC driver. Auto-detected based on the URL by default.
	 */
	private String driverClassName;

	/**
	 * JDBC URL of the database.
	 */
	private String url;

	/**
	 * Login username of the database.
	 */
	private String username;

	/**
	 * Login password of the database.
	 */
	private String password;
    

2.DataSourceAutoConfiguration去载入DataSourceProperties ,最终调用 DataSourceConfiguration.Generic.class 对DataSource做自动配置

@Configuration
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ DataSourcePoolMetadataProvidersConfiguration.class,
		DataSourceInitializationConfiguration.class })
public class DataSourceAutoConfiguration {
   //省略...

	@Configuration
	@Conditional(PooledDataSourceCondition.class)
	@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
	@Import({ DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,
			DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.Generic.class,
			DataSourceJmxConfiguration.class })
	protected static class PooledDataSourceConfiguration {

	}

3.最终通过 DataSourceConfiguration.Generic.class 配置DataSource

	//省略...
	@ConditionalOnMissingBean(DataSource.class)
	@ConditionalOnProperty(name = "spring.datasource.type")
	static class Generic {

		@Bean
		public DataSource dataSource(DataSourceProperties properties) {
			return properties.initializeDataSourceBuilder().build();
		}

	}

这里有两个条件,1.在容器中找不到DataSource的Bean ,(我们没有手动配) ,;2.yml中有 spring.datasource.type的配置项,SpringBoot就会帮我们配置DataSource , 在 DataSourceProperties通过反射创建了一个类型为 spring.datasource.type 的值的类型的DataSource,并设置参数四大金刚(四大金刚)

2.集成MyBatis

…省略了基本组件生成代码:domain,mapper,service等等…

2.1.配置Mybatis

application.yml

mybatis:
  mapper-locations: classpath:cn/chenxin/mapper/*Mapper.xml
  #type-aliases-package: 别名可以不用配置
2.2.配置Mapper接口扫描包
@SpringBootApplication
@MapperScan("mapper接口的包名")
public class ApplicationConfig {
   ...
}
2.3.使用SpringBoot的Test测试

测试类中注入Service进行测试…省略…

也可以使用Controller直接测

十六.集成事务

在Spring中我们可以使用注解式事务配置,也可以使用xml方式进行事务配置,在SpringBoot同样可以使用这两种方式,只是SpringBoot推荐使用注解进行编程,所以我们这里主要采用注解的方式配置事务。

1.使用注解方式

1.1开启事务管理器

导入了MyBatis的依赖之后,事务管理器就已经存在,我们只需要在配置类开启事务管理即可。

@SpringBootApplication
@MapperScan("cn.chenxin.mapper")
@EnableTransactionManagement
public class ApplicationConfig{
...}
1.2.在service打事务标签

@Transactional赋予service有事务的功能

@Transactional
@Service
public class EmployeeServiceImpl

2.使用xml方式配置 - 了解

1.1.导入AOP的依赖
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-aop</artifactId>
 </dependency>
1.2.配置事务xml
<!-- 配置事物管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <aop:config>
        <aop:pointcut expression="execution(* cn.chenxin.web.controller.service..*.*(..))" id="coreServicePointcut"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="coreServicePointcut"/>
    </aop:config>

    <!-- aop应用事务管理 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="select*" read-only="true"/>
            <tx:method name="*" propagation="REQUIRED" />
        </tx:attributes>
    </tx:advice>
1.3.配置类导入xml配置
...
@ImportResource("classpath:applicationContext-service.xml")
public class ApplicationConfig

十七.扩展部分

1.FactoryBean

通过工厂的方式去定义bean

1.1.定义MyBean
class MyBean{}
1.2.定义FactoryBean工厂
public class MyBeanFactoryBean implements FactoryBean<MyBean> {
    public MyBean getObject() throws Exception {
        return new MyBean();
    }

    public Class<?> getObjectType() {
        return MyBean.class;
    }

    public boolean isSingleton() {
        return true;
    }
}
1.3.配置 MyBeanFactoryBean的bean定义
@Configuration
public class ApplicationConfig {

    @Bean
    public MyBeanFactoryBean myBean(){
        return new MyBeanFactoryBean();
    }
}
3.测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes ={ ApplicationConfig.class})
public class AnnoTest {
    @Autowired
    private MyBean myBean;

    @Test
    public void test(){
        System.out.println(myBean);
    }
}

2.Bean生命周期

1.Bean+InitMethod+DestoryMethod

通过@Bean标签的InitMethod,DestoryMethod属性指定Bean的生命周期方法

@Bean(InitMethod="" , DestoryMethod="")
2.InitializingBean, DisposableBean

通过InitializingBean, DisposableBean接口做Bean的初始化和销毁

public class MyBean implements InitializingBean, DisposableBean {
    public MyBean(){
        System.out.println("创建.............");
    }
    public void destroy() throws Exception {
        System.out.println("destroy方法...........");
    }
    public void afterPropertiesSet() throws Exception {
        System.out.println("初始化方法...........");
    }
}
3.PostConstruct+PreDestroy
@Component
public class MyBean {

    @PostConstruct
    public void init(){
        System.out.println("init.....");
    }
    @PreDestroy
    public void destory(){
        System.out.println("destory.....");
    }
}

4.BeanPostProcessor后置处理器

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化之前.....:"+bean);
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化之后.....:"+bean);
        return bean;
    }
}

3.PageHelper的使用

1.导入依赖
<dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.3</version>
        </dependency>
2.编写查询语句
<select id="selectPage" resultType="cn.chenxin.web.controller.domain.Employee">
	select id,username,realName from t_employee
</select>

注意:用了pagehelper之后 ,查询总条数的sql不用写 , limit 不用写 , 如上:

3.查询的service
 @Override
    public Page<Employee> selectPage() {
        PageHelper.startPage(1,5 );
        Page<Employee> page = (Page<Employee>) employeeMapper.selectPage();
        return  page;
    }

PageHelper.startPage(1,5 ):设置当前页和每页条数

Page :是pagehelper自己封装的页面对象,如同我们以前的PageList ,里面有总条数,列表,总页数等等

4.获取结果
 Page<Employee> page = employeeService.selectPage();
 System.out.println("总条数:"+page.getTotal());
 for (Employee employee : page.getResult()) {
 	System.out.println(employee);
 }

itMethod="" , DestoryMethod="")


#### 2.InitializingBean, DisposableBean

通过InitializingBean, DisposableBean接口做Bean的初始化和销毁

```java
public class MyBean implements InitializingBean, DisposableBean {
    public MyBean(){
        System.out.println("创建.............");
    }
    public void destroy() throws Exception {
        System.out.println("destroy方法...........");
    }
    public void afterPropertiesSet() throws Exception {
        System.out.println("初始化方法...........");
    }
}
3.PostConstruct+PreDestroy
@Component
public class MyBean {

    @PostConstruct
    public void init(){
        System.out.println("init.....");
    }
    @PreDestroy
    public void destory(){
        System.out.println("destory.....");
    }
}

4.BeanPostProcessor后置处理器

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化之前.....:"+bean);
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化之后.....:"+bean);
        return bean;
    }
}

3.PageHelper的使用

1.导入依赖
<dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.3</version>
        </dependency>
2.编写查询语句
<select id="selectPage" resultType="cn.chenxin.web.controller.domain.Employee">
	select id,username,realName from t_employee
</select>

注意:用了pagehelper之后 ,查询总条数的sql不用写 , limit 不用写 , 如上:

3.查询的service
 @Override
    public Page<Employee> selectPage() {
        PageHelper.startPage(1,5 );
        Page<Employee> page = (Page<Employee>) employeeMapper.selectPage();
        return  page;
    }

PageHelper.startPage(1,5 ):设置当前页和每页条数

Page :是pagehelper自己封装的页面对象,如同我们以前的PageList ,里面有总条数,列表,总页数等等

4.获取结果
 Page<Employee> page = employeeService.selectPage();
 System.out.println("总条数:"+page.getTotal());
 for (Employee employee : page.getResult()) {
 	System.out.println(employee);
 }
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值