Spring boot + mybatis + 多数据源入门搭建 + 跨域集成以及过滤器配置的方式和过滤器加载顺序控制

Posted Smile_Miracle

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring boot + mybatis + 多数据源入门搭建 + 跨域集成以及过滤器配置的方式和过滤器加载顺序控制相关的知识,希望对你有一定的参考价值。

 Spring boot + mybatis + 多数据源入门搭建 + 跨域集成以及过滤器配置的方式和过滤器加载顺序控制

由于项目需要,最近研究了一下spring boot的项目搭建,下面和大家说说项目搭建的心得体会


开发环境:

              JDK1.8 

              Eclipse

              maven3.3.9


起始工作:

              新建一个maven simple工程,导入pom依赖如下:

           

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>zhy_springboot</groupId>
  <artifactId>zhy_springboot</artifactId>
  <version>1.0.0</version>
  <packaging>war</packaging>
  <!-- 定义公共资源版本 -->
	<parent>
	    <groupId>org.springframework.boot</groupId>
	    <artifactId>spring-boot-starter-parent</artifactId>
	    <version>2.0.2.RELEASE</version>
	    <relativePath /> 
	</parent>

	<properties>
	    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
	    <java.version>1.8</java.version>
	</properties>
	
	<dependencies>
	    <!-- 上边引入 parent,因此 下边无需指定版本 -->
	    <!-- 包含 mvc,aop 等jar资源 -->
	    <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>
		    <scope>test</scope>
		</dependency>
		
		<!-- 热部署模块 -->
		<dependency>
		    <groupId>org.springframework.boot</groupId>
		    <artifactId>spring-boot-devtools</artifactId>
		    <optional>true</optional>
		</dependency>
		
		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
			<scope>provided</scope>
		</dependency>
		
	    <!-- 支持 @ConfigurationProperties 注解 -->  
	    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-configuration-processor -->  
	   <dependency>
		    <groupId>org.springframework.boot</groupId>
		    <artifactId>spring-boot-configuration-processor</artifactId>
		    <optional>true</optional>
		</dependency>
        
        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
        <!--  Mybatis -->
		<dependency>
		    <groupId>org.mybatis</groupId>
		    <artifactId>mybatis</artifactId>
		    <version>3.4.6</version>
		</dependency>
		
		<!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
		<dependency>
		    <groupId>org.mybatis.spring.boot</groupId>
		    <artifactId>mybatis-spring-boot-starter</artifactId>
		    <version>1.3.2</version>
		</dependency>
		
		 <!-- https://mvnrepository.com/artifact/tk.mybatis/mapper-spring-boot-starter -->
		<dependency>
		    <groupId>tk.mybatis</groupId>
		    <artifactId>mapper-spring-boot-starter</artifactId>
		    <version>2.0.2</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/tk.mybatis/mapper -->
		<dependency>
		    <groupId>tk.mybatis</groupId>
		    <artifactId>mapper</artifactId>
		    <version>4.0.2</version>
		</dependency>
		
		<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>		
		
		 <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.datatype</groupId>
            <artifactId>jackson-datatype-joda</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.module</groupId>
            <artifactId>jackson-module-parameter-names</artifactId>
        </dependency>
        <!-- 分页插件 -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.5</version>
        </dependency>
        <!-- alibaba的druid数据库连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.9</version>
        </dependency>
		
		<!-- https://mvnrepository.com/artifact/javax.persistence/persistence-api -->
		<dependency>
		    <groupId>javax.persistence</groupId>
		    <artifactId>persistence-api</artifactId>
		    <version>1.0.2</version>
		</dependency>
		
		
	</dependencies>
	
   <build>
	    <plugins>
	         <plugin>
	            <groupId>org.springframework.boot</groupId>
	            <artifactId>spring-boot-maven-plugin</artifactId>
	            <dependencies>
                    <dependency>
                        <groupId>org.springframework</groupId>
                        <artifactId>springloaded</artifactId>
                        <version>1.2.8.RELEASE</version>
                    </dependency>
                </dependencies>
	            <configuration>
	                <!-- 没有该配置,devtools 不生效  -->
	                <fork>true</fork>
	            </configuration>
        </plugin>
         <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>
	    </plugins>
	</build>
</project>

启动类:

         

package com.zhy.springboot;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;

