文章目录

  • 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路径

java收藏功能是怎么实现的 springboot收藏功能_后端


如果想要自定义资源的位置,可以使用如下的方法

@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文件

java收藏功能是怎么实现的 springboot收藏功能_spring boot_02

访问即可

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

java收藏功能是怎么实现的 springboot收藏功能_spring_03

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

书写配置

java收藏功能是怎么实现的 springboot收藏功能_spring_04

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>
创建数据源连接同上

java收藏功能是怎么实现的 springboot收藏功能_java收藏功能是怎么实现的_05


java收藏功能是怎么实现的 springboot收藏功能_后端_06

7:SpringBoot整合事务

在方法上添加@Transactional注解即可

8:SpringBoot整合多数据源

多数据源:在一个项目当中使用多个数据库

   解决方案: 按照报名进行化为  
   比如com.cloudwalk.user1 就操作user1的数据库
          com.cloudwalk.user2 就操作user2的数据库

java收藏功能是怎么实现的 springboot收藏功能_java收藏功能是怎么实现的_07

数据源配置文件
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里面

java收藏功能是怎么实现的 springboot收藏功能_java收藏功能是怎么实现的_08

第三种方式

如果发现有些属性值前两种方式都不适合可以采用第三种方式

配置Pass enviroment variables

java收藏功能是怎么实现的 springboot收藏功能_java收藏功能是怎么实现的_09

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测试

需求的出现

**在做项目的时候,领导有一个需求就是当我们的项目给别人的时候,此时的数据库账号密码都是自己的账号信息,当别人拿到项目之后还需要自己去进行重新设置值很繁琐

项目结构

java收藏功能是怎么实现的 springboot收藏功能_java_10


项目依赖

<?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配置的改变

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 #相对路径 首部请勿添加斜杠

项目结构

java收藏功能是怎么实现的 springboot收藏功能_spring_11

24 springboot 全局日期格式化配置