Spring Boot 学习

2018-12-16  本文已影响0人  桥er桑

一、入门

1.介绍

使用Spring Boot 可以更轻松地创建独立的、生产级的基于 Spring 的Java应用程序,这些应用程序可以使用 java -jar或更传统的 war 部署来部署
Spring Boot 2.0.2.RELEASE 需要 Java 8(或 9)和 Spring Framework 5.0.6.RELEASE
参考:官方文档

2.Spring Boot的特点

3. Spring Boot 搭建

参考:如何使用IDEA创建SpringBoot项目

项目结构图
pom.xml主要内容如下
    <!--继承父启动器-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.2.RELEASE</version>
    </parent>
    <!-- Additional lines to be added here... -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

在项目根目录下创建Application启动入口

@SpringBootApplication
@EnableAutoConfiguration
@ImportResource({"classpath:applicationContext.xml"}) //根据具体情况配置
public class JackDawsonApplication {
    public static void main(String[] args) {
        SpringApplication.run(JackDawsonApplication.class, args);
    }
}

一个controller文件

import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;
import org.springframework.web.bind.annotation.*;

@RestController
public class ExampleController {

    @RequestMapping("/")
    String home() {
        return "Hello World!";
    }

}

配置bean

package com.jack.jackdawson.config;

@Configuration
public class BeanConfig implements EnvironmentAware{

    private Environment env;

    @Override
    public void setEnvironment(@NonNull Environment env) { this.env = env}

    @Bean(name = "myBeanA")
//    @Qualifier("myBean")
    public A getA(){
        A a = new A();
        a.setName(env.getProperty("a.name"))
        return a;
    }

    @Bean(name = "myBeanAback")
//    @Qualifier("myBeanAback")
    public A getA(){
        A a = new A();
        a.setName(env.getProperty("a.name.back"))
        return a;
    }
}

4.基本注解

Spring boot的注解

Spring 5.0中的注解

Spring web mvc 注解

Java 注解

二、使用

1.mysql数据库配置

配置mysql数据源,jdbc方式
添加pom依赖

  <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>

application.properties配置,SpringBoot能够自动识别到以下这些mysql配置

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#spring.datasource.max-idle=10
#spring.datasource.max-wait=10000
#spring.datasource.min-idle=5
#spring.datasource.initial-size=5

在代码中直接使用jdbcTemplate

@Autowired
private JdbcTemplate jdbcTemplate;

多数据源配置
可以新建一个db.properties文件,里面定义各个数据库的连接配置,然后通过注册bean的方式手动定义各个datasource
db.properties文件如下

datasource.url=jdbc:mysql://localhost:3306/test
datasource.username=root
datasource.password=123456

datasource.back.url=jdbc:mysql://localhost:3306/jack
datasource.back.username=root
datasource.back.password=123456

DataSourceConfig配置文件如下

@Configuration
@PropertySource("classpath:config/db.properties")
@ComponentScan(value = "com.jack.jackdawson")
public class DataSourceConfig {

    @Autowired
    private Environment env;

    @Bean(name = "myDataSource1")
    public DataSource getDataSource1(){
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setUrl(env.getProperty("spring.datasource.url"));
        dataSource.setUsername(env.getProperty("spring.datasource.username"));
        dataSource.setPassword(env.getProperty("spring.datasource.password"));
        return dataSource;
    }

    @Bean(name = "myDataSource2")
    public DataSource getMyDataSource2(){
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setUrl(env.getProperty("spring.datasource.back.url"));
        dataSource.setUsername(env.getProperty("spring.datasource.back.username"));
        dataSource.setPassword(env.getProperty("spring.datasource.back.password"));
        return dataSource;
    }
}

附各种datasource对比

2.JPA

参考博客
2.1 特点
JPA顾名思义就是Java Persistence API的意思

2.3 配置

# pom依赖配置
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
# yml格式的application.properties
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mytest
    type: com.alibaba.druid.pool.DruidDataSource
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
  jpa:
    hibernate:
      ddl-auto: update //自动更新
    show-sql: true  //日志中显示sql语句

定义实体类以及数据访问接口

@Entity
@Table(name = "person") //如果未指定则和类名一致
@Data
public class Person {

    @Id
    @GeneratedValue
    private Long id;

    @Column(name = "name", nullable = true, length = 20)
    private String name;

    @Column(name = "agee", nullable = true, length = 4)
    private int age;
}
public interface PersonDAO extends JpaRepository<Person, Long> {
}