import com.zhy.springboot.test.TestFilter2;
import com.zhy.springboot.test.TestFilter4;

/**
 * 经测试,过滤器第二种方式配置设置Order可完美控制顺序,而第一种加@order注解没起作用
 *
 */
@SpringBootApplication
//这里是扫描dao接口的包用于识别mybatis
@MapperScan(basePackages="com.zhy.springboot.mapper")
//@ServletComponentScan(basePackages="com.zhy.springboot.filter")//springboot过滤器创建的第一种方式(注解)
public class SpringbootApplication 
	
	
	public static void main(String[] args) 
		SpringApplication.run(SpringbootApplication.class, args);
	
	
	@Bean//扫描多个properties
    public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() 
        PropertySourcesPlaceholderConfigurer c = new PropertySourcesPlaceholderConfigurer();
        c.setIgnoreUnresolvablePlaceholders(true);
        return c;
    
	
	@Bean//springboot过滤器创建的第二种方式(代码配置)
	public FilterRegistrationBean<TestFilter2> indexFilterConfigurer()
		FilterRegistrationBean<TestFilter2> filter = new FilterRegistrationBean<TestFilter2>(new TestFilter2());
		filter.addUrlPatterns("/*");
		filter.setOrder(Integer.MAX_VALUE);//设置过滤器执行顺序,值越大越后执行
		return filter;
	
	
	@Bean//springboot过滤器创建的第二种方式(代码配置)
	public FilterRegistrationBean<TestFilter4> indexFilterConfigurer2()
		FilterRegistrationBean<TestFilter4> filter = new FilterRegistrationBean<TestFilter4>(new TestFilter4());
		filter.addUrlPatterns("/*");
		filter.setOrder(Integer.MAX_VALUE-1);
		return filter;
	
	

YML文件配置:

   

server:
          port: 8080
          
spring:         
    # HTTP ENCODING  
    http:  
        encoding.charset: UTF-8  
        encoding.enable: true  
        encoding.force: true  
    mvc:
        view.prefix: /WEB-INF/jsp/
        view.suffix: .jsp
        
    #JPA
    jpa:
        hibernate:
            ddl-auto: create-drop
            naming:
                strategy: org.hibernate.cfg.ImprovedNamingStrategy
        properties:
            hibernate:
                dialect: org.hibernate.dialect.MySQL5Dialect
        show-sql: true
    
    # DATASOURCE  
    datasource: 
        type: com.alibaba.druid.pool.DruidDataSource
        base:
            type: com.alibaba.druid.pool.DruidDataSource
            driver-class-name: com.mysql.jdbc.Driver 
            url: jdbc:mysql://localhost:3306/zhy?useUnicode=true&characterEncoding=utf-8  
            username: root  
            password: 123456
            name: baseDb
            initial-size: 1
            min-idle: 1
            max-active: 20
            #获取连接等待超时时间
            max-wait: 60000
            #间隔多久进行一次检测,检测需要关闭的空闲连接
            time-between-eviction-runs-millis: 60000
            #一个连接在池中最小生存的时间
            min-evictable-idle-time-millis: 300000
            validation-query: SELECT 'x'
            test-while-idle: true
            test-on-borrow: false
            test-on-return: false
            #打开PSCache,并指定每个连接上PSCache的大小。oracle设为true,mysql设为false。分库分表较多推荐设置为false
            pool-prepared-statements: false
            max-pool-prepared-statement-per-connection-size: 20
        second:
            type: com.alibaba.druid.pool.DruidDataSource
            driver-class-name: com.mysql.jdbc.Driver 
            url: jdbc:mysql://localhost:3306/mvs?useUnicode=true&characterEncoding=utf-8  
            username: root  
            password: 123456
            name: secondDb
            initial-size: 1
            min-idle: 1
            max-active: 20
            #获取连接等待超时时间
            max-wait: 60000
            #间隔多久进行一次检测,检测需要关闭的空闲连接
            time-between-eviction-runs-millis: 60000
            #一个连接在池中最小生存的时间
            min-evictable-idle-time-millis: 300000
            validation-query: SELECT 'x'
            test-while-idle: true
            test-on-borrow: false
            test-on-return: false
            #打开PSCache,并指定每个连接上PSCache的大小。oracle设为true,mysql设为false。分库分表较多推荐设置为false
            pool-prepared-statements: false
            max-pool-prepared-statement-per-connection-size: 20
            
        
