今回は、Aspectクラスで対象メソッドの引数・戻り値・メソッド名・リクエストURLを取得してみたので、そのサンプルプログラムを共有する。
前提条件
下記記事の実装が完了していること。
IntelliJ IDEA上でGradleを使ってWeb画面のSpring Bootプロジェクトを作成してみたSpring Bootのプロジェクトを新規作成を「IntelliJ IDEA」のメニューから実施しようとしたところ、無料の「Commun...
サンプルプログラムの作成
作成したサンプルプログラムの構成は以下の通り。

なお、上記の赤枠は、前提条件のプログラムから変更したプログラムである。
アスペクトクラスの内容は以下の通りで、endLogメソッド内で、対象メソッドの引数・戻り値・メソッド名・リクエストURLを取得している。
package com.example.demo;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.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.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
@Aspect
@Component
public class DemoInvocation {
//ログ出力のためのクラス
private Logger logger = LogManager.getLogger(DemoInvocation.class);
/**
* Beforeアノテーションにより、指定したメソッドの前に処理を追加する
* Beforeアノテーションの引数には、Pointcut式 execution(戻り値 パッケージ.クラス.メソッド(引数))を
* 指定し、ここではControllerクラスの全メソッドの実行前にログ出力するようにしている
*
* @param jp 横断的な処理を挿入する場所
*/
@Before("execution(public * com.example.demo.*Controller.*(..))")
public void startLog(JoinPoint jp){
//開始ログを出力
String signature = jp.getSignature().toString();
logger.info("開始ログ : " + signature);
}
/**
* AfterReturningアノテーションにより、指定したメソッドが正常終了した場合に、
* 指定したメソッドの後に処理を追加する
* AfterReturningアノテーションの引数には、Pointcut式を指定
*
* @param jp 横断的な処理を挿入する場所
* @param returnValue 指定したメソッドの戻り値
*/
@AfterReturning(value = "execution(public * com.example.demo.*Controller.*(..))"
, returning = "returnValue")
public void endLog(JoinPoint jp, Object returnValue){
//引数を取得しログに出力
logger.info("引数 : " + getArgStr(jp));
//戻り値を取得しログに出力
logger.info("戻り値 : " + returnValue);
//メソッド名を取得しログに出力
String methodName
= ((MethodSignature)jp.getSignature()).getMethod().getName();
logger.info("メソッド名 : " + methodName);
//リクエストURLを取得しログに出力
HttpServletRequest request
= ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getRequest();
logger.info("リクエストURL : " + request.getRequestURL().toString());
//終了ログを出力
String signature = jp.getSignature().toString();
logger.info("終了ログ : " + signature);
logger.info("");
}
/**
* 指定したメソッドの引数の文字列を取得する
*
* @param jp 横断的な処理を挿入する場所
* @return 指定したメソッドの引数
*/
private String getArgStr(JoinPoint jp){
StringBuilder sb = new StringBuilder();
Object[] args = jp.getArgs();
if(args.length > 0){
for(Object arg : args){
sb.append(arg + ", ");
}
sb.delete(sb.length() - 2, sb.length() - 1);
}else{
sb.append("(なし)");
}
return sb.toString();
}
}
また、コントローラクラス・Formクラスの内容は以下の通り。
package com.example.demo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.ModelAndView;
@Controller
@SessionAttributes(types = DemoForm.class)
public class DemoController {
/**
* Formオブジェクトを初期化して返却する
* @return Formオブジェクト
*/
@ModelAttribute("demoForm")
public DemoForm createDemoForm(){
DemoForm demoForm = new DemoForm();
return demoForm;
}
/**
* 初期表示画面に遷移する
* @return 初期表示画面へのパス
*/
@GetMapping("/")
public String index(){
return "index";
}
/**
* 確認画面に遷移する
* @param demoForm demoFormオブジェクト
* @param mav ModelAndViewオブジェクト
* @return ModelAndViewオブジェクト
*/
@PostMapping("/confirm")
public ModelAndView confirm(DemoForm demoForm, ModelAndView mav){
System.out.println("demoForm name : " + demoForm.getName());
mav.setViewName("confirm");
return mav;
}
}package com.example.demo;
import lombok.Data;
@Data
public class DemoForm {
/** 名前 */
private String name;
}さらに、HTMLファイルの内容は以下の通り。
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>入力画面</title>
</head>
<body>
<p>下記必要事項を記載の上、「確認」ボタンを押下してください。</p><br/>
<form method="post" th:action="@{/confirm}" th:object="${demoForm}">
名前: <input type="text" th:value="*{name}" th:field="*{name}" />
<br/><br/>
<input type="submit" value="確認" />
</form>
</body>
</html><!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>確認画面</title>
</head>
<body>
<p>入力内容を確認してください。</p><br/>
<form method="post" th:object="${demoForm}">
<span th:text="'名前: ' + *{name}">ここに名前が表示されます</span>
<br/><br/>
<input type="button" value="戻る" onclick="history.back();" />
</form>
</body>
</html> フリーランスエンジニアのエージェントは就業中でも無料で登録できるITエンジニアには、フリーランスという働き方がある。 フリーランスとは、会社や団体などに所属せず、仕事に応じて自由に契約する人のこ...
その他、build.gradle、application.propertiesの内容は以下の通り。
plugins {
id 'org.springframework.boot' version '2.1.7.RELEASE'
id 'java'
}
apply plugin: 'io.spring.dependency-management'
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
//AOPを利用するための設定
implementation 'org.springframework.boot:spring-boot-starter-aop'
//lombokを利用するための設定
compileOnly 'org.projectlombok:lombok:1.18.10'
annotationProcessor 'org.projectlombok:lombok:1.18.10'
}
server.port = 8084 logging.level.root = INFO logging.level.com.example.demo = DEBUG logging.file = C:/work/logs/demo.log
サンプルプログラムの実行結果
サンプルプログラムの実行結果は、以下の通り。
1) Spring Bootアプリケーションを起動し、「http:// (ホスト名):(ポート番号)」とアクセスすると、以下の画面が表示される

2) このときのログ出力内容は以下の通りで、赤枠の引数・戻り値・メソッド名・リクエストURLが出力されていることが確認できる

3) 画面上で名前を入力し、「確認」ボタンを押下すると、以下のように、確認画面に入力した名前が表示される


4) このときのログ出力内容は以下の通りで、赤枠の引数・戻り値・メソッド名・リクエストURLが出力されていることが確認できる

要点まとめ
- Aspectクラスで、JoinPointクラス等を利用して、対象メソッドの引数・戻り値・メソッド名・リクエストURLを取得することができる。