然后在业务代码中直接引用PersonDAO 的对象即可,提供了各种操作Person对象的方法,如果需要自己定义复杂的sql语句,可以在PersonDAO 接口中进行声明

@Query(nativeQuery = true, value = "SELECT * FROM persion WHERE name = :name1  OR name = :name2 ")
List<Persion> findTwoName(@Param("name1") String name1, @Param("name2") String name2);

如果需要可以在application.properties中配置spring.jpa.hibernate.ddt-auto等参数,控制项目启动后是否需要自动连接数据库将表建好或更新,参考

3.过滤器与拦截器等web配置

Spring boot 已经可以完全抛弃web.xml
TomcatStarter 中的 org.springframework.boot.context.embedded.ServletContextInitializer 是 springboot 初始化 servlet,filter,listener 的关键
使用WebMvcConfigurerAdapter抽象类来处理SpringMVC相关的配置
下面的WebAppRootContext配置类分别实现了这两个接口,并在里面定义了filter和interceptor

@Configuration
@ComponentScan
@EnableAutoConfiguration
@PropertySource("classpath:config/web.properties")
public class WebAppRootContext implements ServletContextInitializer, WebMvcConfigurer, EnvironmentAware {

    private Environment env;

    @Resource
    private RequestMappingHandlerAdapter handlerAdapter;

    @Override
    public void setEnvironment(@NonNull Environment environment) {
        this.env = environment;
    }

    //这里可以设置initParam
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        String casServerName = env.getProperty("cas_server_name");

        servletContext.addListener(WebAppRootListener.class);
        servletContext.setInitParameter("cas_server_name", casServerName);
    }

    @Bean
    public FilterRegistrationBean getAuthenticationFilter() {
        AuthenticationFilter authenticationFilter = new AuthenticationFilter();
        authenticationFilter.setCasServerLoginUrl("***");
        authenticationFilter.setServerName("localhost:8080");
        authenticationFilter.setIgnoreInitConfiguration(true);

        FilterRegistrationBean<AuthenticationFilter> casFilterBean = new FilterRegistrationBean<>();
        casFilterBean.setUrlPatterns(Collections.singletonList("/*"));
        casFilterBean.setFilter(authenticationFilter);

        return casFilterBean;
    }

    @Bean
    public FilterRegistrationBean getTicketValidationFilter() {
        Cas20ProxyReceivingTicketValidationFilter ticketValidationFilter = new Cas20ProxyReceivingTicketValidationFilter();

        FilterRegistrationBean<Cas20ProxyReceivingTicketValidationFilter> ticketFilterBean = new FilterRegistrationBean<>();
        ticketFilterBean.setFilter(ticketValidationFilter);
        ticketFilterBean.setUrlPatterns(Collections.singletonList("/*"));

        Map<String, String> initParameters = new HashMap<>();
        initParameters.put("casServerUrlPrefix", "***");
        initParameters.put("serverName", "http://localhost:9080");
        ticketFilterBean.setInitParameters(initParameters);
        ticketFilterBean.setOrder(1);
        return ticketFilterBean;
    }

    /*
     * 这里需要把拦截器注册一下,否则里面依赖的bean无法使用
     */
    @Bean
    public LoginRequiredInterceptor getLoginRequiredInterceptor() {
        return new LoginRequiredInterceptor();
    }

    @Bean
    public PrivilegeInterceptor getPrivilegeInterceptor() {
        return new PrivilegeInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //登录拦截的管理器
        registry.addInterceptor(getLoginRequiredInterceptor())     //拦截的对象会进入这个类中进行判断
                .addPathPatterns("/**")                    //所有路径都被拦截
                .excludePathPatterns("/","/login*","/logout*", "/noPrivilege*", "/error*", "/assets");       //添加不拦截路径
        registry.addInterceptor(getPrivilegeInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/","/login*","/logout*", "/noPrivilege*", "/error*", "/assets");

    }

//后面设置controller层默认参数会用到
 @PostConstruct
    public void initEditableValidation() {

        ConfigurableWebBindingInitializer initializer = (ConfigurableWebBindingInitializer)handlerAdapter.getWebBindingInitializer();
        if(initializer.getConversionService()!=null) {
            GenericConversionService genericConversionService = (GenericConversionService)initializer.getConversionService();

            genericConversionService.addConverter(new StringToDateConverter());
            genericConversionService.addConverter(new StringToIntConverter());
            genericConversionService.addConverter(new StringToLongConverter());

        }

    }
}

4.前端模板配置

