1. 什么是spring boot?
随着使用 Spring 进行开发的个人和企业越来越多,Spring 也慢慢从一个单一简洁的小框架变成一个大而全的开源软件,Spring 的边界不断的进行扩充,到了后来 Spring 几乎可以做任何事情了,市面上主流的开源软件、中间件都有 Spring 对应组件支持,人们在享用 Spring 的这种便利之后,也遇到了一些问题。
Spring 每集成一个开源软件,就需要增加一些基础配置,慢慢的随着人们开发的项目越来越庞大,往往需要集成很多开源软件,因此后期使用 Spirng 开发大型项目需要引入很多配置文件,太多的配置非常难以理解,并容易配置出错,到了后来人们甚至称 Spring 为配置地狱。 Spring 似乎也意识到了这些问题,急需有这么一套软件可以解决这些问题,这个时候微服务的概念也慢慢兴起,快速开发微小独立的应用变得更为急迫,Spring 刚好处在这么一个交叉点上,于 2013 年初开始的 Spring Boot 项目的研发,2014年4月,Spring Boot 1.0.0 发布。
Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是: 用来简化Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。用我的话来理解,就是 Spring Boot 其实不是什么新的框架,它默认配置了很多框架的使用方式。
2. 怎样1分钟构建一个spring boot应用?
(1)intel idea创建new project
(2)选择Spring Initializr
(3)填写项目信息
(4)选择项目默认依赖web
(5)项目创建完成,其中Chapter1Application是spring boot默认启动类,application.properties是默认配置文件,module1包是我新建的示例业务模块
(6)项目创建完成后的pom文件如下。
(7)查看spring-boot-starter-parent的pom文件,发现项目结构是chapter1—->spring-boot-starter-parent—->spring-boot-dependencies,我们在spring-boot-dependencies的pom文件中看到了dependencyManagement标签,dependencyManagement标签一般声明在父POM中,用来声明依赖项的默认版本号,保证所有的子项目都是一个版本号。该依赖不会引入,因此子项目需要显示声明所需要引入的依赖。
(8)我们不直接依赖spring-boot-starter-parent父项目,而是maven import项目spring-boot-dependencies。
(9)我们删掉application.properties文件,新建application.yml文件,使用新式的语法来写配置项。
(10)然后在pom文件中,显式的声明必要的依赖项。
<!-- dependencies标签:声明依赖的jar包 -->
<dependencies>
<!-- DAO相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
<exclusion>
<artifactId>spring-boot-starter-jdbc</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
<exclusion>
<artifactId>mybatis-spring-boot-autoconfigure</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
<exclusion>
<artifactId>mybatis-spring</artifactId>
<groupId>mybatis-spring</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.4</version>
</dependency>
<!-- spring mvc相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- spring test相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- json相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<!-- spring aop相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- redis java api -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 日志相关 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- 一个很好用的通过注解提供getter setter方法的插件 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- end -->
</dependencies>
spring boot提供了一系列类似spring-boot-starter-*的模块化依赖,方便你构建你自己的项目,例如spring-boot-starter-web模块就声明了以下依赖。
(11)项目启动。
(12)接下来我们测试下DAO,这里使用mysql的示例库sakila,它的模型如下所示。
在spring boot2.0中,默认连接池是HikariDataSource,因为在代码实现上很高效,所以速度很优秀。我们先配置下mybatis的mapper路径和分页插件
使用pagehelper进行自动分页。
直接使用spring boot的测试类Chapter1ApplicationTests。
打印信息如下。
(13)接下来我们配置下MVC,我们都知道HttpServletRequest类提供的获取请求参数方法getParameter()返回类型为java.lang.String,对于restful接口的断言不够方便,我们在这里提取HttpServletRequest的参数,封装成JSON形式的参数类,以提供获取参数的快捷接口。 首先添加fastjson的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
定义参数类
/**
* 描述: 入口参数类
*
* @author linfengda
* @create 2018-08-19 22:46
*/
public class RequestParam extends JSONObject {
public List<Long> getArrayLong(String key) {
JSONArray jsonArray = getJSONArray(key);
if (jsonArray==null){
return null;
}
List<Long> ls = new ArrayList<>(jsonArray.size());
for (Object ob:jsonArray) {
if(ob instanceof String){
String v = (String)ob;
if (StringUtils.isNotEmpty(v)){
ls.add(Long.valueOf(v));
}
continue;
} else if (ob instanceof Long){
ls.add((Long)ob);
continue;
} else if (ob instanceof Integer){
Integer ov = (Integer)ob;
ls.add(Long.valueOf(ov.toString()));
continue;
}else{
throw new ParamParesException("参数类型不对");
}
}
return ls;
}
......
使用ThreadLocal维持线程封闭
/**
* 描述: 请求参数上下文
*
* @author linfengda
* @create 2018-08-19 22:46
*/
public class RequestParamContext {
private final static ThreadLocal<RequestParam> REQUEST_PARAM_THREAD_LOCAL = new ThreadLocal();
public static void setParam(RequestParam requestParam){
REQUEST_PARAM_THREAD_LOCAL.set(requestParam);
}
public static RequestParam getParams(){
return REQUEST_PARAM_THREAD_LOCAL.get();
}
public static void remove(){
REQUEST_PARAM_THREAD_LOCAL.remove();
}
}
使用aop拦截请求,拦截请求之后可以做很多事情,这里我们仅仅封装下参数。
package com.linfengda.sb.support.api.aop;
import com.linfengda.sb.support.api.context.RequestParamContext;
import com.linfengda.sb.support.api.entity.RequestParam;
import com.linfengda.sb.support.api.util.HttpServletUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.support.ApplicationObjectSupport;
import org.springframework.stereotype.Component;
/**
* 描述: HTTP请求AOP
*
* @author linfengda
* @create 2018-08-19 23:10
*/
@Aspect
@Component
@Slf4j
public class ApiAspect extends ApplicationObjectSupport {
@Pointcut("execution(public * com.linfengda.sb..api..*(..))")
public void authPoint() {
}
@Around("authPoint()")
public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
RequestParam requestParam = null;
Object result = null;
try {
requestParam = HttpServletUtil.getParams();
RequestParamContext.setParam(requestParam);
Object[] args = proceedingJoinPoint.getArgs();
result = proceedingJoinPoint.proceed(args);
return result;
} finally {
releaseSource();
}
}
/**
* 释放资源
*/
private void releaseSource() {
RequestParamContext.remove();
}
}
统一controller层参数处理
/**
* 描述: 基本control控制类
*
* @author linfengda
* @create 2018-08-19 22:51
*/
public class BaseController {
/** 默认成功的result **/
public static final Result SUCCESS_RESULT = new Result();
/**
* 获取传入参数
* @return
* @throws Exception
*/
protected RequestParam getParams(){
return RequestParamContext.getParams();
}
}
添加restful api,然后直接使用postman测试请求。
/**
* 描述: 测试MVC
*
* @author linfengda
* @create 2018-08-16 10:29
*/
@RestController
public class FilmBizController extends BaseController {
@Resource
private FilmBizService filmBizService;
@PostMapping("/film/queryFilmList")
public Result queryFilmList() throws Exception {
// 从context中获取封装的请求参数
RequestParam params = getParams();
// 使用spring提供的断言
Assert.notNull(params.getInteger("pageNo"), "分页页码必须为数字且不能为空");
Assert.notNull(params.getInteger("pageSize"), "分页大小必须为数字且不能为空");
Page<FilmPlacardInfo> filmPlacardInfoPage = filmBizService.queryFilmPlacardInfo(params);
return new Result(filmPlacardInfoPage);
}
}
返回信息如下。
(14)如果你没有声明HttpMessageConverter,spring boot2.0默认的json格式解析器为MappingJackson2HttpMessageConverter,我们这里不搞骚操作,因为Jackson目前是最快的json处理方式了。
(15)到这里一个准生产spring boot框架已经搭建起来了,快去试试给它添加缓存(redis)或者集群通信机制(zookeeper)吧。
转自:@Massively
「人生在世,留句话给我吧」