目录
SpringBoot 基础(一)
一、简介
- 官方文档 https://spring.io/projects/spring-boot/
- Spring Boot 的设计目的是简化 Spring 应用的初始搭建以及开发过程。SpringBoot框架中还有两个非常重要的策略:开箱即用和约定优于配置。
- 开箱即用(Outofbox):在开发过程中,通过在MAVEN项目的pom文件中添加相关依赖包,然后使用对应注解来代替繁琐的XML配置文件以管理对象的生命周期。这个特点使得开发人员摆脱了复杂的配置工作以及依赖的管理工作,更加专注于业务逻辑。
- 约定优于配置(Convention over configuration):在项目中会内置一些习惯性配置,如果不需要改变这些配置,可以在很少配置的情况下将项目搭建出来。
二、重要注解
- Spirng Boot 会存在一个启动类,*Application,再启动类上有一个
@SpringBootApplication
。@SpringBootConfiguration
:继承了Configuration,表示当前是注解类@EnableAutoConfiguration
:开启springboot的注解功能。借助@Import的帮助,将所有符合自动配置条件的bean定义加载到IoC容器ComponentScan
:@ComponentScan的功能其实就是自动扫描并加载符合条件的组件(比如@Component和@Repository等)或者bean定义,最终将这些bean定义加载到IoC容器中。@Bean
:其返回值将作为一个bean定义注册到Spring的IoC容器,方法名将默认成该bean定义的id@AutoConfigurationPackage
:自动配置包@Import
:导入自动配置的组件@EnableScheduling
:通过@Import将Spring调度框架相关的bean定义都加载到IoC容器。EnableMBeanExport
:通过@Import将JMX相关的bean定义加载到IoC容器。
三、基本应用开发
1. lombok的使用
介绍:简单的注解形式来简化java代码
- 通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equals、hashcode、toString方法。但是在源码中没有getter和setter方法,但是在编译生成的字节码文件中有getter和setter方法。这样就省去了手动重建这些代码的麻烦,使代码看起来更简洁些。
- 常用注解
@Data
:会为类的所有属性自动生成setter/getter、equals、canEqual、hashCode、toString方法,如为final属性,则不会为该属性生成setter方法。@Getter/@Setter
:为相应的属性自动生成Getter/Setter方法@NonNull
:用在属性或构造器上,可用于校验参数,能帮助避免空指针。@Cleanup
:自动调用close()方法@EqualsAndHashCode
:生成equals和hasCode,也能通过exclude注解来排除一些属性。@ToString
:生成一个toString()方法@NoArgsConstructor
:无参构造器@RequiredArgsConstructor
:部分参数构造器@AllArgsConstructor
:全参构造器@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd hh:mm:ss")
:此注解不属于lombok,属于Jackson。将日期类型格式化为指定形式。
2. SpringBoot 的参数传递
- 请求路径传参,使用 url/{id} 的形式接收参数。需要在参数前加上
@PathVariable
。或者使用 url?id=1 的形式接收参数,可以在参数前加上@RequestParam
,如果参数名都一致的话,可以不加这个注解。 - 使用
@RequestBody
的形式来接收参数。用来处理content-type不是默认的application/x-www-form-urlcoded编码的内容,比如说:application/json或者是application/xml等。
3. 对象参数校验
- 使用
@RequestBody
的方式传入数据,错误信息也会以json的方式传回。 - SpringBoot支持JSR-303 标准的校验
@NotNull
: 限制必须不为null,注意支持String类型校验@NotEmpty
: 验证注解的元素值不为 null 且不为空(字符串长度不为0、集合大小不为0)@NotBlank
: 验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的空格@Pattern(value)
: 限制必须符合指定的正则表达式@Size(max,min)
: 限制字符长度必须在 min 到 max 之间(也可以用在集合上)@Email
: 验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式@Max(value)
: 限制必须为一个不大于指定值的数字@Min(value)
: 限制必须为一个不小于指定值的数字@Past
: 限制必须是一个过去的日期@Future
: 限制必须是一个将来的日期@Pattern(regexp =“el”,message=“msg”)
:自定义限制和出错信息@Validated
: 开启数据有效性校验。添加在类上即为验证方法,添加在方法参数中即为验证参数对象。@DateTimeFormat(pattern = "yyyy-MM-dd hh:mm:ss")
:此注解属于spring框架,要求传入的日期对象格式必须如此。@JsonIgnore
:忽略字段,不转换为json@JsonInclude
:当属性值为空时候,不转换为json
- 对于普通参数的校验,需要在方法上加入BindingResult 参数,可以将错误响应到前端。
public String getcarvalidation4(@Validated Car car,BindingResult bindingResult) {
if (bindingResult.hasErrors()){
return bindingResult.getFieldError().getDefaultMessage();
}
return car.toString();
}
@InitBinder
private void initBinder(WebDataBinder webDataBinder){
// 对参数的日期进行格式化
webDataBinder.addCustomFormatter(new DateFormatter("yyyy-MM-dd HH:mm:ss"));
}
}
4. 静态资源
- Spring Boot 默认将 /** 所有访问映射到以下目录。
- classpath:/static
- classpath:/public
- classpath:/resources
- classpath:/META-INF/resources。
自定义静态访问
可以通过配置文件的方式实现
# 自定义静态文件路径配置 web.upload-path: D:/pic/ spring.mvc.static-path-pattern: /** spring.resources.static-locations: classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,file:${web.upload-path}
可以通过配置类的形式
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { //将所有D:\\springboot\\pic\\ 访问都映射到/myPic/** 路径下 registry.addResourceHandler("/myPic/**").addResourceLocations("file:D: \\pic\\"); } }
webjars https://www.webjars.org/all
在SpringBoot中,允许我们直接访问WEB-INF/lib下的jar包中的/META-INF/resources目录资源,即WEB-INF/lib/{*.jar}/META-INF/resources下的资源可以直接访问。WebJars也是利用了此功能,将所有前端的静态文件打包成一个jar包,这样对于引用放而言,和普通的jar引入是一样的,还能很好的对前端静态资源进行管理。
静态文件存放规则:META-INF/resources/webjars/${name}/${version}。
创建webjars
src/main/resouces路径下创建META-INF/resources/webjars/demo/0.0.1目录,放置静态资源。
编写配置类,也可以不写,因为springboot默认的四个资源路径里面就包含了/META-INF/resources/
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { //配置映射关系 registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); } }
在pom中加入配置
<build> <resources> <resource> <directory>${project.basedir}/src/main/resources</directory> <targetPath>${project.build.outputDirectory}/META-INF/resources/webjars</targetPath> </resource> </resources> </build>
被其它项目引入
<dependency> <groupId>com.offcn</groupId> <artifactId>Webjars-Demo</artifactId> <version>1.0</version> </dependency>
WebJars使用webjars-locator,可以省略版本号
<dependency> <groupId>org.webjars</groupId> <artifactId>webjars-locator-core</artifactId> </dependency>
修改配置类,不然还是去除了版本时路径找不到的。
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { //配置映射关系 registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/").resourceChain(true);//加入resourceChain属性,不然还是去除了版本时路径找不到的 } }
四、SpringBoot 属性
pring Boot并不真正是所谓的『零配置』,他的理念是“习惯优于配置”采用了一些默认的习惯性配置。但是一些配置还是有必要的。
修改默认。
# application-prod.yml server: port: 8888 servlet: context-path: /java001
自定义常量
# application-const.yml # 自定义常量,可以通过 @Value(“${属性名}”) 读取 offcn_ip: 1.1.1.1 offcn_port: 9999
实体属性赋值
# application-bean.yml # 自定义属性,可以通过 @ConfigurationProperties(prefix="userbody")给实体 bean 赋值 # 在调用类或者启动类上,使用 @EnableConfigurationProperties({UserBody.class}) userbody: name: zs password: 123 birthday: 1992.10.28 mobile: 13842098465 address: 北京市朝阳区
自定义配置文件
# 这种自定义,是名字完全自定义,比如test.properties,无法被自动加载。 # 需要使用注解 @Configuration,如果此注解报错可以使用 @Component # @PropertySource("classpath:test.properties") # @ConfigurationProperties(prefix = "testuser") testuser.name = "ls" testuser.password = "123" testuser.birthday = "1978.10.28"
多环境配置文件
# application.yml spring: profiles: # 使用命令行选择 profile,使用参数 -Dspring.profiles.active=dev。也可以同时激活多个文件,用逗号分隔。 active: test # 无条件的添加生效的配置 include: prod,const,bean
五、RESTful
- RESTful是一种软件架构风格。数据的元操作,即CRUD(create, read, update和delete,即数据的增删查改)操作,分别对应于HTTP方法:
- GET用来获取资源
- POST用来新建资源(也可以用于更新资源)
- PUT用来更新资源
- DELETE用来删除资源
以用户数据的基本操作为例:
HTTP协议请求方法 SpringBoot注解 URL 功能说明 POST @PostMapping /users 创建一个用户 GET @GetMapping /users 查询用户列表 GET @GetMapping /users/id 根据id查询一个用户 PUT @PutMapping /users/id 根据id更新一个用户 DELETE @DeleteMapping /users/id 根据id删除一个用户 Swagger2 构建 API 文档
Swagger2这套自动化文档工具来生成文档,它可以轻松的整合到Spring Boot中,并与Spring MVC程序配合组织出强大RESTful API文档。
加入依赖
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.2.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.2.2</version> </dependency>
Swagger2配置类
@Configuration @EnableSwagger2 public class SwaggerConfig { @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.example.demo.controller")) .paths(PathSelectors.any()) .build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("Spring Boot中使用Swagger2构建RESTful APIs") .description("优就业") .termsOfServiceUrl("http://www.ujiuye.com/") .contact("Sunny") .version("1.0") .build(); } }
Controller增加文档注释
@PutMapping("/{id}") @ApiOperation(value="更新指定id用户信息", notes="根据id更新用户信息") @ApiImplicitParams({ @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long"), @ApiImplicitParam(name = "user", value = "用户详细实体user", required = true, dataType = "User") }) public String updateUser(@PathVariable("id") Long id,User user) { for (User user2 : listUser) { if(user2.getId().equals(id)) { user2.setName(user.getName()); user2.setAge(user.getAge()); } } return "success"; }
Controller增加文档注释
@PutMapping("/{id}") @ApiOperation(value="更新指定id用户信息", notes="根据id更新用户信息") @ApiImplicitParams({ @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long"), @ApiImplicitParam(name = "user", value = "用户详细实体user", required = true, dataType = "User") }) public String updateUser(@PathVariable("id") Long id,User user) { for (User user2 : listUser) { if(user2.getId().equals(id)) { user2.setName(user.getName()); user2.setAge(user.getAge()); } } return "success"; }
查看Swagger2文档 http://localhost:8080/swagger-ui.html