velocity
使用阿里巴巴提供的velocity-starter,参考文档
pom配置

    <dependency>
        <groupId>com.alibaba.boot</groupId>
        <artifactId>velocity-spring-boot-starter</artifactId>
        <version>1.0.4.RELEASE</version>
    </dependency>

application.properties配置

spring.velocity.resource-loader-path = classpath:/templates
spring.velocity.prefix = /view/
spring.velocity.suffix = .vm

velocimacro.library = global_library.vm
#velocimacro.permissions.allow.inline = true
#velocimacro.permissions.allow.inline.to.replace.global = false
#velocimacro.context.localscope = false
#velocimacro.library.autoreload = false

spring.velocity.layout-url = /template/layout.vm
spring.velocity.layout-enabled = true

thymeleaf
Thymeleaf 是一种模板语言,和velocity类似

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

application.properties配置

#thymelea模板配置
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=HTML5
spring.thymeleaf.encoding=UTF-8
#热部署文件,页面不产生缓存,及时更新
spring.thymeleaf.cache=false
spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**

thymeleaf入门
thymeleaf官方文档
velocity -> thymeleaf迁移参考

5.log4j2 配置

Spring Boot 2.0 默认情况下是使用logback作为日志系统,如果需要使用log4j2需要进行以下配置,这里需要使用log42而不是log4j,从 spring boot 1.4开始Spring Boot就支持log4j2,写法和log4j类似,只是有些标签的名字不同

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion><!--剔除原来默认的logging-->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

如下时一个log4j2.xml文件,将该文件放到resources目录下,SpringBoot项目会自动识别到该配置文件进行配置,当然了如果不添加log4j.xml文件,springboot会提示你没有对应文件,并使用默认的配置文件,这个时候日志级别可以在application.properties中配置

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT" follow="true">
            <PatternLayout>
                <pattern>[%-5p] %d %c - %m%n</pattern>
            </PatternLayout>
        </Console>
        <!--添加一个文本追加器,文件位于根目录下,名为log.log-->
        <File name="File" fileName="log.log">
            <PatternLayout>
                <pattern>[%-5p] %d %c - %m%n</pattern>
            </PatternLayout>
        </File>
    </Appenders>
    <Loggers>
        <Logger name="com.jack-dawson" level="debug" >
            <!-- AppenderRef 可以控制文件输出对象-->
            <AppenderRef ref="File" />
        </Logger>
        <Logger name="org.spring" level="debug">
            <AppenderRef ref="File" />
        </Logger>
        <!--根记录全部输出到控制台上-->
        <Root level="debug">
            <AppenderRef ref="Console" />
        </Root>
    </Loggers>
</Configuration>

参考

三、拓展

Spring Boot为什么没有web.xml了
使用spring-boot-devtools实现热部署及热更新
过滤器Filter和拦截器Interceptor区别
处理前端模型数据ModelAndView
Maven常用插件

四、问题

1.@Environment 注解失效,获取到的对象是null
原来使用@Autowired方式获取Environment对象,改成实现EnvironmentAware接口
2.bean初始化顺序问题
在用@Configuration注解标记为配置文件的类中使用@Resource等方式去获取bean实例可能会发生错误,改为@bean方式获取即可
3.controller层接收的参数类型是int,如果请求中未设置对应值会报错
项目初始化bean完成后通过ConfigurableWebBindingInitializer类添加自定义的参数转换器
4.前端模板文件必须放在resources目录下
5.velocity配置指定layout-enabled=true时tools.xml的配置会失效
[velocity-spring-boot-starter](https://github.com/alibaba/velocity-spring-boot-project/blob/master/README_CN.md)
6.application.properties中无法通过${}方式获取pom的变量
Spring Boot已经将maven-resources-plugins默认的${}方式改为了@@方式,如@name@

参考

7.Spring boot集成rose框架后启动时初始化失败
rose框架在初始化时会创建SpringContext对象,和SpringBoot创建的SpringContext对象发生冲突
8.Spring boot继承rose框架,把项目打成jar包后启动失败,提示FileNotFoundException
rose框架内会去项目依赖的jar包中寻找是否有需要初始化的bean,比如用@DAO注解标记的类,但是将项目打成jar包后,无法加载到项目jar内的jar包
9.继承velocity后controller层返回的vm模板名称被当成普通字符串处理
@RestController -> @Controller,如果方法需要返回json用@ResponseBody标记,同时指定@RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET, produces="application/json")  中的produces为json
上一篇下一篇

猜你喜欢

热点阅读