SpringBoot学习笔记

SpringBoot

一、SpringBoot的简介

1.1 SpringBoot产生的背景

Spring 框架的常见问题是要快速创建一个可以运行的应用比较麻烦,对于新接触 Spring 框架的开发人员来说,并不知道如何更好的使用这些组件。

Spring Boot 是 Spring 框架的一个新的子项目,用于创建 Spring 4.0 项目。它的开发始于 2013 年。2014 年 4 月发布 1.0.0 版本。它可以自动配置 Spring 的各种组件,并不依赖代码生成和 XML 配置文件。Spring Boot 也提供了对于常见场景的推荐组件配置。Spring Boot 可以大大提升使用 Spring 框架时的开发效率

Ø 使用Spring boot ,可以轻松的创建独立运行的程序,非常容易构建独立的服务组件,是实现分布式架构、微服务架构利器。

Ø Spring boot简化了第三方包的引用,通过提供的starter,简化了依赖包的配置。

1.2 SpringBoot的优缺点

Ø 轻松创建独立的Spring应用程序。

Ø 内嵌Tomcat、jetty等web容器,不需要部署WAR文件。

Ø 提供一系列的“starter” 来简化的Maven配置,不需要添加很多依赖

Ø 开箱即用,尽可能自动配置Spring。

NameServlet VersionJava Version
Tomcat 8 3.1 Java 7+
Tomcat 7 3.0 Java 6+
Jetty 9.3 3.1 Java 8+
Jetty 9.2 3.1 Java 7+
Jetty 8 3.0 Java6+

二、SpringBoot入门案例

Step01:

解压一个maven3.5到本地

Step02:

修改maven的conf\setting的本地仓库存储路径

Step03:

修改maven的conf\setting 中远程仓库为阿里云的

Step04:

把Eclipse中的本地和全局的仓库文件都改成conf\setting

Step05:

创建一个 maven war项目(test1)或创建一个 maven jar(test2)。 这两种都可以,但一般都使用jar,因为spring是用于服务,不建议与jsp使用

+springbootdemo1 pom.xml

+springbootdemo2 pom.xml

Step06:

在pom.xml添加spring-boot-starter-web依赖,如图

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.9.RELEASE</version>
</parent>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

spring-boot-starter-parent作用:

在pom.xml中引入spring-boot-start-parent,它可以提供dependency management,也就是说依赖管理引入以后在申明其它dependency的时候就不需要version了,后面可以看到。

spring-boot-starter-web作用:springweb 核心组件

Step07:

写一个控制器如下,然后写一个main方法,把程序跑起来:

package com.jihaiyang.web.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.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
​
@RestController//相当于声明Controller - 提共restful 风格
@EnableAutoConfiguration//自动配置,不需要写spring的配置文件
class HelloController {
​
    @RequestMapping(value = "hello/{name}")
    public String hello1(@PathVariable("name") String name){
        return name+"Hello,SpringBoot";
    }
    public static void main(String[] args) {
        SpringApplication.run(HelloController.class);//启动当前控制器
    }
}

Step08:

在浏览器中访问http://localhost:8080/hello

三、SpringBoot的两种启动方式

3.1 在每个控制器中启动

在控制器配置@EnableAutoConfiguration并使用SpringApplication.run()启动程序

3.2 创建一个App类

创建一个App类,在App类中配置@EnableAutoConfiguration和组件扫描ComponentScan,

然后使用SpringApplication启动程序,这样就可以访问多个Controller了.

@RequestMapping("{id}")
@ResponseBody
public User userInfo(@PathVariable(varlue="id") Integer id)
{
    User user=new User("gyf","123");
    return user;
}

创建App类

@ComponentScan(basePackages="com.jihaiyang.web.controller")//controller所在的包进行扫描
@EnableAutoConfiguration//此处只需写一个,其他控制器不用写了
public class App{
    public static void main(String[] args){
        SpringApplication.run(App.class,args);
    }
}

四、SpringBoot的Starter Project Options介绍

