SpringBoot入门和简单使用

一、SpringBoot相关知识理解

  1. SpringBoot简介
    在您第1次接触和学习Spring框架的时候,是否因为其繁杂的配置而退却了?在你第n次使用Spring框架的时候,是否觉得一堆反复黏贴的配置有一些厌烦?那么您就不妨来试试使用Spring Boot来让你更易上手,更简单快捷地构建Spring应用!
    Spring Boot让我们的Spring应用变的更轻量化。比如:你可以仅仅依靠一个Java类来运行一个Spring应用。你也可以打包你的应用为jar并通过使用java -jar来运行你的Spring Web应用。
    SpringBoot并不是对Spring功能上的增强,而是提供了一种快速使用Spring的方式。
    :SpringBoot是一个独立的应用程序,单独war工程,不需要集成tomcat插件运行,因为SpringBoot自身已经内嵌了tomcat。创建SpringBoot项目时可以jar也可以是war,但是不建议建成war工程(如果要使用jsp可以建成war,但是SpringBoot不建议使用jsp),因为SpringBoot是一个独立的应用程序,所以建议选择jar创建SpringBoot项目。
    Spring Boot的主要优点:
    1. 为所有Spring开发者更快的入门(简化Maven配置、自动配置Spring)。
    2. 开箱即用,提供各种默认配置来简化项目配置。同时也可以修改默认值来满足特定的需求。
    3. 内嵌式容器简化Web项目(嵌入的Tomcat,无需部署war文件)。
    4. 没有冗余代码生成和XML配置的要求。
    5. 提供了一些大型项目中常见的非功能特性:生产就绪功能,如:指标,健康检查和外部配置等。
  2. 使用SpringBoot环境要求:
    Java 7及以上,Spring Framework 4.1.5及以上。

二、SpringBoot快速入门及环境搭建(jdk1.8+springboot1.3.2)

  1. 创建一个maven管理的jar工程,在此不做示例。
  2. 在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>chuancy</groupId>
      <artifactId>SpringBoot</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      
      <!-- 必须要引入继承springboot-parent,因为该父工程帮助实现了很多jar包的依赖管理,不要写jar包版本,这样可以控制jar包版本冲突的问题 。-->
      <parent>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-parent</artifactId>
          <version>1.3.3.RELEASE</version>
      </parent>
      <dependencies>
          <!-- 不需要引入SpringMVC,SpringBoot默认集成,只需要引入SpringBoot的web组件:springboot-web即可。 -->
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
          </dependency>
      </dependencies>
          
    </project>
    
    1. spring-boot-starter-parent作用:
      在pom.xml中引入spring-boot-start-parent,可以提供dependency management,也就是说依赖管理,引入以后再声明其它dependency的时候就不需要version了。
    2. spring-boot-starter-web作用:
      springweb 核心组件,包含springmvc等。
  3. 创建测试类测试框架是否搭建成功:
    package chauncy.controller;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**   
     * @classDesc: 功能描述(第一个springboot)
     * 注解:@RestController是SpringBoot提供的http restful风格,等同于 :类上@Controller+每个方法@ResponseBody,表示该类所有请求方法返回json格式。
     * @author: ChauncyWang
     * @version: 1.0  
     */  
    @RestController
    @RequestMapping("/TestController")
    @EnableAutoConfiguration
    public class TestController {
    	
    	@RequestMapping("/hello")
    	public String hello(){
    		return "success";
    	}
    	
    	public static void main(String[] args) {
    		//运行SpringBoot应用,不要写多个main函数,因为SpringBoot是一个独立的应用程序。
    		SpringApplication.run(TestController.class, args);
    	}
    }
    
  4. 相关知识汇总:
    1. @RestController解释:
      在类上加上RestController 表示修饰该Controller类所有的方法返回JSON格式,直接可以编写Restful接口。
    2. @EnableAutoConfiguration解释:
      该注解作用在于:让Spring Boot根据应用所声明的依赖来对Spring框架进行自动配置。
      这个注解告诉Spring Boot根据添加的jar依赖猜测开发设计者想如何配置Spring。由于spring-boot-starter-web添加了Tomcat和Spring MVC,所以auto-configuration将假定开发设计者正在开发一个web应用并相应地对Spring进行设置。
    3. SpringApplication.run(TestController.class, args);解释
      标识TestController为启动类。
    4. Spring启动方式:
      1. 启动方式1:
        以上环境搭建第3步。
        Springboot默认端口号为8080,启动成功后,打开浏览器访问http://127.0.0.1:8080/TestController/hello,可以看到页面输出:success。
        但是因为SpringBoot默认端口为8080,再写一个Controller同样也需要启动的话,如果写两个main方法同时启动会报端口号被占用的异常,所以不建议写在某一个业务Controller中进行启动,建议写通用类进行启动配置的操作,例以下启动方式2.
      2. 启动方式2:
        @ComponentScan(basePackages = “chauncy.controller”)–控制器扫包范围
        @ComponentScan(basePackages = "chauncy.controller")
        @EnableAutoConfiguration
        public class App {
        	public static void main(String[] args) {
        		SpringApplication.run(App.class, args);
        	}
        }
        

