文章目录
- 1:SpringBoot中如何访问静态资源
- 2:SpringBoot全局捕获异常
- 3:SpringBoot集成Freemaker
- 4:Springboot集成JSP
- 5:SpringBoot集成JDBC
- 6:SpringBoot集合mybaties
- 7:SpringBoot整合事务
- 8:SpringBoot整合多数据源
- 9:SpringBoot集成log4j日志管理
- 10:SpringBoot使用aop统一处理web请求日志
- 11:SpringBoot整合EnCache缓存
- 12:SpringBoot创建定时任务
- 13:SpringBoot使用Async实现异步调用
- 14:SpringBoot获取自定义参数
- 15:SpringBoot多环境的区分
- 16:SpringBoot修改端口号
- 17:SpringBoot 打包
- 18:SpringBoot如何打war包
- 19:SpringBoot实现devtools热部署
- 20:SpringBoot基于Mockito测试
- 21:SpringBoot配置RedisTemplate
- 22:SpringBoot之restTemplate的简单使用
- 23: Springboot i18n国际化
- 24 springboot 全局日期格式化配置
1:SpringBoot中如何访问静态资源
在resouces中创建static文件夹图片存在static文件夹下即可,在访问的时候,SpringBoot默认自带static路径
如果想要自定义资源的位置,可以使用如下的方法
@Configuration
public class WebMvcAutoConfiguration implements WebMvcConfigurer{
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//无论访问什么,都会加载这里面的两个东西
registry.addResourceHandler("/**") //针对css 和 js
.addResourceLocations("classpath:/templates/")
.addResourceLocations("classpath:/admin/");
//当访问有类似 redirect:/admin/index.html 下面的时候,自动映射到admin底下的文件
registry.addResourceHandler("/admin/**")
.addResourceLocations("classpath:/admin/");
}
}
2:SpringBoot全局捕获异常
@ExceptionHandler 表示拦截异常
@ControllerAdvice 是 controller 的一个辅助类,最常用的就是作为全局异常处理的切面类
@ControllerAdvice 可以指定扫描范围
@ControllerAdvice 约定了几种可行的返回值,如果是直接返回 model 类的话,需要使用 @ResponseBody 进行 json 转换
返回 String,表示跳到某个 view
返回 modelAndView
返回 model + @ResponseBody
@ControllerAdvice
public class GlobalException {
@ExceptionHandler(RuntimeException.class)
@ResponseBody
public Map<String, Object> exceptionHandler() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("errorCode", "101");
map.put("errorMsg", "系統错误!");
return map;
}
}
3:SpringBoot集成Freemaker
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
创建templates文件夹创建html文件
访问即可
4:Springboot集成JSP
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
创建application.properties文件
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
5:SpringBoot集成JDBC
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.21</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
application.properties新增配置
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
书写配置
6:SpringBoot集合mybaties
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.2.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.21</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
创建数据源连接同上
7:SpringBoot整合事务
在方法上添加@Transactional注解即可
8:SpringBoot整合多数据源
多数据源:在一个项目当中使用多个数据库
解决方案: 按照报名进行化为
比如com.cloudwalk.user1 就操作user1的数据库
com.cloudwalk.user2 就操作user2的数据库
数据源配置文件
spring.datasource.test1.driverClassName = com.mysql.jdbc.Driver
spring.datasource.test1.url = jdbc:mysql://localhost:3306/test01?useUnicode=true&characterEncoding=utf-8
spring.datasource.test1.username = root
spring.datasource.test1.password = root
spring.datasource.test2.driverClassName = com.mysql.jdbc.Driver
spring.datasource.test2.url = jdbc:mysql://localhost:3306/test02?useUnicode=true&characterEncoding=utf-8
spring.datasource.test2.username = root
spring.datasource.test2.password = root
配置文件中新增两个数据源
@Configuration // 注册到springboot容器中
@MapperScan(basePackages = "com.itmayiedu.user1", sqlSessionFactoryRef = "test1SqlSessionFactory")
public class DataSource1Config {
/**
*
* @methodDesc: 功能描述:(配置test1数据库)
* @param: @return
* @createTime:2017年9月17日 下午3:16:44
* @returnType:@return DataSourc
*/
@Bean(name = "test1DataSource")
@Primary
@ConfigurationProperties(prefix = "spring.datasource.test1")
public DataSource testDataSource() {
return DataSourceBuilder.create().build();
}
/**
*
* @methodDesc: 功能描述:(test1 sql会话工厂)
* @param: @param
* dataSource
* @param: @return
* @param: @throws
* Exception
* @createTime:2017年9月17日 下午3:17:08
* @returnType:@param dataSource
* @returnType:@return
* @returnType:@throws Exception SqlSessionFactory
*/
@Bean(name = "test1SqlSessionFactory")
@Primary
public SqlSessionFactory testSqlSessionFactory(@Qualifier("test1DataSource") DataSource dataSource)
throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
// bean.setMapperLocations(
// new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/test1/*.xml"));
return bean.getObject();
}
/**
*
* @methodDesc: 功能描述:(test1 事物管理)
* @param: @param
* dataSource
* @param: @return
* @param: @throws
* Exception
* @createTime:2017年9月17日 下午3:17:08
* @returnType:@param dataSource
* @returnType:@return
* @returnType:@throws Exception SqlSessionFactory
*/
@Bean(name = "test1TransactionManager")
@Primary
public DataSourceTransactionManager testTransactionManager(@Qualifier("test1DataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "test1SqlSessionTemplate")
public SqlSessionTemplate testSqlSessionTemplate(
@Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
9:SpringBoot集成log4j日志管理
新建log4j配置文件
#log4j.rootLogger=CONSOLE,info,error,DEBUG
log4j.rootLogger=info,error,CONSOLE,DEBUG
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n
log4j.logger.info=info
log4j.appender.info=org.apache.log4j.DailyRollingFileAppender
log4j.appender.info.layout=org.apache.log4j.PatternLayout
log4j.appender.info.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n
log4j.appender.info.datePattern='.'yyyy-MM-dd
log4j.appender.info.Threshold = info
log4j.appender.info.append=true
#log4j.appender.info.File=/home/admin/pms-api-services/logs/info/api_services_info
log4j.appender.info.File=/Users/dddd/Documents/testspace/pms-api-services/logs/info/api_services_info
log4j.logger.error=error
log4j.appender.error=org.apache.log4j.DailyRollingFileAppender
log4j.appender.error.layout=org.apache.log4j.PatternLayout
log4j.appender.error.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n
log4j.appender.error.datePattern='.'yyyy-MM-dd
log4j.appender.error.Threshold = error
log4j.appender.error.append=true
#log4j.appender.error.File=/home/admin/pms-api-services/logs/error/api_services_error
log4j.appender.error.File=/Users/dddd/Documents/testspace/pms-api-services/logs/error/api_services_error
log4j.logger.DEBUG=DEBUG
log4j.appender.DEBUG=org.apache.log4j.DailyRollingFileAppender
log4j.appender.DEBUG.layout=org.apache.log4j.PatternLayout
log4j.appender.DEBUG.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n
log4j.appender.DEBUG.datePattern='.'yyyy-MM-dd
log4j.appender.DEBUG.Threshold = DEBUG
log4j.appender.DEBUG.append=true
#log4j.appender.DEBUG.File=/home/admin/pms-api-services/logs/debug/api_services_debug
log4j.appender.DEBUG.File=/Users/dddd/Documents/testspace/pms-api-services/logs/debug/api_services_debug
在代码类中加上 privatestatic Logger log = Logger.getLogger(当前类.class)即可
10:SpringBoot使用aop统一处理web请求日志
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
package com.tvunetworks.useractivity.aspect;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
/**
*
* 版权归属:2020-TUVNETWORKS
* 项目名:news-center
* 类名:LogAspectServiceApi
* 描述:TODO<p>
* 在方法之前之后打印日志,存放在指定的文件
* </p>
* 创建人:Gabrielliu(lk)
* 创建时间:Jan 3, 2020 3:07:21 PM
* 修改人:
* 修改时间:
* 修改备注:
* @version v1.0
*
*/
@Aspect
@Component
@Slf4j
public class LogApiAspect {
// 切点(*:任意返回值、*:表示任意方法名)
@Pointcut("execution(public * com.tvunetworks.useractivity.service.impl.*.*(..))")
private void serviceAspect() {
}
// 前置通知
@Before(value = "serviceAspect()")
public void methodBefore(JoinPoint joinPoint) {
ServletRequestAttributes requestAttributes = null;
HttpServletRequest request = null;
log.info("<<<<<<<<<<<<request api:{} content>>>>>>>>>>>>>>", joinPoint.getSignature().getName());
try {
requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (requestAttributes != null) {
request = requestAttributes.getRequest();
log.info("request address:{}", request.getRequestURL().toString());
log.info("request mode:{}", request.getMethod());
log.info("request method:{}", joinPoint.getSignature().getName());
log.info("request params:{}", joinPoint.getArgs());
}
} catch (Exception e) {
// 异常需要捕获,防止前置通知异常,影响业务代码
log.error("###LogAspectServiceApi.class methodBefore() ### ERROR:{}", e);
}
}
// 在方法执行完结后打印返回内容
@AfterReturning(returning = "retObj", pointcut = "serviceAspect()")
public void methodAfterReturing(JoinPoint joinPoint, Object retObj) {
log.info("====================response api:{} content=====================",
joinPoint.getSignature().getName());
try {
log.info("reponse content:{}", JSONUtil.toJsonStr(retObj));
} catch (Exception e) {
log.info("###LogAspectServiceApi.class methodAfterReturing() ### ERROR:{}", e);
}
}
// 异常通知,记录api中的异常信息(也可在全局异常捕获中处理)
@AfterThrowing(throwing = "ex", pointcut = "serviceAspect()")
public void methodAfterThrowing(JoinPoint joinPoint, Throwable ex) {
log.info("the method {} is exception,the exception message :{}", joinPoint.getSignature().getName(), ex);
}
}
11:SpringBoot整合EnCache缓存
加入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
新建ehcache.xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updateCheck="false">
<diskStore path="java.io.tmpdir/Tmp_EhCache" />
<!-- 默认配置 -->
<defaultCache maxElementsInMemory="5000" eternal="false"
timeToIdleSeconds="120" timeToLiveSeconds="120"
memoryStoreEvictionPolicy="LRU" overflowToDisk="false" />
<cache name="baseCache" maxElementsInMemory="10000"
maxElementsOnDisk="100000" />
</ehcache>
配置信息介绍
1. <!--
2. name:缓存名称。
3. maxElementsInMemory:缓存最大个数。
4. eternal:对象是否永久有效,一但设置了,timeout将不起作用。
5. timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
6. timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
7. overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。
8. diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
9. maxElementsOnDisk:硬盘最大缓存个数。
10. diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
11. diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
12. memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
13. clearOnFlush:内存数量最大时是否清除。
14. -->
使用缓存
@CacheConfig(cacheNames = "baseCache")
public interface UserMapper {
@Select("select * from users where name=#{name}")
@Cacheable
UserEntity findName(@Param("name") String name);
}
删除缓存
@Autowired
private CacheManager cacheManager;
@RequestMapping("/remoKey")
public void remoKey() {
cacheManager.getCache("baseCache").clear();
}
这里引出一个重要的面试重点和难点 : 如何保证缓存和数据库的一致性,让大家思考下
12:SpringBoot创建定时任务
在Spring Boot的主类中加入@EnableScheduling注解,启用定时任务的配置
@Component
public class ScheduledTasks {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
@Scheduled(fixedRate = 5000)
public void reportCurrentTime() {
System.out.println("现在时间:" + dateFormat.format(new Date()));
}
}
13:SpringBoot使用Async实现异步调用
启动加上@EnableAsync ,需要执行异步方法上加入 @Async
相当于继承Thread
14:SpringBoot获取自定义参数
@value($"{}")
15:SpringBoot多环境的区分
spring.profiles.active=pre ## 读取pre开头的配置文件
application-dev.properties:开发环境
application-test.properties:测试环境
application-prod.properties:生产环境
16:SpringBoot修改端口号
server.port=8888
server.context-path=/itmayiedu
17:SpringBoot 打包
使用mvn package 打包
使用java –jar 包名
如果报错没有主清单,在pom文件中新增
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<maimClass>com.itmayiedu.app.App</maimClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
18:SpringBoot如何打war包
<groupId>com.disney</groupId>
<artifactId>demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging> <!--打包方式-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope><!-- 打包加上provided -->
</dependency>
启动类配置文件
package com;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.stereotype.Component;
@Component
public class ServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder
application) {
return application.sources(Application.class);
}
}
tomcat的如何读取外部坏境变量配置信息
第一种方式
把war放入webapp当中
其中类似jvm的在catalia.sh配置参数的设置
我们可以新建在bin目录下面建一个脚本setenv.sh
内容如下
export JAVA_OPTS="-Dswitch.env=dev -Xms256m -Xmx1024m -Xmn128m -XX:+HeapDumpOnOutOfMemoryError"
第二种方式
直接把自己的想注入的变量配置在Idea的Vm Options里面
第三种方式
如果发现有些属性值前两种方式都不适合可以采用第三种方式
配置Pass enviroment variables
19:SpringBoot实现devtools热部署
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
进行属性设置
打开idea的setting-->搜索complier--找到build project autonatically 打上勾
然后搜索 Registry 设置快捷键
然后找到 Compiler autoMake allow when app running 打勾即可
重启Idea 即可
20:SpringBoot基于Mockito测试
需求的出现
**在做项目的时候,领导有一个需求就是当我们的项目给别人的时候,此时的数据库账号密码都是自己的账号信息,当别人拿到项目之后还需要自己去进行重新设置值很繁琐
项目结构
项目依赖
<?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.chhliu.springboot.h2</groupId>
<artifactId>springboot-h2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springboot-h2</name>
<description>Demo project for Spring Boot H2</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.7</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
<!--我这里写成
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.197</version>
<scope>test</scope>
找了一天的BUG,B了狗啦
这个runtime很重要,重点!!!!!!!!-->
</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>
编写实体类
package com.chhliu.springboot.h2.entity;
import java.math.BigDecimal;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column
private String username;
@Column
private String name;
@Column
private Short age;
@Column
private BigDecimal balance;
……省略gettter和setter方法
}
编写数据层
package com.chhliu.springboot.h2.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.chhliu.springboot.h2.entity.User;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}
编写控制层
package com.chhliu.springboot.h2.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import com.chhliu.springboot.h2.entity.User;
import com.chhliu.springboot.h2.repository.UserRepository;
@RestController
public class UserController {
@Autowired
private UserRepository userRepository;
@GetMapping("/user/{id}")// 注意,此处使用的是GetMapping注解,该注解的作用类似与@RequestMapping(value="/user/{id}" ,method=RequestMethod.GET),@PostMapping注解同理
public User findById(@PathVariable Long id) {
return this.userRepository.findOne(id);
}
}
配置文件
# 服务器端口号
server.port=7900
# 是否生成ddl语句
spring.jpa.generate-ddl=false
# 是否打印sql语句
spring.jpa.show-sql=true
# 自动生成ddl,由于指定了具体的ddl,此处设置为none
spring.jpa.hibernate.ddl-auto=none
# 使用H2数据库
spring.datasource.platform=h2
# 指定生成数据库的schema文件位置
spring.datasource.schema=classpath:schema.sql
# 指定插入数据库语句的脚本位置
spring.datasource.data=classpath:data.sql
# 配置日志打印信息
logging.level.root=INFO
logging.level.org.hibernate=INFO
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
logging.level.org.hibernate.type.descriptor.sql.BasicExtractor=TRACE
logging.level.com.itmuch=DEBUG
启动程序
在浏览器中输入如下URL:
http://localhost:7900/user/4
可以看到测试结果
> {"id":4,"username":"user4","name":"马六","age":20,"balance":100.00}
说明,我们的整合是OK的
测试dao层
package com.chhliu.springboot.h2;
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 com.chhliu.springboot.h2.entity.User;
import com.chhliu.springboot.h2.repository.UserRepository;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootH2ApplicationTests {
@Autowired
private UserRepository repository;
@Test
public void test(){
User u = repository.findOne(1L);
Assert.assertEquals("成功的测试用例", "张三", u.getName());
}
}
扩展提高
@MockBean
private SenseTimeService senseTimeService;
@Autowired
private TmsPassStatusService tmsPassStatusService;
//redis的缓存模拟,不然也会报错的
@Before
public void mockRedisConfig() {
doNothing().when(redisBlockingService).addToCache(anyString(), any());
doNothing().when(redisImageService).addToCache(anyString(), any());
doNothing().when(redisBlockingService).deleteCache(anyString());
}
//期望的的异常类型
@Test(expected = FrVasServiceException.class)
public void testQueryPassStatusDataIsNull() {
TmsPassStatusRequest tmsPassStatusRequest = new TmsPassStatusRequest();
SenseTimePassStatusResponse senseTimePassStatusResponse = new SenseTimePassStatusResponse();
MockUtils.setBaseSenseResponse(senseTimePassStatusResponse, null);
ArrayList<PassStatus> passStatusList = Lists.newArrayList();
PassStatus passStatus = new PassStatus();
passStatus.setVisualId(VISUAL_ID);
passStatus.setEnabled(false);
passStatusList.add(passStatus);
doThrow(new
//假设调用他时返回什么结果 SenseTimeBusinessException(QUERY_PASS_FAILURE)).when(senseTimeService).queryPassStatus(any());
// 直接调用真实的
TmsPassStatusResponse tmsPassStatusResponse = tmsPassStatusService.queryPassStatus(tmsPassStatusRequest);
assertTrue(tmsPassStatusResponse.getVisualIds().get(0).isEnabled());
发现测试是ok的!
总结
由于H2是关系内存数据库,当程序启动的时候,会在内存中创建表,并将数据存储在内存中,当重启程序后,会自动删除内存中的数据,从而可以很好的用来做dao层的单元测试和service层的单元测试,使整个程序不会依赖具体的数据库,同时也提高了单元测试的效率。
21:SpringBoot配置RedisTemplate
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.*;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
@Configuration
@ConfigurationProperties(prefix = "spring.cache.redis")
public class RedisConfig {
private Duration timeToLive = Duration.ZERO;
public void setTimeToLive(Duration timeToLive) {
this.timeToLive = timeToLive;
}
private static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
private static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
private static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
// for some convert failed case
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalDateTime.class,
new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)));
javaTimeModule.addSerializer(LocalDate.class,
new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));
javaTimeModule.addSerializer(LocalTime.class,
new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
javaTimeModule.addDeserializer(LocalDateTime.class,
new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)));
javaTimeModule.addDeserializer(LocalDate.class,
new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));
om.registerModule(javaTimeModule);
jackson2JsonRedisSerializer.setObjectMapper(om);
//设置缓存时间为1个小时
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().entryTtl(timeToLive)
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(
RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager.builder(factory).cacheDefaults(config).build();
return cacheManager;
}
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
template.setKeySerializer(keySerializer());
template.setHashKeySerializer(keySerializer());
template.setValueSerializer(valueSerializer());
template.setHashValueSerializer(valueSerializer());
return template;
}
private RedisSerializer<String> keySerializer() {
return new StringRedisSerializer();
}
private RedisSerializer<Object> valueSerializer() {
return new GenericJackson2JsonRedisSerializer();
}
}
SpringBoot版本不同的CacheManager配置的改变
https://www.jianshu.com/p/20366ecf12ce?utm_source=oschina-app
22:SpringBoot之restTemplate的简单使用
首先把RestTemplate注入容器对象
**注入容器**
```java
@Configuration
public class RestConfig {
@Bean
RestTemplate configRestTemplate() {
RestTemplate restTemplate = new RestTemplate();
return restTemplate;
}
}
当进行MULTIPART_FORM_DATA访问时
public CheckResponse CheckPhoto(String imageData) {
CheckResponse CheckResponse = null;
try {
MultiValueMap<String, String> params = new LinkedMultiValueMap();
params.add(IMGAGE, imageData);
HttpEntity<MultiValueMap<String, String>> requestEntity = getHttpEntity(MediaType.MULTIPART_FORM_DATA, params);
ResponseEntity<CheckResponse> responseEntity = restTemplate.exchange(Url + qualityPath, HttpMethod.POST, requestEntity, CheckResponse.class);
CheckResponse = responseEntity.getBody();
return CheckResponse;
}
当进行APPLICATION_JSON访问时
public ImageResponse uploadBasePhoto(ImageRequest ImageRequest) {
ImageResponse ImageResponse = null;
try {
HttpEntity<ImageRequest> request = getHttpEntity(MediaType.APPLICATION_JSON, ImageRequest);
ResponseEntity<ImageResponse> responseEntity = restTemplate.exchange(senseTimeUrl + uploadImage, HttpMethod.POST, request, ImageResponse.class);
ImageResponse = responseEntity.getBody();
return ImageResponse;
}
需要注意的是,当使用APPLICATION_JSON 传入是对象,其他为属性
23: Springboot i18n国际化
package com.tongwei.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.*;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import java.util.List;
import java.util.Locale;
@Configuration
public class LocalConfig {
/**
* 默认解析器 其中locale表示默认语言
*/
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver localeResolver = new SessionLocaleResolver();
localeResolver.setDefaultLocale(Locale.US);
return localeResolver;
}
/**
* 默认拦截器 其中lang表示切换语言的参数名
*/
@Bean
public WebMvcConfigurer localeInterceptor() {
return new WebMvcConfigurer() {
@Override
public void addInterceptors(InterceptorRegistry registry) {
LocaleChangeInterceptor localeInterceptor = new LocaleChangeInterceptor();
//lang 代表切换的语言
localeInterceptor.setParamName("lang");
registry.addInterceptor(localeInterceptor);
}
};
}
}
配置映射路径
@Configuration
public class WebMvcAutoConfiguration implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//无论访问什么,都会加载这里面的两个东西
registry.addResourceHandler("/**") //针对css 和 js
.addResourceLocations("classpath:/templates/")
.addResourceLocations("classpath:/admin/");
//当访问有类似 redirect:/admin/index.html 下面的时候,自动映射到admin底下的文件
registry.addResourceHandler("/admin/**")
.addResourceLocations("classpath:/admin/");
}
}
启动类
@SpringBootApplication
@RestController
public class LocaleI18nApplication {
public static void main(String[] args) {
SpringApplication.run(LocaleI18nApplication.class, args);
}
/**
* 登陆页面
*/
@GetMapping("/log")
public ModelAndView index() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("login.html");
return modelAndView;
}
}
yml文件 (我也不知道啥原因我的thymeleaf无效,我直接用的config配置的)
spring:
thymeleaf:
cache: false #关闭页面缓存
prefix: classpath:/templates/ #页面拼接路径
messages:
basename: static/i18n/messages #相对路径 首部请勿添加斜杠
项目结构