spring-boot-starter核心 POM,包含自动配置支持、日志库和对 YAML 配置文件的支持
spring-boot-starter-amqp 通过 spring-rabbit 支持 AMQP
spring-boot-starter-aop 包含 spring-aop 和 AspectJ 来支持面向切面编程(AOP)。
spring-boot-starter-batch 支持 Spring Batch,包含 HSQLDB。
spring-boot-starter-data-jpa 包含 spring-data-jpa、spring-orm 和 Hibernate 来支持 JPA。
spring-boot-starter-data-mongodb 包含 spring-data-mongodb 来支持 MongoDB。
spring-boot-starter-data-rest 通过 spring-data-rest-webmvc 支持以 REST 方式暴露 Spring Data 仓库。
spring-boot-starter-jdbc 支持使用 JDBC 访问数据库
spring-boot-starter-security 包含 spring-security。
spring-boot-starter-test 包含常用的测试所需的依赖,如 JUnit、Hamcrest、Mockito 和 spring-test 等。
spring-boot-starter-velocity 支持使用 Velocity 作为模板引擎。
spring-boot-starter-web 支持 Web 应用开发,包含 Tomcat 和 spring-mvc。
spring-boot-starter-websocket 支持使用 Tomcat 开发 WebSocket 应用。
spring-boot-starter-ws 支持 Spring Web Services
spring-boot-starter-actuator 添加适用于生产环境的功能,如性能指标和监测等功能。
spring-boot-starter-remote-shell 添加远程 SSH 支持
spring-boot-starter-jetty 使用 Jetty 而不是默认的 Tomcat 作为应用服务器。
spring-boot-starter-log4j 添加 Log4j 的支持
spring-boot-starter-logging 使用 Spring Boot 默认的日志框架 Logback
spring-boot-starter-tomcat 使用 Spring Boot 默认的 Tomcat 作为应用服务器。

spring-boot-starter-web

Ø POM 文件中可以看到,应用所声明的依赖很少

Ø 只有一个“org.springframework.boot:spring-boot-starter-web”

Ø 而不是像其他 Spring 项目一样需要声明很多的依赖。

Ø 当使用 Maven 命令“mvn dependency:tree”来查看项目实际的依赖时

Ø 发现其中包含SpringMVC框架、SLF4J、Jackson、Hibernate Validator 和 Tomcat 等依赖。

Ø 这实际上 Spring 推荐的 Web 应用中使用的开源库的组合。

EnableAutoConfiguration

Ø EnableAutoConfiguration”注解的作用在于让 Spring Boot 根据应用所声明的依赖来对 Spring 框架进行自动配置,这就减少了开发人员的工作量。

Ø Spring Boot 推荐采用基于 Java 注解的配置方式,而不是传统的 XML。只需要在主配置 Java 类上添加“@EnableAutoConfiguration”注解就可以启用自动配置。

Ø 注解“@RestController”和”@RequestMapping”由 Spring MVC 提供,用来创建 REST 服务。这两个注解和 Spring Boot 本身并没有关系。

五、Web开发

5.1 静态资源的访问

在我们开发Web应用的时候,需要引用大量的js、css、图片等静态资源。

Spring Boot默认提供静态资源目录位置需置于classpath下,目录名需符合如下规则:

/static

/public

/resources

/META-INF/resources

举例:我们可以在src/main/resources/目录下创建static/imgs,在该位置放置一个图片文件。启动程序后,尝试访问http://localhost:8080/imgs/d.jpg,访问时不用加static目录。如能显示图片,配置成功。

5.2 控制器返回JSON格式数据

@RestController
public class UserController{
    @RestMapping("/login")
    @ResponseBody
    public Map<String,Object> login(Sring username,String password){
        Map<String,Object> map=new HashMap<String,Object>();
        if("季海洋".equals(username) && "123".equal(password)){
            map.put("status",true);
            map.put("info","登陆成功");
        }else{
            map.put("status",false);
            map.put("info","用户名或密码错误");
        }
        return map;
    }
}

5.3 全局捕获异常

@ExceptionHandler 表示拦截异常。@ControllerAdvicecontroller 的一个辅助类,最常用的就是作为全局异常处理的切面类,可以指定扫描范围,约定了几种可行的返回值,如果是直接返回 model 类的话,需要使用

