1.项目中增加aop实现,记录针对controller的入参,出参,ip信息等
表中存了这些信息:
@Entity
@Table(name = "t_aaa")
class LogRecord(@Id @GeneratedValue(strategy = GenerationType.TABLE) var id: Long? = null) : BaseModel() {
var reqUri: String? = null
// 请求类型
var reqMethod: String? = null
// 调用类型
var classMethod: String? = null
// 请求地址
var ipAddr: String? = null
// 入参
@Lob
var inParams: String? = null
// 出参
@Lob
var outParams: String? = null
// 请求时间
var elapsedTime: Long? = null
// 状态 0 成功 -1 失败
var status: Int? = null
// 失败原因
@Lob
var errMsg: String? = null
// 日志描述
var description: String? = null
constructor(classMethod: String, reqURI: String, reqMethod: String, ipAddr: String) : this() {
this.classMethod = classMethod
this.reqUri = reqURI
this.reqMethod = reqMethod
this.ipAddr = ipAddr
}
}
日志是这样的:
也就是针对controller类的入参出参和异常做记录。
2.实现
增加依赖
compile('org.springframework.boot:spring-boot-starter-aop')
增加aop类
package 略
import com.alibaba.fastjson.JSONObject
import org.aspectj.lang.JoinPoint
import org.aspectj.lang.annotation.*
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import org.springframework.web.context.request.RequestContextHolder
import org.springframework.web.context.request.ServletRequestAttributes
import 略
@Aspect //基于注解的实现
@Service
class WebAopService {
@Autowired
private lateinit var logRecordRepo: LogRecordRepository
val logger = LoggerFactory.getLogger(WebAopService::class.java)
private val logThread = ThreadLocal<LogRecord>()
@Pointcut("execution(public * org.aaa.server.controller..*.*(..))") //定义切点,在该位置织入通知
fun webLog() {
}
@Before("webLog()") //方法执行前
fun doBefore(joinPoint: JoinPoint) = beforeAction(joinPoint, "webLog")
private fun beforeAction(joinPoint: JoinPoint, aopType: String) {
val attributes = RequestContextHolder.currentRequestAttributes() as ServletRequestAttributes
val request = attributes.request
// 记录内容
val classMethod = "${joinPoint.target.javaClass.name}.${joinPoint.signature.name}()"
val uri = request.requestURI
val reqMethod = request.method
val ip = GlobalConfig.api.getRemoteIp(request)
val ipAddr = if (ip == null) "" else ip!!
val params = if (request.parameterMap.isNotEmpty()) JSONObject.toJSONString(request.parameterMap) else ""
logger.info("=============================START============================")
logger.info("REQ CLASS: $classMethod")
logger.info("URI: ${uri}")
logger.info("HTTP METHOD: ${reqMethod}")
logger.info("IP: $ipAddr")
logger.info("HTTP INPUT: $params")
val logRecord = LogRecord(classMethod, uri, reqMethod, ipAddr)
try {
logRecord.inParams = params
logRecordRepo.save(logRecord)
logThread.set(logRecord)
} catch (e: Exception) {
logger.error("$aopType aop error", e)
logRecord.status = -1
logRecord.errMsg = e.message
logRecord.description = "occur error"
logRecordRepo.save(logRecord)
}
}
@AfterReturning(returning = "resp", pointcut = "webLog()") //方法成功后处理
fun doAfter(resp: Any) = afterAction(resp)
private fun afterAction(resp: Any) {
val logRecord = logThread.get()
val elapsedTime = System.currentTimeMillis() - logRecord.createAt!!.time
logRecord.outParams = resp.toString()
logRecord.status = 0
logRecord.elapsedTime = elapsedTime
logRecordRepo.save(logRecord)
logger.info("OUTPUT: $resp")
logger.info("ELAPSEDTIME: $elapsedTime")
logger.info("=============================FINISH============================")
logThread.remove()
}
@AfterThrowing(pointcut = "webLog()", throwing = "e") //方法抛出异常后
fun doAfterThrowing(joinPoint: JoinPoint, e: Throwable) {
logger.info("exception method: ${joinPoint.target.javaClass.name}.${joinPoint.signature.name}()")
logger.info("exception code: ${e.javaClass.name}")
logger.info("exception msg: ${e.message}")
val logRecord = logThread.get()
logRecord.errMsg = GlobalConfig.api.getExceptionMsg(e)
logRecord.status = -1
logRecord.description = e.javaClass.name
logRecordRepo.save(logRecord)
logger.info("=============================FINISH============================")
logThread.remove()
}
}