三、使用SpringBoot进行Web开发

  1. 静态资源访问:
    在进行Web应用开发的时候,需要引用大量的js、css、图片等静态资源。
    默认配置:
    Spring Boot默认提供静态资源目录位置需置于classpath下,目录名需符合如下规则:
    /static
    /public
    /resources
    /META-INF/resources
    举例:我们可以在src/main/resources/目录下创建static,在该位置放置一个图片文件。启动程序后,尝试访问http://localhost:8080/test.jpg(访问不需要加static)。如能显示图片,配置成功。

  2. 全局捕获异常:
    @ExceptionHandler 表示拦截异常。
    @ControllerAdvice 是controller的一个辅助类,最常用的就是作为全局异常处理的切面类。
    @ControllerAdvice 可以指定扫描范围。
    @ControllerAdvice 约定了几种可行的返回值:

    1. 如果是直接返回 model 类的话,需要使用 @ResponseBody 进行 json 转换。
    2. 返回 String,表示跳到某个 view。
    3. 返回 modelAndView。

    代码示例,当应用有运行时异常进行捕获处理:

    package chauncy.controller.catchexception;
    
    import java.util.HashMap;
    import java.util.Map;
    
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    /**
     * @classDesc: 功能描述:(全局捕获异常)
     * @author: ChauncyWang
     * @verssion: v1.0
     */
    @ControllerAdvice
    public class GlobalExceptionHandler {
    	
    	@ExceptionHandler(RuntimeException.class)
    	@ResponseBody//拦截异常返回json格式的结果
    	public Map<String,Object> execptionHandler(){
    		Map<String, Object> result = new HashMap<String, Object>();
    		result.put("code", "500");
    		result.put("msg", "系统错误,请稍后重试。");
    		return result;
    	}
    }
    
  3. 渲染Web页面
    在以上的代码中,都是通过@RestController来处理请求,所以返回的内容为json对象。那么如果需要渲染html页面的时候,要如何实现呢?
    在动态HTML实现上,Spring Boot依然可以完美胜任,并且提供了多种模板引擎的默认配置支持,所以在推荐的模板引擎下,可以很快的上手开发动态网站。
    Spring Boot提供了默认配置的模板引擎主要有以下几种:

    1. Thymeleaf
    2. FreeMarker
    3. Velocity
    4. Groovy
    5. Mustache

    Spring Boot建议使用以上这些模板引擎,避免使用JSP,若一定要使用JSP将无法实现Spring Boot的多种特性,具体可见后文:支持JSP的配置。
    当使用上述模板引擎中的任何一个,它们默认的模板配置路径为:src/main/resources/templates。当然也可以修改这个路径,具体如何修改,可在后续各模板引擎的配置属性中查询并修改。
    PS:模板引擎主要作用是动态页面静态化,为什么要动态页面静态化,因为好让搜索引擎搜索到,就是SEO(Search Engine Optimization搜索引擎优化),最终转化成html(伪静态),可以提高互联网站在搜索引擎中的排名,获取流量收益等。

  4. 使用Freemarker模板引擎渲染web视图

    1. 在pom.xml文件中引入freemarker依赖(注意一定要使用springboot相关依赖,不要从maven库中找):
      <!-- 引入freeMarker的依赖包. -->
      <dependency>
      	<groupId>org.springframework.boot</groupId>
      	<artifactId>spring-boot-starter-freemarker</artifactId>
      </dependency>
      
    2. 在默认路径src/main/resources/templates下,创建一个后缀名为ftl的文件,内容如下:
      <!DOCTYPE html>
      <html>
      <head lang="en">
      <meta charset="UTF-8" />
      <title></title>
      </head>
      <body>
          ${name}<br/>
          <#if sex==1>
                      男
          <#elseif sex==2>
                      女
          <#else>
                      其他      
          </#if>
          <br/>
          <#list userList as user>
              ${user}
          </#list>
         
      </body> 
      </html>
      
    3. 后台编写请求访问创建的ftl文件:
      package chauncy.controller.web;
      
      import java.util.ArrayList;
      import java.util.List;
      
      import org.springframework.stereotype.Controller;
      import org.springframework.ui.ModelMap;
      import org.springframework.web.bind.annotation.RequestMapping;
      
      @Controller
      @RequestMapping("/IndexController")
      public class IndexController {
      	
      	
      	@RequestMapping("/index")
      	public String index(ModelMap map){
      		//ModelMap类似于HttpServletRequest的request.setAttribute,只不过ModelMap是SpringMVC封装好的。
      		map.put("name", "ChauncyWang");
      		map.put("sex", 1);
      		List<String> userlist=new ArrayList<String>();
      		userlist.add("chauncy1");
      		userlist.add("chauncy2");
      		userlist.add("chauncy3");
      		map.put("userList", userlist);
      		return "index";
      	}
      }
      
    4. Freemarker的一些配置:
      在src/main/resources下新建application.properties文件,添加如下配置(具体属性含义及修改参考互联网资料):
      ########################################################
      ###FREEMARKER (FreeMarkerAutoConfiguration)
      ########################################################
      spring.freemarker.allow-request-override=false
      spring.freemarker.cache=true
      spring.freemarker.check-template-location=true
      spring.freemarker.charset=UTF-8
      spring.freemarker.content-type=text/html
      spring.freemarker.expose-request-attributes=false
      spring.freemarker.expose-session-attributes=false
      spring.freemarker.expose-spring-macro-helpers=false
      #spring.freemarker.prefix=
      #spring.freemarker.request-context-attribute=
      #spring.freemarker.settings.*=
      spring.freemarker.suffix=.ftl
      spring.freemarker.template-loader-path=classpath:/templates/
      #comma-separated list
      #spring.freemarker.view-names= # whitelist of view names that can be resolved
      
  5. 使用JSP渲染Web视图
    SpringBoot要求使用jsp的话项目必须构建为war工程。

    1. 创建一个maven管理的war工程,在此不做示例。
    2. 在pom.xml文件中引入相关依赖:
      <parent>
      	<groupId>org.springframework.boot</groupId>
      	<artifactId>spring-boot-starter-parent</artifactId>
      	<version>1.3.3.RELEASE</version>
      </parent>
      <dependencies>
      	<!-- SpringBoot 核心组件 -->
      	<dependency>
      		<groupId>org.springframework.boot</groupId>
      		<artifactId>spring-boot-starter-web</artifactId>
      	</dependency>
      	<dependency>
      		<groupId>org.springframework.boot</groupId>
      		<artifactId>spring-boot-starter-tomcat</artifactId>
      	</dependency>
      	<dependency>
      		<groupId>org.apache.tomcat.embed</groupId>
      		<artifactId>tomcat-embed-jasper</artifactId>
      	</dependency>
      </dependencies>
      
    3. 在src/main/resources下新建application.properties文件,添加如下配置:
      spring.mvc.view.prefix=/WEB-INF/jsp/
      spring.mvc.view.suffix=.jsp
      
    4. 在src/main/webapp下创建文件夹WEB-INF/jsp,创建文件index.jsp:
      <%@ page language="java" contentType="text/html; charset=utf-8"
          pageEncoding="utf-8"%>
      <!DOCTYPE html>
      <html>
      <head>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <title></title>
      </head>
      <body>
          this is springboot!
      </body>
      </html>
      
    5. 后台编写请求访问index.jsp文件(简化启动,运行main即可):
      package chauncy.controller;
      
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
      import org.springframework.stereotype.Controller;
      import org.springframework.web.bind.annotation.RequestMapping;
      
      @Controller
      @RequestMapping("/IndexController")
      @EnableAutoConfiguration
      public class IndexController {
      	
      	@RequestMapping("/index")
      	public String index(){
      		return "index";
      	}
      	
      	public static void main(String[] args) {
      		SpringApplication.run(IndexController.class, args);
      	}
      }
      

