美文网首页
Spring Boot 学习

Spring Boot 学习

作者: 桥er桑 | 来源:发表于2018-12-16 09:44 被阅读0次

    一、入门

    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的特点

    • 项目搭建更迅速便捷,可无需配置的自动整合主流第三方框架
    • 遵循习惯优于配置的原则,大多数时候使用默认配置即可
    • 内嵌servlet容器(Servlet、Jetty、Undertow),降低了对环境的要求,可用命令直接执行项目
    • 提供了starter POM,能够非常方便的进行包管理
    • 没有代码生成,也不需要 XML 配置
    • 应用监控
    • Spring cloud

    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的注解

    • @SpringBootApplication:申明让spring boot自动给程序进行必要的配置,包含了@ComponentScan、@Configuration和@EnableAutoConfiguration注解。其中@ComponentScan让spring Boot扫描到Configuration类并把它加入到程序上下文
    • @EnableAutoConfiguration 自动配置
    • @AutoConfigureBefore、@AutoConfigureAfter、@AutoConfigureOrder 制定类加载顺序在参数类之前、之后或自定义顺序,可以用于定制配置文件加载顺序
    • @ConfigurationProperties 定义bean时,bean会根据该注解内的参数去application.properties文件内匹配对应的变量自动注入

    Spring 5.0中的注解

    • @Configuration 等同于spring的XML配置文件;使用Java代码可以检查类型安全
    • @Bean 注册Bean到Spring IoC的注解
    • @ComponentScan 组件扫描,可自动发现和装配一些Bean
    • @Conditional 根据参数中设置的条件装载不同的bean,该注解的参数是一个实现了Condition接口的类
    • @Import 是引入带有@Configuration的java类
    • @ImportResource 引入Spring的xml配置文件
    • @PropertySource 将properties配置文件中的值存储到Spring的 Environment中
    • @Autowired 装配bean,按类型装配
    • @Controller:注解在类上,表示这是一个控制层bean
    • @Service: 注解在类上,表示这是一个业务层bean
    • @Repository: 注解在类上,表示这是一个数据访问层bean
    • @Component: 注解在类上,表示通用bean

    Spring web mvc 注解

    Java 注解

    • @Resource 装配bean,按名称装配
    • @PostConstruct 注解在方法上,构造函数执行后执行
    • @PreDestroy 注解在方法上,在Bean销毁前执行

    二、使用

    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的意思

    • 标准化:JPA 是Java EE 标准之一,任何符合 JPA 标准的框架都遵循同样的架构,基于JPA开发的企业应用能够经过少量的修改就能够在不同的JPA框架下运行。
    • 支持大数据集、事务、并发等容器级事务
    • 简单方便:在JPA框架下创建实体和创建Java 类一样简单,只需要使用 @Entity进行注释,JPA的框架和接口也都非常简单,没有太多特别的规则和设计模式的要求,可以很容易的和其它框架或者容器集成。
    • 查询能力:JPA的查询语言是面向对象而非面向数据库的,它以面向对象的自然语法构造查询语句,可以看成是Hibernate HQL的等价物。JPA定义了独特的JPQL
      2.2 常用注解
      @Entity 声明为实体类
      @Table 声明表名
      @Id 标识表的主键
      @GeneratedValue 指定主键生成策略
      @Column 指定持久属性栏属性
      @Basic 表示一个简单的属性到数据库表的字段的映射
      @ManyToMany、@ManyToOne、@OneToMany、@OneToOne 定义连接表之间的关系

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

    • 静态资源(css、js、图片等)默认放在resources/static下面。如果要修改默认存放目录,可以通过设置属性 spring.mvc.static-path-pattern来实现。
    • 模板文件默认放在 templates目录下
      pom配置
            <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

    相关文章

      网友评论

          本文标题:Spring Boot 学习

          本文链接:https://www.haomeiwen.com/subject/ypytkqtx.html