Spring

基于Spring Boot+JPA,使用AOP打印请求日志功能

2019-08-27  本文已影响0人  bearPotMan

用过Spring的朋友应该多多少少都知道AOP(即面向切面),本篇文章我们就来实战如何使用AOP打印请求日志功能

一、简单web项目
1.创建项目

使用 IDEA 工具创建一个Spring Initializr项目,选择
Web>Spring Web Starter
SQL>Spring Data JPA
SQL>MySQL Driver
Developer Tools>Lombok
这几个组件。

2.基本依赖
<dependencies>
    <!-- web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- mysql --->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <!-- Spring Data JPA -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <!-- 方便部分编码 -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.8</version>
    </dependency>
    <!--test-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>
3.创建数据库
create database spring_boot_aop;

这里我们先不创建表,因为我们用了spring-data-jpa,后面我们用它来创建表。

4.配置文件application.yml
server:
  port: 8080
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/spring_boot_aop?characterEncoding=utf8&useSSL=true&serverTimezone=GMT%2B8
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
  jpa:
    hibernate:
      # update: 没有表就新建,有表则更新
      ddl-auto: update
    # 控制台显示sql语句(正式环境还是不要用)
    show-sql: true
5.实体类
@Data
@Entity
@Table(name = "aop_user")
public class User {
    @Id
    @GeneratedValue
    private Long id;
    private String phone;
    private String password;
    private Date createTime;
    private Date updateTime;
}
6.启动项目

完成以上几个步骤之后,我们启动项目来创建对应的 user 表。
启动项目,如果控制台能看到如下日志即表明项目没有问题,表创建成功!

Hibernate: create table aop_user (id bigint not null, create_time datetime, password varchar(255), phone varchar(255), update_time datetime, primary key (id)) engine=MyISAM
Hibernate: create table hibernate_sequence (next_val bigint) engine=MyISAM
Hibernate: insert into hibernate_sequence values ( 1 )
7.repository
public interface UserRepository extends JpaRepository<User, Long> {
    User findByPhone(String phone);
}
8.service & Impl

UserService

public interface UserService {
    /**
     * 注册
     *
     * @param phone
     * @param password
     * @return
     */
    Result register(String phone, String password);

    /**
     * 登录
     *
     * @param phone
     * @param password
     * @return
     */
    Result login(String phone, String password);
}

UserServiceImpl

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    /**
     * 注册
     *
     * @param phone
     * @param password
     * @return
     */
    @Override
    public Result register(String phone, String password) {
        User byPhone = userRepository.findByPhone(phone);
        if (byPhone != null) {
            return ResultUtil.error(ResultEnum.REGISTER_ERROR);
        }
        User user = new User();
        user.setPhone(phone);
        user.setPassword(getMd5(phone, password));
        userRepository.save(user);
        return ResultUtil.success();
    }

    /**
     * 登录
     *
     * @param phone
     * @param password
     * @return
     */
    @Override
    public Result login(String phone, String password) {
        User user = userRepository.findByPhone(phone);
        if (user == null) {
            return ResultUtil.error(ResultEnum.ACCOUNT_ERROR);
        }
        String md5 = getMd5(phone, password);
        if (!md5.equals(user.getPassword())) {
            return ResultUtil.error(ResultEnum.PASSWORD_ERROR);
        }
        UserVO userVO = new UserVO();
        userVO.setUserId(user.getId());
        userVO.setPhone(user.getPhone());
        return ResultUtil.success(userVO);
    }

    // md5加密
    public String getMd5(String phone, String password) {
        String salt = "^#)$^&$$!~@+(,.';-`";
        byte[] bytes = new StringBuilder(phone).append(password).append(salt).toString().getBytes();
        String md5DigestAsHex = DigestUtils.md5DigestAsHex(bytes);
        return md5DigestAsHex;
    }
}
9.controller
@RestController
public class UserController {

    @Autowired
    private UserService userService;

    /**
     * 注册
     *
     * @param phone
     * @param password
     * @return
     */
    @PostMapping("/register")
    public Result register(String phone, String password) {
        return userService.register(phone, password);
    }

    /**
     * 登录
     *
     * @param phone
     * @param password
     * @return
     */
    @PostMapping("/login")
    public Result login(String phone, String password) {
        return userService.login(phone, password);
    }
}
10.重启项目,检测接口是否可用

使用 Postman 或相似工具,请求接口测试!
下面是我本地调试结果的截图(图比较多,请耐心查看)

好,接口基本上都是没有问题的!下面就进入我们今天的主题[废话真多,我还以为要结束了呢~]:使用AOP打印请求日志!

二、加入AOP

1.切面类
@Component
@Aspect
@Slf4j
public class LogAspect {

    @Pointcut("execution(public * com.bpm.aop.web.*.*(..))")
    public void log(){
    }

    @Before("log()")
    public void doBefore(JoinPoint joinPoint){
        ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // url
        log.info("url={}", request.getRequestURL());
        // method(Get/Post...)
        log.info("method={}", request.getMethod());
        // ip
        log.info("ip={}", request.getRemoteAddr());
        // 类方法
        log.info("class_method={}", joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        // 参数
        log.info("args={}", Arrays.asList(joinPoint.getArgs()));
    }

    @AfterReturning(returning = "resp", pointcut = "log()")
    public void doAfter(Object resp) {
        log.info("response={}", resp);
    }
}
2.重启项目,请求接口,查看日志
2019-08-27 10:22:14.350  INFO 20636 --- [nio-8081-exec-3] com.bpm.aop.aspect.LogAspect             : url=http://localhost:8081/login
2019-08-27 10:22:14.350  INFO 20636 --- [nio-8081-exec-3] com.bpm.aop.aspect.LogAspect             : method=POST
2019-08-27 10:22:14.350  INFO 20636 --- [nio-8081-exec-3] com.bpm.aop.aspect.LogAspect             : ip=0:0:0:0:0:0:0:1
2019-08-27 10:22:14.350  INFO 20636 --- [nio-8081-exec-3] com.bpm.aop.aspect.LogAspect             : class_method=com.bpm.aop.web.UserController.login
2019-08-27 10:22:14.350  INFO 20636 --- [nio-8081-exec-3] com.bpm.aop.aspect.LogAspect             : args=[17694870628, 123456]
Hibernate: select user0_.id as id1_0_, user0_.create_time as create_t2_0_, user0_.password as password3_0_, user0_.phone as phone4_0_, user0_.update_time as update_t5_0_ from aop_user user0_ where user0_.phone=?
2019-08-27 10:22:14.353  INFO 20636 --- [nio-8081-exec-3] com.bpm.aop.aspect.LogAspect             : response=Result(code=0, message=成功, data=User(id=1, phone=17694870628, password=8913dbaa6619b17369f3b85464a883d8, createTime=2019-08-27 10:06:53.0, updateTime=null))

通过上述步骤,我们已经实现了基本功能,好了,今天就到此位置了!

结束语:
完整代码已提交至 Github,可结合本文使用!

上一篇下一篇

猜你喜欢

热点阅读