全局捕获异常
- @ExpectionHandler 拦截异常
- @ControllerAdvice 切面
案例
- 定义一个全局异常类
/**
* 用于捕获全局的异常
*/
@ControllerAdvice //控制器切面
public class GlobalExpectionHandler {
@ExceptionHandler(RuntimeException.class) //捕获运行时异常
@ResponseBody //返回json
public Map<String,Object> expectionHandler(){ //处理异常方法
Map<String,Object> map = new HashMap<String,Object>();
map.put("errorCode","101");
map.put("errorMsg","系统错误");
return map;
}
}
- APP中配置扫描包的范围,得包括expection包
@EnableAutoConfiguration
@ComponentScan(basePackages = "com.tang.web")
public class App
{
public static void main(String[] args)
{
//启动Springboot项目
SpringApplication.run(App.class,args);
}
}
- 算数异常捕获结果(int i= 10/0)
{“errorCode”:“101”,“errorMsg”:“系统错误”}
Freemaker使用(相当于jsp)
- pom.xml中导入依赖
<!-- 引入freeMarker的依赖包. -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
- 编写控制器,返回数据
-
这里使用Controller
@RestController用于写API,给移动客户端提供数据,一般是返回json数据 @Contoller一般用于写后台(有页面)
@Controller
@RequestMapping("stu")
public class StudentController {
@RequestMapping("list")
public String list(Model model){
model.addAttribute("username","tang");
model.addAttribute("age",20);
List<Student> stuList = new ArrayList<Student>();
stuList.add(new Student(1001,"zhangsan","男"));
stuList.add(new Student(1002,"lisi","男"));
stuList.add(new Student(1003,"wangwu","男"));
model.addAttribute("stuList",stuList);
return "stu/list"; //找模板页面
}
}
- 创建.ftl模板文件
- 在resources包里创建templates文件夹
<body>
欢迎 ${username}
<#if (age < 17) >-小哥
<#elseif (age > 30) >大叔
<#else> 帅哥/美女
</#if>
登录
<br>
学生列表<br>
<table border="1">
<tr>
<td>ID</td>
<td>名字</td>
<td>性别</td>
</tr>
<#list stuList?sort_by("id")?reverse as stu>
<tr>
<td>${stu.id}</td>
<td>${stu.username}</td>
<td>${stu.gender}</td>
</tr>
</#list>
</table>
</body>
Springboot使用jsp,不常用
- 创建war maven工程
- 导入依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<dependencies>
<!-- SpringBoot 核心组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<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>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
- 在resources文件夹创建application.properties配置文件
spring.mvc.view.prefix=/WEB-INF/view/
spring.mvc.view.suffix=.jsp
server.port=8888
server.context-path=/test1
- 创建Controller
@Controller
@EnableAutoConfiguration
@RequestMapping("teacher")
public class TeacherController {
@RequestMapping("list")
public String list(){
return "teacher/list";
}
public static void main(String[] args) {
SpringApplication.run(TeacherController.class,args);
}
}
5.在WEB-INF文件夹创建view以及其他文件,进行访问
- 路径 http://localhost:8888/test1/teacher/list
- 结果 aaa
Springboot数据库访问
使用jdbc
- 添加依赖
<!--JDBC -->
<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.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
- application.properties新增配置
#数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/edu1
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
- 创建Service
- 创建IUserService接口
public interface IUserService {
public void register(String username,String password);
}
- 创建UserServiceImpl实现类
@Service
public class UserServiceImpl implements IUserService {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void register(String username, String password) {
String sql = "insert t_user (username,password) values (?,?)";
jdbcTemplate.update(sql,username,password);
}
}
- 在UserController中添加注册方法
@Autowired
private IUserService userService;
@RequestMapping("register")
@ResponseBody
public String register(String username,String password){
userService.register(username,password);
return "success";
}
- App启动中@ComponentScan扫描包中添加Service包
@EnableAutoConfiguration
@ComponentScan(basePackages = {"com.tang.web","com.tang.service"})
public class App
{
public static void main( String[] args )
{
//启动Springboot项目
SpringApplication.run(App.class,args);
}
}
SpringBoot整合Mybatis
注解方式
- 导入依赖
<!--Spring boot 父依赖提供了依赖管理,之后申明其他的dependency的时候就不需要version了-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<dependencies>
<!--Spring boot配置web的依赖-->
<!--springweb核心组件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--引入freeMarker的依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!-- mybaties -->
<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>
</dependency>
<!--单元测试-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
- 数据库配置文件application.properties
- 注解形式Mapper
public interface UserMapper {
@Insert("insert t_user (username,password) values (#{username},#{password})")
public int save(@Param("username") String username ,@Param("password") String password);
@Select("select * from t_user where username = #{username}")
public User findByUsername(@Param("username") String username);
}
- Service接口和实现类
- IUserService
public interface IUserService {
public void register(String username,String password);
}
- UserServiceImpl
@Service
public class UserServiceImpl implements IUserService {
@Autowired
private UserMapper userMapper;
@Override
public void register(String username, String password) {
userMapper.save(username, password);
}
}
- Controller
@Autowired
private IUserService userService;
@RequestMapping("register")
@ResponseBody
public String register(String username,String password){
userService.register(username,password);
return "success";
}
xml方式
- 在Mapper包中创建xml形式的Mapper文件
<?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.tang.mapper.UserMapper" >
<insert id="save">
insert into t_user (username,password) values(#{0},#{1})
</insert>
<select id="findByUsername" resultType="com.tang.model.User" parameterType="string">
select * from t_user where username = #{username,jdbcType=VARCHAR}
</select>
</mapper>
- 这里values后面#{}里面必须为0开始的数字
- 如果要不写成0,1的形式,需要在接口方法添加@Param
public int save(@Param("username") String username ,@Param("password") String password);
public User findByUsername(String username);
- #{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换。#{}可以有效防止sql注入。#{}可以接收简单类型值或pojo属性值。如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。
- 表 示 拼 接 s q l 串 , 通 过 {}表示拼接sql串,通过 表示拼接sql串,通过{}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, 可 以 接 收 简 单 类 型 值 或 p o j o 属 性 值 , 如 果 p a r a m e t e r T y p e 传 输 单 个 简 单 类 型 值 , {}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值, 可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,{}括号中只能是value
- 在pom添加resources使得能够扫描到xml文件中的SQL语句
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
- Service中实现findByUsername
public User findByUsername(String username);
@Override
public User findByUsername(String username) {
return userMapper.findByUsername(username);
}
- Controller
@RequestMapping("find")
@ResponseBody
public User find(String username){
return userService.findByUsername(username);
}
- 运行结果
- http://localhost:8080/user/find?username=tang
- {“id”:1,“username”:“tang”,“password”:“1234”}
配置多个数据源
- 一个工程操作两个数据库
- 通过注解来配置数据源,以前在applicationContext.xml中配置数据源
- 配置两个数据库
application.properties
spring.datasource.test1.driverClassName=com.mysql.jdbc.Driver
spring.datasource.test1.url=jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf-8
spring.datasource.test1.username=roota
spring.datasource.test1.password=123456
spring.datasource.test2.driverClassName=com.mysql.jdbc.Driver
spring.datasource.test2.url=jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8
spring.datasource.test2.username=root
spring.datasource.test2.password=123456
- 创建datasource包,写两个数据源配置
DataSource01
@Configuration//注解到springboot容器中
@MapperScan(basePackages="com.gyf.test1.mapper",sqlSessionFactoryRef="test1SqlSessionFactory")
public class DataSource01 {
/**
* @return 返回test1数据库的数据源
*/
@Bean(name="test1DataSource")
@Primary//主数据源
@ConfigurationProperties(prefix="spring.datasource.test1")
public DataSource dateSource(){
return DataSourceBuilder.create().build();
}
/**
* @return 返回test1数据库的会话工厂
*/
@Bean(name = "test1SqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(@Qualifier("test1DataSource") DataSource ds) throws Exception{
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(ds);
return bean.getObject();
}
/**
* @return 返回test1数据库的事务
*/
@Bean(name = "test1TransactionManager")
@Primary
public DataSourceTransactionManager transactionManager(@Qualifier("test1DataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
DataSource02
@Configuration//注解到springboot容器中
@MapperScan(basePackages="com.gyf.test2.mapper",sqlSessionFactoryRef="test2SqlSessionFactory")
public class DataSource02 {
/**
* @return 返回test2数据库的数据源
*/
@Bean(name="test2DataSource")
@ConfigurationProperties(prefix="spring.datasource.test2")
public DataSource dateSource(){
return DataSourceBuilder.create().build();
}
/**
* @return 返回test2数据库的会话工厂
*/
@Bean(name = "test2SqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(@Qualifier("test2DataSource") DataSource ds) throws Exception{
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(ds);
return bean.getObject();
}
/**
* @return 返回test2数据库的事务
*/
@Bean(name = "test2TransactionManager")
public DataSourceTransactionManager transactionManager(@Qualifier("test2DataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
- 只能有一个主数据源
- 分别在test1和test2包中编写service和mapper
- Controller中@Autowired两个Service并在方法中同时调用两个Service层方法
- App中@ComponentScan中添加datasource包进行扫描
多数据源存在的问题
@Service
@Transactional
public class UserServiceImpl{
@Autowired
private UserMapper userMapper;
@Autowired
private CustomerMapper customerMapper;
public void register(String username, String password) {
customerMapper.save(username,"1");
int i = 10/0;
userMapper.save(username,password);
}
}
test1中的service发生错误时无法对test2操作的事务进行回滚
SpringBoot的多事务管理
- 使用spingboot+jta+atomikos分布式事务管理解决上面的问题
- 添加jta事务依赖
<!--jta事务依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jta-atomikos</artifactId>
<version>2.1.5.RELEASE</version>
</dependency>
- 修改application.properties
# Mysql 1
mysql.datasource.test1.url = jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf-8
mysql.datasource.test1.username = root
mysql.datasource.test1.password = 123456
mysql.datasource.test1.minPoolSize = 3
mysql.datasource.test1.maxPoolSize = 25
mysql.datasource.test1.maxLifetime = 20000
mysql.datasource.test1.borrowConnectionTimeout = 30
mysql.datasource.test1.loginTimeout = 30
mysql.datasource.test1.maintenanceInterval = 60
mysql.datasource.test1.maxIdleTime = 60
mysql.datasource.test1.testQuery = select 1
# Mysql 2
mysql.datasource.test2.url =jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8
mysql.datasource.test2.username =root
mysql.datasource.test2.password =123456
mysql.datasource.test2.minPoolSize = 3
mysql.datasource.test2.maxPoolSize = 25
mysql.datasource.test2.maxLifetime = 20000
mysql.datasource.test2.borrowConnectionTimeout = 30
mysql.datasource.test2.loginTimeout = 30
mysql.datasource.test2.maintenanceInterval = 60
mysql.datasource.test2.maxIdleTime = 60
mysql.datasource.test2.testQuery = select 1
- 创建dbconfig包,添加两个配置模型
- 注意:要生成两个类的getter/setter方法
@ConfigurationProperties("mysql.datasource.test1")
public class DBConfig1 {
private String url;
private String username;
private String password;
private int minPoolSize;
private int maxPoolSize;
private int maxLifetime;
private int borrowConnectionTimeout;
private int loginTimeout;
private int maintenanceInterval;
private int maxIdleTime;
private String testQuery;
}
@ConfigurationProperties("mysql.datasource.test2")
public class DBConfig2 {
private String url;
private String username;
private String password;
private int minPoolSize;
private int maxPoolSize;
private int maxLifetime;
private int borrowConnectionTimeout;
private int loginTimeout;
private int maintenanceInterval;
private int maxIdleTime;
private String testQuery;
}
- 重新修改datasource包里DataSource1和DataSource2的代码
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import com.atomikos.jdbc.AtomikosDataSourceBean;
import com.gyf.dbconfig.DBConfig1;
import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource;
@Configuration//注解到springboot容器中
@MapperScan(basePackages="com.gyf.test1.mapper",sqlSessionFactoryRef="test1SqlSessionFactory")
public class DataSource01 {
// 配置数据源
@Primary
@Bean(name = "test1DataSource")
public DataSource testDataSource(DBConfig1 testConfig) throws SQLException {
MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();
mysqlXaDataSource.setUrl(testConfig.getUrl());
mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
mysqlXaDataSource.setPassword(testConfig.getPassword());
mysqlXaDataSource.setUser(testConfig.getUsername());
mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
xaDataSource.setXaDataSource(mysqlXaDataSource);
xaDataSource.setUniqueResourceName("test1DataSource");
xaDataSource.setMinPoolSize(testConfig.getMinPoolSize());
xaDataSource.setMaxPoolSize(testConfig.getMaxPoolSize());
xaDataSource.setMaxLifetime(testConfig.getMaxLifetime());
xaDataSource.setBorrowConnectionTimeout(testConfig.getBorrowConnectionTimeout());
xaDataSource.setLoginTimeout(testConfig.getLoginTimeout());
xaDataSource.setMaintenanceInterval(testConfig.getMaintenanceInterval());
xaDataSource.setMaxIdleTime(testConfig.getMaxIdleTime());
xaDataSource.setTestQuery(testConfig.getTestQuery());
return xaDataSource;
}
@Bean(name = "test1SqlSessionFactory")
public SqlSessionFactory testSqlSessionFactory(@Qualifier("test1DataSource") DataSource dataSource)
throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
return bean.getObject();
}
@Bean(name = "test1SqlSessionTemplate")
public SqlSessionTemplate testSqlSessionTemplate(
@Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
@Configuration//注解到springboot容器中
@MapperScan(basePackages="com.gyf.test2.mapper",sqlSessionFactoryRef="test2SqlSessionFactory")
public class DataSource02 {
/**
* @return 返回test2数据库的数据源
*/
@Bean(name="test2DataSource")
@ConfigurationProperties(prefix="spring.datasource.test2")
public DataSource dateSource(){
return DataSourceBuilder.create().build();
}
/**
* @return 返回test2数据库的会话工厂
*/
@Bean(name = "test2SqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(@Qualifier("test2DataSource") DataSource ds) throws Exception{
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(ds);
return bean.getObject();
}
/**
* @return 返回test2数据库的事务
*/
@Bean(name = "test2TransactionManager")
public DataSourceTransactionManager transactionManager(@Qualifier("test2DataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
/**
* @return 返回test2数据库的会话模版
*/
@Bean(name = "test2SqlSessionTemplate")
public SqlSessionTemplate sqlSessionTemplate(
@Qualifier("test2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
- 在App中追加配置
@EnableAutoConfiguration
@ComponentScan(basePackages = {"com.gyf.datasource","com.gyf.web","com.gyf.test1.service","com.gyf.test2.service"})
@EnableConfigurationProperties(value= {DBConfig1.class, DBConfig2.class})
public class App
{
public static void main( String[] args )
{
//启动springboot项目
SpringApplication.run(App.class,args);
}
}
-
REST Client工具启动方式: Tools->HTTP Client->Test Restful Web Service
IDEA打开文件快捷键:Ctrl+Shift+N
SpringBoot整合Log4j
- 在resources包中创建log4j.properties
log4j.rootLogger=INFO,Console,File
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.Target=System.out
log4j.appender.Console.layout = org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=[%p] [%d{yyyy-MM-dd HH\:mm\:ss}][%c - %L]%m%n
log4j.appender.File = org.apache.log4j.RollingFileAppender
log4j.appender.File.File = D:/test/logs/info/info.log
log4j.appender.File.MaxFileSize = 10MB
log4j.appender.File.Threshold = ALL
log4j.appender.File.layout = org.apache.log4j.PatternLayout
log4j.appender.File.layout.ConversionPattern =[%p] [%d{yyyy-MM-dd HH\:mm\:ss}][%c - %L]%m%n
- pom.xml中进行配置
- 去除springboot的logging,添加log4j,因为自带的logging没效果
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--重新导入log4j-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j</artifactId>
<version>1.3.8.RELEASE</version>
</dependency>
- 在Controller中添加logger,并调用logger.info方法进行信息展示,通过配置文件可以生成目录的log包
@RestController //声明Rest风格的控制器
//@EnableAutoConfiguration //自动配置,相当于写了spring的配置文件
@RequestMapping("user")
public class UserController {
@Autowired
private UserServiceImpl userService;
Logger logger = Logger.getLogger(UserController.class);
@Autowired
private CustomerServiceImpl customerService;
@RequestMapping("register")
@ResponseBody
public String register(String username,String password){
//记录客户端请求参数
logger.info("=====" + "username" + username + " password" + password);
//把数据保存到test1数据库
userService.register(username,password);
//把数据保存到test2数据库
customerService.save(username,"120");
return "success";
}
}
-
结果
打开:D:/test/logs/info/info.log
结果:[INFO] [2019-05-23 13:39:01][com.gyf.web.controller.UserController - 30]=====usernamehu password1234
使用AOP统一处理Web请求日志
- 使用切面拦截所有控制器的方法,统一来记录
- 导入依赖
<!-- Aspectj Weaver切面 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.2</version>
</dependency>
- 创建aspect包,编写切面类
package com.gyf.aspect;
import java.util.Enumeration;
import javax.servlet.http.HttpServletRequest;
import org.apache.log4j.Logger;
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;
@Aspect
@Component
public class WebLogAspect {
private Logger logger = Logger.getLogger(getClass());
@Pointcut("execution(public * com.gyf.web.controller..*.*(..))")
public void webLog() {
}
@Before("webLog()")
public void doBefore(JoinPoint joinPoint) throws Throwable {
// 接收到请求,记录请求内容
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 记录下请求内容
logger.info("---------------request----------------");
logger.info("URL : " + request.getRequestURL().toString());
logger.info("HTTP_METHOD : " + request.getMethod());
logger.info("IP : " + request.getRemoteAddr());
Enumeration<String> enu = request.getParameterNames();
while (enu.hasMoreElements()) {
String name = (String) enu.nextElement();
logger.info("name:" + name + "value" + request.getParameter(name));
}
}
@AfterReturning(returning = "ret", pointcut = "webLog()")
public void doAfterReturning(Object ret) throws Throwable {
logger.info("---------------response----------------");
// 处理完请求,返回内容
logger.info("RESPONSE : " + ret);
}
}
- Controller中将之前log4j的调用方法去掉,使用Aop切面的方式
@RestController //声明Rest风格的控制器
//@EnableAutoConfiguration //自动配置,相当于写了spring的配置文件
@RequestMapping("user")
public class UserController {
@Autowired
private UserServiceImpl userService;
@Autowired
private CustomerServiceImpl customerService;
@RequestMapping("register")
@ResponseBody
public String register(String username,String password){
//把数据保存到test1数据库
userService.register(username,password);
return "success";
}
@RequestMapping("login")
@ResponseBody
public String login(String username,String password){
return "success";
}
}
- 访问
URL:http://localhost:8080/user/login?username=yi&password=123
结果:Success
日志打印
[INFO] [2019-05-23 14:37:49][com.gyf.aspect.WebLogAspect - 31]---------------request----------------
[INFO] [2019-05-23 14:37:49][com.gyf.aspect.WebLogAspect - 32]URL : http://localhost:8080/user/login
[INFO] [2019-05-23 14:37:49][com.gyf.aspect.WebLogAspect - 33]HTTP_METHOD : GET
[INFO] [2019-05-23 14:37:49][com.gyf.aspect.WebLogAspect - 34]IP : 0:0:0:0:0:0:0:1
[INFO] [2019-05-23 14:37:49][com.gyf.aspect.WebLogAspect - 38]name:usernamevalueyi
[INFO] [2019-05-23 14:37:49][com.gyf.aspect.WebLogAspect - 38]name:passwordvalue123
[INFO] [2019-05-23 14:37:49][com.gyf.aspect.WebLogAspect - 43]---------------response----------------
[INFO] [2019-05-23 14:37:49][com.gyf.aspect.WebLogAspect - 45]RESPONSE : success