四、数据访问

  1. springboot整合使用JdbcTemplate:

    1. 创建一个maven管理的jar工程,在此不做示例。
    2. 在pom.xml文件中引入相关依赖:
      <parent>
      	<groupId>org.springframework.boot</groupId>
      	<artifactId>spring-boot-starter-parent</artifactId>
      	<version>1.5.2.RELEASE</version>
      </parent>
      <dependencies>
      	<dependency>
      		<groupId>org.springframework.boot</groupId>
      		<artifactId>spring-boot-starter-jdbc</artifactId>
      	</dependency>
      	<dependency>
      		<groupId>mysql</groupId>
      		<artifactId>mysql-connector-java</artifactId>
      		<version>8.0.15</version>
      	</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-starter-web</artifactId>
      	</dependency>
      </dependencies>
      
    3. 在src/main/resources下新建application.properties文件,添加如下配置:
      spring.datasource.url=jdbc:mysql://localhost:3306/architect?serverTimezone=GMT
      spring.datasource.username=root
      spring.datasource.password=root
      spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
      
    4. 编写后台请求实现使用JdbcTemplate对数据库表增加记录的操作:
      package chauncy.service;
      
      public interface UserService {
      	
      	public void createJdbcUser();
      }
      
      package chauncy.service.impl;
      
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.jdbc.core.JdbcTemplate;
      import org.springframework.stereotype.Service;
      
      import chauncy.service.UserService;
      
      @Service
      public class UserServiceImpl implements UserService {
      
      	@Autowired
      	private JdbcTemplate jdbcTemplate;
      
      	@Override
      	public void createJdbcUser() {
      		jdbcTemplate.update("insert into users values(null,?,?);", "chauncy", 18);
      
      	}
      
      }
      
      package chauncy.controller;
      
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RestController;
      
      import chauncy.service.UserService;
      
      @RestController
      @RequestMapping("/IndexController")
      public class IndexController {
      	
      	@Autowired
      	UserService userService;
      	
      	@RequestMapping("/index")
      	public String index(){
      		userService.createJdbcUser();
      		return "add success";
      	}
      }
      
      package chauncy;
      
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
      import org.springframework.context.annotation.ComponentScan;
      
      @ComponentScan(basePackages = "chauncy.*")
      @EnableAutoConfiguration
      public class APP {
      
      	public static void main(String[] args) {
      		SpringApplication.run(APP.class, args);
      	}
      }
      
    5. 使用浏览器访问请求,若正常造成请求,数据库users表应该增加一条记录。

    注意:使用JdbcTemplate需要spring-boot-starter-parent在1.5以上。

  2. springboot整合使用mybatis:

    1. 创建一个maven管理的jar工程,在此不做示例。
    2. 在pom.xml文件中引入相关依赖:
      <parent>
      	<groupId>org.springframework.boot</groupId>
      	<artifactId>spring-boot-starter-parent</artifactId>
      	<version>1.3.2.RELEASE</version>
      	<relativePath /> <!-- lookup parent from repository -->
      </parent>
      <dependencies>
      	<dependency>
      		<groupId>org.springframework.boot</groupId>
      		<artifactId>spring-boot-starter</artifactId>
      	</dependency>
      	<dependency>
      		<groupId>org.springframework.boot</groupId>
      		<artifactId>spring-boot-starter-test</artifactId>
      		<scope>test</scope>
      	</dependency>
      	<dependency>
      		<groupId>org.mybatis.spring.boot</groupId>
      		<artifactId>mybatis-spring-boot-starter</artifactId>
      		<version>1.1.1</version>
      	</dependency>
      	<dependency>
                 <groupId>mysql</groupId>
                 <artifactId>mysql-connector-java</artifactId>
                 <version>8.0.15</version>
             </dependency>
      	<dependency>
      		<groupId>org.springframework.boot</groupId>
      		<artifactId>spring-boot-starter-web</artifactId>
      	</dependency>
      </dependencies>
      
    3. 在src/main/resources下新建application.properties文件,添加如下配置:
      spring.datasource.url=jdbc:mysql://localhost:3306/architect?serverTimezone=GMT
      spring.datasource.username=root
      spring.datasource.password=root
      spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
      
    4. 编写后台请求实现使用Mybatis对数据库表条件查询的操作:
      package chauncy.entity;
      
      public class UserEntity {
      
      	private Integer id;
      
      	private String name;
      
      	private Integer age;
      
      	public Integer getId() {
      		return id;
      	}
      
      	public void setId(Integer id) {
      		this.id = id;
      	}
      
      	public String getName() {
      		return name;
      	}
      
      	public void setName(String name) {
      		this.name = name;
      	}
      
      	public Integer getAge() {
      		return age;
      	}
      
      	public void setAge(Integer age) {
      		this.age = age;
      	}
      
      }
      
      package chauncy.mapper;
      
      import org.apache.ibatis.annotations.Param;
      import org.apache.ibatis.annotations.Select;
      
      import chauncy.entity.UserEntity;
      
      
      public interface UserMapper {
      	
      	@Select("select * from users where name=#{name}")
      	UserEntity findUser(@Param("name")String name);
      }
      
      package chauncy.controller;
      
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Controller;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.ResponseBody;
      
      import chauncy.entity.UserEntity;
      import chauncy.mapper.UserMapper;
      
      @Controller
      @RequestMapping("/IndexController")
      public class IndexController {
      
      	@Autowired
      	private UserMapper userMapper;
      
      	@ResponseBody
      	@RequestMapping("/getUserName")
      	public UserEntity getUserName(String name) {
      		return userMapper.findUser(name);
      
      	}
      }
      
      package chauncy;
      
      import org.mybatis.spring.annotation.MapperScan;
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
      import org.springframework.context.annotation.ComponentScan;
      
      @ComponentScan(basePackages = "chauncy.*")
      @MapperScan(basePackages="chauncy.*")
      @EnableAutoConfiguration
      public class APP {
      
      	public static void main(String[] args) {
      		SpringApplication.run(APP.class, args);
      	}
      }
      
    5. 使用浏览器造成get请求进行访问,若条件匹配应有json数据返回。
  3. springboot整合使用springjpa:
    什么是SpringJPA?SpringJPA其实就是对Hibernate的封装。

    1. 创建一个maven管理的jar工程,在此不做示例。
    2. 在pom.xml文件中引入相关依赖:
      <parent>
      	<groupId>org.springframework.boot</groupId>
      	<artifactId>spring-boot-starter-parent</artifactId>
      	<version>1.4.2.RELEASE</version>
      </parent>
      <dependencies>
      	<dependency>
      		<groupId>org.springframework.boot</groupId>
      		<artifactId>spring-boot-starter-data-jpa</artifactId>
      	</dependency>
      	<dependency>
                 <groupId>mysql</groupId>
                 <artifactId>mysql-connector-java</artifactId>
                 <version>8.0.15</version>
             </dependency>
      	<dependency>
      		<groupId>org.springframework.boot</groupId>
      		<artifactId>spring-boot-starter-web</artifactId>
      	</dependency>
      </dependencies>
      
    3. 在src/main/resources下新建application.properties文件,添加如下配置:
      spring.datasource.url=jdbc:mysql://localhost:3306/architect?serverTimezone=GMT
      spring.datasource.username=root
      spring.datasource.password=root
      spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
      
    4. 编写后台请求实现使用SpringJPA对数据库表条件查询的操作:
      package chauncy.entity;
      
      import javax.persistence.Column;
      import javax.persistence.Entity;
      import javax.persistence.GeneratedValue;
      import javax.persistence.Id;
      
      //注解都是使用javax反射包下的
      @Entity(name = "users")
      public class UserEntity {
      	
      	@Id
      	@GeneratedValue
      	private Integer id;
      
      	@Column
      	private String name;
      
      	@Column
      	private Integer age;
      
      	public Integer getId() {
      		return id;
      	}
      
      	public void setId(Integer id) {
      		this.id = id;
      	}
      
      	public String getName() {
      		return name;
      	}
      
      	public void setName(String name) {
      		this.name = name;
      	}
      
      	public Integer getAge() {
      		return age;
      	}
      
      	public void setAge(Integer age) {
      		this.age = age;
      	}
      
      	@Override
      	public String toString() {
      		return "UserEntity [id=" + id + ", name=" + name + ", age=" + age + "]";
      	}
      	
      	
      }
      
      package chauncy.dao;
      
      import org.springframework.data.jpa.repository.JpaRepository;
      
      import chauncy.entity.UserEntity;
      
      //规范:使用jpa的dao层必须要继承JpaRepository<实体类, 序列化主键>接口
      public interface UserDao extends JpaRepository<UserEntity, Integer> {
      
      }
      
      package chauncy.controller;
      
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Controller;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RestController;
      
      import chauncy.dao.UserDao;
      import chauncy.entity.UserEntity;
      
      @RestController
      @RequestMapping("/IndexController")
      public class IndexController {
      
      	@Autowired
      	private UserDao userDao;
      
      	@RequestMapping("/index")
      	public String index(Integer id) {
      		UserEntity userEntity = userDao.findOne(id);
      		return userEntity.toString();
      	}
      }
      
      package chauncy;
      
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
      import org.springframework.boot.autoconfigure.domain.EntityScan;
      import org.springframework.context.annotation.ComponentScan;
      import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
      
      @EnableAutoConfiguration
      @ComponentScan(basePackages = "chauncy.*")
      @EnableJpaRepositories(basePackages = "chauncy.*")
      @EntityScan("chauncy.*")
      public class APP {
      	public static void main(String[] args) {
      		SpringApplication.run(APP.class, args);
      	}
      }
      
    5. 使用浏览器造成get请求进行访问,若条件匹配应有toString数据返回。
  4. springboot整合多数据源:
    有的时候一个项目需要操作多个JDBC,此时就需要整合多数据源。
    例:大型互联网公司分为base数据库(字典、相同配置信息)、主数据库,需要操作多数据源。
    操作多数据源的方式:1.使用注解,但是较繁琐,需要写很多,不推荐。2.分包进行配置,一个包对一个数据源进行操作。
    PS:Spring默认支持多数据源事务回滚。

    1. 创建一个maven管理的jar工程,在此不做示例。
    2. 在pom.xml文件中引入相关依赖:
      <parent>
      	<groupId>org.springframework.boot</groupId>
      	<artifactId>spring-boot-starter-parent</artifactId>
      	<version>1.3.2.RELEASE</version>
      	<relativePath /> <!-- lookup parent from repository -->
      </parent>
      <dependencies>
      	<dependency>
      		<groupId>org.springframework.boot</groupId>
      		<artifactId>spring-boot-starter</artifactId>
      	</dependency>
      	<dependency>
      		<groupId>org.springframework.boot</groupId>
      		<artifactId>spring-boot-starter-test</artifactId>
      		<scope>test</scope>
      	</dependency>
      	<dependency>
      		<groupId>org.mybatis.spring.boot</groupId>
      		<artifactId>mybatis-spring-boot-starter</artifactId>
      		<version>1.1.1</version>
      	</dependency>
      	<dependency>
                 <groupId>mysql</groupId>
                 <artifactId>mysql-connector-java</artifactId>
                 <version>8.0.15</version>
             </dependency>
      	<dependency>
      		<groupId>org.springframework.boot</groupId>
      		<artifactId>spring-boot-starter-web</artifactId>
      	</dependency>
      </dependencies>
      
    3. 在src/main/resources下新建application.properties文件,添加如下配置:
      spring.datasource.test1.driverClassName = com.mysql.cj.jdbc.Driver
      spring.datasource.test1.url = jdbc:mysql://localhost:3306/test01?serverTimezone=GMT&useUnicode=true&characterEncoding=utf-8
      spring.datasource.test1.username = root
      spring.datasource.test1.password = root
      
      spring.datasource.test2.driverClassName = com.mysql.cj.jdbc.Driver
      spring.datasource.test2.url = jdbc:mysql://localhost:3306/test02?serverTimezone=GMT&useUnicode=true&characterEncoding=utf-8
      spring.datasource.test2.username = root
      spring.datasource.test2.password = root
      
    4. 使用java代码增加两个数据源的配置:
      package chauncy.datasource;
      
      
      import javax.sql.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.autoconfigure.jdbc.DataSourceBuilder;
      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.jdbc.datasource.DataSourceTransactionManager;
      
      /**   
       * @classDesc: 功能描述(数据源1的配置)  
       * @author: ChauncyWang
       * @version: 1.0  
       */ 
      @Configuration // 注册到spring容器中
      @MapperScan(basePackages="chauncy.test01",sqlSessionFactoryRef="test1SqlSessionFactory")
      public class Datasource1 {
      	
      	/**   
      	 * @methodDesc: 功能描述(配置test1数据库)  
      	 * @author: ChauncyWang
      	 * @param: @return   
      	 * @returnType: DataSource  
      	 */  
      	@Bean(name = "test1DataSource")
      	@Primary
      	@ConfigurationProperties(prefix = "spring.datasource.test1")
      	public DataSource testDataSource() {
      		return DataSourceBuilder.create().build();
      	}
      
      	
      	/**   
      	 * @methodDesc: 功能描述(test1 sql会话工厂)  
      	 * @author: ChauncyWang
      	 * @param: @param dataSource
      	 * @param: @return
      	 * @param: @throws Exception   
      	 * @returnType: SqlSessionFactory  
      	 */  
      	@Bean(name = "test1SqlSessionFactory")
      	@Primary
      	public SqlSessionFactory testSqlSessionFactory(@Qualifier("test1DataSource") DataSource dataSource)
      			throws Exception {
      		SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
      		bean.setDataSource(dataSource);
      //		bean.setMapperLocations(
      //				new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/test1/*.xml"));
      		return bean.getObject();
      	}
      
      
      	/**   
      	 * @methodDesc: 功能描述(test1 事物管理)  
      	 * @author: ChauncyWang
      	 * @param: @param dataSource
      	 * @param: @return   
      	 * @returnType: DataSourceTransactionManager  
      	 */  
      	@Bean(name = "test1TransactionManager")
      	@Primary
      	public DataSourceTransactionManager testTransactionManager(@Qualifier("test1DataSource") DataSource dataSource) {
      		return new DataSourceTransactionManager(dataSource);
      	}
      
      	@Bean(name = "test1SqlSessionTemplate")
      	public SqlSessionTemplate testSqlSessionTemplate(
      			@Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
      		return new SqlSessionTemplate(sqlSessionFactory);
      	}
      
      }
      
      package chauncy.datasource;
      
      
      import javax.sql.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.autoconfigure.jdbc.DataSourceBuilder;
      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.jdbc.datasource.DataSourceTransactionManager;
      
      /**   
       * @classDesc: 功能描述(数据源2的配置)  
       * @author: ChauncyWang
       * @version: 1.0  
       */ 
      @Configuration // 注册到spring容器中
      @MapperScan(basePackages="chauncy.test02",sqlSessionFactoryRef="test2SqlSessionFactory")
      public class Datasource2 {
      	
      	/**   
      	 * @methodDesc: 功能描述(配置test2数据库)  
      	 * @author: ChauncyWang
      	 * @param: @return   
      	 * @returnType: DataSource  
      	 */  
      	@Bean(name = "test2DataSource")
      	@ConfigurationProperties(prefix = "spring.datasource.test2")
      	public DataSource testDataSource() {
      		return DataSourceBuilder.create().build();
      	}
      
      	
      	/**   
      	 * @methodDesc: 功能描述(test2 sql会话工厂)  
      	 * @author: ChauncyWang
      	 * @param: @param dataSource
      	 * @param: @return
      	 * @param: @throws Exception   
      	 * @returnType: SqlSessionFactory  
      	 */  
      	@Bean(name = "test2SqlSessionFactory")
      	public SqlSessionFactory testSqlSessionFactory(@Qualifier("test2DataSource") DataSource dataSource)
      			throws Exception {
      		SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
      		bean.setDataSource(dataSource);
      //		bean.setMapperLocations(
      //				new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/test2/*.xml"));
      		return bean.getObject();
      	}
      
      
      	/**   
      	 * @methodDesc: 功能描述(test2 事物管理)  
      	 * @author: ChauncyWang
      	 * @param: @param dataSource
      	 * @param: @return   
      	 * @returnType: DataSourceTransactionManager  
      	 */  
      	@Bean(name = "test2TransactionManager")
      	public DataSourceTransactionManager testTransactionManager(@Qualifier("test2DataSource") DataSource dataSource) {
      		return new DataSourceTransactionManager(dataSource);
      	}
      
      	@Bean(name = "test2SqlSessionTemplate")
      	public SqlSessionTemplate testSqlSessionTemplate(
      			@Qualifier("test2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
      		return new SqlSessionTemplate(sqlSessionFactory);
      	}
      
      }
      
    5. 编写分包请求,对两个数据源进行操作:
      package chauncy.controller;
      
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Controller;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.ResponseBody;
      import org.springframework.web.bind.annotation.RestController;
      
      import chauncy.entity.UserEntity;
      import chauncy.mapper.UserMapper;
      import chauncy.service.UserService;
      import chauncy.test01.service.UserService1;
      import chauncy.test02.service.UserService2;
      
      @RestController
      @RequestMapping("/IndexController")
      public class IndexController {
      
      	@Autowired
      	private UserService1 userService1;
      
      	@Autowired
      	private UserService2 userService2;
      	
      	@RequestMapping("/add")
      	public String add(String name, Integer age) {
      		userService1.addUser(name, age);
      		userService2.addUser(name, age);
      		return "success";
      	}
      
      }
      
      package chauncy.test01.service;
      
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Service;
      
      import chauncy.test01.mapper.UserMapper1;
      
      @Service
      public class UserService1 {
      	
      	@Autowired
      	private UserMapper1 userMapper1;
      	
      	
      	public int addUser(String name,Integer age){
      		return userMapper1.addUser(name, age);
      	}
      }
      
      package chauncy.test01.mapper;
      
      import org.apache.ibatis.annotations.Insert;
      import org.apache.ibatis.annotations.Param;
      
      public interface UserMapper1 {
      	
      	@Insert("insert into users values(null,#{name},#{age})")
      	public int addUser(@Param("name")String name,@Param("age")Integer age);
      }
      
      package chauncy.test02.service;
      
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Service;
      
      import chauncy.test02.mapper.UserMapper2;
      
      @Service
      public class UserService2 {
      	
      	@Autowired
      	private UserMapper2 userMapper2;
      	
      	
      	public int addUser(String name,Integer age){
      		return userMapper2.addUser(name, age);
      	}
      }
      
      package chauncy.test02.mapper;
      
      import org.apache.ibatis.annotations.Insert;
      import org.apache.ibatis.annotations.Param;
      
      public interface UserMapper2 {
      	
      	@Insert("insert into users values(null,#{name},#{age})")
      	public int addUser(@Param("name")String name,@Param("age")Integer age);
      }
      
      package chauncy;
      
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
      import org.springframework.context.annotation.ComponentScan;
      
      @ComponentScan(basePackages = "chauncy.*")
      @EnableAutoConfiguration
      public class APP {
      
      	public static void main(String[] args) {
      		SpringApplication.run(APP.class, args);
      	}
      }
      
    6. 使用浏览器造成get请求进行访问,返回success后比对test01、test02数据库是否都有数据新增,若是则证明springboot整合多数据源成功。

五、事务管理

  1. springboot整合事物管理:
    springboot默认集成事物,只主要在方法上加上@Transactional即可。
  2. 分布式事务(操作多个数据源)解决方案:
    jta+atomikos(不仅限于springboot)、两段提交协议、MQ推送。
  3. SpringBoot分布式事物管理:
    使用springboot+jta+atomikos分布式事物管理。把所有的数据源都交给atomikos进行事务管理。
  4. 操作多个数据源进行事务管理时,问题重现:
    package chauncy.controller;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.bind.annotation.RestController;
    
    import chauncy.entity.UserEntity;
    import chauncy.mapper.UserMapper;
    import chauncy.service.UserService;
    import chauncy.test01.service.UserService1;
    import chauncy.test02.service.UserService2;
    
    @RestController
    @RequestMapping("/IndexController")
    public class IndexController {
    
    	@Autowired
    	private UserService1 userService1;
    
    	@RequestMapping("/addUser1AndUser2")
    	public String addUser1AndUser2(){
    		userService1.addUser1AndUser2();
    		return "success";
    	}
    
    }
    
    package chauncy.test01.service;
    
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    
    import chauncy.test01.mapper.UserMapper1;
    import chauncy.test02.mapper.UserMapper2;
    
    @Service
    public class UserService1 {
    	
    	@Autowired
    	private UserMapper1 userMapper1;
    	@Autowired
    	private UserMapper2 userMapper2;
    	
    	@Transactional
    	public int addUser1AndUser2(){
    		userMapper1.addUser("test01", 18);
    		System.out.println("数据库01插入完毕。。");
    		userMapper2.addUser("test02", 19);
    		int i=1/0;
    		return 0;
    	}
    }
    
    package chauncy.test01.mapper;
    
    import org.apache.ibatis.annotations.Insert;
    import org.apache.ibatis.annotations.Param;
    
    public interface UserMapper1 {
    	
    	@Insert("insert into users values(null,#{name},#{age})")
    	public int addUser(@Param("name")String name,@Param("age")Integer age);
    }
    
    package chauncy.test02.mapper;
    
    import org.apache.ibatis.annotations.Insert;
    import org.apache.ibatis.annotations.Param;
    
    public interface UserMapper2 {
    	
    	@Insert("insert into users values(null,#{name},#{age})")
    	public int addUser(@Param("name")String name,@Param("age")Integer age);
    }
    
    package chauncy.datasource;
    
    
    import javax.sql.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.autoconfigure.jdbc.DataSourceBuilder;
    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.jdbc.datasource.DataSourceTransactionManager;
    
    /**   
     * @classDesc: 功能描述(数据源1的配置)  
     * @author: ChauncyWang 
     * @version: 1.0  
     */ 
    @Configuration // 注册到spring容器中
    @MapperScan(basePackages="chauncy.test01",sqlSessionFactoryRef="test1SqlSessionFactory")
    public class Datasource1 {
    	
    	/**   
    	 * @methodDesc: 功能描述(配置test1数据库)  
    	 * @author: ChauncyWang
    	 * @param: @return 
    	 * @returnType: DataSource  
    	 */  
    	@Bean(name = "test1DataSource")
    	@Primary
    	@ConfigurationProperties(prefix = "spring.datasource.test1")
    	public DataSource testDataSource() {
    		return DataSourceBuilder.create().build();
    	}
    
    	
    	/**   
    	 * @methodDesc: 功能描述(test1 sql会话工厂)  
    	 * @author: ChauncyWang
    	 * @param: @param dataSource
    	 * @param: @return
    	 * @param: @throws Exception  
    	 * @returnType: SqlSessionFactory  
    	 */  
    	@Bean(name = "test1SqlSessionFactory")
    	@Primary
    	public SqlSessionFactory testSqlSessionFactory(@Qualifier("test1DataSource") DataSource dataSource)
    			throws Exception {
    		SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
    		bean.setDataSource(dataSource);
    //		bean.setMapperLocations(
    //				new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/test1/*.xml"));
    		return bean.getObject();
    	}
    
    
    	/**   
    	 * @methodDesc: 功能描述(test1 事物管理)  
    	 * @author: ChauncyWang
    	 * @param: @param dataSource
    	 * @param: @return  
    	 * @returnType: DataSourceTransactionManager  
    	 */  
    	@Bean(name = "test1TransactionManager")
    	@Primary
    	public DataSourceTransactionManager testTransactionManager(@Qualifier("test1DataSource") DataSource dataSource) {
    		return new DataSourceTransactionManager(dataSource);
    	}
    
    	@Bean(name = "test1SqlSessionTemplate")
    	public SqlSessionTemplate testSqlSessionTemplate(
    			@Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
    		return new SqlSessionTemplate(sqlSessionFactory);
    	}
    
    }
    
    package chauncy.datasource;
    
    
    import javax.sql.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.autoconfigure.jdbc.DataSourceBuilder;
    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.jdbc.datasource.DataSourceTransactionManager;
    
    /**   
     * @classDesc: 功能描述(数据源2的配置)  
     * @author: ChauncyWang
     * @version: 1.0  
     */ 
    @Configuration // 注册到spring容器中
    @MapperScan(basePackages="chauncy.test02",sqlSessionFactoryRef="test2SqlSessionFactory")
    public class Datasource2 {
    	
    	/**   
    	 * @methodDesc: 功能描述(配置test2数据库)  
    	 * @author: ChauncyWang
    	 * @param: @return     
    	 * @returnType: DataSource  
    	 */  
    	@Bean(name = "test2DataSource")
    	@ConfigurationProperties(prefix = "spring.datasource.test2")
    	public DataSource testDataSource() {
    		return DataSourceBuilder.create().build();
    	}
    
    	
    	/**   
    	 * @methodDesc: 功能描述(test2 sql会话工厂)  
    	 * @author: ChauncyWang
    	 * @param: @param dataSource
    	 * @param: @return
    	 * @param: @throws Exception    
    	 * @returnType: SqlSessionFactory  
    	 */  
    	@Bean(name = "test2SqlSessionFactory")
    	public SqlSessionFactory testSqlSessionFactory(@Qualifier("test2DataSource") DataSource dataSource)
    			throws Exception {
    		SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
    		bean.setDataSource(dataSource);
    //		bean.setMapperLocations(
    //				new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/test2/*.xml"));
    		return bean.getObject();
    	}
    
    
    	/**   
    	 * @methodDesc: 功能描述(test2 事物管理)  
    	 * @author: ChauncyWang
    	 * @param: @param dataSource
    	 * @param: @return     
    	 * @returnType: DataSourceTransactionManager  
    	 */  
    	@Bean(name = "test2TransactionManager")
    	public DataSourceTransactionManager testTransactionManager(@Qualifier("test2DataSource") DataSource dataSource) {
    		return new DataSourceTransactionManager(dataSource);
    	}
    
    	@Bean(name = "test2SqlSessionTemplate")
    	public SqlSessionTemplate testSqlSessionTemplate(
    			@Qualifier("test2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
    		return new SqlSessionTemplate(sqlSessionFactory);
    	}
    
    }
    
    问题:上述代码会出现,造成访问请求报错后,一个方法中两个不同数据源的事务无法统一进行回滚的问题,即test01数据库的users表没有新增记录,test02数据库的users表新增了记录,正确结果是都不应该增加记录。
  5. 使用springboot+jta+atomikos分布式事物管理,解决以上问题:
    1. 在pom文件中新增引入jta依赖:
      <dependency>
      	<groupId>org.springframework.boot</groupId>
      	<artifactId>spring-boot-starter-jta-atomikos</artifactId>
      </dependency>
      
    2. 在application.properties中创建两个数据源:
      # Mysql 1
      mysql.datasource.test1.url = jdbc:mysql://localhost:3306/test01?serverTimezone=GMT&useUnicode=true&characterEncoding=utf-8
      mysql.datasource.test1.username = root
      mysql.datasource.test1.password = root
      
      mysql.datasource.test1.minPoolSize = 3
      mysql.datasource.test1.maxPoolSize = 25
      mysql.datasource.test1.maxLifetime = 20000
      mysql.datasource.test1.borrowConnectionTimeout = 30
      mysql.datasource.test1.loginTimeout = 30
      mysql.datasource.test1.maintenanceInterval = 60
      mysql.datasource.test1.maxIdleTime = 60
      mysql.datasource.test1.testQuery = select 1
      
      
      # Mysql 2
      mysql.datasource.test2.url =jdbc:mysql://localhost:3306/test02?serverTimezone=GMT&useUnicode=true&characterEncoding=utf-8
      mysql.datasource.test2.username =root
      mysql.datasource.test2.password =root
      
      mysql.datasource.test2.minPoolSize = 3
      mysql.datasource.test2.maxPoolSize = 25
      mysql.datasource.test2.maxLifetime = 20000
      mysql.datasource.test2.borrowConnectionTimeout = 30
      mysql.datasource.test2.loginTimeout = 30
      mysql.datasource.test2.maintenanceInterval = 60
      mysql.datasource.test2.maxIdleTime = 60
      mysql.datasource.test2.testQuery = select 1
      
      server.port = 80
      server.context.path=/
      
    3. 读取application.properties配置文件的信息:
      package chauncy.config;
      
      import org.springframework.boot.context.properties.ConfigurationProperties;
      
      @ConfigurationProperties(prefix = "mysql.datasource.test1")
      public class DBConfig1 {
      
      	private String url;
      	private String username;
      	private String password;
      	private int minPoolSize;
      	private int maxPoolSize;
      	private int maxLifetime;
      	private int borrowConnectionTimeout;
      	private int loginTimeout;
      	private int maintenanceInterval;
      	private int maxIdleTime;
      	private String testQuery;
      
      	public String getUrl() {
      		return url;
      	}
      
      	public void setUrl(String url) {
      		this.url = url;
      	}
      
      	public String getUsername() {
      		return username;
      	}
      
      	public void setUsername(String username) {
      		this.username = username;
      	}
      
      	public String getPassword() {
      		return password;
      	}
      
      	public void setPassword(String password) {
      		this.password = password;
      	}
      
      	public int getMinPoolSize() {
      		return minPoolSize;
      	}
      
      	public void setMinPoolSize(int minPoolSize) {
      		this.minPoolSize = minPoolSize;
      	}
      
      	public int getMaxPoolSize() {
      		return maxPoolSize;
      	}
      
      	public void setMaxPoolSize(int maxPoolSize) {
      		this.maxPoolSize = maxPoolSize;
      	}
      
      	public int getMaxLifetime() {
      		return maxLifetime;
      	}
      
      	public void setMaxLifetime(int maxLifetime) {
      		this.maxLifetime = maxLifetime;
      	}
      
      	public int getBorrowConnectionTimeout() {
      		return borrowConnectionTimeout;
      	}
      
      	public void setBorrowConnectionTimeout(int borrowConnectionTimeout) {
      		this.borrowConnectionTimeout = borrowConnectionTimeout;
      	}
      
      	public int getLoginTimeout() {
      		return loginTimeout;
      	}
      
      	public void setLoginTimeout(int loginTimeout) {
      		this.loginTimeout = loginTimeout;
      	}
      
      	public int getMaintenanceInterval() {
      		return maintenanceInterval;
      	}
      
      	public void setMaintenanceInterval(int maintenanceInterval) {
      		this.maintenanceInterval = maintenanceInterval;
      	}
      
      	public int getMaxIdleTime() {
      		return maxIdleTime;
      	}
      
      	public void setMaxIdleTime(int maxIdleTime) {
      		this.maxIdleTime = maxIdleTime;
      	}
      
      	public String getTestQuery() {
      		return testQuery;
      	}
      
      	public void setTestQuery(String testQuery) {
      		this.testQuery = testQuery;
      	}
      
      }
      
      package chauncy.config;
      
      import org.springframework.boot.context.properties.ConfigurationProperties;
      
      @ConfigurationProperties(prefix = "mysql.datasource.test2")
      public class DBConfig2 {
      
      	private String url;
      	private String username;
      	private String password;
      	private int minPoolSize;
      	private int maxPoolSize;
      	private int maxLifetime;
      	private int borrowConnectionTimeout;
      	private int loginTimeout;
      	private int maintenanceInterval;
      	private int maxIdleTime;
      	private String testQuery;
      
      	public String getUrl() {
      		return url;
      	}
      
      	public void setUrl(String url) {
      		this.url = url;
      	}
      
      	public String getUsername() {
      		return username;
      	}
      
      	public void setUsername(String username) {
      		this.username = username;
      	}
      
      	public String getPassword() {
      		return password;
      	}
      
      	public void setPassword(String password) {
      		this.password = password;
      	}
      
      	public int getMinPoolSize() {
      		return minPoolSize;
      	}
      
      	public void setMinPoolSize(int minPoolSize) {
      		this.minPoolSize = minPoolSize;
      	}
      
      	public int getMaxPoolSize() {
      		return maxPoolSize;
      	}
      
      	public void setMaxPoolSize(int maxPoolSize) {
      		this.maxPoolSize = maxPoolSize;
      	}
      
      	public int getMaxLifetime() {
      		return maxLifetime;
      	}
      
      	public void setMaxLifetime(int maxLifetime) {
      		this.maxLifetime = maxLifetime;
      	}
      
      	public int getBorrowConnectionTimeout() {
      		return borrowConnectionTimeout;
      	}
      
      	public void setBorrowConnectionTimeout(int borrowConnectionTimeout) {
      		this.borrowConnectionTimeout = borrowConnectionTimeout;
      	}
      
      	public int getLoginTimeout() {
      		return loginTimeout;
      	}
      
      	public void setLoginTimeout(int loginTimeout) {
      		this.loginTimeout = loginTimeout;
      	}
      
      	public int getMaintenanceInterval() {
      		return maintenanceInterval;
      	}
      
      	public void setMaintenanceInterval(int maintenanceInterval) {
      		this.maintenanceInterval = maintenanceInterval;
      	}
      
      	public int getMaxIdleTime() {
      		return maxIdleTime;
      	}
      
      	public void setMaxIdleTime(int maxIdleTime) {
      		this.maxIdleTime = maxIdleTime;
      	}
      
      	public String getTestQuery() {
      		return testQuery;
      	}
      
      	public void setTestQuery(String testQuery) {
      		this.testQuery = testQuery;
      	}
      
      }
      
    4. 创建多数据源,放入Atomikos数据源中进行集中管理:
      package chauncy.datasource;
      
      import java.sql.SQLException;
      
      import javax.sql.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.jta.atomikos.AtomikosDataSourceBean;
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      import org.springframework.context.annotation.Primary;
      
      import com.mysql.cj.jdbc.MysqlXADataSource;
      
      import chauncy.config.DBConfig1;
      
      @Configuration
      //basePackages 最好分开配置 如果放在同一个文件夹可能会报错
      @MapperScan(basePackages = "chauncy.test01", sqlSessionTemplateRef = "testSqlSessionTemplate1")
      public class TestMybatisConfig1 {
      	// 配置数据源
      	@Primary
      	@Bean(name = "testDataSource1")
      	public DataSource testDataSource(DBConfig1 testConfig) throws SQLException {
      		MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();
      		mysqlXaDataSource.setUrl(testConfig.getUrl());
      		mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
      		mysqlXaDataSource.setPassword(testConfig.getPassword());
      		mysqlXaDataSource.setUser(testConfig.getUsername());
      		mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
      
      		AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
      		xaDataSource.setXaDataSource(mysqlXaDataSource);
      		xaDataSource.setUniqueResourceName("testDataSource1");
      
      		xaDataSource.setMinPoolSize(testConfig.getMinPoolSize());
      		xaDataSource.setMaxPoolSize(testConfig.getMaxPoolSize());
      		xaDataSource.setMaxLifetime(testConfig.getMaxLifetime());
      		xaDataSource.setBorrowConnectionTimeout(testConfig.getBorrowConnectionTimeout());
      		xaDataSource.setLoginTimeout(testConfig.getLoginTimeout());
      		xaDataSource.setMaintenanceInterval(testConfig.getMaintenanceInterval());
      		xaDataSource.setMaxIdleTime(testConfig.getMaxIdleTime());
      		xaDataSource.setTestQuery(testConfig.getTestQuery());
      		return xaDataSource;
      	}
      
      	@Bean(name = "testSqlSessionFactory1")
      	public SqlSessionFactory testSqlSessionFactory(@Qualifier("testDataSource1") DataSource dataSource)
      			throws Exception {
      		SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
      		bean.setDataSource(dataSource);
      		return bean.getObject();
      	}
      
      	@Bean(name = "testSqlSessionTemplate1")
      	public SqlSessionTemplate testSqlSessionTemplate(
      			@Qualifier("testSqlSessionFactory1") SqlSessionFactory sqlSessionFactory) throws Exception {
      		return new SqlSessionTemplate(sqlSessionFactory);
      	}
      }
      
      package chauncy.datasource;
      
      import java.sql.SQLException;
      
      import javax.sql.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.jta.atomikos.AtomikosDataSourceBean;
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      import org.springframework.context.annotation.Primary;
      
      import com.mysql.cj.jdbc.MysqlXADataSource;
      
      import chauncy.config.DBConfig1;
      
      @Configuration
      //basePackages 最好分开配置 如果放在同一个文件夹可能会报错
      @MapperScan(basePackages = "chauncy.test02", sqlSessionTemplateRef = "testSqlSessionTemplate2")
      public class TestMybatisConfig2 {
      	// 配置数据源
      	@Bean(name = "testDataSource2")
      	public DataSource testDataSource(DBConfig1 testConfig) throws SQLException {
      		MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();
      		mysqlXaDataSource.setUrl(testConfig.getUrl());
      		mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
      		mysqlXaDataSource.setPassword(testConfig.getPassword());
      		mysqlXaDataSource.setUser(testConfig.getUsername());
      		mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
      
      		AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
      		xaDataSource.setXaDataSource(mysqlXaDataSource);
      		xaDataSource.setUniqueResourceName("testDataSource2");
      
      		xaDataSource.setMinPoolSize(testConfig.getMinPoolSize());
      		xaDataSource.setMaxPoolSize(testConfig.getMaxPoolSize());
      		xaDataSource.setMaxLifetime(testConfig.getMaxLifetime());
      		xaDataSource.setBorrowConnectionTimeout(testConfig.getBorrowConnectionTimeout());
      		xaDataSource.setLoginTimeout(testConfig.getLoginTimeout());
      		xaDataSource.setMaintenanceInterval(testConfig.getMaintenanceInterval());
      		xaDataSource.setMaxIdleTime(testConfig.getMaxIdleTime());
      		xaDataSource.setTestQuery(testConfig.getTestQuery());
      		return xaDataSource;
      	}
      
      	@Bean(name = "testSqlSessionFactory2")
      	public SqlSessionFactory testSqlSessionFactory(@Qualifier("testDataSource2") DataSource dataSource)
      			throws Exception {
      		SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
      		bean.setDataSource(dataSource);
      		return bean.getObject();
      	}
      
      	@Bean(name = "testSqlSessionTemplate2")
      	public SqlSessionTemplate testSqlSessionTemplate(
      			@Qualifier("testSqlSessionFactory2") SqlSessionFactory sqlSessionFactory) throws Exception {
      		return new SqlSessionTemplate(sqlSessionFactory);
      	}
      }
      
    5. 启动加载配置:
      package chauncy;
      
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
      import org.springframework.boot.context.properties.EnableConfigurationProperties;
      import org.springframework.context.annotation.ComponentScan;
      
      import chauncy.config.DBConfig1;
      import chauncy.config.DBConfig2;
      
      @ComponentScan(basePackages = "chauncy.*")
      @EnableAutoConfiguration
      @EnableConfigurationProperties(value={DBConfig1.class,DBConfig2.class})
      public class APP {
      
      	public static void main(String[] args) {
      		SpringApplication.run(APP.class, args);
      	}
      }
      
    6. 变更成以上配置后,再次验证“4. 操作多个数据源进行事务管理时,问题重现”中所提问题,不会重现,则证明使用springboot+jta+atomikos可解决操作多个数据源事务管理的问题。

六、日志管理

  1. 使用log4j记录日志:
    1. 新建log4j配置文件:
      #log4j.rootLogger=CONSOLE,info,error,DEBUG
      log4j.rootLogger=info,error,CONSOLE,DEBUG
      log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender     
      log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout     
      log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n     
      log4j.logger.info=info
      log4j.appender.info=org.apache.log4j.DailyRollingFileAppender
      log4j.appender.info.layout=org.apache.log4j.PatternLayout     
      log4j.appender.info.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n  
      log4j.appender.info.datePattern='.'yyyy-MM-dd
      log4j.appender.info.Threshold = info   
      log4j.appender.info.append=true   
      #log4j.appender.info.File=/home/admin/pms-api-services/logs/info/api_services_info
      log4j.appender.info.File=D://EclipseWorkspace/EclipseMars2/ArchitectFirstPhase/AllProjectLogs/SpringBoot-Mybatis.log
      log4j.logger.error=error  
      log4j.appender.error=org.apache.log4j.DailyRollingFileAppender
      log4j.appender.error.layout=org.apache.log4j.PatternLayout     
      log4j.appender.error.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n  
      log4j.appender.error.datePattern='.'yyyy-MM-dd
      log4j.appender.error.Threshold = error   
      log4j.appender.error.append=true   
      #log4j.appender.error.File=/home/admin/pms-api-services/logs/error/api_services_error
      log4j.appender.error.File=D://EclipseWorkspace/EclipseMars2/ArchitectFirstPhase/AllProjectLogs/SpringBoot-Mybatis.log
      log4j.logger.DEBUG=DEBUG
      log4j.appender.DEBUG=org.apache.log4j.DailyRollingFileAppender
      log4j.appender.DEBUG.layout=org.apache.log4j.PatternLayout     
      log4j.appender.DEBUG.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n  
      log4j.appender.DEBUG.datePattern='.'yyyy-MM-dd
      log4j.appender.DEBUG.Threshold = DEBUG   
      log4j.appender.DEBUG.append=true   
      #log4j.appender.DEBUG.File=/home/admin/pms-api-services/logs/debug/api_services_debug
      log4j.appender.DEBUG.File=D://EclipseWorkspace/EclipseMars2/ArchitectFirstPhase/AllProjectLogs/SpringBoot-Mybatis.log
      
    2. 使用log4j进行日志打印:
      package chauncy.controller;
      
      import org.apache.log4j.Logger;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RestController;
      
      @RestController
      @RequestMapping("/IndexController")
      public class IndexController {
      	
      	private static Logger logger = Logger.getLogger(IndexController.class);
      
      	@RequestMapping("/log")
      	public String log(){
      		logger.info("test log");
      		return "success";
      	}
      }
      
    3. 使用浏览器造成请求,监视控制台打印信息,若正确打印,证明springboot整合log4j成功。
  2. 使用AOP统一处理Web请求日志:
    1. 在pom文件中新增引入依赖:
      <dependency>
      	<groupId>org.springframework.boot</groupId>
      	<artifactId>spring-boot-starter-aop</artifactId>
      </dependency>
      
    2. 编写切面类对日志进行处理:
      package chauncy.log;
      
      import java.util.Enumeration;
      
      import javax.servlet.http.HttpServletRequest;
      
      
      import org.aspectj.lang.JoinPoint;
      import org.aspectj.lang.annotation.AfterReturning;
      import org.aspectj.lang.annotation.Aspect;
      import org.aspectj.lang.annotation.Before;
      import org.aspectj.lang.annotation.Pointcut;
      import org.slf4j.Logger;
      import org.slf4j.LoggerFactory;
      import org.springframework.stereotype.Component;
      import org.springframework.web.context.request.RequestContextHolder;
      import org.springframework.web.context.request.ServletRequestAttributes;
      
      @Aspect
      @Component
      public class WebLogAspect {
      	
      	private static Logger logger=LoggerFactory.getLogger(WebLogAspect.class);
      	
      	@Pointcut("execution(public * chauncy.controller.*.*(..))")
      	public void webLog() {
      	}
      	
      	@Before("webLog()")
      	public void doBefore(JoinPoint joinPoint) throws Throwable {
      		// 接收到请求,记录请求内容
      		ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
      		HttpServletRequest request = attributes.getRequest();
      		// 记录下请求内容
      		logger.info("URL : " + request.getRequestURL().toString());
      		logger.info("HTTP_METHOD : " + request.getMethod());
      		logger.info("IP : " + request.getRemoteAddr());
      		Enumeration<String> enu = request.getParameterNames();
      		while (enu.hasMoreElements()) {
      			String name = (String) enu.nextElement();
      			logger.info("name:{},value:{}", name, request.getParameter(name));
      		}
      	}
      	@AfterReturning(returning = "ret", pointcut = "webLog()")
      	public void doAfterReturning(Object ret) throws Throwable {
      		// 处理完请求,返回内容
      		logger.info("RESPONSE : " + ret);
      	}
      
      
      }
      
    3. 对chauncy.controller包下任意类任意方法造成请求,都会打印相关详细信息,如请求URL、当前服务器IP、请求类型、参数名称、参数值、请求状态(是否成功)等。

七、缓存支持

  1. 缓存分为:1.jvm缓存(只能在java中使用,并且只在当前jvm有效) 2. 内存缓存(redis、mongodb等非关系型数据库)
  2. 为什么要用到缓存?
    因为使用缓存可以减轻数据库压力。
  3. 注解配置与EhCache使用:
    1. pom文件引入
      <dependency>
      	<groupId>org.springframework.boot</groupId>
      	<artifactId>spring-boot-starter-cache</artifactId>
      </dependency>
      
    2. 在src/main/resources下新建ehcache.xml文件,添加如下配置:
      <?xml version="1.0" encoding="UTF-8"?>
      <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      	xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
      	updateCheck="false">
          <!--  
              name:缓存名称。  
              maxElementsInMemory:缓存最大个数。  
              eternal:对象是否永久有效,一但设置了,timeout将不起作用。  
              timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。  
              timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。  
              overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。  
              diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。  
              maxElementsOnDisk:硬盘最大缓存个数。  
              diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.  
              diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。  
              memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。  
              clearOnFlush:内存数量最大时是否清除。  
          --> 
      	
      	<diskStore path="java.io.tmpdir/Tmp_EhCache" />
      
      	<!-- 默认配置 -->
      	<defaultCache maxElementsInMemory="5000" eternal="false"
      		timeToIdleSeconds="120" timeToLiveSeconds="120"
      		memoryStoreEvictionPolicy="LRU" overflowToDisk="false" />
      
      	<cache name="baseCache" maxElementsInMemory="10000"
      		maxElementsOnDisk="100000" />
      
      </ehcache>
      
    3. 编写后台请求,持久化层查询使用缓存:
      package chauncy.controller;
      
      import org.apache.log4j.Logger;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Controller;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.ResponseBody;
      import org.springframework.web.bind.annotation.RestController;
      
      import chauncy.entity.UserEntity;
      import chauncy.mapper.UserMapper;
      import chauncy.service.UserService;
      import chauncy.test01.mapper.UserMapper1;
      import chauncy.test01.service.UserService1;
      import chauncy.test02.service.UserService2;
      
      @RestController
      @RequestMapping("/IndexController")
      public class IndexController {
      	
      	private static Logger logger = Logger.getLogger(IndexController.class);
      	
      	@Autowired
      	private UserMapper1 userMapper1;
      
      	@RequestMapping("/getUserName")
      	public UserEntity getUserName(String name){
      		return userMapper1.findByUserName(name);
      	}
      }
      
      package chauncy.test01.mapper;
      
      import org.apache.ibatis.annotations.Insert;
      import org.apache.ibatis.annotations.Param;
      import org.apache.ibatis.annotations.Select;
      import org.springframework.cache.annotation.CacheConfig;
      import org.springframework.cache.annotation.Cacheable;
      
      import chauncy.entity.UserEntity;
      
      @CacheConfig(cacheNames = "baseCache")
      public interface UserMapper1 {
      	
      	@Select("select * from users t where t.name=#{name}")
      	@Cacheable
      	public UserEntity findByUserName(@Param("name")String name);
      }
      
    4. 编写启动类,启动容器:
      package chauncy;
      
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
      import org.springframework.boot.context.properties.EnableConfigurationProperties;
      import org.springframework.cache.annotation.EnableCaching;
      import org.springframework.context.annotation.ComponentScan;
      
      import chauncy.config.DBConfig1;
      import chauncy.config.DBConfig2;
      
      @ComponentScan(basePackages = "chauncy.*")
      @EnableCaching // 开启缓存注解
      @EnableAutoConfiguration
      @EnableConfigurationProperties(value = { DBConfig1.class, DBConfig2.class })
      public class APP {
      
      	public static void main(String[] args) {
      		SpringApplication.run(APP.class, args);
      	}
      }
      
    5. 清除缓存的请求代码:
      package chauncy.controller;
      
      import org.apache.log4j.Logger;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.cache.CacheManager;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RestController;
      
      
      @RestController
      @RequestMapping("/IndexController")
      public class IndexController {
      	
      	private static Logger logger = Logger.getLogger(IndexController.class);
      
      	@Autowired
      	private CacheManager cacheManager;
      	
      	@RequestMapping("/removeCache")
      	public String removeCache() {
      		cacheManager.getCache("baseCache").clear();
      		return "success";
      	}
      }
      

八、其他内容

  1. 使用@Scheduled创建定时任务:
    在Spring Boot的主类中加入@EnableScheduling注解,启用定时任务的配置(以下示例为简单demo,没考虑分布式、异常等情况):
    package chauncy;
    
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Component;
    
    @Component
    public class ScheduledTask {
    	
    	@Scheduled(fixedRate=1000)
    	public void add(){
    		System.out.println("正在执行。。。"+System.currentTimeMillis());
    	}
    }
    
    package chauncy;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.cache.annotation.EnableCaching;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.scheduling.annotation.EnableScheduling;
    
    import chauncy.config.DBConfig1;
    import chauncy.config.DBConfig2;
    
    @ComponentScan(basePackages = {"chauncy.*","chauncy"})
    @EnableScheduling//开启定时任务注解
    @EnableAutoConfiguration
    @EnableConfigurationProperties(value = { DBConfig1.class, DBConfig2.class })
    public class APP {
    
    	public static void main(String[] args) {
    		SpringApplication.run(APP.class, args);
    	}
    }
    
  2. 使用@Async实现异步调用(多线程的使用):
    启动加上@EnableAsync,需要执行异步方法上加入@Async。
    PS:多线程的情况,执行路径会打乱。使用多线程的好处:提高程序的效率。
    package chauncy.controller;
    
    import org.apache.log4j.Logger;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("/IndexController")
    public class IndexController {
    	
    	private static Logger logger = Logger.getLogger(IndexController.class);
    
    	@Autowired
    	private UserService1 userService1;
    	
    	@RequestMapping("/sendSms")
    	public String sendSms(){
    		System.out.println("userService1->sendSms()开始调用");
    		userService1.sendSms();
    		System.out.println("userService1->sendSms()结束调用");
    		return "success";
    	}
    }
    
    package chauncy.test01.service;
    
    import org.springframework.scheduling.annotation.Async;
    import org.springframework.stereotype.Service;
    
    @Service
    public class UserService1 {
    	
    	//当一个方法执行时间比较长,就要使用多线程
    	@Async
    	public void sendSms(){
    		System.out.println("sendSms()方法开始执行。。。");
    		for (int i = 0; i < 5; i++) {
    			try {
    				Thread.sleep(1000);
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    			System.out.println("i:"+i);
    		}
    		System.out.println("sendSms()方法结束执行。。。");
    	}
    }
    
    package chauncy;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.cache.annotation.EnableCaching;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.scheduling.annotation.EnableAsync;
    import org.springframework.scheduling.annotation.EnableScheduling;
    
    import chauncy.config.DBConfig1;
    import chauncy.config.DBConfig2;
    
    @ComponentScan(basePackages = {"chauncy.*","chauncy"})
    @EnableAsync//开启异步注解	
    @EnableAutoConfiguration
    @EnableConfigurationProperties(value = { DBConfig1.class, DBConfig2.class })
    public class APP {
    
    	public static void main(String[] args) {
    		SpringApplication.run(APP.class, args);
    	}
    }
    
  3. 获取自定义参数:
    1. 配置文件中创建自定义参数:
      name=ChauncyWang
      
    2. 代码中获取自定义参数:
      package chauncy.controller;
      
      import org.apache.log4j.Logger;
      import org.springframework.beans.factory.annotation.Value;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RestController;
      
      @RestController
      @RequestMapping("/IndexController")
      public class IndexController {
      	
      	private static Logger logger = Logger.getLogger(IndexController.class);
      	
      	@Value("${name}")
      	private String name;
      
      	@RequestMapping("/getName")
      	public String getName(){
      		return name;
      	}
      }
      
  4. 多环境区分:
    1. 实际项目开发中分为:Dev(开发环境)、Sit(集成测试环境)、Pre(预生产环境、灰度环境)、Prd(生产环境),针对于不同环境需要进行不同的配置处理,此时就要进行多环境区分。
    2. 具体实现:
      1. 新建两个不同环境配置文件:
        1. application-pre.properties
          name=pre.ChauncyWang
          
        2. application-prd.properties
          name=prd.ChauncyWang
          
      2. 在主环境配置文件中声明使用哪个环境:
        spring.profiles.active=prd
        
      3. 获取自定义参数步骤如上述3。
  5. 修改端口号:
    在配置文件中写入:
    server.port = 80
    server.context.path=/
    
  6. SpringBootYml使用:
    创建application.yml(注意ymL规范,冒号:后面要有空格):
    server:
      port: 80
      context-path: /
    
  7. 发布打包
    1. 使用命令mvn package进行打包。
    2. 打包完成会在项目target目录下生成相应的包。
    3. 使用java -jar 包名 运行包。
      如果报错“没有主清单”,在pom文件中增加:
      <build>
      	<plugins>
      		<plugin>
      			<groupId>org.apache.maven.plugins</groupId>
      			<artifactId>maven-compiler-plugin</artifactId>
      			<configuration>
      				<source>1.8</source>
      				<target>1.8</target>
      			</configuration>
      		</plugin>
      		<plugin>
      			<groupId>org.springframework.boot</groupId>
      			<artifactId>spring-boot-maven-plugin</artifactId>
      			<configuration>
      				<maimClass>chauncy.App</maimClass>
      			</configuration>
      			<executions>
      				<execution>
      					<goals>
      						<goal>repackage</goal>
      					</goals>
      				</execution>
      			</executions>
      
      		</plugin>
      	</plugins>
      </build>
      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值