mybatis:
    mapper-locations: classpath:sqlmaps/*.xml

#pagehelper
pagehelper:
    helperDialect: mysql
    reasonable: true
    supportMethodsArguments: true
    params: count=countSql
    returnPageInfo: check
            
#自定义person
person:
    age: 18
    name: Jack
    sex: boy
    hobbies: football,basketball,movies
    family:
        father: Tommy
        mother: Rose
        sister: Tina
        
      

注意事项:

            ① 基于yml配置文件启动的方式对yml文件里面的数据格式有严格的要求,其余的开发软件没试过,但是在eclipse中要    注意配置是以树状结构的层级展开的,配置头不可以有空格或者别的多余字符,树状结构的下二级要两个缩进位置,在eclipse中也就是四个空格,如果你启动时配置报错说配置文件哪一行挂了,那么你就要仔细检查一下自己的格是否正确

            ②在其余文件扫面yml属性的时候名字要注意,名字要对应上,而且yml配置文件里面的属性名字还不能乱写,它不跟你  讲我们常用的驼峰法什么的,最好全小写,或者按他推荐的加“”-“”隔开,如果你写成aaaB这种方式,那么启时会直接报错说你没按他的格式来,这点要特别注意


读取yml文件属性:

             spring boot数通过@ConfigurationProperties(prefix="xxxx") 注解来映射yml中的属性的,只要你将数据写好,用特定的类型来接收这个数据就行,spring boot有专门解析yml文件的jar包,这里不多做赘述,这里有一个实例:

          

#自定义person
person:
    age: 18
    name: Jack
    sex: boy
    hobbies: football,basketball,movies
    family:
        father: Tommy
        mother: Rose
        sister: Tina

可以看到我在yml中自定义了一个person属性,那么如何接收它呢

package com.zhy.springboot.model;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix="person") //application.yml中的person下的属性
public class Person 
	private String age;
	private String name;
	private String sex;
	private String[] hobbies;
	private Family family;
	
	public Family getFamily() 
		return family;
	
	public void setFamily(Family family) 
		this.family = family;
	
	public String getAge() 
		return age;
	
	public void setAge(String age) 
		this.age = age;
	
	public String getName() 
		return name;
	
	public void setName(String name) 
		this.name = name;
	
	public String getSex() 
		return sex;
	
	public void setSex(String sex) 
		this.sex = sex;
	
	public String[] getHobbies() 
		return hobbies;
	
	public void setHobbies(String[] hobbies) 
		this.hobbies = hobbies;
	

基本上就两点:

                     ① 标记这个类是被spring管理的文件,也就是@Component注解;

                     ②@ConfigurationProperties注解设置prefix属性映射它在yml文件中的属性名字


配置mybatis: 

mybatis:
    mapper-locations: classpath:sqlmaps/*.xml

当然你也可以再加个config-locations,然后配置一个路径再给他配置一个别名分页助手什么的,由个人喜欢配置

要注意的是在启动类中一定要加上mybatis的文件映射

//这里是扫描dao接口的包用于识别mybatis
@MapperScan(basePackages="com.zhy.springboot.mapper")


配置多数据源:

这里并没有对spring.datasource配置数据源,因为增加新数据源后,系统会覆盖由spring.datasource自动配置的内容。

spring:         
    # HTTP ENCODING  
    http:  
        encoding.charset: UTF-8  
        encoding.enable: true  
        encoding.force: true  
    mvc:
        view.prefix: /WEB-INF/jsp/
        view.suffix: .jsp
        
    # DATASOURCE  
    datasource: 
        type: com.alibaba.druid.pool.DruidDataSource
        base:
            type: com.alibaba.druid.pool.DruidDataSource
            driver-class-name: com.mysql.jdbc.Driver 
            url: jdbc:mysql://localhost:3306/zhy?useUnicode=true&characterEncoding=utf-8  
            username: root  
            password: 123456
            name: baseDb
            initial-size: 1
            min-idle: 1
            max-active: 20
            #获取连接等待超时时间
            max-wait: 60000
            #间隔多久进行一次检测,检测需要关闭的空闲连接
            time-between-eviction-runs-millis: 60000
            #一个连接在池中最小生存的时间
            min-evictable-idle-time-millis: 300000
            validation-query: SELECT 'x'
            test-while-idle: true
            test-on-borrow: false
            test-on-return: false
            #打开PSCache,并指定每个连接上PSCache的大小。oracle设为true,mysql设为false。分库分表较多推荐设置为false
            pool-prepared-statements: false
            max-pool-prepared-statement-per-connection-size: 20
        second:
            type: com.alibaba.druid.pool.DruidDataSource
            driver-class-name: com.mysql.jdbc.Driver 
            url: jdbc:mysql://localhost:3306/mvs?useUnicode=true&characterEncoding=utf-8  
            username: root  
            password: 123456
            name: secondDb
            initial-size: 1
            min-idle: 1
            max-active: 20
            #获取连接等待超时时间
            max-wait: 60000
            #间隔多久进行一次检测,检测需要关闭的空闲连接
            time-between-eviction-runs-millis: 60000
            #一个连接在池中最小生存的时间
            min-evictable-idle-time-millis: 300000
            validation-query: SELECT 'x'
            test-while-idle: true
            test-on-borrow: false
            test-on-return: false
            #打开PSCache,并指定每个连接上PSCache的大小。oracle设为true,mysql设为false。分库分表较多推荐设置为false
            pool-prepared-statements: false
            max-pool-prepared-statement-per-connection-size: 20

可以看到我们这里给它配置了两个数据源,一个base,一个second,数据源配置完后我们还得给它配置数据源的配置代码,这个有多少个数据源就得配置多少个,数据源base详情如下:

package com.zhy.springboot.dataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import com.alibaba.druid.pool.DruidDataSource;

@Configuration
@MapperScan(basePackages = "com.zhy.springboot.mapper.base", sqlSessionTemplateRef = "baseSqlSessionTemplate")
public class BaseDataSourceConfig 
            @Bean(name = "baseDataSource")
            @ConfigurationProperties(prefix="spring.datasource.base")
            @Primary//标记基本库,为了有多个实例一样的时候以这个为主
            public DruidDataSource setDataSource() 
            	return new DruidDataSource();
            
            
            @Bean(name="baseTransactionManager")
            @Primary
            public DataSourceTransactionManager setTransactionManager(@Qualifier("baseDataSource") DruidDataSource dataSource) 
            	return new DataSourceTransactionManager(dataSource);
            	
            
            
            @Bean(name = "baseSqlSessionFactory")
            @Primary
            public SqlSessionFactory setSqlSessionFactory(@Qualifier("baseDataSource") DruidDataSource dataSource) throws Exception 
                SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
                bean.setDataSource(dataSource);
                bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:sqlmaps/base/*.xml"));
                return bean.getObject();
            

            @Bean(name = "baseSqlSessionTemplate")
            @Primary
            public SqlSessionTemplate setSqlSessionTemplate(@Qualifier("baseSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception 
                return new SqlSessionTemplate(sqlSessionFactory);
            


数据源second详情如下:

package com.zhy.springboot.dataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import com.alibaba.druid.pool.DruidDataSource;

@Configuration
@MapperScan(basePackages = "com.zhy.springboot.mapper.secondDb", sqlSessionTemplateRef = "secondDbSqlSessionTemplate")
public class SecondDbDataSourceConfig 
   
	    @Bean(name = "secondDbDataSource")
	    @ConfigurationProperties(prefix = "spring.datasource.second")
	    public DruidDataSource setDataSource() 
	        return new DruidDataSource();
	    
	    
	    @Bean(name = "secondDbTransactionManager")
	    public DataSourceTransactionManager setTransactionManager(@Qualifier("secondDbDataSource") DruidDataSource dataSource) 
	        return new DataSourceTransactionManager(dataSource);
	    

	    @Bean(name = "secondDbSqlSessionFactory")
	    public SqlSessionFactory setSqlSessionFactory(@Qualifier("secondDbDataSource") DruidDataSource dataSource) throws Exception 
	        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
	        bean.setDataSource(dataSource);
	        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:sqlmaps/secondDb/*.xml"));
	        return bean.getObject();
	    

	    @Bean(name = "secondDbSqlSessionTemplate")
	    public SqlSessionTemplate setSqlSessionTemplate(@Qualifier("secondDbSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception 
	        return new SqlSessionTemplate(sqlSessionFactory);
	    


注意:

配置类需要对DataSource、DataSourceTransactionManager、SqlSessionFactory 、SqlSessionTemplate四个数据项进行配置;DataSource类型需要引入javax.sql.DataSource;当系统中有多个数据源时,必须有一个数据源为主数据源,使用@Primary修饰。 

@MapperScan对指定dao包建立映射,确保在多个数据源下,自动选择合适的数据源,而在service层里不需要做特殊说明。


基本上这样配置完就可以使用多数据源了,原理是配置扫面特定的dao文件已经特定的xml文件来达到不同源用不同接口的方式,所以你开发的时候要注意别把属于别的数据源的接口放入另一个包里面;

演示:

     


可以看到我有两个库,mvs和zhy

项目目录层级:

 

接口测试:

   

package com.zhy.springboot.controller;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.zhy.springboot.model.Person;
import com.zhy.springboot.model.Student;
import com.zhy.springboot.service.iservice.IBookService;
import com.zhy.springboot.service.iservice.IStudentService;

@RestController
public class TestController 

	@GetMapping("/hello")
	public String test1() 
		return "HelloWorld";
	
	
	@GetMapping("/hello2")
	public String test2() 
		return "HelloWorld222";
	
	
	@GetMapping("/hello3")
	public String test3() 
		return "HelloWorld444";
	
	
	@GetMapping("/hello4")
	public String test4() 
		String str = "";
		try 
			Properties properties = new Properties();
			// 使用ClassLoader加载properties配置文件生成对应的输入流
			InputStream in = TestController.class.getClassLoader().getResourceAsStream("static/test.properties");
			// 使用properties对象加载输入流
			properties.load(in);
			//获取key对应的value值
			str =  properties.getProperty("abc").toString();
		 catch (IOException e) 
			e.printStackTrace();
		
		return str;
	
	
	@Autowired
	private Person person;
	
	@Value("$person.name")
	private String name;
	@Value("$person.age")
	private String age;
	@Value("$person.sex")
	private String sex;
	@Value("$person.hobbies")
	private String[]hobbies;
	@Value("$person.family.father")
	private String father;
	@Value("$person.family.mother")
	private String mother;
	@Value("$person.family.sister")
	private String sister;
	
	@GetMapping("/hello5")
	public Map<String,Object> test5() 
		Map<String,Object> result1 = new HashMap<>();
		result1.put("age", person.getAge());
		result1.put("name", person.getName());
		result1.put("sex", person.getSex());
		result1.put("hobbies", person.getHobbies());
		result1.put("father", person.getFamily().getFather());
		result1.put("mother", person.getFamily().getMother());
		result1.put("sister", person.getFamily().getSister());
		return result1;
	
	
	@Autowired
	private IStudentService studentService;
	@GetMapping("/hello6")
	public Map<String,Object> test6() 
		Map<String,Object> result = new HashMap<>();
		Student student = studentService.findById(1);
		result.put("student", student);
		return result;
	
	
	/*@Autowired
	private UserMapper userDao;
	@GetMapping("/hello7")
	public Map<String,Object> test7() 
		Map<String,Object> result = new HashMap<>();
		System.err.println(userDao.findAll());
		Optional<User> findById = userDao.findById(2);
		System.out.println(findById.toString());
		return result;
	*/
	
	@Autowired
	private IBookService bookService;
	@GetMapping("/hello8")
	public Map<String,Object> test8() 
		Map<String,Object> result = new HashMap<>();
		result.put("Student", studentService.findById(1));
		result.put("Book", bookService.findById(1));
		return result;
	
	

