我有一个读者看到我写的文章,说了你老写spring,现在是springboot时代了啊,能不能写点springbooot相关的文章。
那既然读者有需求,那我就更呗。
首先我来说说springboot:
工作有一定时间的程序员最开始接触的就是spring 。当时我们写代码的时候写的最多的就是代码里面的配置。有的时候会反复复制代码去更改配置。后来spring全家桶推出了springboot。让你更容易上手,更简单快捷的构建spring的应用。
我们先动手构建一个简单的springboot项目
我使用的是jdk1.8版本,maven idea。
首先我们打开idea
点开
我们在点击Spring Initializr 点击next
Web下勾选Spring Web Start,(网上创建springboot项目多是勾选Web选项,而较高版本的Springboot没有此选项,勾选Spring Web Start即可,2.1.8版本是Spring Web);Template Englines勾选Thymeleaf;SQL勾选:MySQL Driver,JDBC API 和 MyBatis Framework三项;点击next;
我们全部做完后,第一个程序当然是helloworld
启动主程序 打开浏览器访问 可以看到页面上输出了结果。
Springboot 在编写单元测试用例也是比较方便的。
在测试的包下,我们建立一个ApplicationTest类 引入注解
在这个类中我们写一些代码
Private MockMvc mvc;
@before
public void setUp() throws Exception{
mvc=MockMvcBuilders.standaloneSetup(new HelloController)).build();
}
@Test
public void getHello()throws Exception{
mvc.perform(MockMvcRequestBuilders.get(“/hello”).accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk())
.andExpect(content().string(equalTo(HelloWorld)))
}
使⽤MockServletContext 来构建⼀个空的 WebApplicationContext ,这样我们创建
的 HelloController 就可以在 @Before 函数中传建并传递
到 MockMvcBuilders.standaloneSetup() 函数中。
当然我们这篇文章不是让你简单的让你去搭建springboot项目。
注意引⼊下⾯内容,让 status 、 content 、 equalTo 函数可⽤
import static org.hamcrest.Matchers.equalTo;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.con
tent;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.sta
tus;
⾄此已完成⽬标,通过Maven构建了⼀个空⽩Spring Boot项⽬,再通过引⼊web模块实现了⼀个简单
的请求处理。
单体最好的结构我们认为应该是这样的
对于common 其他的完全可以另外启用服务。
自定义属性与加载
我们在用springboot项目的时候,使用自己定义的一些属性。
然后通过 @Value("$") 注解来加载对应的配置属性
参数间在配置文件中可以直接进行引用,我们用${}括号的形式引用其他参数。
配置文件中,当然也支持随机数。密钥,服务端口等可以用$,$,$$
$
通过命令行来设置属性值
相信使⽤过⼀段时间Spring Boot的⽤户,⼀定知道这条命令:java -jar xxx.jar --
server.port=8888 ,通过使⽤--server.port属性来设置xxx.jar应⽤的端⼝为8888。
在命令⾏运⾏时,连续的两个减号 -- 就是对 application.properties 中的属性值进⾏赋值的标
识。所以, java -jar xxx.jar --server.port=8888 命令,等价于我们
在 application.properties 中添加属性 server.port=8888 ,该设置在样例⼯程中可⻅,读者可通
过删除该值或使⽤命令⾏来设置该值来验证。
多环境配置
我们在开发Spring Boot应⽤时,通常同⼀套程序会被应⽤和安装到⼏个不同的环境,⽐如:开发、测
试、⽣产等。其中每个环境的数据库地址、服务器端⼝等等配置都会不同,如果在为不同环境打包时
都要频繁修改配置⽂件的话,那必将是个⾮常繁琐且容易发⽣错误的事。
对于多环境的配置,各种项⽬构建⼯具或是框架的基本思路是⼀致的,通过配置多份不同环境的配置
⽂件,再通过打包命令指定需要打包的内容之后进⾏区分打包,Spring Boot也不例外,或者说更加简
单。
在Spring Boot中多环境配置⽂件名需要满⾜ application-.properties 的格式,其
中 对应你的环境标识,⽐如:
application-dev.properties :开发环境
application-test.properties :测试环境
application-prod.properties :⽣产环境
⾄于哪个具体的配置⽂件会被加载,需要在 application.properties ⽂件中通
过 spring.profiles.active 属性来设置,其值对应 值。
如:spring.profiles.active=test 就会加载 application-test.properties 配置⽂件内容
下⾯,以不同环境配置不同的服务端⼝为例,进⾏样例实验。
针对各环境新建不同的配置⽂件 application-dev.properties 、 application-
test.properties 、 application-prod.properties
在这三个⽂件均都设置不同的 server.port 属性,如:dev环境设置为1111,test环境设置为
2222,prod环境设置为3333
application.properties中设置 spring.profiles.active=dev ,就是说默认以dev环境设置
测试不同配置的加载
执⾏ java -jar xxx.jar ,可以观察到服务端⼝被设置为 1111 ,也就是默认的开发环境
(dev)
执⾏ java -jar xxx.jar --spring.profiles.active=test ,可以观察到服务端⼝被设置
为 2222 ,也就是测试环境的配置(test)
执⾏ java -jar xxx.jar --spring.profiles.active=prod ,可以观察到服务端⼝被设置
为 3333 ,也就是⽣产环境的配置(prod)
按照上⾯的实验,可以如下总结多环境的配置思路:
application.properties 中配置通⽤内容,并设置 spring.profiles.active=dev ,以开发环
境为默认配置
application-.properties 中配置各个环境不同的内容
通过命令⾏⽅式去激活不同环境的配置
开发resultful 接口服务及单元测试。
⾸先,回顾并详细说明⼀下在快速⼊⻔中使⽤
的 @Controller 、 @RestController 、 @RequestMapping 注解。如果您对Spring MVC不熟悉并且
还没有尝试过快速⼊⻔案例,建议先看⼀下快速⼊⻔的内容。
@Controller :修饰class,⽤来创建处理http请求的对象
@RestController :Spring4之后加⼊的注解,原来在 @Controller 中返回json需
要 @ResponseBody 来配合,如果直接⽤ @RestController 替代 @Controller 就不需要再配
置 @ResponseBody ,默认返回json格式。
@RequestMapping :配置url映射
开发web应用
在我们开发Web应⽤的时候,需要引⽤⼤量的js、css、图⽚等静态资源
Spring Boot默认提供静态资源⽬录位置需置于classpath下,⽬录名需符合如下规则:
/static
/public
/resources
/META-INF/resources
举例:我们可以在 src/main/resources/ ⽬录下创建 static ,在该位置放置⼀个图⽚⽂件。启动
程序后,尝试访问 http://localhost:8080/D.jpg 。如能显示图⽚,配置成功。
我们都是通过@RestController来处理请求,所以返回的内容为json对象。那么如果
需要渲染html⻚⾯的时候,要如何实现呢?
在动态HTML实现上Spring Boot依然可以完美胜任,并且提供了多种模板引擎的默认配置⽀持,所以
在推荐的模板引擎下,我们可以很快的上⼿开发动态⽹站。
Spring Boot提供了默认配置的模板引擎主要有以下⼏种:
Thymeleaf
FreeMarker
Velocity
Groovy
Mustache
Spring Boot建议使⽤这些模板引擎,避免使⽤JSP,若⼀定要使⽤JSP将⽆法实现Spring Boot的多
种特性
当你使⽤上述模板引擎中的任何⼀个,它们默认的模板配置路径
为:src/main/resources/templates 。当然也可以修改这个路径,具体如何修改,可在后续各模板
引擎的配置属性中查询并修改。
Thymelef
Thymeleaf是⼀个XML/XHTML/HTML5模板引擎,可⽤于Web与⾮Web环境中的应⽤开发。它是⼀个
开源的Java库,基于Apache License 2.0许可,由Daniel Fernández创建,该作者还是Java加密库
Jasypt的作者。
Thymeleaf提供了⼀个⽤于整合Spring MVC的可选模块,在应⽤开发中,你可以使⽤Thymeleaf来完全
代替JSP或其他模板引擎,如Velocity、FreeMarker等。Thymeleaf的主要⽬标在于提供⼀种可被浏览
器正确显示的、格式良好的模板创建⽅式,因此也可以⽤作静态建模。你可以使⽤它创建经过验证的
XML与HTML模板。相对于编写逻辑或代码,开发者只需将标签属性添加到模板中即可。接下来,这些
标签属性就会在DOM(⽂档对象模型)上执⾏预先制定好的逻辑
Spring在使用的时候直接引入依赖
在完成配置之后,举⼀个简单的例⼦,在快速⼊⻔⼯程的基础上,举⼀个简单的示例来通过Thymeleaf
渲染⼀个⻚⾯。
@Controller
public class HelloController {
@RequestMapping("/")
public String index(ModelMap map) {
// 加⼊⼀个属性,⽤来在模板中读取
map.addAttribute("host", "http://blog.didispace.com");
// return模板⽂件的名称,对应src/main/resources/templates/index.html
return "index";
}
}
Themlef的参数配置,这里不做过多篇幅。
Web应用统一异常处理
我们在做Web应⽤的时候,请求处理过程中发⽣错误是⾮常常⻅的情况。Spring Boot提供了⼀个默认
的映射:/error ,当处理中抛出异常之后,会转到该请求中处理,并且该请求有⼀个全局的错误⻚
⾯⽤来展示异常内容。
@RequestMapping("/hello")
public String hello() throws Exception {
throw new Exception("发⽣错误");
}
虽然,Spring Boot中实现了默认的error映射,但是在实际应⽤中,上⾯你的错误⻚⾯对⽤户来说并不
够友好,我们通常需要去实现我们⾃⼰的异常提示。
下⾯我们以之前的Web应⽤例⼦为基础(Chapter3-1-2),进⾏统⼀异常处理的改造。
创建全局异常处理类:通过使⽤ @ControllerAdvice 定义统⼀的异常处理类,⽽不是在每个
Controller中逐个定义。@ExceptionHandler ⽤来定义函数针对的异常类型,最后将Exception对
象和请求URL映射到 error.html 中
@ControllerAdvice
class GlobalExceptionHandler {
public static final String DEFAULT_ERROR_VIEW = "error";
@ExceptionHandler(value = Exception.class)
public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) th
rows Exception {
ModelAndView mav = new ModelAndView();
mav.addObject("exception", e);
mav.addObject("url", req.getRequestURL());
Web应⽤的统⼀异常处理
mav.setViewName(DEFAULT_ERROR_VIEW);
return mav;
}
}
实现 error.html ⻚⾯展示:在 templates ⽬录下创建 error.html ,将请求的URL和
Exception对象的message输出。
通过实现上述内容之后,我们只需要在 Controller 中抛出 Exception ,当然我们可能会有多种不
同的 Exception 。然后在 @ControllerAdvice 类中,根据抛出的具体 Exception 类型匹
配 @ExceptionHandler 中配置的异常类型来匹配错误映射和处理。
@ExceptionHandler()
public ResultData exceptionHandler(Exception e){
log.error("全局异常处理 :[{}]",e);
if( e instanceof BizException ){
log.info("进入bizExcetion处理器");
BizException bizException = (BizException) e;
String errMsg = bizException.getErrMsg();
if( bizException.getErrCode() != null){
Integer errCode = Integer.parseInt(bizException.getErrCode());
return ResultData.fail(errMsg,errCode);
};
return ResultData.fail(errMsg);
}
if( e instanceof ValidateException ){
ValidateException validateException = (ValidateException) e;
String errMsg = validateException.getErrMsg();
if( validateException.getErrCode() != null){
Integer errCode = Integer.parseInt(validateException.getErrCode());
return ResultData.fail(errMsg,errCode);
};
return ResultData.fail(errMsg);
}
if ( e instanceof ConstraintViolationException ){
Set constraintViolations =((ConstraintViolationException) e).getConstraintViolations();
Iterator iterator = constraintViolations.iterator();
StringBuffer errMsg=new StringBuffer();
while (iterator.hasNext()) {
ConstraintViolation cvl = iterator.next();
errMsg.append(cvl.getMessageTemplate());
if(iterator.hasNext()){
errMsg.append(",");
}
}
return ResultData.fail(errMsg.toString());
}
return ResultData.fail(e.getMessage() == null ? "空指针异常": e.getMessage());
}
使用swagger
由于Spring Boot能够快速开发、便捷部署等特性,相信有很⼤⼀部分Spring Boot的⽤户会⽤来构建
RESTful API。⽽我们构建RESTful API的⽬的通常都是由于多终端的原因,这些终端会共⽤很多底层
业务逻辑,因此我们会抽象出这样⼀层来同时服务于多个移动端或者Web前端。
这样⼀来,我们的RESTful API就有可能要⾯对多个开发⼈员或多个开发团队:IOS开发、Android开发
或是Web开发等。为了减少与其他团队平时开发期间的频繁沟通成本,传统做法我们会创建⼀份
RESTful API⽂档来记录所有接⼝细节,然⽽这样的做法有以下⼏个问题:
由于接⼝众多,并且细节复杂(需要考虑不同的HTTP请求类型、HTTP头部信息、HTTP请求内容
等),⾼质量地创建这份⽂档本身就是件⾮常吃⼒的事,下游的抱怨声不绝于⽿。
随着时间推移,不断修改接⼝实现的时候都必须同步修改接⼝⽂档,⽽⽂档与代码⼜处于两个不
同的媒介,除⾮有严格的管理机制,不然很容易导致不⼀致现象。
为了解决上⾯这样的问题,本⽂将介绍RESTful API的重磅好伙伴Swagger2,它可以轻松的整合到
Spring Boot中,并与Spring MVC程序配合组织出强⼤RESTful API⽂档。它既可以减少我们创建⽂档
的⼯作量,同时说明内容⼜整合⼊实现代码中,让维护⽂档和修改代码整合为⼀体,可以让我们在修
改代码逻辑的同时⽅便的修改⽂档说明。另外Swagger2也提供了强⼤的⻚⾯测试功能来调试每个
在pom中引入依赖
@Configuration
@EnableSwagger2
public class Swagger2 {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.didispace.web"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Spring Boot中使⽤Swagger2构建RESTful APIs")
.description("更多Spring Boot相关⽂章请关注:http://blog.didispace.com
/")
.termsOfServiceUrl("http://blog.didispace.com/")
.contact("程序员DD")
.version("1.0")
.build();
}
}
添加⽂档内容
在完成了上述配置后,其实已经可以⽣产⽂档内容,但是这样的⽂档主要针对请求本身,⽽描述主要
来源于函数等命名产⽣,对⽤户并不友好,我们通常需要⾃⼰增加⼀些说明来丰富⽂档内容。如下所
示,我们通过 @ApiOperation 注解来给API增加说明、通
过 @ApiImplicitParams 、 @ApiImplicitParam 注解来给参数增加说明
@RestController
@RequestMapping(value="/users") // 通过这⾥配置使下⾯的映射都在/users下,可去除
public class UserController {
static Map users = Collections.synchronizedMap(new HashMap
er>());
@ApiOperation(value="获取⽤户列表", notes="")
@RequestMapping(value={""}, method=RequestMethod.GET)
public List getUserList() {
List r = new ArrayList(users.values());
return r;
}
@ApiOperation(value="创建⽤户", notes="根据User对象创建⽤户")
@ApiImplicitParam(name = "user", value = "⽤户详细实体user", required = true, dat
aType = "User")
@RequestMapping(value="", method=RequestMethod.POST)
public String postUser(@RequestBody User user) {
users.put(user.getId(), user);
return "success";
}
@ApiOperation(value="获取⽤户详细信息", notes="根据url的id来获取⽤户详细信息")
@ApiImplicitParam(name = "id", value = "⽤户ID", required = true, dataType = "Lo
ng")
@RequestMapping(value="/", method=RequestMethod.GET)
public User getUser(@PathVariable Long id) {
return users.get(id);
}
@ApiOperation(value="更新⽤户详细信息", notes="根据url的id来指定更新对象,并根据传过来的
user信息来更新⽤户详细信息")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "⽤户ID", required = true, dataTy
pe = "Long"),
使⽤Swagger2⾃动构建强⼤的API⽂档
33
公众号:程序员DD
博客:didispace.com
@ApiImplicitParam(name = "user", value = "⽤户详细实体user", required = t
rue, dataType = "User")
})
@RequestMapping(value="/", method=RequestMethod.PUT)
public String putUser(@PathVariable Long id, @RequestBody User user) {
User u = users.get(id);
u.setName(user.getName());
u.setAge(user.getAge());
users.put(id, u);
return "success";
}
@ApiOperation(value="删除⽤户", notes="根据url的id来指定删除对象")
@ApiImplicitParam(name = "id", value = "⽤户ID", required = true, dataType = "Lo
ng")
@RequestMapping(value="/", method=RequestMethod.DELETE)
public String deleteUser(@PathVariable Long id) {
users.remove(id);
return "success";
}
}
扩展XML请求和响应的⽀持
在之前的所有Spring Boot教程中,我们都只提到和⽤到了针对HTML和JSON格式的请求与响应处理。
那么对于XML格式的请求要如何快速的在Controller中包装成对象,以及如何以XML的格式返回⼀个对
象呢?
实现原理:消息转换器(Message Converter)
在扩展上述问题之前,我们先要知道Spring Boot中处理HTTP请求的实现是采⽤的Spring MVC。⽽在
Spring MVC中有⼀个消息转换器这个概念,它主要负责处理各种不同格式的请求数据进⾏处理,并包
转换成对象,以提供更好的编程体验。
在Spring MVC中定义了 HttpMessageConverter 接⼝,抽象了消息转换器对类型的判断、对读写的判
断与操作,具体可⻅如下定义:
public interface HttpMessageConverter {
boolean canRead(Class clazz, @Nullable MediaType mediaType);
boolean canWrite(Class clazz, @Nullable MediaType mediaType);
List getSupportedMediaTypes();
T read(Class clazz, HttpInputMessage inputMessage) throws IOExcept
ion, HttpMessageNotReadableException;
void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessag
e) throws IOException, HttpMessageNotWritableException;
}
众所周知,HTTP请求的Content-Type有各种不同格式定义,如果要⽀持Xml格式的消息转换,就必须
要使⽤对应的转换器。Spring MVC中默认已经有⼀套采⽤Jackson实现的转换
器 MappingJackson2XmlHttpMessageConverter 。
我们只需要引入
创建接收xml请求的接⼝
完成了要转换的对象之后,可以编写⼀个接⼝来接收xml并返回xml,⽐如:
@Controller
public class UserController {
@PostMapping(value = "/user",
consumes = MediaType.APPLICATION_XML_VALUE,
produces = MediaType.APPLICATION_XML_VALUE)
@ResponseBody
public User create(@RequestBody User user) {
user.setName("didispace.com : " + user.getName());
user.setAge(user.getAge() + 100);
return user;
}
}
最后,启动Spring Boot应⽤,通过POSTMAN等请求⼯具,尝试⼀下这个接⼝,可以看到请求Xml,
并且返回了经过处理后的Xml内容。
使⽤Spring Security进⾏安全控制
我们在编写Web应⽤时,经常需要对⻚⾯做⼀些安全控制,⽐如:对于没有访问权限的⽤户需要转到
登录表单⻚⾯。要实现访问控制的⽅法多种多样,可以通过Aop、拦截器实现,也可以通过框架实现
(如:Apache Shiro、Spring Security)。
本⽂将具体介绍在Spring Boot中如何使⽤Spring Security进⾏安全控制。
⾸先,构建⼀个简单的Web⼯程,以⽤于后续添加安全控制,也可以⽤之前Chapter3-1-2做为基础⼯
程。若对如何使⽤Spring Boot构建Web应⽤,可以先阅读《Spring Boot开发Web应⽤》⼀⽂。
Web层实现请求映射
@Controller
public class HelloController {
@RequestMapping("/")
public String index() {
return "index";
}
@RequestMapping("/hello")
public String hello() {
return "hello";
}
}
/ :映射到index.html
/hello :映射到hello.html
实现映射的⻚⾯
src/main/resources/templates/index.html
s:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
使⽤Spring-Security进⾏安全控制
src/main/resources/templates/hello.html
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
可以看到在index.html中提供到 /hello 的链接,显然在这⾥没有任何安全控制,所以点击链接后就可
以直接跳转到hello.html⻚⾯。
整合Spring Security
在这⼀节,我们将对 /hello ⻚⾯进⾏权限控制,必须是授权⽤户才能访问。当没有权限的⽤户访问
后,跳转到登录⻚⾯。
添加依赖
在pom.xml中添加如下配置,引⼊对Spring Security的依赖。
...
...
Spring Security配置
创建Spring Security的配置类 WebSecurityConfig ,具体如下:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
使⽤Spring-Security进⾏安全控制
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
{
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
}
通过 @EnableWebSecurity 注解开启Spring Security的功能
继承 WebSecurityConfigurerAdapter ,并重写它的⽅法来设置⼀些web安全的细节
configure(HttpSecurity http) ⽅法
通过 authorizeRequests() 定义哪些URL需要被保护、哪些不需要被保护。例如以上代码指
定了 / 和 /home 不需要任何认证就可以访问,其他的路径都必须通过身份验证。
通过 formLogin() 定义当需要⽤户登录时候,转到的登录⻚⾯。
configureGlobal(AuthenticationManagerBuilder auth) ⽅法,在内存中创建了⼀个⽤户,该
⽤户的名称为user,密码为password,⽤户⻆⾊为USER。
新增登录请求与⻚⾯
在完成了Spring Security配置之后,我们还缺少登录的相关内容。
HelloController中新增 /login 请求映射⾄ login.html
@Controller
public class HelloController {
// 省略之前的内容...
@RequestMapping("/login")
public String login() {
return "login";
}
使⽤Spring-Security进⾏安全控制
新增登录⻚⾯:src/main/resources/templates/login.html
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
⽤户名或密码错
您已注销成功
密 码 :
div>
可以看到,实现了⼀个简单的通过⽤户名和密码提交到 /login 的登录⽅式。
根据配置,Spring Security提供了⼀个过滤器来拦截请求并验证⽤户身份。如果⽤户身份认证失败,⻚
⾯就重定向到 /login?error ,并且⻚⾯中会展现相应的错误信息。若⽤户想要注销登录,可以通过
访问 /login?logout 请求,在完成注销之后,⻚⾯展现相应的成功消息。
到这⾥,我们启⽤应⽤,并访问 http://localhost:8080/ ,可以正常访问。但是访
问 http://localhost:8080/hello 的时候被重定向到了 http://localhost:8080/login ⻚⾯,因为
没有登录,⽤户没有访问权限,通过输⼊⽤户名user和密码password进⾏登录后,跳转到了Hello
World⻚⾯,再也通过访问 http://localhost:8080/login?logout ,就可以完成注销操作。
为了让整个过程更完成,我们可以修改 hello.html ,让它输出⼀些内容,并提供“注销”的链接。
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
使⽤Spring-Security进⾏安全控制
本⽂通过⼀个最简单的示例完成了对Web应⽤的安全控制,Spring Security提供的功能还远不⽌于
此
Spring Boot⽇志管理
Spring Boot在所有内部⽇志中使⽤Commons Logging,但是默认配置也提供了对常⽤⽇志的⽀持,
如:Java Util Logging,Log4J, Log4J2和Logback。每种Logger都可以通过配置使⽤控制台或者⽂件
输出⽇志内容。
格式化⽇志
默认的⽇志输出如下:
2016-04-13 08:23:50.120 INFO 37397 --- [ main] org.hibernate.Version
: HHH000412: Hibernate Core
输出内容元素具体如下:
时间⽇期 — 精确到毫秒
⽇志级别 — ERROR, WARN, INFO, DEBUG or TRACE
进程ID
分隔符 — --- 标识实际⽇志的开始
线程名 — ⽅括号括起来(可能会截断控制台输出)
Logger名 — 通常使⽤源代码的类名
⽇志内容
控制台输出
在Spring Boot中默认配置了 ERROR 、 WARN 和 INFO 级别的⽇志输出到控制台。
我们可以通过两种⽅式切换⾄ DEBUG 级别:
在运⾏命令后加⼊ --debug 标志,如:$ java -jar myapp.jar --debug
在 application.properties 中配置 debug=true ,该属性置为true的时候,核⼼Logger(包含
嵌⼊式容器、hibernate、spring)会输出更多内容,但是你⾃⼰应⽤的⽇志并不会输出为DEBUG
级别。
多彩输出
如果你的终端⽀持ANSI,设置彩⾊输出会让⽇志更具可读性。通过在 application.properties 中设
置 spring.output.ansi.enabled 参数来⽀持。
NEVER:禁⽤ANSI-colored输出(默认项)
DETECT:会检查终端是否⽀持ANSI,是的话就采⽤彩⾊输出(推荐项)
ALWAYS:总是使⽤ANSI-colored格式输出,若终端不⽀持的时候,会有很多⼲扰信息,不推荐
使⽤
Spring Boot⽇志管理
⽂件输出
Spring Boot默认配置只会输出到控制台,并不会记录到⽂件中,但是我们通常⽣产环境使⽤时都需要
以⽂件⽅式记录。
若要增加⽂件输出,需要在 application.properties 中配置 logging.file 或 logging.path 属
性。
logging.file,设置⽂件,可以是绝对路径,也可以是相对路径。如:logging.file=my.log
logging.path,设置⽬录,会在该⽬录下创建spring.log⽂件,并写⼊⽇志内容,
如:logging.path=/var/log
⽇志⽂件会在10Mb⼤⼩的时候被截断,产⽣新的⽇志⽂件,默认级别为:ERROR、WARN、INFO
级别控制
在Spring Boot中只需要在 application.properties 中进⾏配置完成⽇志记录的级别控制。
配置格式:logging.level.*=LEVEL
logging.level :⽇志级别控制前缀, * 为包名或Logger名
LEVEL :选项TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF
举例:
logging.level.com.didispace=DEBUG :com.didispace 包下所有class以DEBUG级别输出
logging.level.root=WARN :root⽇志以WARN级别输出
⾃定义⽇志配置
由于⽇志服务⼀般都在ApplicationContext创建前就初始化了,它并不是必须通过Spring的配置⽂件控
制。因此通过系统属性和传统的Spring Boot外部配置⽂件依然可以很好的⽀持⽇志控制和管理。
根据不同的⽇志系统,你可以按如下规则组织配置⽂件名,就能被正确加载:
Logback:logback-spring.xml , logback-spring.groovy , logback.xml ,
logback.groovy
Log4j:log4j-spring.properties , log4j-spring.xml , log4j.properties , log4j.xml
Log4j2:log4j2-spring.xml , log4j2.xml
JDK (Java Util Logging):logging.properties
Spring Boot官⽅推荐优先使⽤带有 -spring 的⽂件名作为你的⽇志配置(如使⽤ logback-
spring.xml ,⽽不是 logback.xml )
⾃定义输出格式
在Spring Boot中可以通过在 application.properties 配置如下参数控制输出格式:
Spring Boot⽇志管理
logging.pattern.console:定义输出到控制台的样式(不⽀持JDK Logger)
logging.pattern.file:定义输出到⽂件的样式(不⽀持JDK Logger)
使⽤AOP统⼀处理Web请求⽇志
AOP为Aspect Oriented Programming的缩写,意为:⾯向切⾯编程,通过预编译⽅式和运⾏期动态化
理实现程序功能的统⼀维护的⼀种技术。AOP是Spring框架中的⼀个重要内容,它通过对既有程序定
义⼀个切⼊点,然后在其前后切⼊不同的执⾏内容,⽐如常⻅的有:打开数据库连接/关闭数据库连
接、打开事务/关闭事务、记录⽇志等。基于AOP不会破坏原来程序逻辑,因此它可以很好的对业务逻
辑的各个部分进⾏隔离,从⽽使得业务逻辑各部分之间的耦合度降低,提⾼程序的可重⽤性,同时提
⾼了开发的效率。
切面在其他文章又说道,这一篇不做过多。
Springboot可以配置log4j,mongdb,jdbcTemplete,Spring-data-jpa
多数据源的配置与使⽤,结合mybaits,自定义异步线程池,mq等可以自己私下配置,不懂的读者可以关注我,我会对你一对一辅导。
最后,总结下springboot的优点。
Springboot的优点:
1. 为所有spring开发更快的入门
2. 开箱即用,提供各种默认配置来简化项目配置
3. 内嵌式容器简化web项目
4. 没有冗余代码和xml配置的要求