F1V3.0-8 Springboot基本使用及要点

来源:互联网 发布:java 开启gzip压缩 编辑:程序博客网 时间:2024/05/16 05:00

1 SpringBoot简介

Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。

该框架使用了特定的方式(继承starter,约定优先于配置)来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。

Spring Boot并不是一个框架,从根本上将,它就是一些库的集合,maven或者gradle项目导入相应依赖即可使用Spring Boot,而且无需自行管理这些库的版本。

github地址:https://github.com/spring-projects/spring-boot

Spring Boot默认使用tomcat作为服务器,使用logback提供日志记录。
最根本上来讲,Spring Boot就是一些库的集合,它能够被任意项目的构建系统所使用。简便起见,该框架也提供了命令行界面,它可以用来运行和测试Boot应用。框架的发布版本,包括集成的CLI(命令行界面),可以在Spring仓库中手动下载和安装。一种更为简便的方式是使用Groovy环境管理器(Groovy enVironment Manager,GVM),它会处理Boot版本的安装和管理。Boot及其CLI可以通过GVM的命令行gvm install springboot进行安装。在OS X上安装Boot可以使用Homebrew包管理器。为了完成安装,首先要使用brew tap pivotal/tap切换到Pivotal仓库中,然后执行brew install springboot命令。

要进行打包和分发的工程会依赖于像Maven或Gradle这样的构建系统。为了简化依赖图,Boot的功能是模块化的,通过导入Boot所谓的“starter”模块,可以将许多的依赖添加到工程之中。为了更容易地管理依赖版本和使用默认配置,框架提供了一个parent POM,工程可以继承它


2 Spring Boot基本使用

2.1 构建一个简单的SpringBoot应用

2.1.1构建一个pom文件

Spring Boot提供很多”Starter POMs”, 这能够让你轻松的将jars添加到你的classpath下。 我们的示例程序已经在POM的partent节点使用spring-boot-starter-paren。 spring-boot-starter-parent是一个特殊的starter, 它提供了有用的Maven默认设置。 同时, 它也提供了一个dependency-management 节点,这样对于”blessed“依赖你可以省略version标记。
其他的”Starter POMs“简单的提供依赖, 这些依赖可能是你开发特定类型的应用时需要的。 由于正在开发一个web应用, 我们将添加一个 spring-boot-starter-web 依赖 。

<parent>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-parent</artifactId>    <version>1.3.0.BUILD-SNAPSHOT</version></parent> <!--starter-web提供了内置的Tomcat web服务器和Spring MVC依赖 --><dependencies>    <dependency>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-web</artifactId>    </dependency></dependencies> 

2.1.2 编写一个启动类

为了完成应用程序, 我们需要创建一个单独的Java文件。 Maven默认会编译 src/main/java 下的源码, 所以你需要创建那样的文件结构, 然后添加一个名为 src/main/java/Example.java 的文件:

import org.springframework.boot.*;import org.springframework.boot.autoconfigure.*;import org.springframework.stereotype.*;import org.springframework.web.bind.annotation.*;@RestController@EnableAutoConfigurationpublic class Example {    @RequestMapping("/")    String home() {        return "Hello World!";    }     public static void main(String[] args) throws Exception {        SpringApplication.run(Example.class, args);    }} 

尽管这里没有太多代码, 但很多事情正在发生。 让我们分步探讨重要的部分。

① @RestController和@RequestMapping注解
我们的Example类上使用的第一个注解是 @RestController 。 这被称为一个构造型(stereotype) 注解。 它为阅读代码的人们提供建议。对于Spring,该类扮演了一个特殊角色。 在本示例中, 我们的类是一个web @Controller,所以当处理进来的web请求时, Spring会询问它。

@RequestMapping 注解提供路由信息。 它告诉Spring任何来自”/”路径的HTTP请求都应该被映射到 home 方法。 @RestController 注解告诉Spring以字符串的形式渲染结果, 并直接返回给调用者。