@ResponseBody 进行 json 转换。

@ControllerAdvice//切面
public class GlobalExceptionHandler {
    @ExceptionHandler(RuntimeException.class)//捕获运行时异常
    @ResponseBody
    public Map<String,Object> exceptionHander(){
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("status",false);
        map.put("info","系统异常");
        return map;
    }
}

在启动spring中,配置扫描包为com.jihaiyang.web

@ComponentScan(basePackages="com.jihaiyang.web")
@EnableAutoConfiguration
public class App{
    public static void main(args){
        SpringApplication.run(App.class,args);
    }
}

 

在某个映射的方法中添加个int i=10/0的算术异常

@RestController
public class UserController{
    @RequestMapping("/login")//映射路径
    @ResponseBody//响应体-自动返回json格式字符串
    public Map<String,Object> login(String username,String password){
        int i=10/0;
        Map<String,Object> map=new HashMap<String,Object>();
        if("jihaiyang".equals(username) && "123".equals(password)){
            map.put("status",true);
            map.put("info","登录成功!");
        }else{
            map.put("status",false);
            map.put("info","登录失败!");
        }
        return map;
    };
}

 

5.4、渲染Web页面

模板引擎

在动态HTML实现上Spring Boot依然可以完美胜任,并且提供了多种模板引擎的默认配置支持,所以在推荐的模板引擎下,我们可以很快的上手开发动态网站。

Spring Boot提供了默认配置的模板引擎主要有以下几种:

1 Thymeleaf

2 FreeMarker

3 Velocity

4 Groovy

5 Mustache

Springboot+freemarker

Spring Boot建议使用这些模板引擎,避免使用JSP,若一定要使用JSP将无法实现Spring Boot的多种特性,具体可见后文:支持JSP的配置

当你使用上述模板引擎中的任何一个,它们默认的模板配置路径为:src/main/resources/templates。当然也可以修改这个路径,具体如何修改,可在后续各模板引擎的配置属性中查询并修改。

5.5 Freemarker的使用

5.5.1:引入freeMarker的依赖包

<!-- 引入freeMarker的依赖包. -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency> 

5.5.2:写个控制器,并返回些数据

@Controller//如果访问freemarker模板,就不要用RestController
@RequestMapping("/stu")
public class StudentController{
    @RequestMapping("/list")
    public String list(Map data){
        HashMap data=new HashMap();
        //添加数据
        data.put("loginname","jihaiyang");
        data.put("age",32);
        ArrayList arrayList = new ArrayList();
        String[][] strings = {
            new String[]{"1001","张三","男"},
            new String[]{"1002","李四","男"},
            new String[]{"1003","王五","男"},
            new String[]{"1004","赵六","男"}
        };
        for (String[] string : strings) {
            HashMap hashMap = new HashMap();
            hashMap.put("id",string[0]);
            hashMap.put("name",string[1]);
            hashMap.put("gender",string[2]);
            arrayList.add(hashMap);
        }
        data.put("stuList",arrayList);
        return "stu/list";
    }
}

 

5.5.3:创建.ftl模板文件

Ø 在src/main/resources/创建一个templates/stu文件夹,后缀为*.ftl

Ø 掌握如何取值和判断

list.ftl文件

<!DOCTYPE html>
<html>
    <head lang="en">
        <meta   charset="UTF-8" />
        <title></title>
    </head>
    <body>
        欢迎${loginname}
        <#if age <= 17>小哥
            <#elseif age <= 30>先生
            <#else>大叔
        </#if>登录
        <table border="1">
            <tr>
                <td>ID</td>
                <td>名字</td>
                <td>性别</td>
            </tr>
            <#list   stuList?sort_by("id")?reverse as stu>
                <tr>
                    <td>   ${stu.id}</td> 
                    <td>   ${stu.name}</td>
                    <td>   ${stu.gender}</td>
                </tr>
             </#list>
        </table>
    </body>
</html>   

5.6 SpringBoot 使用jsp

Step1:创建war maven工程

Step2:pom文件引入以下依赖

<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>