结果:

   

可以发现多数据源配置成功


跨域集成:

package com.zhy.springboot;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration  
@EnableWebMvc 
public class CorsConfig implements WebMvcConfigurer    

	@Override  
    public void addCorsMappings(CorsRegistry registry)   
        //设置允许跨域的路径  
        registry.addMapping("/**")  
                //设置允许跨域请求的域名  
                .allowedOrigins("*")  
                //是否允许证书 不再默认开启  
                .allowCredentials(true)  
                //设置允许的方法  
                .allowedMethods("*")  
                //设置允许的请求头
                .allowedHeaders("*")
                //跨域允许时间  
                .maxAge(3600);  
      

这一种比较通用,当然你也可以写一个过滤器然后配置在启动类里面也一样可以


过滤器配置及加载顺序控制:

spring boot常用的过滤器配置有两种方式,第一种基于注解

//@ServletComponentScan(basePackages="com.zhy.springboot.filter")//springboot过滤器创建的第一种方式(注解)

直接在指定的包下面写好过滤器,然后在启动类重加上上面的注解扫面过滤器包即可,但是这种@order注解控制加载顺序未生效,正在研究中

package com.zhy.springboot.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.core.annotation.Order;


@WebFilter(filterName="baseFilter",urlPatterns= "/*")
//指定过滤器的执行顺序,值越小越靠后执行
@Order(100)
public class TestFilter implements Filter

	@Override
	public void destroy() 
		
	

	@Override
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
			throws IOException, ServletException 
		
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) res;
		System.out.println(req.getLocalAddr()+"进过滤器...................");
		chain.doFilter(request, response);
	

	@Override
	public void init(FilterConfig arg0) throws ServletException 
		
	

                   

