本人使用的编辑器是idea。周末学习技术框架,根据前人的文章整理了下知识点,写下了这篇纯小白的springboot框架搭建的入门贴。是一篇很琐碎详细的知识点,如果哪里有问题还请指教。大神请绕道或轻喷谢谢。
附加源码: https://github.com/SeriousWatermelon/springboot
1. 创建项目
- new一个Spring Initializer类型的项目,默认的jdk版本,next。
- 填写groupId和ArtifactId的内容。选择打包方式。next。
- 选择web下的web。next。
- 填写项目工程名称。finish。
2.在pom.xml中添加所需依赖
- 引入了mysql-connector-java依赖;
- 使用jpa管理数据库,因此需要引入spring-boot-starter-data-jpa依赖;
- 引入了lombok依赖。可以在实体类使用@Data注解,在项目打包时自动封装get/set/toString()方法,大大减少了实体类中的代码量和冗余度。同时idea需要安装lombok插件。
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.pratice</groupId>
<artifactId>springboot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springboot</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3. 引入SLF4J日志管理
- 使用slf4j的优点:节省内存;使用{}占位符拼接字符串效率高;自动重新加载修改过的配置文件;可以通过过滤器打印各种级别(error,warn,info,debug)的日志;可以自动去除老旧的日志文件等等。
- 配置日志logback-spring.xml
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<!--配置控制台的日志格式输出-->
<appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>
%d-%msg%n
</pattern>
</layout>
</appender>
<!--info级别的文件格式输出-->
<appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--过滤器_只输出Info日志。级别过滤器,匹配level则禁止,否则通过-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>DENY</onMatch>
<onMismatch>ACCEPT</onMismatch>
</filter>
<encoder>
<pattern>
%d-%msg%n
</pattern>
</encoder>
<!--滚动策略——每天生成一个日志文件,因此需要配置时间滚动策略-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--路径-->
<fileNamePattern>e:/log/info_%d.log</fileNamePattern>
</rollingPolicy>
</appender>
<!--error级别的文件格式输出-->
<appender name="fileErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--过滤器只输出error日志-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<encoder>
<pattern>
%d-%msg%n
</pattern>
</encoder>
<!--滚动策略——每天生成一个日志文件,因此需要配置时间滚动策略-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--路径-->
<fileNamePattern>e:/log/error_%d.log</fileNamePattern>
</rollingPolicy>
</appender>
<root level="info">
<appender-ref ref="consoleLog" />
<appender-ref ref="fileInfoLog" />
<appender-ref ref="fileErrorLog" />
</root>
</configuration>
3.使用日志时,在类前引入@SLF4J注解即可。
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class LoggerTest {
@Test
public void test1(){
String name="sun";
String password="0717";
log.error("error...");
log.warn("warn...");
log.info("name:{},password:{}",name,password);
log.debug("debug...");
}
}
4.修改application配置
- 将resources下的application.properties修改成yml格式的,更加方便编辑;
- 配置application.yml的数据源
# 关键字都小写啊
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
username: root
password: root
url: jdbc:mysql://127.0.0.1/test?characterEncoding=utf-8&useSSL=false
jpa:
show-sql: true
5.建库和实体对象
- 建库。一个简单的小栗子~
# @DataBaseName:test
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_name` varchar(20) not null COMMENT '用户名称',
`password` varchar(50) not null comment '用户密码',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP on update current_timestamp comment '修改时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
2. 实体对象的创建
@Table:对应表的名称
@Eneity:作为实体类数据源
@DynamicUpdate:修改时间时可以动态更新
@Data:lombok可以通过该注解封装get/set/toString()方法
import lombok.Data;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import java.util.Date;
@Table(name = "users")
@Entity
@DynamicUpdate
@Data
public class UserCategory {
@Id
@GeneratedValue
private Integer id;
private String userName;
private String password;
private Date createTime;
private Date updateTime;
public UserCategory() { }
}
6. 数据持久层及单元测试
1. 由于本工程使用了jpa进行数据库管理,因此很多数据库操作可以直接调用jpa的方法进行实现。
import com.pratice.dataObject.UserCategory;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface UserCategoryRepository extends JpaRepository<UserCategory,Integer>{
/**
* 根据用户id查找所有用户
* @param userIdList
* @return
*/
List<UserCategory> findByIdIn(List<Integer> userIdList);
}
2. 单元测试类
import com.pratice.dataObject.UserCategory;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.transaction.Transactional;
import java.util.Arrays;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserCategoryRepositoryTest {
@Autowired
private UserCategoryRepository repository;
/**
* @Transactional
* 抛出异常后会回滚。
* 在测试类中,即使没有异常也会在执行完毕后回滚,避免测试数据更改数据库
*/
@Test
@Transactional
public void saveTest(){
UserCategory userCategory=new UserCategory();
userCategory.setUserName("ccc");
userCategory.setPassword("123456");
repository.save(userCategory);
}
@Test
public void deleteOneTest(){
repository.delete(1);
}
@Test
public void deleteAllTest(){
repository.deleteAll();
}
@Test
@Transactional
public void updateTest(){
UserCategory userCategory=repository.findOne(2);
userCategory.setPassword("123456");
UserCategory result=repository.save(userCategory);
Assert.assertNotNull(result);
//Assert.assertNotEquals(null,result);
}
@Test
public void findOneTest(){
UserCategory userCategory=repository.findOne(6);
System.out.println(userCategory.toString());
}
@Test
public void findByIdInTest(){
List<Integer> list= Arrays.asList(2,3);
List<UserCategory> result=repository.findByIdIn(list);
Assert.assertNotEquals(0,result.size());
}
}
7. 业务逻辑层实现
- 业务逻辑层的接口
import com.pratice.dataObject.UserCategory;
import java.util.List;
public interface IUserService {
/**
* 根据id查询用户
* @param id
* @return
*/
UserCategory findOne(Integer id);
/**
* 查询用户列表
* @return
*/
List<UserCategory> findAll();
/**
* 根据用户id的集合,查询用户信息
* @param list
* @return
*/
List<UserCategory> findByIdIn(List<Integer> list);
/**
* 新增用户信息和更新用户信息
* @param userCategory
* @return
*/
UserCategory save(UserCategory userCategory);
}
2. 接口的实现
import com.pratice.dataObject.UserCategory;
import com.pratice.repository.UserCategoryRepository;
import com.pratice.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService implements IUserService {
@Autowired
private UserCategoryRepository repository;
@Override
public UserCategory findOne(Integer id) {
return repository.findOne(id);
}
@Override
public List<UserCategory> findAll() {
return repository.findAll();
}
@Override
public List<UserCategory> findByIdIn(List<Integer> list) {
return repository.findByIdIn(list);
}
@Override
public UserCategory save(UserCategory userCategory) {
return repository.save(userCategory);
}
}
3. 业务逻辑层的单元测试
import com.pratice.dataObject.UserCategory;
import com.pratice.repository.UserCategoryRepository;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Arrays;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTest {
@Autowired
private UserCategoryRepository repository;
@Test
public void findOne() throws Exception {
UserCategory userCategory=repository.findOne(1);
Assert.assertEquals(new Integer(1),userCategory.getId());
}
@Test
public void findAll() throws Exception {
List<UserCategory> list=repository.findAll();
Assert.assertNotEquals(0,list.size());
}
@Test
public void findByIdIn() throws Exception {
List<UserCategory> list=repository.findByIdIn(Arrays.asList(1,2));
Assert.assertNotEquals(0,list.size());
}
@Test
public void save() throws Exception {
UserCategory userCategory=new UserCategory();
userCategory.setUserName("gang");
userCategory.setPassword("123456");
UserCategory result = repository.save(userCategory);
Assert.assertNotNull(result);
}
}
8. 总结
控制层就算了。其他的根据需求进行修改就可以了。
使用SpringBoot框架的优点:
- 去除了大量的xml配置文件;
- 简化复杂的依赖管理;
- 配合各种starter使用,基本上可以做到自动化配置;
- 快速启动容器;
- 配合Maven或Gradle等构件工具打成Jar包后,Java -jar 进行部署运行十分方便;
即SpringBoot框架使代码编写、项目配置和部署、监控变得简单。
缺点:
1. 缺少注册、发现等外围方案;
2. 缺少外围监控集成方案;
3. 缺少外围安全管理方案;
4. 缺少REST落地的URI规划方案。
即SprngBoot框架只是一个入门级的微框架,是微服务框架的起点。