SpringBootWeb应用实战
1 介绍
SpringBoot是由Pivotal团队在2013年开始研发、2014年4月发布第一个版本的全新开源的轻量级框架。它基于Spring4.0设计,不仅继承了Spring框架原有的优秀特性,而且还通过简化配置来进一步简化了Spring应用的整个搭建和开发过程。另外SpringBoot通过集成大量的框架使得依赖包的版本冲突,以及引用的不稳定性等问题得到了很好的解决。
SpringBoot所具备的特征有:
(1)可以创建独立的Spring应用程序,并且基于其Maven或Gradle插件,可以创建可执行的JARs和WARs;
(2)内嵌Tomcat或Jetty等Servlet容器;
(3)提供自动配置的“starter”项目对象模型(POMS)以简化Maven配置;
(4)尽可能自动配置Spring容器;
(5)提供准备好的特性,如指标、健康检查和外部化配置;
(6)绝对没有代码生成,不需要XML配置;
SpringBoot和SpringMvc区别:
Spring 是一个“引擎”;
Spring MVC 是基于Spring的一个 MVC 框架 ;
Spring Boot 是基于Spring的条件注册的一套快速开发整合包。
SpringBoot几个常用的注解:
(1)@RestController和@Controller指定一个类,作为控制器的注解 ,并说明其区别
(2)@RequestMapping方法级别的映射注解,这一个用过Spring MVC的小伙伴相信都很熟悉
(3)@EnableAutoConfiguration和@SpringBootApplication是类级别的注解,根据maven依赖的jar来自动猜测完成正确的spring的对应配置,只要引入了spring-boot-starter-web的依赖,默认会自动配置Spring MVC和tomcat容器
(4)@Configuration类级别的注解,一般这个注解,我们用来标识main方法所在的类,完成元数据bean的初始化。
(5)@ComponentScan类级别的注解,自动扫描加载所有的Spring组件包括Bean注入,一般用在main方法所在的类上
(6)@ImportResource类级别注解,当我们必须使用一个xml的配置时,使用@ImportResource和@Configuration来标识这个文件资源的类。
(7)@Autowired注解,一般结合@ComponentScan注解,来自动注入一个Service或Dao级别的Bean
(8)@Component类级别注解,用来标识一个组件,比如我自定了一个filter,则需要此注解标识之后,Spring Boot才会正确识别。
(9)@Transactional事务注解就行,在方法就是方法事务,类上就是类事务。
2 实战
2.1 项目搭建
创建maven工程,引入依赖
<parent> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.0.RELEASE</version>
<relativePath></relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependencies>
在resource下创建application.properties文件
#编码设置server.tomcat.uri-encoding=UTF-8
spring.http.encoding.charset=UTF-8
spring.http.encoding.force=true
spring.http.encoding.enabled=true
spring.messages.encoding=UTF-8
# tomcat config
server.tomcat.accept-count=1000
server.tomcat.max-threads=500
# session超时时间,单位是秒
server.servlet.session.timeout=1800
#当前应用http端口
server.port=8787
#访问地址
#server.servlet.context-path=/spring-boot-web-demo
创建启动类
@SpringBootApplicationpublic class Application {
private static Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
SpringApplication application = new SpringApplication(Application.class);
application.run(args);
logger.info("启动成功");
}
}
创建Controller类
@RestController@RequestMapping("/api/demo")
public class DemoController {
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String hello() {
return "hello world";
}
}
运行Application类,后打开浏览器访问
2.2 配置
2.2.1 本地配置
Spring程序会按优先级从下面这些路径来加载application.yml和application.properties配置文件,同时会先加载application.yml文件再加载application.properties配置文件。
(1)当前目录下的/config目录
(2)当前目录
(3)classpath里的/config目录
(4)classpath 跟目录
因此,要外置配置文件就很简单了,在jar所在目录新建config文件夹,然后放入配置文件,或者直接放在配置文件在jar目录。
同时可以按Profile不同环境读取不同配置,不同环境的配置设置一个配置文件,例如:
- dev环境下的配置配置在application-dev.properties中
- test环境下的配置配置在application-test.properties中
在application.properties中指定使用哪一个文件
spring.profiles.active = dev
2.2.2 自定义配置文件
2.2.3 远程配置
目前比较流行的远程配置有spring官方的spring-clould-config、携程的apollo以及阿里nacos,它们各有千秋。参考链接5,6,7
2.3 Swagger2集成
现如今,前后端分离已经逐渐成为互联网项目一种标准的开发方式,前端与后端交给不同的人员开发,但是项目开发中的沟通成本也随之升高,这部分沟通成本主要在于前端开发人员与后端开发人员对WebAPI接口的沟通,Swagger2 就可以很好地解决,它可以动态生成Api接口文档,降低沟通成本,促进项目高效开发。
pom.xml添加依赖
<dependency> <groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
Swagger配置类
@Configuration@EnableSwagger2
public class SwaggerConfigurer {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select().apis(RequestHandlerSelectors.basePackage("com.linewell.license"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
ApiInfoBuilder builder = new ApiInfoBuilder();
builder.title("spring-boot-demo");
builder.description("spring-boot-demo rest api文档");
builder.version("1.0");
return builder.build();
}
}
在开发中使用相关注解
@Api(tags = {"DEMO相关接口"})@RestController
@RequestMapping("/api/demo")
public class DemoController {
@ApiOperation("HELLO接口")
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String hello() {
return "hello world";
}
}
启动项目,打开浏览器查看接口信息
2.4 Mybatis集成
<dependency> <groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.4</version>
</dependency>
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.1.5</version>
</dependency>
<!--分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.10</version>
</dependency>
application.properties添加数据库相关配置
#数据库相关配置spring.datasource.url=jdbc:mysql://127.0.0.1:3306/demo
spring.datasource.username=root
spring.datasource.password=123456
#最大连接数
spring.datasource.tomcat.max-active=20
#最大空闲数
spring.datasource.tomcat.max-idle=8
#最小空闲数
spring.datasource.tomcat.min-idle=8
#初始化连接数
spring.datasource.tomcat.initial-size=10
#对池中空闲的连接是否进行验证,验证失败则回收此连接
spring.datasource.tomcat.test-while-idle=true
spring.datasource.tomcat.validation-query=SELECT 1
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# mybatis
mybatis.type-aliases-package=com.spring.boot.demo.model
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
如果想要看sql日志则需要在logback中配置相应的mapper日志等级为debug
<logger name="com.spring.boot.demo.mapper" level="DEBUG" />
开启事务
2.5 Security集成
SpringBoot和Security高度集成,这里只介绍初级的用法。
<dependency> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
Security配置
2.6 组件封装
2.6.1 过滤器
方式一:
方式二:
2.6.2 拦截器
2.6.3 事件监听器
方式一:
方式二:
在resource路径下新建META-INF/spring.factories文件,SpringBoot在加载的时候会自动加载该配置文件。
2.6.4 定时器
在Application中新增@EnableScheduling注解
定义任务类
@Componentpublic class CustomTask {
@Scheduled(cron = "0/15 * * * * ? ")
public void taskDemo(){
//任务开始
}
}
2.11 健康检测
SpringBoot自带的监控神器Actuator,集成非常简单,使用起来更是简单到爽歪歪,就是简单地rest接口调用查看,在要求不高的监控环境可以使用。
2.11.1 集成
<dependency> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
在application.properties配置文件新增配置
#监控相关配置#设置监控访问的应用根路径,默认是/actuator
management.endpoints.web.base-path=/actuator
#暴露监控访问接口,默认是/health和/info
management.endpoints.web.exposure.include=*
#显式屏蔽监控访问接口
#management.endpoints.web.exposure.exclude=env,metrics
#开放关闭应用程序端点,不建议开启
management.endpoint.shutdown.enabled=false
#显示健康详情
management.endpoint.health.show-details=always
启动项目,这里要注意一点是,由于一般监控是不需要登录就能够访问的,所以在security的配置中应该将监控相应的url过滤掉。
启动项目,通过浏览器访问监控相应url
2.11.2自定义应用信息
在application.properties添加以下配置
#应用基本信息info.app.name=spring boot demo
info.company.name=www.linewell.com
info.build.artifactId=$project.artifactId$
info.build.version=$project.version$
info.build.time=$project.build.time$
在浏览器中访问
2.11.3自定义检测端点
actuator自带了一些检测端点,如mysql等,但是有时候项目需要自定义一些检测端点,但是又想使用actuator故需要自定义检测端点。
@Componentpublic class CustomHealthIndicator extends AbstractHealthIndicator {
@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
builder.status(Status.UP);
builder.withDetail("message" ,"custom health indicator");
}
}
在浏览器中访问
2.12 单元测试
SpringBoot的单元测试很简单,只需在pom.xml添加以下依赖即可
<dependency> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
2.12.1 Service层测
@RunWith(SpringRunner.class)@SpringBootTest
public class UserServiceTest {
@Autowired
private UserDao userDao;
@Test
public void getUser(){
User user = userDao.getUserByUserName("admin");
System.out.println(user.getUserName());
}
}
2.12.2 Controller层测试
@RunWith(SpringRunner.class)@SpringBootTest
public class MenuControllerTest {
@Autowired
private WebApplicationContext wac;
@Autowired
private UserDao userDao;
private MockMvc mvc;
private MockHttpSession session;
@Before
public void setupMockMvc(){
//初始化MockMvc对象
mvc = MockMvcBuilders.webAppContextSetup(wac).build();
session = new MockHttpSession();
User user = userDao.getUserByUserName("admin");
//拦截器那边会判断用户是否登录,所以这里注入一个用户
session.setAttribute("LOGIN-INFO",user);
}
@Test
public void getMenus() throws Exception{
mvc.perform(MockMvcRequestBuilders.get(AipVersionConstant.API + AipVersionConstant.API_VERSION_01 + "/menu")
.contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
.accept(MediaType.APPLICATION_JSON_UTF8_VALUE)
.session(session))
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print());
}
}
1.mockMvc.perform执行一个请求
2.MockMvcRequestBuilders.get(“/user/1”)构造一个请求,Post请求就用.post方法
3.contentType(MediaType.APPLICATION_JSON_UTF8)代表发送端发送的数据格式是application/json;charset=UTF-8
4.accept(MediaType.APPLICATION_JSON_UTF8)代表客户端希望接受的数据类型为application/json;charset=UTF-8
5.session(session)注入一个session,这样拦截器才可以通过
6.ResultActions.andExpect添加执行完成后的断言
7.ResultActions.andExpect(MockMvcResultMatchers.status().isOk())方法看请求的状态响应码是否为200如果不是则抛异常,测试不通过
8.andExpect(MockMvcResultMatchers.jsonPath(“$.author”).value(“嘟嘟MD独立博客”))这里jsonPath用来获取author字段比对是否为嘟嘟MD独立博客,不是就测试不通过
9.ResultActions.andDo添加一个结果处理器,表示要对结果做点什么事情,比如此处使用MockMvcResultHandlers.print()输出整个响应结果信息
2.13 静态资源
SpringBoot默认的静态文件路径是在resource/static文件夹下,如果想改变静态资源路径可以在application.properties中新增或修改以下配置,多个路径用逗号隔开。
#静态资源路径spring.resources.static-locations= classpath:./static
2.14打包
SpringBoot由于内置了Tomcat或者Jetty所以SpringBoot推荐使用jar包的方式进行打包,但是也支持War包的方式进行打包,看各个项目的自己的需求。
2.14.1 .jar方式打包
jar方式打包一般会配合maven-assembly-plugin进行打包。
<build> <plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.linewell.license.demo.Application</mainClass>
<layout>ZIP</layout>
<includes>
<!--<include>
<groupId>nothing</groupId>
<artifactId>nothing</artifactId>
</include>-->
<include>
<groupId>com.linewell.license.platform</groupId>
<artifactId>license-platform-common-mybatis-mapper</artifactId>
</include>
<include>
<groupId>com.linewell.license.platform</groupId>
<artifactId>license-platform-common-model</artifactId>
</include>
</includes>
</configuration>
</plugin>
<!-- 将jar包和外部配置等文件整体打包(zip,tar,tar.gz等) -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<skipAssembly>${assembly.skip.param}</skipAssembly>
<!--jar包名称 -->
<finalName>${project.artifactId}</finalName>
<descriptors>
<descriptor>package.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<includes>
<include>config/**</include>
<include>mybatis/**</include>
<include>logback-spring.xml</include>
<include>META-INF/spring.factories</include>
<!-- 如果是war打包则可以注释静态资源的包含 -->
<include>static/**</include>
</includes>
</resource>
</resources>
</build>
在跟目录下新建package.xml文件
<?xml version="1.0" encoding="UTF-8"?><assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
<id>package</id>
<formats>
<format>tar.gz</format>
</formats>
<!-- 改为false不会出现两层相同的目录 -->
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<!-- bin文件 -->
<fileSet>
<directory>src/main/bin</directory>
<outputDirectory>./</outputDirectory>
</fileSet>
<!-- 配置文件 -->
<fileSet>
<directory>target/classes/config</directory>
<outputDirectory>./config</outputDirectory>
<includes>
<include>application.yml</include>
</includes>
</fileSet>
<!-- 前端工程文件 -->
<fileSet>
<directory>/target/classes/static</directory>
<outputDirectory>./static</outputDirectory>
</fileSet>
<!-- 把项目自己编译出来的jar文件,打包进zip文件的根目录 -->
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory>${file.separator}</outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<outputDirectory>libs</outputDirectory>
<scope>runtime</scope>
<excludes>
<exclude>com.linewell.license:*</exclude>
<exclude>com.linewell.license.platform:*</exclude>
</excludes>
</dependencySet>
</dependencySets>
</assembly>
2.14.2 .war方式打包
pom.xml中将SpringBoot自带的tomcat依赖去除
<dependency> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- 如果打包成war或者使用jetty应该移除SpringBoot内置的tomcat包 -->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
添加war包插件
<plugin> <artifactId>maven-war-plugin</artifactId>
<configuration>
<!--如果想在没有web.xml文件的情况下构建WAR,请设置为false。-->
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
静态文件
在那个项目新增webapp目录放置静态文件,这样会自动打到war中,这里需要注意一点在WEB-INF下新建web.xml是有效的可以在里面设置过滤或者sessionTime等配置。
3 参考链接
1、https://baike.baidu.com/item/Spring%20Boot/20249767?fr=aladdin
2、https://www.zhihu.com/question/64671972/answer/223383505
3、https://blog.csdn.net/kikock/article/details/81021578
4、https://blog.csdn.net/d124939312/article/details/89711865
5、https://www.jianshu.com/p/2b14544f7773
6、https://www.jianshu.com/p/85d76c878fb0
7、https://nacos.io/zh-cn/docs/what-is-nacos.html
8、https://baijiahao.baidu.com/s?id=1634315317161175683&wfr=spider&for=pc
9、https://www.jianshu.com/p/d59f06724f1b
10、https://www.cnblogs.com/harrychinese/p/springboot_unittesting.html
以上是 SpringBootWeb应用实战 的全部内容, 来源链接: utcz.com/z/513184.html