第二种是在启动类中配置bean文件:

package com.zhy.springboot.test;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebFilter(filterName="baseFilter2")
public class TestFilter2  implements Filter

	@Override
	public void destroy() 
		
	

	@Override
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
			throws IOException, ServletException 
		
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) res;
		System.out.println("2.2.2.2.2.2.2.2.2"+"进入过滤器...................");
		chain.doFilter(request, response);
	

	@Override
	public void init(FilterConfig arg0) throws ServletException 
		
	



@Bean//springboot过滤器创建的第二种方式(代码配置)
	public FilterRegistrationBean<TestFilter2> indexFilterConfigurer()
		FilterRegistrationBean<TestFilter2> filter = new FilterRegistrationBean<TestFilter2>(new TestFilter2());
		filter.addUrlPatterns("/*");
		filter.setOrder(Integer.MAX_VALUE);//设置过滤器执行顺序,值越大越后执行
		return filter;
	
	
	@Bean//springboot过滤器创建的第二种方式(代码配置)
	public FilterRegistrationBean<TestFilter4> indexFilterConfigurer2()
		FilterRegistrationBean<TestFilter4> filter = new FilterRegistrationBean<TestFilter4>(new TestFilter4());
		filter.addUrlPatterns("/*");
		filter.setOrder(Integer.MAX_VALUE-1);
		return filter;
	