② @EnableAutoConfiguration注解
第二个类级别的注解是 @EnableAutoConfiguration 。 这个注解告诉Spring Boot根据添加的jar依赖猜测你想如何配置Spring。由于 spring-boot-starter-web 添加了Tomcat和Spring MVC, 所以auto-configuration将假定你正在开发一个web应用并相应地对Spring进行设置。

③ main方法
main方法通过调用run, 将业务委托给了Spring Boot的SpringApplication类。 SpringApplication将引导我们的应用, 启动Spring, 相应地启动被自动配置的Tomcat web服务器。 我们需要将 Example.class 作为参数传递给run方法来告诉SpringApplication谁是主要的Spring组件。 为了暴露任何的命令行参数, args数组也会被传递过去。

run方法执行顺序:

1.初始化SpringApplicationRunListeners并且开始监听

2.加载StandardEnvironment(包括系统参数 环境变量参数 properties/yml文件 profiles)

3.把environment set到Listeners里面

4.默认通过AnnotationConfigApplicationContext扫描所有的注解类,创建并且注册bean(默认都是创建的单列)

5.创建context,并且把environment set到context里面
备注:如果需要初始化spring-boot即将完成的时候马上去做一些事情,我们可以实现CommandLineRunner该接口

2.1.3 启动Spring-boot

我们可以听过IDE来启动主类程序,也可以通过maven命令的方式启动服务(在项目根目录下输入 mvn spring-boot:run 来启动应用)


这里写图片描述

如果使用一个浏览器打开localhost:8080, 你应该可以看到以下输出:

hello world

2.2 Starter POMs

starter POMs是可以包含到应用中的一个方便的依赖关系描述符集合。 你可以获取所有Spring及相关技术的一站式服务, 而
不需要翻阅示例代码, 拷贝粘贴大量的依赖描述符。 例如, 如果你想使用Spring和JPA进行数据库访问, 只需要在你的项目中包含 spring-boot-starter-data-jpa 依赖, 然后你就可以开始了。

该starters包含很多你搭建项目, 快速运行所需的依赖, 并提供一致的, 管理的传递依赖集


这里写图片描述

Spring Boot生产准备的starters


这里写图片描述

最后, Spring Boot包含一些可用于排除或交换具体技术方面的starters


这里写图片描述

2.3 SpringBoot常用注解及功能

主类通常位于根包中,可以使用@EnableAutoConfiguration注解你的主类。使用根包允许你使用 @ComponentScan 注解而不需要定义一个 basePackage 属性。 如果main类位于根包中, 你也可以使用 @SpringBootApplication 注解。

Springbooot包结构推介:


这里写图片描述

2.3.1 Spring Beans和依赖注入

我们经常使用 @ComponentScan 注解搜索beans, 并结合 @Autowired 构造器注入

如果按照上面的结构划分包结构,你可以添加 @ComponentScan 注解而不需要任何参数,也可是自己定义扫描路劲@ComponentScan (basePackages = “xxx.xxx.xxx”),你的所有应用程序组件( @Component , @Service , @Repository , @Controller 等) 将被自动注册为Spring Beans。

2.3.2 @SpringBootApplication

很多Spring Boot开发者总是使用 @Configuration , @EnableAutoConfiguration 和 @ComponentScan 注解他们的main类。 由于这些注解被如此频繁地一块使用,Spring Boot提供一个方便的 @SpringBootApplication 选择。

该 @SpringBootApplication 注解等价于以默认属性使用 @Configuration,@EnableAutoConfiguration 和 @ComponentScan。当需要特殊的包扫描时可以结合 @ComponentScan来配置你的扫描路劲。

2.3.3 @RestController

用于标注控制层组件(如struts中的action),包含@Controller和@ResponseBody。@RestController 注解告诉Spring以字符串的形式渲染结果,并直接返回给调用者

2.3.4 @Configuration

Spring Boot提倡基于Java的配置。尽管你可以使用一个XML源来调用 SpringApplication.run() ,我们通常建议你使用 @Configuration 类作为主要源。一般定义 main 方法的类也是主要 @Configuration 的一个很好候选。你不需要将所有的 @Configuration 放进一个单独的类。 @Import 注解可以用来导入其他配置类。另外,你也可以使用 @ComponentScan 注解自动收集所有的Spring组件,包括 @Configuration 类。

