zoukankan      html  css  js  c++  java
  • 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的confsetting的本地仓库存储路径

    Step03:

    修改maven的confsetting 中远程仓库为阿里云的

    Step04:

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

    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,会端口没有关掉。

  • 相关阅读:
    openldap
    Java实现 洛谷 P1200 [USACO1.1]你的飞碟在这儿Your Ride Is He…
    Java实现 洛谷 P1200 [USACO1.1]你的飞碟在这儿Your Ride Is He…
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P1567 统计天数
    Java实现 洛谷 P1567 统计天数
  • 原文地址:https://www.cnblogs.com/kitor/p/11272660.html
Copyright © 2011-2022 走看看