IDEA2019版本创建Spring boot项目:搭建纯Java进程服务,去掉web依赖
- 1.前言
- 2.使用Spring Initializer【官方推荐】搭建环境
- 3.修改pom文件,引入框架用到的工具包依赖
- 4.介绍pom文件常用的启动器介绍
- 5.集成mybatis及mybatis-plus
- 6.集成日志框架,简化日志编码
- 7.demo实例编写
- 7.1 编写mapper接口及实现文件
- 7.1.1 首先创建Person.java类:
- 7.1.2 编写PersonMapper.java接口类:
- 7.1.3 在resources目录下创建mapper目录,并在此目录下创建PersonMapper.xml文件,内容如下:
- 7.1.4 创建数据库、表
- 7.2 编写service类
- 8.集成Junit单元测试
- 9.总结
- 10.启动一个线程的实例
- 11.后续
- 12. 附录
1.前言
本文主要介绍基于Springboot搭建和web无关的纯Java进程服务,提供mybatis、日志、单元测试等一系列的集成方法,为初学者提供完整集成方案。
2.使用Spring Initializer【官方推荐】搭建环境
2.1创建项目:按照图中的步骤进行搭建,建议使用IDEA2019版,非常好用并且炫。
File->New->Project,进行新建项目:
选择“Spring Initializer”,java的版本号尽量用1.8版本,Default选项打钩,点击Next
组织名称(一般就是项目的包名前缀,这个根据具体公司自己修改)和工程名填写后,点击Next
这一步比较重要,左边默认选择的是“developer Tools”开发工具,右边的三相,选中前两项,如图所示,图中介绍了两个工具的作用。
如果是web开发,记着再选择左边的“web”,然后在右侧选择Spring web选项即可,这样idea会我们引入默认的web相关启动器配置,不是web开发的人员此处可以忽略
点击FInish完成项目创建,初始创建时,maven需要下载相关依赖,因此较慢,请耐心等待。
2.2默认目录介绍
pom默认文件部分代码: 在本周最后附上全部文件代码
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
从默认生成的pom文件我们可以看出:为我们默认生成了spring-boot-starter、spring-boot-devtools、lombok、spring-boot-starter-test这四个启动器及插件
注:测试代码一定要放在测试目录,养成良好的习惯。
3.修改pom文件,引入框架用到的工具包依赖
常用的工具类引入
guava:这个工具包非常的强大,必须用。
fastjson:阿里巴巴的json处理工具,非常快速,也必须用。
在pom文件中增加如下代码
<!--集成工具库 start-->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!--集成工具库 end-->
4.介绍pom文件常用的启动器介绍
这一章节,在我另一篇文章有详细介绍,请查阅。https://blog.csdn.net/houpeibin2012/article/details/104309150
5.集成mybatis及mybatis-plus
用到mybatis必然要用到他的增加软件mybatis-plus,这一章节详细介绍Springboot怎么集成这两种框架。
5.1 pom文件增加对mybatis及mybatis-plus的集成
<!--集成mybatis start-->
<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>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!-- druid 数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<!-- mybatis plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.0</version>
</dependency>
<!--集成mybatis end-->
从配置文件可以看出,我们使用了druid 数据库连接池,这是阿里巴巴提供的,内置web监控界面,可以监控数据库访问情况及语句执行信息。
5.2 配置文件增加mybatis及mybatis-plus相关参数配置
spring:
datasource:
username: root
password: root
url: jdbc:mysql://localhost:3306/springboot?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
driver-class-name: com.mysql.jdbc.Driver
mybatis:
mapper-locations: classpath:mapping/*Mapper.xml
type-aliases-package: com.ieslab.powergrid.entity
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
global-config:
# 关闭MP3.0自带的banner
banner: false
db-config:
# 默认数据库表下划线命名
table-underline: true
配置文件中的用户名和密码、数据库名等需要根据实际情况而设置;
5.3 增加分页插件配置类
新建MybatisPlusConfig.java类
package com.ieslab.powergrid.demosvr.config;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
//实现分页插件
@EnableTransactionManagement(proxyTargetClass = true)
@Configuration
@MapperScan("mapper")
public class MybatisPlusConfig {
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
这个类主要就是让分页插件功能生效。
这样mybatis和mybatis-plus就集成完毕了,后续会编写代码进行测试
6.集成日志框架,简化日志编码
6.1 pom文件增加日志相关依赖
<!-- set/get方法免写,需要安装idea的插件 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
6.2 使用注解进行日志使用
在测试目录创建测试类DemosvrApplicationTests.java,代码如下:
package com.ieslab.powergrid.demosvr;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
@Slf4j
class DemosvrApplicationTests {
@Test
void contextLoads() {
log.info("contextLoads is running");
}
}
代码中在类是前面添加:@Slf4j 注解后,就可以在本类中直接用log.info 进行打印日志。
7.demo实例编写
7.1 编写mapper接口及实现文件
7.1.1 首先创建Person.java类:
package com.ieslab.powergrid.demosvr.entity;
import lombok.Data;
import org.springframework.stereotype.Component;
@Data
public class Person {
int id;
String lastName;
String firstName;
String address ;
String city;
public Person() {
}
public Person(String lastName, String firstName, String address, String city) {
this.lastName = lastName;
this.firstName = firstName;
this.address = address;
this.city = city;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", lastName='" + lastName + '\'' +
", firstName='" + firstName + '\'' +
", address='" + address + '\'' +
", city='" + city + '\'' +
'}';
}
}
7.1.2 编写PersonMapper.java接口类:
package com.ieslab.powergrid.demosvr.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ieslab.powergrid.demosvr.entity.Person;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Map;
@Mapper
public interface PersonMapper extends BaseMapper<Person> {
//根据过滤条件获取用户
List<Person> getPersonByFilter(Map<String, String> param);
}
7.1.3 在resources目录下创建mapper目录,并在此目录下创建PersonMapper.xml文件,内容如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ieslab.powergrid.demosvr.mapper.PersonMapper">
<select id="getPersonByFilter" resultType="com.ieslab.powergrid.demosvr.entity.Person">
select * from person
<where>
<if test="id != null">
id=#{id}
</if>
<if test="name != null and name != ''">
and last_name like CONCAT('%','${name}','%' )
</if>
</where>
</select>
</mapper>
关于mapper文件的写法,有几个重点需要注意:
- namespace=“com.ieslab.powergrid.demosvr.mapper.PersonMapper” 这是一定要写对应的接口类
- resultType=“com.ieslab.powergrid.demosvr.entity.Person” 这是返回的数据类型,一定要正确,还有别的写法,可以查阅相关资料学习。
- 对于sql语句,尽量要用标签的方法编写,比如: 标签,ognl的写法一定不能缺少。
7.1.4 创建数据库、表
mysql数据库的安装,请查阅:https://blog.csdn.net/houpeibin2012/article/details/104224168
创建数据库:springboot
创建person表,建表语句如下:
建表语句:
CREATE TABLE Person
(
id int,
Last_Name varchar(255),
First_Name varchar(255),
Address varchar(255),
City varchar(255)
)
注意:表字段和person类的变量要对应,java实体类中采取驼峰方式进行命名时,数据要用下划线方式进行分开,比如:java类中lastName 变量对应数据库表中last_name的名称。
这样数据库表、数据库层的代码已经编写完毕。
7.2 编写service类
编写业务层代码,创建PersonService.java类:
package com.ieslab.powergrid.demosvr.service;
import com.ieslab.powergrid.demosvr.entity.Person;
import com.ieslab.powergrid.demosvr.mapper.PersonMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/** <p>Title: PersonService </p>
* <p>Description: 用户业务类,测试demo使用</p>
*
* @author houpeibin
* @date 2020-2-20 下午7:15:30
* @version V1.0
*/
@Service
public class PersonService {
@Autowired
PersonMapper personMapper;
/**
* 获取所有用户
* @return
*/
public List<Person> getPersons(){
return personMapper.selectList(null);
}
/**
* 插入用户
* @param person 用户信息类
* @return 插入几条数据
*/
public int insertPersons(Person person){
return personMapper.insert(person);
}
}
8.集成Junit单元测试
8.1 编写测试代码
在PersonService.java类上点击右键,选择Generate,再选择Test…
弹出框中的测试类,一般不用改名,他就是service类加了后缀Test,方便找。
开发这个测试类,编写如下代码:
package com.ieslab.powergrid.demosvr.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ieslab.powergrid.demosvr.entity.Person;
import com.ieslab.powergrid.demosvr.mapper.PersonMapper;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** <p>Title: PersonServiceTest </p>
* <p>Description: PersonService测试类</p>
*
* @author houpeibin
* @date 2020-2-20 下午7:15:30
* @version V1.0
*/
@SpringBootTest
@Slf4j
class PersonServiceTest {
@Autowired
PersonService personService;
@Autowired
PersonMapper personMapper;
/**
* 插入用户
*/
@Test
void insertPersons(){
for (int i=0;i<10;++i){
Person person = new Person();
person.setId(i);
person.setFirstName("zhang");
person.setLastName(""+i);
person.setCity("jinan");
person.setAddress("huayang");
log.info("insert person:" + personService.insertPersons(person));
}
}
/**
* 根据id获取用户
*/
@Test
void getPersonsById(){
Map<String, String> mapParam = new HashMap<>();
mapParam.put("id","1");
List<Person> persons = personMapper.getPersonByFilter(mapParam);
log.info(persons.toString());
}
/**
* 根据名称模糊查询
*/
@Test
void getPersonsByName(){
Map<String, String> mapParam = new HashMap<>();
mapParam.put("name","3");
List<Person> persons = personMapper.getPersonByFilter(mapParam);
log.info(persons.toString());
}
/**
* 分页查询测试
*/
@Test
void getPersonsPage(){
IPage<Person> page = new Page<Person>(0,5);
IPage<Map<String, Object>> pageData = personMapper.selectMapsPage(page,null);
List list = pageData.getRecords();
for (Object obj:list){
System.out.println(obj.toString());
}
}
}
上面写了四个测试方法,一个是插入10条数据,一个是按照id查询,一个是按照name模糊查询,最后一个是分页查询,下面我们来运行测试用例。
8.2 使用单元测试进行测试
查看执行结果:
用类似的方法,去执行其他方法进行测试。
怎么样,这样测试是不是很方便,Springboot集成mybatis也就成功了,简单吧,后续你只要好好学习sql的写法就可以了。
如果测试出现问题,请查看这篇文章
https://blog.csdn.net/houpeibin2012/article/details/104382360
9.总结
本文由于是去掉tomcat的纯java进程,因此,主类启动一次之后就会退掉,因此需要在主类上添加如下代码:
package com.ieslab.powergrid.demosvr;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemosvrApplication {
public static void main(String[] args) {
SpringApplication.run(DemosvrApplication.class, args);
//保持进程不退出
DemosvrApplication DemosvrApplication = new DemosvrApplication();
synchronized (DemosvrApplication) {
try {
DemosvrApplication.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
这样运行此程序就不会退出了。
10.启动一个线程的实例
因为此程序不是web程序,因此没有针对前端的API层。但是线程和定时任务必不可少,不然,此程序还能干什么呢?下面介绍一下线程池的配置及如何在springboot启动之后去运行程序。
10.1 配置线程池
package com.ieslab.powergrid.demosvr.thread;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
/** <p>Title: PersonService </p>
* <p>Description: 线程池配置</p>
*
* @author houpeibin
* @date 2020-2-20 下午7:15:30
* @version V1.0
*/
@Configuration
@EnableAsync // 启用异步任务
public class AsyncConfiguration {
// 声明一个线程池(并指定线程池的名字)
@Bean("taskExecutor")
public Executor asyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//核心线程数5:线程池创建时候初始化的线程数
executor.setCorePoolSize(5);
//最大线程数5:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
executor.setMaxPoolSize(5);
//缓冲队列500:用来缓冲执行任务的队列
executor.setQueueCapacity(500);
//允许线程的空闲时间60秒:当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
executor.setKeepAliveSeconds(60);
//线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池
executor.setThreadNamePrefix("DailyAsync-");
executor.initialize();
return executor;
}
}
10.2 编写线程类
package com.ieslab.powergrid.demosvr.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ieslab.powergrid.demosvr.entity.Person;
import com.ieslab.powergrid.demosvr.mapper.PersonMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
@Service
@Slf4j
public class ThreadServiceDemo {
@Autowired
private PersonMapper personMapper;
public static boolean runFlag = false;
// 这里进行标注为异步任务,在执行此方法的时候,会单独开启线程来执行(并指定线程池的名字)
@Async("taskExecutor")
public void findPersonTest() throws InterruptedException {
while (runFlag){
log.info("访问数据库开始");
IPage<Person> page = new Page<Person>(0,5);
IPage<Map<String, Object>> pageData = personMapper.selectMapsPage(page,null);
List list = pageData.getRecords();
for (Object obj:list){
log.info(obj.toString());
}
log.info("访问数据库结束");
//线程等待,在接收数据时,经常使用,此处我们就直接访问数据进行测试
try {
Thread.sleep(5*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
注意文中的注释:// 这里进行标注为异步任务,在执行此方法的时候,会单独开启线程来执行(并指定线程池的名字)。说明运行此方法时,会启动一个程序进行运行。
10.3 在springboot启动之后启动线程
package com.ieslab.powergrid.demosvr.thread;
import com.ieslab.powergrid.demosvr.service.ThreadServiceDemo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class ApplicationRunnerImpl implements ApplicationRunner {
@Autowired
ThreadServiceDemo threadServiceDemo;
@Override
public void run(ApplicationArguments args) throws Exception {
log.info("通过实现ApplicationRunner接口,在spring boot项目启动后打印参数");
//可以在这里启动你的业务线程
if(!ThreadServiceDemo.runFlag){
ThreadServiceDemo.runFlag = true;
threadServiceDemo.findPersonTest();
}
}
}
在此类,调用刚刚定义的多线程方法即可,实现多线程调用,此处我们用一个标志位来控制,本线程只启动一次,并且会循环执行。此种场景比较适用于循环接收数据的情景。
这样线程集成就已经完成了,可以运行主类进行测试一下。
11.后续
到此,一个简单的基于Springboot的java后台开发框架就搭建完毕了,是不是很简单。
入门简单,精通难,后续开发你还会遇到如下问题,比如:
- 集成多线程
- 集成定时任务
- 集成kafka
- 集成mongodb
- 集成dubbo
等等等等的知识点,后续会有专门的文章进行描述。
12. 附录
pom文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.ieslab.powergrid</groupId>
<artifactId>demosvr</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demosvr</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<mybatisplus.version>3.1.0</mybatisplus.version>
<druid.version>1.1.13</druid.version>
<mybatis.version>2.1.1</mybatis.version>
<fastjson.version>1.2.47</fastjson.version>
<guava.version>28.2-jre</guava.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>-->
<!--集成mybatis start-->
<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>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.version}</version>
</dependency>
<!-- druid 数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- mybatis plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatisplus.version}</version>
</dependency>
<!--集成mybatis end-->
<!--集成工具库 start-->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!--集成工具库 end-->
<!-- 热部署时使用 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- set/get方法免写,需要安装idea的插件 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--单元测试-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>