2.3.5 @EntityScan

用于扫描Jpa实体类

2.3.6 @Component和 @Bean

@Component被用在要被自动扫描和装配的类上。@Component类中使用方法或字段时不会使用CGLIB增强(及不使用代理类:调用任何方法,使用任何变量,拿到的是原始对象)Spring 注解@Component等效于@Service,@Controller,@Repository

@Bean主要被用在方法上,来显式声明要用生成的类;用@Configuration注解该类,等价 与XML中配置beans;用@Bean标注方法等价于XML中配置bean。现在项目上,本工程中的类,一般都使用@Component来生成bean。在把通过web service取得的类,生成Bean时,使用@Bean和getter方法来生成bean

2.4属性配置以及读取

spring-boot 属性分为两种:

1.spring-boot默认属性(application.properties或者application.yml 系统属性 环境变量属性)

2.自定义加载属性
spring-boot启动的时候会默认扫描resources目录下面的application.properties或者application.yml,扫瞄结束后会把值放入到Environment。

初始化bean的时候需要用到配置的值,我们可以根据这三种方式去获取:

1).继承EnvironmentAware获取Environment

2).通过注解@value进行填充值

3).注入environment 通过environment获取

@Configuration  public class MyProperty  implements EnvironmentAware {   public void setEnvironment(Environment environment) {          //方案一 继承EnvironmentAware 获取yml里面的值              RelaxedPropertyResolver propertyResolver = new RelaxedPropertyResolver(environment, "jdbc.");          String url = propertyResolver.getProperty("url");   }      //方案二  通过注解value进行填充值   @Value("${jdbc.url}")   private String url;   //方案三  注入environment  通过environment获取   @Autowired   private Environment environment;   public void init(){              RelaxedPropertyResolver propertyResolver = new RelaxedPropertyResolver(environment, "jdbc.");         String url = environment.getProperty("url");     }  }  

2.4.1 自定义配置文件读取

Spring Boot支持自定义属性文件的读取,请看下面的例子:
该例子的核心是:

@PropertySource(value="classpath:/config/custom.properties",ignoreResourceNotFound= true)
// application 注解@Configuration@ComponentScan@EnableAutoConfiguration@PropertySource(value="classpath:/config/custom.properties", ignoreResourceNotFound = true)@Controllerpublic class PropertiesController {    @Value("${CONSTANT_PASSWORD}")    private String password;    @Autowired    private ConfigBean configBean;    @RequestMapping("/custom")    public String custom(@RequestParam(value="name",required=false, defaultValue="${CONSTANT_USER}") String name            , Model model) {        model.addAttribute("name", name);        model.addAttribute("password", password);        System.out.println(configBean);        return "custom";    }    public static void main(String[] args) {        SpringApplication.run(PropertiesController.class,args);    }}

config/custom.properties

## 常量配置CONSTANT_USER=vergiylnCONSTANT_PASSWORD=中文123## thymeleaf 配置spring.thymeleaf.prefix=classpath:/templates/properties/spring.thymeleaf.suffix=.htmlspring.thymeleaf.mode=HTML5spring.thymeleaf.encoding=UTF-8spring.thymeleaf.content-type=text/html# set to false for hot refreshspring.thymeleaf.cache=false

ConfigBean.properties

vergilyn.map[blog]=http://www.cnblogs.com/VergiLyn/vergilyn.map[name]=VergiLynvergilyn.map[remark]=备注,中文23333vergilyn.list[0]=Carpentersvergilyn.list[1]=Celine Dionvergilyn.list[2]=Bon Jovivergilyn.list[3]=Taylor Swiftvergilyn.str=stringvergilyn.num=124vergilyn.date=2017-01-14 23:55:19vergilyn.isSuccess=false

读取ConfigBean.properties的Java类如下:

@Configuration@ConfigurationProperties(prefix = "vergilyn")// 配置文件中的前缀@PropertySource("classpath:config/ConfigBean.properties")@Componentpublic class ConfigBean implements Serializable{    private String str;    private Integer num;    private boolean isSuccess;    private Map<String, String> map;    private List<String> list;    public String getStr() {        return str;    }    public void setStr(String str) {        this.str = str;    }    public Integer getNum() {        return num;    }    public void setNum(Integer num) {        this.num = num;    }    public Map<String, String> getMap() {        return map;    }    public void setMap(Map<String, String> map) {        this.map = map;    }    public List<String> getList() {        return list;    }    public void setList(List<String> list) {        this.list = list;    }    public Boolean isSuccess() {        return isSuccess;    }    public void setIsSuccess(Boolean success) {        isSuccess = success;    }}

2.4.2 默认配置方式:application.properties

application.properties文件可以放在一下四个位置:

A、jar包所在目录同级的目录“/config”的子目录下;
B、jar包锁在目录的同级目录下;
C、classpath根目录的“/config”包下;
D、classpath的根目录下;
同样,这个列表按照优先级排序,也就是说,src/main/resources/config下application.properties覆盖src/main/resources下application.properties中相同的属性,如图:


这里写图片描述

相关知识补充

1.A、B适合生产环境,C、D适合开发环境;

2.如果同时存在,则按照A、B、C、D的顺序优先选取;

2.5 spring boot默认提供的常用类

2.5.1 Spring boot数据访问配置

需要引入jpa依赖

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

这里使用druid连接池,还需要引入druid的依赖

<dependency>        <groupId>com.alibaba</groupId>        <artifactId>druid</artifactId>          <version>1.0.25</version>  </dependency> 

Spring Boot中的application.properties配置信息:

# 驱动配置信息  spring.datasource.type=com.alibaba.druid.pool.DruidDataSource  spring.datasource.url = jdbc:mysql://127.0.0.1:3306/mealsystem?useUnicode=true&characterEncoding=utf-8  spring.datasource.username = root  spring.datasource.password = 123456  spring.datasource.driverClassName = com.mysql.jdbc.Driver  #连接池的配置信息  spring.datasource.initialSize=5  spring.datasource.minIdle=5  spring.datasource.maxActive=20  spring.datasource.maxWait=60000  spring.datasource.timeBetweenEvictionRunsMillis=60000  spring.datasource.minEvictableIdleTimeMillis=300000  spring.datasource.validationQuery=SELECT 1 FROM DUAL  spring.datasource.testWhileIdle=true  spring.datasource.testOnBorrow=false  spring.datasource.testOnReturn=false  spring.datasource.poolPreparedStatements=true  spring.datasource.maxPoolPreparedStatementPerConnectionSize=20  spring.datasource.filters=stat,wall,log4j  spring.datasource.connectionProperties=druid.stat.mergdruid.stat.slowSqlMillis=5000  

2.5.2 redis的配置详细说明

Redis是一个缓存, 消息中间件及具有丰富特性的键值存储系统。 Spring Boot为Jedis客户端库和由Spring Data Redis提供的
基于Jedis客户端的抽象提供自动配置。 spring-boot-starter-redis ‘Starter POM’为收集依赖提供一种便利的方式。

连接Redis :引入Spring boot 对redies 的支持

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

Redies配置

#redis  spring.redis.host=localhost spring.redis.port=6379    spring.redis.password=xxx  spring.redis.pool.maxActive=8    spring.redis.pool.maxWait=-1    spring.redis.pool.maxIdle=8    spring.redis.pool.minIdle=0    spring.redis.timeout=0 

2.6 自动装配Spring Bean

pring Boot会检查你发布的jar中是否存在META-INF/spring.factories文件。我们在使用Spring Boot时使用最多的就是starter,我们在使用某个功能时,开发者不需要关注各种依赖库的处理,不需要具体的配置信息,直接@Autowired就可以注入这些Bean。

因此我们可以自定义一些starter,当需要启动一些Bean时只需要在src/main/resources目录下新建META-INF文件夹,然后新建spring.factories文件,这个文件用于告诉Spring Boot去找指定的自动配置文件,这些文件将会被装载成Spring Bean:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.jb.cache.configure.CacheConfigure,\com.jb.cache.configure.EntityCacheConfig

2.7 静态文件

Spring Boot能大大简化WEB应用开发的原因, 最重要的就是遵循“约定优于配置”这一基本原则。Spring Boot的关于静态资源的默认配置已经完全满足绝大部分WEB应用的需求。没必要去弄手续繁杂的自定义,用Spring Boot的约定就好了。
在Maven 工程目录下,所有静态资源都放在src/main/resource目录下,结构如下:


这里写图片描述

页面可以这样访问

<img src="images/newDemo.jpg">

添加自定义:

注意是添加,不是替换,添加不影响原来的默认约定。非要自定义,那就配置类继承WebMvcConfigurerAdapter

@Configurationpublic class MyWebAppConfig extends WebMvcConfigurerAdapter {@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry){    registry.addResourceHandler("/myResource/**").addResourceLocations("classpath:/myRes          ource/");super.addResourceHandlers(registry);}

这个是添加了一个新位置


这里写图片描述

3 swagger配置及使用

Swagger2,它可以轻松的整合到Spring Boot中,并与Spring MVC程序配合组织出强大RESTful API文档。它既可以减少我们创建文档的工作量,同时说明内容又整合入实现代码中,让维护文档和修改代码整合为一体,可以让我们在修改代码逻辑的同时方便的修改文档说明。另外Swagger2也提供了强大的页面测试功能来调试每个RESTful API。具体效果如下图所示:


这里写图片描述

在 pom.xml 中加入Swagger2的依赖

这里写图片描述

创建swagger2配置类:

如下代码所示,通过 @Configuration 注解,让Spring来加载该类配置。再通过 @EnableSwagger2 注解来启用Swagger2

@Configuration@EnableSwagger2public class SwaggerConfigure {    @Bean    public Docket createRestApi() {        return new Docket(DocumentationType.SWAGGER_2)                .apiInfo(apiInfo())                .select()                .apis(RequestHandlerSelectors.basePackage("com.xxx.xx"))          .paths(PathSelectors.any())//TODO 修改为正则匹配          .build();    }    /**     * api基本信息内容     * @Title: apiInfo     * @Description: TODO     * @param      * @return ApiInfo     * @throws     */    private ApiInfo apiInfo() {        //TODO 从配置文件读取        return new ApiInfoBuilder()                .title("xxxxxAPI")                .description("xxxxxxxx")                .termsOfServiceUrl("xxxxxx")                .contact("平台组")                .version("3.0.0")                .build();    }}

通过 createRestApi 函数创建 Docket 的Bean之后, apiInfo() 用来创建该Api的基本信息(这些基本信息会展现在文档页面中)。 select() 函数返回一个 ApiSelectorBuilder 实例用来控制哪些接口暴露给Swagger来展现,本例采用指定扫描的包路径来定义,Swagger会扫描该包下所有Controller定义的API,并产生文档内容(除了被 @ApiIgnore 指定的请求)。

添加文档内容

在完成了上述配置后,其实已经可以生产文档内容,但是这样的文档主要针对请求本身,而描述主要来源于函数等命名产生,对用户并不友好,我们通常需要自己增加一些说明来丰富文档内容。如下所示,我们通过 @ApiOperation 注解来给API增加说明、通过 @ApiImplicitParams 、 @ApiImplicitParam 注解来给参数增加说明。

@ApiOperation(value ="获取模型类型对应的属性",notes = "模型")@ApiImplicitParam(name="clsID",value="类型id",     paramType="query",required=true,dataType="String")@RequestMapping(value = "getNonGroupAttrsOfClass.do", method = RequestMethod.POST)@ResponseBodypublic List<TbModelClsattr>getNonGroupAttrsOfClass(String clsID) {        List<TbModelClsattr> list = bfObjectModelService                .getNonGroupAttrsOfClass(clsID);        return list;    }

启动Spring Boot访问:http://localhost:8080/swagger-ui.html,可以看到就能看到前文所展示的RESTful API的页面


这里写图片描述

API文档访问与调试

在上图请求的页面中,我们看到user的Value是个输入框?是的,Swagger除了查看接口功能外,还提供了调试测试功能,我们可以点击上图中右侧的Model Schema(黄色区域:它指明了User的数据结构),此时Value中就有了user对象的模板,我们只需要稍适修改,点击下方 “Try it out!” 按钮,即可完成了一次请求调用!(具体使用请自行百度这里只提供一个配置说明

4 Spring Boot单元测试

单元测试 是针对 程序的最小单元 来进行正确性检验的测试工作。程序单元是应用的最小可测试部件。一个单元可能是单个程序、类、对象、方法等—–维基百科

Junit基本注解介绍

@BeforeClass
在所有测试方法前执行一次,一般在其中写上整体初始化的代码

@AfterClass
在所有测试方法后执行一次,一般在其中写上销毁和释放资源的代码

@Before
在每个测试方法前执行,一般用来初始化方法(比如我们在测试别的方法时,类中与其他测试方法共享的值已经被改变,为了保证测试结果的有效性,我们会在@Before注解的方法中重置数据)

@After
在每个测试方法后执行,在方法执行完成后要做的事情

@Test(timeout = 1000)
测试方法执行超过1000毫秒后算超时,测试将失败

@Test(expected = Exception.class)
测试方法期望得到的异常类,如果方法执行没有抛出指定的异常,则测试失败

@Ignore(“not ready yet”)
@Test
执行测试时将忽略掉此方法,如果用于修饰类,则忽略整个类

@RunWith
在JUnit中有很多个Runner,他们负责调用你的测试代码,每一个Runner都有各自的特殊功能,你要根据需要选择不同的Runner来运行你的测试代码。
如果我们只是简单的做普通Java测试,不涉及Spring Web项目,你可以省略@RunWith注解,这样系统会自动使用默认Runner来运行你的代码。

5 MockMvc测试

5.1 MockMvcBuilder

MockMvcBuilder是用来构造MockMvc的构造器,其主要有两个实现:StandaloneMockMvcBuilderDefaultMockMvcBuilder,分别对应两种测试方式,即独立安装和集成Web环境测试(此种方式并不会集成真正的web环境,而是通过相应的Mock API进行模拟测试,无须启动服务器)。对于我们来说直接使用静态工厂MockMvcBuilders创建即可。

@RunWith(SpringRunner.class)@SpringBootTest(classes={ModelApplication.class})@AutoConfigureMockMvc@Transactional //提供事物回滚机制public class IncotermsRestServiceTest {    @Autowired    private WebApplicationContext wac;    private MockMvc mockMvc;    @Before    public void setup() {        //构造MockMvc        this.mockMvc=   MockMvcBuilders.webAppContextSetup(this.wac).build();       }    ...}

注意:

(1)@SpringBootTest:Spring Boot测试环境使用,classes指定程序启动类

(2)通过@Autowired WebApplicationContext wac:注入web环境的ApplicationContext容器;

(3)然后通过MockMvcBuilders.webAppContextSetup(wac).build()创建一个MockMvc进行测试;

(4)@Transactional :添加可以是事物回滚,不会因为测试数据而造成数据的错误。

看一个具体的例子:

@Testpublic void cmdGetAppAttrOfAppCls() throws Exception{        String result= this.mockMvc.perform(post("/appAttr/cmdGetAppAttrOfAppCls.do",).param("appID","123").param("clsID","345"))       .andDo(print()).andReturn().getResponse().getContentAsString();         System.out.println(result.toString());        Assert.assertNotNull(result);}

perform:执行一个RequestBuilder请求,会自动执行SpringMVC的流程并映射到相应的控制器执行处理;

param:添加control需要的参数

andDo:添加ResultHandler结果处理器,比如调试时打印结果到控制台;

andReturn:最后返回相应的MvcResult;然后进行自定义验证进行下一步的异步处理;

最后使用断言来进行返回值判断。

原创粉丝点击