这种可以通过配置order来控制过滤器的加载顺序,值越小越先执行。


日志管理:

   添加pom依赖

<!-- 日志相关 -->
        <dependency>
		    <groupId>org.springframework.boot</groupId>
		    <artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
<!-- 引入log4j2依赖 -->  
        <dependency> 
	        <groupId>org.springframework.boot</groupId>  
	        <artifactId>spring-boot-starter-log4j2</artifactId>  
	    </dependency>  
	    <dependency>  <!-- 加上这个才能辨认到log4j2.yml文件 -->  
	        <groupId>com.fasterxml.jackson.dataformat</groupId>  
	        <artifactId>jackson-dataformat-yaml</artifactId>  
	    </dependency> 

yml配置文件配置

#配置日志
logging:
    config: classpath:log4j.xml

log4j.xml:

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">

    <!-- 每个logger都关联到logger上下文,默认上下文名称为“default”。但可以使用设置成其他名字,用于区分不同应用程序的记录。
    一旦设置,不能修改,可以通过%contextName来打印日志上下文名称,一般来说我们不用这个属性,可有可无。 -->
    <contextName>zhy_springboot</contextName>
    <!-- 用来定义变量值的标签, 有两个属性,name和value;其中name的值是变量的名称,
    value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“$”来使用变量。 -->
    <property name="logback.logdir" value="D:\\\\Devlop\\\\Work_Spaces\\\\zhy_springboot\\\\src\\\\main\\\\resources\\\\log"/>
    <property name="logback.appname" value="zhy_springboot"/>

    <!--输出到控制台 ConsoleAppender-->
    <appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
        <!--展示格式 layout-->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>
                <pattern>%dHH:mm:ss.SSS %contextName [%thread] %-5level %logger36 - %msg%n</pattern>
            </pattern>
        </layout>
    </appender>
    
    <appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
	    <!--如果只是想要 Info 级别的日志,只是过滤 info 还是会输出 Error 日志,因为 Error 的级别高,
	    所以我们使用下面的策略,可以避免输出 Error 的日志-->
	    <filter class="ch.qos.logback.classic.filter.LevelFilter">
	        <!--过滤 Error-->
	        <level>ERROR</level>
	        <!--匹配到就禁止-->
	        <onMatch>DENY</onMatch>
	        <!--没有匹配到就允许-->
	        <onMismatch>ACCEPT</onMismatch>
	    </filter>
	    <!--日志名称,如果没有File 属性,那么只会使用FileNamePattern的文件路径规则
	        如果同时有<File>和<FileNamePattern>,那么当天日志是<File>,明天会自动把今天
	        的日志改名为今天的日期。即,<File> 的日志都是当天的。
	    -->
	    <File>$logback.logdir/info.$logback.appname.log</File>
	    <!--滚动策略,按照时间滚动 TimeBasedRollingPolicy-->
	    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
	        <!--文件路径,定义了日志的切分方式——把每一天的日志归档到一个文件中,以防止日志填满整个磁盘空间-->
	        <FileNamePattern>$logback.logdir/info.$logback.appname.%dyyyy-MM-dd.log</FileNamePattern>
	        <!--只保留最近90天的日志-->
	        <maxHistory>90</maxHistory>
	        <!--用来指定日志文件的上限大小,那么到了这个值,就会删除旧的日志-->
	        <totalSizeCap>1GB</totalSizeCap>
	    </rollingPolicy>
	    <!--日志输出编码格式化-->
	    <encoder>
	        <charset>UTF-8</charset>
	        <pattern>%d [%thread] %-5level %logger36 %line - %msg%n</pattern>
	    </encoder>
	</appender>


	<appender name="fileErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
	    <!--如果只是想要 Error 级别的日志,那么需要过滤一下,默认是 info 级别的,ThresholdFilter-->
	    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
	        <level>Error</level>
	    </filter>
	    <!--日志名称,如果没有File 属性,那么只会使用FileNamePattern的文件路径规则
	        如果同时有<File>和<FileNamePattern>,那么当天日志是<File>,明天会自动把今天
	        的日志改名为今天的日期。即,<File> 的日志都是当天的。
	    -->
	    <File>$logback.logdir/error.$logback.appname.log</File>
	    <!--滚动策略,按照时间滚动 TimeBasedRollingPolicy-->
	    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
	        <!--文件路径,定义了日志的切分方式——把每一天的日志归档到一个文件中,以防止日志填满整个磁盘空间-->
	        <FileNamePattern>$logback.logdir/error.$logback.appname.%dyyyy-MM-dd.log</FileNamePattern>
	        <!--只保留最近90天的日志-->
	        <maxHistory>90</maxHistory>
	        <!--用来指定日志文件的上限大小,那么到了这个值,就会删除旧的日志-->
	        <totalSizeCap>1GB</totalSizeCap>
	    </rollingPolicy>
	    <!--日志输出编码格式化-->
	    <encoder>
	        <charset>UTF-8</charset>
	        <pattern>%d [%thread] %-5level %logger36 %line - %msg%n</pattern>
	    </encoder>
	</appender>

    <!--指定最基础的日志输出级别-->
    <root level="INFO">
        <!--appender将会添加到这个loger-->
        <appender-ref ref="consoleLog"/>
        <appender-ref ref="fileInfoLog"/>
        <appender-ref ref="fileErrorLog"/>
    </root>
</configuration>


总结:

       可以看到spring boot搭建的项目相比于spring springmvc mybatis来说简化了许多东西,最直面的感官就是配置文件少了很多,而且配置方式也简化了许多,不管你是用properties还是yml方式都比配置spring文件然后写一堆<bean>来的轻松,而且它还可以完美集成hibernate,提供了专门的JPA方式操作,确实很强大。

完整项目下载地址:

点击打开链接


以上是关于Spring boot + mybatis + 多数据源入门搭建 + 跨域集成以及过滤器配置的方式和过滤器加载顺序控制的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot + MyBatis + Pagehelper 配置多数据源

spring-boot2.0 Mybatis多数据源配置

Spring Boot 2.X:MyBatis 多数据源配置

shardingsphere多数据源(springboot + mybatis+shardingsphere+druid)

spring boot+mybatis整合

spring boot+mybatis 多数据源切换