@@ -1,6 +1,6 @@ | |||||
# Spring Boot Demo | # Spring Boot Demo | ||||
spring boot demo 是一个用来学习 spring boot 的项目,已经集成 actuator(监控)、logback(日志)、JPA(ORM 框架)、mybatis(ORM 框架)、redis-cache(缓存)、swagger(API 接口管理测试)、ureport2(中国式报表)模块,后续会集成activemq,email, freemarker,shiro,websocket,quartz,netty等模块。 | |||||
spring boot demo 是一个用来学习 spring boot 的项目,已经集成 actuator(监控)、admin(可视化监控)、logback(日志)、aopLog(通过 AOP 记录 web 请求日志)、JPA(ORM 框架)、mybatis(ORM 框架)、redis-cache(缓存)、swagger(API 接口管理测试)、ureport2(中国式报表)模块,后续会集成activemq,email, freemarker,shiro,websocket,quartz,netty等模块。 | |||||
依赖的 Spring Boot 版本: | 依赖的 Spring Boot 版本: | ||||
@@ -50,6 +50,7 @@ spring boot demo 是一个用来学习 spring boot 的项目,已经集成 actu | |||||
<module>../spring-boot-demo-actuator</module> | <module>../spring-boot-demo-actuator</module> | ||||
<module>../spring-boot-demo-admin</module> | <module>../spring-boot-demo-admin</module> | ||||
<module>../spring-boot-demo-logback</module> | <module>../spring-boot-demo-logback</module> | ||||
<module>../spring-boot-demo-aoplog</module> | |||||
<module>../spring-boot-demo-orm-jpa</module> | <module>../spring-boot-demo-orm-jpa</module> | ||||
<module>../spring-boot-demo-orm-mybatis</module> | <module>../spring-boot-demo-orm-mybatis</module> | ||||
<module>../spring-boot-demo-cache-redis</module> | <module>../spring-boot-demo-cache-redis</module> | ||||
@@ -146,6 +147,7 @@ spring boot demo 是一个用来学习 spring boot 的项目,已经集成 actu | |||||
| [spring-boot-demo-actuator](./spring-boot-demo-actuator) | spring-boot 集成 spring-boot-starter-actuator 用于监控 spring-boot 的启动和运行状态 | | | [spring-boot-demo-actuator](./spring-boot-demo-actuator) | spring-boot 集成 spring-boot-starter-actuator 用于监控 spring-boot 的启动和运行状态 | | ||||
| [spring-boot-demo-admin](./spring-boot-demo-admin) | spring-boot 集成 spring-boot-admin 来可视化的监控 spring-boot 程序的运行状态,可以与 actuator 互相搭配使用 | | | [spring-boot-demo-admin](./spring-boot-demo-admin) | spring-boot 集成 spring-boot-admin 来可视化的监控 spring-boot 程序的运行状态,可以与 actuator 互相搭配使用 | | ||||
| [spring-boot-demo-logback](./spring-boot-demo-logback) | spring-boot 集成 logback 日志 | | | [spring-boot-demo-logback](./spring-boot-demo-logback) | spring-boot 集成 logback 日志 | | ||||
| [spring-boot-demo-aoplog](./spring-boot-demo-aoplog) | spring-boot 使用 AOP 切面的方式记录 web 请求日志 | | |||||
| [spring-boot-demo-orm-jpa](./spring-boot-demo-orm-jpa) | spring-boot 集成 spring-boot-starter-data-jpa 操作数据库 | | | [spring-boot-demo-orm-jpa](./spring-boot-demo-orm-jpa) | spring-boot 集成 spring-boot-starter-data-jpa 操作数据库 | | ||||
| [spring-boot-demo-orm-mybatis](./spring-boot-demo-orm-mybatis) | spring-boot 集成 [mybatis-spring-boot-starter](https://github.com/mybatis/spring-boot-starter)、[mybatis-spring-boot-starter](https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter) | | | [spring-boot-demo-orm-mybatis](./spring-boot-demo-orm-mybatis) | spring-boot 集成 [mybatis-spring-boot-starter](https://github.com/mybatis/spring-boot-starter)、[mybatis-spring-boot-starter](https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter) | | ||||
| [spring-boot-demo-cache-redis](./spring-boot-demo-cache-redis) | spring-boot 使用 Redis 做缓存 | | | [spring-boot-demo-cache-redis](./spring-boot-demo-cache-redis) | spring-boot 使用 Redis 做缓存 | | ||||
@@ -7,7 +7,7 @@ | |||||
- [x] ~~spring-boot-demo-actuator(对 Spring boot 的端点监控)~~ | - [x] ~~spring-boot-demo-actuator(对 Spring boot 的端点监控)~~ | ||||
- [x] ~~spring-boot-demo-admin(对 Spring boot 可视化管控)~~ | - [x] ~~spring-boot-demo-admin(对 Spring boot 可视化管控)~~ | ||||
- [x] ~~spring-boot-demo-logback(集成 logback 日志)~~ | - [x] ~~spring-boot-demo-logback(集成 logback 日志)~~ | ||||
- [ ] spring-boot-demo-aopLog(使用 AOP 拦截请求日志信息) | |||||
- [ ] spring-boot-demo-aoplog(使用 AOP 拦截请求日志信息) | |||||
- [ ] spring-boot-demo-exceptionHandler(统一异常处理) | - [ ] spring-boot-demo-exceptionHandler(统一异常处理) | ||||
- [ ] spring-boot-demo-orm-jdbcTemplate(操作 SQL 关系型数据库 - JdbcTemplate) | - [ ] spring-boot-demo-orm-jdbcTemplate(操作 SQL 关系型数据库 - JdbcTemplate) | ||||
- [x] ~~spring-boot-demo-orm-jpa(操作 SQL 关系型数据库 - JPA)~~ | - [x] ~~spring-boot-demo-orm-jpa(操作 SQL 关系型数据库 - JPA)~~ | ||||
@@ -0,0 +1,168 @@ | |||||
# spring-boot-demo-aoplog | |||||
依赖[spring-boot-demo-parent](../spring-boot-demo-parent)、`spring-boot-starter-aop` | |||||
### pom.xml | |||||
```xml | |||||
<?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> | |||||
<artifactId>spring-boot-demo-aoplog</artifactId> | |||||
<version>0.0.1-SNAPSHOT</version> | |||||
<packaging>jar</packaging> | |||||
<name>spring-boot-demo-aoplog</name> | |||||
<description>Demo project for Spring Boot</description> | |||||
<parent> | |||||
<groupId>com.xkcoding</groupId> | |||||
<artifactId>spring-boot-demo-parent</artifactId> | |||||
<version>0.0.1-SNAPSHOT</version> | |||||
<relativePath>../spring-boot-demo-parent/pom.xml</relativePath> | |||||
</parent> | |||||
<properties> | |||||
<useragent.version>1.20</useragent.version> | |||||
</properties> | |||||
<dependencies> | |||||
<dependency> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-starter-aop</artifactId> | |||||
</dependency> | |||||
<!--UserAgent工具类--> | |||||
<dependency> | |||||
<groupId>eu.bitwalker</groupId> | |||||
<artifactId>UserAgentUtils</artifactId> | |||||
<version>${useragent.version}</version> | |||||
</dependency> | |||||
</dependencies> | |||||
<build> | |||||
<finalName>spring-boot-demo-aoplog</finalName> | |||||
</build> | |||||
</project> | |||||
``` | |||||
### AopLog.java | |||||
```java | |||||
/** | |||||
* aop 切面记录请求日志 | |||||
* | |||||
* @package: com.xkcoding.springbootdemoaoplog.aspectj | |||||
* @description:aop 切面记录请求日志 | |||||
* @author: yangkai.shen | |||||
* @date: Created in 2017/11/24 上午9:43 | |||||
* @copyright: Copyright (c) 2017 | |||||
* @version: 0.0.1 | |||||
* @modified: yangkai.shen | |||||
*/ | |||||
@Aspect | |||||
@Component | |||||
@Slf4j | |||||
public class AopLog { | |||||
private static final String START_TIME = "start-request"; | |||||
@Pointcut("execution(public * com.xkcoding.springbootdemoaoplog.controller.*Controller.*(..))") | |||||
public void log() { | |||||
} | |||||
@Before("log()") | |||||
public void beforeLog(JoinPoint joinPoint) { | |||||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); | |||||
HttpServletRequest request = attributes.getRequest(); | |||||
log.info("【请求 URL】:{}", request.getRequestURL()); | |||||
log.info("【请求 IP】:{}", request.getRemoteAddr()); | |||||
log.info("【请求类名】:{},【请求方法名】:{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName()); | |||||
Map parameterMap = request.getParameterMap(); | |||||
log.info("【请求参数】:{},", JsonMapper.obj2Str(parameterMap)); | |||||
Long start = System.currentTimeMillis(); | |||||
request.setAttribute(START_TIME, start); | |||||
} | |||||
@Around("log()") | |||||
public Object arroundLog(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { | |||||
Object result = proceedingJoinPoint.proceed(); | |||||
log.info("【返回值】:{}", JsonMapper.obj2Str(result)); | |||||
return result; | |||||
} | |||||
@AfterReturning("log()") | |||||
public void afterReturning(JoinPoint joinPoint) { | |||||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); | |||||
HttpServletRequest request = attributes.getRequest(); | |||||
Long start = (Long) request.getAttribute(START_TIME); | |||||
Long end = System.currentTimeMillis(); | |||||
log.info("【请求耗时】:{}毫秒", end - start); | |||||
String header = request.getHeader("User-Agent"); | |||||
UserAgent userAgent = UserAgent.parseUserAgentString(header); | |||||
log.info("【浏览器类型】:{},【操作系统】:{},【原始User-Agent】:{}", userAgent.getBrowser().toString(), userAgent.getOperatingSystem().toString(), header); | |||||
} | |||||
} | |||||
``` | |||||
### JsonMapper.java | |||||
```java | |||||
/** | |||||
* Json 转化工具类 | |||||
* | |||||
* @package: com.xkcoding.springbootdemoaoplog.util | |||||
* @description:Json 转化工具类 | |||||
* @author: yangkai.shen | |||||
* @date: Created in 2017/11/24 上午9:36 | |||||
* @copyright: Copyright (c) 2017 | |||||
* @version: 0.0.1 | |||||
* @modified: yangkai.shen | |||||
*/ | |||||
@Slf4j | |||||
public class JsonMapper { | |||||
private static ObjectMapper objectMapper = new ObjectMapper(); | |||||
/** | |||||
* 对象转 json 字符串 | |||||
* | |||||
* @param src 元对象 | |||||
* @param <T> 类型 | |||||
* @return json 字符串 | |||||
*/ | |||||
public static <T> String obj2Str(T src) { | |||||
if (src == null) { | |||||
return null; | |||||
} | |||||
try { | |||||
return src instanceof String ? (String) src : objectMapper.writeValueAsString(src); | |||||
} catch (IOException e) { | |||||
log.error("【JSON 转换:对象 --> 字符串】,异常堆栈:{}", e); | |||||
return null; | |||||
} | |||||
} | |||||
/** | |||||
* json 字符串转化为对象 | |||||
* | |||||
* @param src 源 json 字符串 | |||||
* @param typeReference 转化后的类型 | |||||
* @param <T> 类型 | |||||
* @return 返回转化后的对象 | |||||
*/ | |||||
public static <T> T str2Obj(String src, TypeReference<T> typeReference) { | |||||
if (src == null || typeReference == null) { | |||||
return null; | |||||
} | |||||
try { | |||||
return (T) (typeReference.getType().equals(String.class) ? src : objectMapper.readValue(src, typeReference)); | |||||
} catch (Exception e) { | |||||
log.error("【JSON 转换:字符串 --> 对象】,异常堆栈:{}", e); | |||||
return null; | |||||
} | |||||
} | |||||
} | |||||
``` | |||||
@@ -0,0 +1,41 @@ | |||||
<?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> | |||||
<artifactId>spring-boot-demo-aoplog</artifactId> | |||||
<version>0.0.1-SNAPSHOT</version> | |||||
<packaging>jar</packaging> | |||||
<name>spring-boot-demo-aoplog</name> | |||||
<description>Demo project for Spring Boot</description> | |||||
<parent> | |||||
<groupId>com.xkcoding</groupId> | |||||
<artifactId>spring-boot-demo-parent</artifactId> | |||||
<version>0.0.1-SNAPSHOT</version> | |||||
<relativePath>../spring-boot-demo-parent/pom.xml</relativePath> | |||||
</parent> | |||||
<properties> | |||||
<useragent.version>1.20</useragent.version> | |||||
</properties> | |||||
<dependencies> | |||||
<dependency> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-starter-aop</artifactId> | |||||
</dependency> | |||||
<!--UserAgent工具类--> | |||||
<dependency> | |||||
<groupId>eu.bitwalker</groupId> | |||||
<artifactId>UserAgentUtils</artifactId> | |||||
<version>${useragent.version}</version> | |||||
</dependency> | |||||
</dependencies> | |||||
<build> | |||||
<finalName>spring-boot-demo-aoplog</finalName> | |||||
</build> | |||||
</project> |
@@ -0,0 +1,12 @@ | |||||
package com.xkcoding.springbootdemoaoplog; | |||||
import org.springframework.boot.SpringApplication; | |||||
import org.springframework.boot.autoconfigure.SpringBootApplication; | |||||
@SpringBootApplication | |||||
public class SpringBootDemoAoplogApplication { | |||||
public static void main(String[] args) { | |||||
SpringApplication.run(SpringBootDemoAoplogApplication.class, args); | |||||
} | |||||
} |
@@ -0,0 +1,69 @@ | |||||
package com.xkcoding.springbootdemoaoplog.aspectj; | |||||
import com.xkcoding.springbootdemoaoplog.util.JsonMapper; | |||||
import eu.bitwalker.useragentutils.UserAgent; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.aspectj.lang.JoinPoint; | |||||
import org.aspectj.lang.ProceedingJoinPoint; | |||||
import org.aspectj.lang.annotation.*; | |||||
import org.springframework.stereotype.Component; | |||||
import org.springframework.web.context.request.RequestContextHolder; | |||||
import org.springframework.web.context.request.ServletRequestAttributes; | |||||
import javax.servlet.http.HttpServletRequest; | |||||
import java.util.Map; | |||||
/** | |||||
* aop 切面记录请求日志 | |||||
* | |||||
* @package: com.xkcoding.springbootdemoaoplog.aspectj | |||||
* @description:aop 切面记录请求日志 | |||||
* @author: yangkai.shen | |||||
* @date: Created in 2017/11/24 上午9:43 | |||||
* @copyright: Copyright (c) 2017 | |||||
* @version: 0.0.1 | |||||
* @modified: yangkai.shen | |||||
*/ | |||||
@Aspect | |||||
@Component | |||||
@Slf4j | |||||
public class AopLog { | |||||
private static final String START_TIME = "start-request"; | |||||
@Pointcut("execution(public * com.xkcoding.springbootdemoaoplog.controller.*Controller.*(..))") | |||||
public void log() { | |||||
} | |||||
@Before("log()") | |||||
public void beforeLog(JoinPoint joinPoint) { | |||||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); | |||||
HttpServletRequest request = attributes.getRequest(); | |||||
log.info("【请求 URL】:{}", request.getRequestURL()); | |||||
log.info("【请求 IP】:{}", request.getRemoteAddr()); | |||||
log.info("【请求类名】:{},【请求方法名】:{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName()); | |||||
Map parameterMap = request.getParameterMap(); | |||||
log.info("【请求参数】:{},", JsonMapper.obj2Str(parameterMap)); | |||||
Long start = System.currentTimeMillis(); | |||||
request.setAttribute(START_TIME, start); | |||||
} | |||||
@Around("log()") | |||||
public Object arroundLog(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { | |||||
Object result = proceedingJoinPoint.proceed(); | |||||
log.info("【返回值】:{}", JsonMapper.obj2Str(result)); | |||||
return result; | |||||
} | |||||
@AfterReturning("log()") | |||||
public void afterReturning(JoinPoint joinPoint) { | |||||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); | |||||
HttpServletRequest request = attributes.getRequest(); | |||||
Long start = (Long) request.getAttribute(START_TIME); | |||||
Long end = System.currentTimeMillis(); | |||||
log.info("【请求耗时】:{}毫秒", end - start); | |||||
String header = request.getHeader("User-Agent"); | |||||
UserAgent userAgent = UserAgent.parseUserAgentString(header); | |||||
log.info("【浏览器类型】:{},【操作系统】:{},【原始User-Agent】:{}", userAgent.getBrowser().toString(), userAgent.getOperatingSystem().toString(), header); | |||||
} | |||||
} |
@@ -0,0 +1,38 @@ | |||||
package com.xkcoding.springbootdemoaoplog.controller; | |||||
import com.google.common.collect.Maps; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.springframework.web.bind.annotation.GetMapping; | |||||
import org.springframework.web.bind.annotation.RequestParam; | |||||
import org.springframework.web.bind.annotation.RestController; | |||||
import java.util.Map; | |||||
import java.util.concurrent.ConcurrentMap; | |||||
/** | |||||
* IndexController | |||||
* | |||||
* @package: com.xkcoding.springbootdemoaoplog.controller | |||||
* @description:IndexController | |||||
* @author: yangkai.shen | |||||
* @date: Created in 2017/11/24 上午9:36 | |||||
* @copyright: Copyright (c) 2017 | |||||
* @version: 0.0.1 | |||||
* @modified: yangkai.shen | |||||
*/ | |||||
@Slf4j | |||||
@RestController | |||||
public class IndexController { | |||||
@GetMapping({"", ""}) | |||||
public String index() { | |||||
return "index"; | |||||
} | |||||
@GetMapping({"/test"}) | |||||
public Map test(@RequestParam String name) { | |||||
ConcurrentMap<String, Object> ret = Maps.newConcurrentMap(); | |||||
ret.put("name", name); | |||||
return ret; | |||||
} | |||||
} |
@@ -0,0 +1,62 @@ | |||||
package com.xkcoding.springbootdemoaoplog.util; | |||||
import com.fasterxml.jackson.core.type.TypeReference; | |||||
import com.fasterxml.jackson.databind.ObjectMapper; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
import java.io.IOException; | |||||
/** | |||||
* Json 转化工具类 | |||||
* | |||||
* @package: com.xkcoding.springbootdemoaoplog.util | |||||
* @description:Json 转化工具类 | |||||
* @author: yangkai.shen | |||||
* @date: Created in 2017/11/24 上午9:36 | |||||
* @copyright: Copyright (c) 2017 | |||||
* @version: 0.0.1 | |||||
* @modified: yangkai.shen | |||||
*/ | |||||
@Slf4j | |||||
public class JsonMapper { | |||||
private static ObjectMapper objectMapper = new ObjectMapper(); | |||||
/** | |||||
* 对象转 json 字符串 | |||||
* | |||||
* @param src 元对象 | |||||
* @param <T> 类型 | |||||
* @return json 字符串 | |||||
*/ | |||||
public static <T> String obj2Str(T src) { | |||||
if (src == null) { | |||||
return null; | |||||
} | |||||
try { | |||||
return src instanceof String ? (String) src : objectMapper.writeValueAsString(src); | |||||
} catch (IOException e) { | |||||
log.error("【JSON 转换:对象 --> 字符串】,异常堆栈:{}", e); | |||||
return null; | |||||
} | |||||
} | |||||
/** | |||||
* json 字符串转化为对象 | |||||
* | |||||
* @param src 源 json 字符串 | |||||
* @param typeReference 转化后的类型 | |||||
* @param <T> 类型 | |||||
* @return 返回转化后的对象 | |||||
*/ | |||||
public static <T> T str2Obj(String src, TypeReference<T> typeReference) { | |||||
if (src == null || typeReference == null) { | |||||
return null; | |||||
} | |||||
try { | |||||
return (T) (typeReference.getType().equals(String.class) ? src : objectMapper.readValue(src, typeReference)); | |||||
} catch (Exception e) { | |||||
log.error("【JSON 转换:字符串 --> 对象】,异常堆栈:{}", e); | |||||
return null; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,3 @@ | |||||
server: | |||||
port: 8080 | |||||
context-path: /demo |
@@ -0,0 +1,16 @@ | |||||
package com.xkcoding.springbootdemoaoplog; | |||||
import org.junit.Test; | |||||
import org.junit.runner.RunWith; | |||||
import org.springframework.boot.test.context.SpringBootTest; | |||||
import org.springframework.test.context.junit4.SpringRunner; | |||||
@RunWith(SpringRunner.class) | |||||
@SpringBootTest | |||||
public class SpringBootDemoAoplogApplicationTests { | |||||
@Test | |||||
public void contextLoads() { | |||||
} | |||||
} |
@@ -17,6 +17,7 @@ | |||||
<module>../spring-boot-demo-actuator</module> | <module>../spring-boot-demo-actuator</module> | ||||
<module>../spring-boot-demo-admin</module> | <module>../spring-boot-demo-admin</module> | ||||
<module>../spring-boot-demo-logback</module> | <module>../spring-boot-demo-logback</module> | ||||
<module>../spring-boot-demo-aoplog</module> | |||||
<module>../spring-boot-demo-orm-jpa</module> | <module>../spring-boot-demo-orm-jpa</module> | ||||
<module>../spring-boot-demo-orm-mybatis</module> | <module>../spring-boot-demo-orm-mybatis</module> | ||||
<module>../spring-boot-demo-cache-redis</module> | <module>../spring-boot-demo-cache-redis</module> | ||||