Step3:application.properties创建以下配置

spring.mvc.view.prefix=/WEB-INF/view/
spring.mvc.view.suffix=.jsp 

Step4:控制器代码

@Controller
@EnableAutoConfiguration
@RequestMapping("/teacher")
public class TeacherController{
    @RequestMapping("/list")
    public String list(){
        return "list";
    }
    
    public static void main(String[] args){
        SpringApplication.run(TeacherController.class,args);
    }
}

Step5:jsp

application.properties中设置内容如下

spring.mvc.view.prefix=/WEB-INF/view/
spring.mvc.view.suffix=.jsp

六、数据库访问

6.1 SpringBoot使用JDBC

Step1:添加依赖

<!-- JDBC -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- 数据库驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

Step2:application.properties新增配置

#视图配置
spring.mvc.view.prefix=/WEB-INF/view/
spring.mvc.view.suffix=.jsp
#数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/day12
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

Step3:Service

在com.jihaiyang.service.impl中编写

@Service
private void registerUser(String username,String password,String email){
    @Autowired
    private JdbcTemplate jdbcTemplate;
    String sql ="insert into user(username,password,email) values(?,?,?)"; 
    jdbcTemplate.update(sql,username,password,email);
}

Step4:Controller

在com.jihaiyang.web.controller编写

@Controller
@RequestMapping("/user")
public class UserController{
    @Autowire
    IUservice userService;
    
    @RequestMapping("/register")
    @ResponseBody
    public String register(){
        userService.registerUser("root","root","root");
        return "success";
    }
}

 

Step5:App

在com.jihaiyang.app中编写

@ComponentScan(basePackage={"com.jihaiyang.web","com.jihaiyang.service"})
@EnableAutoConfiguration
public class App{
    public static void main(String[] args){
    SpringApplication.run(App.class,args) ;   
    }
}

 

6.2 使用Mybatis

6.2.1 创建一个maven-jar新项目来讲解

6.2.2 pom导入

<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>
        <!-- mybaties -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.1.1</version>
        </dependency>
        <!-- mysql驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> 
            </dependency>
    </dependencies>

6.2.3 数据库配置文件

application.properties文件的配置如下

#数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

 

6.2.4 Mapper

com.jihaiyang.Mapper中编写Mapper接口

public interface UserMapper{
    @Insert("insert into user(username,password) values(#{username},#{password}")
    public void save(@Param("username") String username,@Param("password") String password)
        @Select("select * from user where username=#{username}")
        public User findByUsername(@Param("username") String username);
}

 

※※※※※※※※※※※※

