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

用過Spring的朋友應(yīng)該多多少少都知道AOP(即面向切面)耀怜,本篇文章我們就來實戰(zhàn)如何使用AOP打印請求日志功能

一茶宵、簡單web項目
1.創(chuàng)建項目

使用 IDEA 工具創(chuàng)建一個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.創(chuàng)建數(shù)據(jù)庫
create database spring_boot_aop;

這里我們先不創(chuàng)建表,因為我們用了spring-data-jpa种蝶,后面我們用它來創(chuàng)建表契耿。

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語句(正式環(huán)境還是不要用)
    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.啟動項目

完成以上幾個步驟之后蛤吓,我們啟動項目來創(chuàng)建對應(yīng)的 user 表宵喂。
啟動項目,如果控制臺能看到如下日志即表明項目沒有問題会傲,表創(chuàng)建成功锅棕!

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 或相似工具淌山,請求接口測試裸燎!
下面是我本地調(diào)試結(jié)果的截圖(圖比較多,請耐心查看)

  • 注冊【成功】


    aop-register.png
  • 注冊【失敗】


    aop-register-repeat.png
  • 登錄【賬號錯誤】


    aop-login-phoneerror.png
  • 登錄【密碼錯誤】


    aop-login-pwderror.png
  • 登錄【成功】


    aop-login-success.png

好泼疑,接口基本上都是沒有問題的德绿!下面就進入我們今天的主題[廢話真多,我還以為要結(jié)束了呢~]:使用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());
        // 參數(shù)
        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))

通過上述步驟个粱,我們已經(jīng)實現(xiàn)了基本功能,好了翻翩,今天就到此位置了都许!

結(jié)束語:
完整代碼已提交至 Github,可結(jié)合本文使用嫂冻!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末胶征,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子桨仿,更是在濱河造成了極大的恐慌睛低,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件服傍,死亡現(xiàn)場離奇詭異暇昂,居然都是意外死亡,警方通過查閱死者的電腦和手機伴嗡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來从铲,“玉大人瘪校,你說我怎么就攤上這事。” “怎么了阱扬?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵泣懊,是天一觀的道長。 經(jīng)常有香客問我麻惶,道長馍刮,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任窃蹋,我火速辦了婚禮卡啰,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘警没。我一直安慰自己匈辱,他們只是感情好,可當我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布杀迹。 她就那樣靜靜地躺著亡脸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪树酪。 梳的紋絲不亂的頭發(fā)上浅碾,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天,我揣著相機與錄音续语,去河邊找鬼垂谢。 笑死,一個胖子當著我的面吹牛绵载,可吹牛的內(nèi)容都是我干的埂陆。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼娃豹,長吁一口氣:“原來是場噩夢啊……” “哼焚虱!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起懂版,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤鹃栽,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后躯畴,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體民鼓,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年蓬抄,在試婚紗的時候發(fā)現(xiàn)自己被綠了丰嘉。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡嚷缭,死狀恐怖饮亏,靈堂內(nèi)的尸體忽然破棺而出耍贾,到底是詐尸還是另有隱情,我是刑警寧澤路幸,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布荐开,位于F島的核電站,受9級特大地震影響简肴,放射性物質(zhì)發(fā)生泄漏晃听。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一砰识、第九天 我趴在偏房一處隱蔽的房頂上張望能扒。 院中可真熱鬧,春花似錦仍翰、人聲如沸赫粥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽越平。三九已至,卻和暖如春灵迫,著一層夾襖步出監(jiān)牢的瞬間秦叛,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工瀑粥, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留挣跋,地道東北人。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓狞换,卻偏偏與公主長得像避咆,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子修噪,可洞房花燭夜當晚...
    茶點故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內(nèi)容