换成xml形式,将这个放入Maper包中

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.jihaiyang.mapper.UserMapper" ><insert id="save">
        insert into t_user (username,password) VALUES(#{0},#{1})
    </insert>
    <select id="findByUsername" resultType="com.gyf.model.User" parameterType="string">
        select * from t_user where username = #{username,jdbcType=VARCHAR}
    </select>
</mapper>

注意这里需要在pom中添加下面代码

<build>
  <resources>
    <resource>
      <directory>src/main/java</directory>
      <includes>
        <include>**/*.xml</include>
      </includes>
    </resource>
  </resources>
</build>

※※※※※※※※※※※※

6.2.4 Controller

package com.jihaiyang.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 com.gyf.mapper.UserMapper;
import com.gyf.model.User;
​
@Controller
@RequestMapping("/user")
public class UserController {
​
    @Autowired
    private UserMapper userMapper;
    @RequestMapping("/find")
    @ResponseBody
    public User find(String name){
        return userMapper.findByName(name);
    }
    
    @ResponseBody
    @RequestMapping("/add")
    public int add(String name){
        return userMapper.insert(name,"e10adc3949ba59abbe56e057f20f883e");
    }
}

6.2.5 App

package com.jihaiyang.app;
​
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={"com.gyf.controller"})
@MapperScan(basePackages={"com.gyf.mapper"})//扫描Mapper
@EnableAutoConfiguration
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

 

6.3 spring 中使用的事务

只需要加个Transactional注解即可

@Transaction
public class UserServiceImpl implements IUserService{
    @Autowired
    private UserMapper userMapper;
    @Override
    public void register(String username,String password){
        userMapper.save(username,password);
        int i=10/0;
    }
}

 

6.4 配置多数据源

以前是在applicationContext.xml中配置数据源,现在我们通过注解来配置数据源,在com.jihaiyang包下创建包datasource

6.4.1 配置文件中新增两个数据源所需的参数

spring.datasource.test1.driverClassName=com.mysql.jdbc.Driver
spring.datasource.test1.url=jdbc:mysql://localhost:3306/dbfirst?useUnicode=true&characterEncoding=utf-8
spring.datasource.test1.username=root
spring.datasource.test1.password=123456
​
spring.datasource.test2.driverClassName=com.mysql.jdbc.Driver
spring.datasource.test2.url=jdbc:mysql://localhost:3306/dbsecond?useUnicode=true&characterEncoding=utf-8
spring.datasource.test2.username=root
spring.datasource.test2.password=123456

数据库SQL语句如下

use dbone;
CREATE table user(
    id  int PRIMARY KEY AUTO_INCREMENT,
  username VARCHAR(50),
    password VARCHAR(50),
    email VARCHAR(50),
  birthday TIMESTAMP
);
​
use dbsecond;
CREATE table customer(
    id  int PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(50),
    tel VARCHAR(50)
);
​

 

6.4.2 编写数据源配置类

dbone数据库的数据源配置信息

@Configuration//注解到springboot容器中
@MapperScan(basePackages="com.jihaiyang.dbFirst.mapper",sqlSessionFactoryRef="dbFirstSqlSessionFactory")
public class DataSource01 {
​
    /**
     * @return 返回dbFirst数据库的数据源
     */
    @Bean(name="dbFirstDataSource")
    @Primary//主数据源
    @ConfigurationProperties(prefix="spring.datasource.dbFirst")
    public DataSource dateSource(){
        return DataSourceBuilder.create().build();
    }
​
    /**
     * @return 返回dbFirst数据库的会话工厂
     */
    @Bean(name = "dbFirstSqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dbFirstDataSource") DataSource ds) throws Exception{
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(ds);
​
        return bean.getObject();
    }
​
    /**
     * @return 返回dbFirst数据库的事务
     */
    @Bean(name = "dbFirstTransactionManager")
    @Primary
    public DataSourceTransactionManager transactionManager(@Qualifier("dbFirstDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
​
    /**
     * @return 返回dbFirst数据库的会话模版
     */
    @Bean(name = "dbFirstSqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(
            @Qualifier("dbFirstSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

dbtwo数据库的数据源配置信息

@Configuration//注解到springboot容器中
@MapperScan(basePackages = "com.jihaiyang.dbSecond.mapper", sqlSessionFactoryRef = "dbSecondSqlSessionFactory")
public class DataSource02 {
​
    /**
     * @return 返回dbSecond数据库的数据源
     */
    @Bean(name = "dbSecondDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.dbSecond")
    public DataSource dateSource() {
        return DataSourceBuilder.create().build();
    }
​
    /**
     * @return 返回dbSecond数据库的会话工厂
     */
    @Bean(name = "dbSecondSqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dbSecondDataSource") DataSource ds) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(ds);
​
        return bean.getObject();
    }
​
    /**
     * @return 返回dbSecond数据库的事务
     */
    @Bean(name = "dbSecondTransactionManager")
    public DataSourceTransactionManager transactionManager(@Qualifier("dbSecondDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
​
    /**
     * @return 返回dbSecond数据库的会话模版
     */
    @Bean(name = "dbSecondSqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(
            @Qualifier("dbSecondSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

 

6.4.3 dbSecond mapper & service

public interface CustomerMapper{
    @Insert("insert into customer(name,phone) values(#{name},#{telphone})")
    int insert(@Param("name") String name,@Param("telphone") String telphone)
}

@Service
public class CustomerService{
    @Autowired
    private CustomerMapper customerMapper;
    /*
    *添加一个客户
    */
    public void add(String name,String telphone){
        customerMapper.insert(name,telphone);
    }
}

 

6.4.4 Controller

@Controller
@RequestMapper("/user")
public class UserController{
    @Autowired
    private UserService userservice;
    @Autowired
    private CustomerService customerService;
    
    @ResponseBody
    @RequestMapping("/add")
    public String add(String name){
        userService.register(name,"123");
        customerService.add(name,"110");
        return "success";
    }
}

 

6.4.5 App

@ComponentScan(basePackages={"com.jihaiyang.datasource","com.jihaiyang.dbone","com.jihaiyang.dbtwo"})
@EnableAutoConfiguration
public class App{
    public static void main(String[] args){
        SpringApplication.run(App.class,args)
    }
}

 

6.5 多数据源问题

验证代码就不敲了,结论是一个事务只对当前的数据源有效。

6.6 springboot中的多事务管理

使用springboot+jta+atomikos 分布式事物管理解决方案

6.6.1 添加jta依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>

6.6.2 修改数据库连接配置数据

# Mysql 1
mysql.datasource.dbfirst.url = jdbc:mysql://localhost:3306/dbone?useUnicode=true&characterEncoding=utf-8
mysql.datasource.dbfirst.username = root
mysql.datasource.dbfirst.password = 123456
​
mysql.datasource.dbfirst.minPoolSize = 3
mysql.datasource.dbfirst.maxPoolSize = 25
mysql.datasource.dbfirst.maxLifetime = 20000
mysql.datasource.dbfirst.borrowConnectionTimeout = 30
mysql.datasource.dbfirst.loginTimeout = 30
mysql.datasource.dbfirst.maintenanceInterval = 60
mysql.datasource.dbfirst.maxIdleTime = 60
​
mysql.datasource.dbfirst.testQuery = select 1
# Mysql 2
mysql.datasource.dbsecond.url =jdbc:mysql://localhost:3306/dbsecond?useUnicode=true&characterEncoding=utf-8
mysql.datasource.dbsecond.username =root
mysql.datasource.dbsecond.password =123456
mysql.datasource.dbsecond.minPoolSize = 3
mysql.datasource.dbsecond.maxPoolSize = 25
mysql.datasource.dbsecond.maxLifetime = 20000
mysql.datasource.dbsecond.borrowConnectionTimeout = 30
mysql.datasource.dbsecond.loginTimeout = 30
mysql.datasource.dbsecond.maintenanceInterval = 60
mysql.datasource.dbsecond.maxIdleTime = 60
mysql.datasource.dbsecond.testQuery = select 1

 

6.6.3 添加2个配置模型

模型放在com.jihaiyang.dbconfig包 dbFirst数据源模型

@ConfigurationProperties("mysql.datasource.dbfirst")
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;
}

dbSecond数据源模型

@ConfigurationProperties("mysql.datasource.dbsecond")
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;
}

6.6.4 设定两个数据源具体的参数

dbfirst数据库的数据源

package com.jihaiyang.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.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;
​
import com.atomikos.jdbc.AtomikosDataSourceBean;
import com.jihaiyang.dbconfig.DBConfig1;
import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource;
​
@Configuration//注解到springboot容器中
@MapperScan(basePackages = "com.jihaiyang.dbFirst.mapper", sqlSessionFactoryRef = "dbFirstSqlSessionFactory")
public class DataSource01 {
​
    // 配置数据源
    @Primary
    @Bean(name = "dbFirstDataSource")
    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("dbFirstDataSource");
​
        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 = "dbFirstSqlSessionFactory")
    public SqlSessionFactory testSqlSessionFactory(@Qualifier("dbFirstDataSource") DataSource dataSource)
            throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        return bean.getObject();
    }
​
    @Bean(name = "dbFirstSqlSessionTemplate")
    public SqlSessionTemplate testSqlSessionTemplate(
            @Qualifier("dbFirstSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

dbsecond数据库的数据源

package com.jihaiyang.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.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
​
import com.atomikos.jdbc.AtomikosDataSourceBean;
import com.gyf.dbconfig.DBConfig2;
import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource;
​
@Configuration//注解到springboot容器中
@MapperScan(basePackages = "com.gyf.dbSecond.mapper", sqlSessionFactoryRef = "dbSecondSqlSessionFactory")
public class DataSource02 {
​
    // 配置数据源
    @Bean(name = "dbSecondDataSource")
    public DataSource testDataSource(DBConfig2 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("dbSecondDataSource");
​
        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 = "dbSecondSqlSessionFactory")
    public SqlSessionFactory testSqlSessionFactory(@Qualifier("dbSecondDataSource") DataSource dataSource)
            throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        return bean.getObject();
    }
​
    @Bean(name = "dbSecondSqlSessionTemplate")
    public SqlSessionTemplate testSqlSessionTemplate(
            @Qualifier("dbSecondSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

七 整合Log4j

7.1 导入Log4j属性文件

log4j.properties

注意,复制时要把每一行后面的空格去除

log4j.rootLogger=INFO,Console,File   
log4j.appender.Console=org.apache.log4j.ConsoleAppender  
log4j.appender.Console.Target=System.out
log4j.appender.Console.layout=org.apache.log4j.PatternLayout  
log4j.appender.Console.layout.ConversionPattern=[%p] [%d{yyyy-MM-dd HH\:mm\:ss}][%c - %L]%m%n
 
log4j.appender.File=org.apache.log4j.RollingFileAppender  
log4j.appender.File.File=C:/Users/10301/Desktop/test/logs/info/info.log 
log4j.appender.File.MaxFileSize=10MB  
 
log4j.appender.File.Threshold=ALL  
log4j.appender.File.layout=org.apache.log4j.PatternLayout  
log4j.appender.File.layout.ConversionPattern=[%p] [%d{yyyy-MM-dd HH\:mm\:ss}][%c - %L]%m%n 

7.2 pom.xml

去除springboot的logging,添加log4j,因为自带的logging不启效果

springboot下的Log4j的版本最新1.3.8,如果你的springboot的parent版本过高,那在在添加log4j自己版本 。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <exclusiions>
        <exclusion>
            <groupID>org.springframework.boot</groupID>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusiions>
</dependency>

添加自己的log4j版本

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j</artifactId>
    <version>1.3.8 RELEASE</version>
</dependency>

7.3 测试

@Autowired
private UserService userService;
Logger logger=Logger.getLogger(UserService.class);
@ResponseBody
@RequestMapping("/add")
public String add(String name){
    logger.info("this is test information !"+"@@Hello :"+name);
    return "success";
}

8. 使用AOP统一处理Web请求日志

Step01

<!-- AOP -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

Step02:写个切面类

package com.jihaiyang.aop;
​
import java.util.Enumeration;
​
import javax.servlet.http.HttpServletRequest;
​
import org.apache.log4j.Logger;
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.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
@Aspect
@Component
public class WebLogAspect {
    private Logger logger = Logger.getLogger(getClass());
    
    @Pointcut("execution(public * com.gyf.controller..*.*(..))")
    public void webLog() {
    
    }
    
    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        // 接收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 记录下请求内容
        logger.info("---------------request----------------");
        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:" + name + "value" + request.getParameter(name));
        }
    }
    @AfterReturning(returning = "ret", pointcut = "webLog()")
    public void doAfterReturning(Object ret) throws Throwable {
        logger.info("---------------response----------------");
        // 处理完请求,返回内容
        logger.info("RESPONSE : " + ret);
    }
}

 

Step3:App

在App类中添加对该AOP类的扫描

8. 修改端口号

在application.properties中

server.port=8888 
server.context-path=/test

在application.yml中

注意冒号后的只能用空格,不能用tab

server:
  port:  8090
  context-path: /test-yml

Springboot 打包部署

  1. 先打成war包或者jar包

  2. 使用java -jar test3-0.0.1-SNAPSHOT.jar 运行即可

打包时添加下面依赖代码

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <encoding>utf-8</encoding>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <mainClass>com.gyf.app.App</mainClass>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

 

在终端要停止服务器时,使用Ctrl + C。直接点x,会端口没有关掉。

posted @ 2019-07-30 20:47  手握钢叉的猹  阅读(298)  评论(0编辑  收藏  举报