/* * Copyright 2019-2020 Zheng Jie * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package me.zhengjie.service.impl; import cn.hutool.core.lang.Dict; import cn.hutool.core.util.ObjectUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import lombok.RequiredArgsConstructor; import me.zhengjie.domain.SysLog; import me.zhengjie.repository.LogRepository; import me.zhengjie.service.SysLogService; import me.zhengjie.service.dto.SysLogQueryCriteria; import me.zhengjie.service.dto.SysLogSmallDto; import me.zhengjie.service.mapstruct.LogErrorMapper; import me.zhengjie.service.mapstruct.LogSmallMapper; import me.zhengjie.utils.*; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.*; /** * @author Zheng Jie * @date 2018-11-24 */ @Service @RequiredArgsConstructor public class SysLogServiceImpl implements SysLogService { private final LogRepository logRepository; private final LogErrorMapper logErrorMapper; private final LogSmallMapper logSmallMapper; @Override public Object queryAll(SysLogQueryCriteria criteria, Pageable pageable) { Page page = logRepository.findAll(((root, criteriaQuery, cb) -> QueryHelp.getPredicate(root, criteria, cb)), pageable); String status = "ERROR"; if (status.equals(criteria.getLogType())) { return PageUtil.toPage(page.map(logErrorMapper::toDto)); } return PageUtil.toPage(page); } @Override public List queryAll(SysLogQueryCriteria criteria) { return logRepository.findAll(((root, criteriaQuery, cb) -> QueryHelp.getPredicate(root, criteria, cb))); } @Override public PageResult queryAllByUser(SysLogQueryCriteria criteria, Pageable pageable) { Page page = logRepository.findAll(((root, criteriaQuery, cb) -> QueryHelp.getPredicate(root, criteria, cb)), pageable); return PageUtil.toPage(page.map(logSmallMapper::toDto)); } @Override @Transactional(rollbackFor = Exception.class) public void save(String username, String browser, String ip, ProceedingJoinPoint joinPoint, SysLog sysLog) { if (sysLog == null) { throw new IllegalArgumentException("Log 不能为 null!"); } MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); me.zhengjie.annotation.Log aopLog = method.getAnnotation(me.zhengjie.annotation.Log.class); // 方法路径 String methodName = joinPoint.getTarget().getClass().getName() + "." + signature.getName() + "()"; // 描述 sysLog.setDescription(aopLog.value()); sysLog.setRequestIp(ip); sysLog.setAddress(StringUtils.getCityInfo(sysLog.getRequestIp())); sysLog.setMethod(methodName); sysLog.setUsername(username); sysLog.setParams(getParameter(method, joinPoint.getArgs())); // 记录登录用户,隐藏密码信息 if(signature.getName().equals("login") && StringUtils.isNotEmpty(sysLog.getParams())){ JSONObject obj = JSON.parseObject(sysLog.getParams()); sysLog.setUsername(obj.getString("username")); sysLog.setParams(JSON.toJSONString(Dict.create().set("username", sysLog.getUsername()))); } sysLog.setBrowser(browser); logRepository.save(sysLog); } /** * 根据方法和传入的参数获取请求参数 */ private String getParameter(Method method, Object[] args) { List argList = new ArrayList<>(); Parameter[] parameters = method.getParameters(); for (int i = 0; i < parameters.length; i++) { // 过滤掉不能序列化的类型: MultiPartFile if (args[i] instanceof MultipartFile) { continue; } //将RequestBody注解修饰的参数作为请求参数 RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class); if (requestBody != null) { argList.add(args[i]); } //将RequestParam注解修饰的参数作为请求参数 RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class); if (requestParam != null) { Map map = new HashMap<>(2); String key = parameters[i].getName(); if (!StringUtils.isEmpty(requestParam.value())) { key = requestParam.value(); } map.put(key, args[i]); argList.add(map); } } if (argList.isEmpty()) { return ""; } return argList.size() == 1 ? JSON.toJSONString(argList.get(0)) : JSON.toJSONString(argList); } @Override public Object findByErrDetail(Long id) { SysLog sysLog = logRepository.findById(id).orElseGet(SysLog::new); ValidationUtil.isNull(sysLog.getId(), "Log", "id", id); byte[] details = sysLog.getExceptionDetail(); return Dict.create().set("exception", new String(ObjectUtil.isNotNull(details) ? details : "".getBytes())); } @Override public void download(List sysLogs, HttpServletResponse response) throws IOException { List> list = new ArrayList<>(); for (SysLog sysLog : sysLogs) { Map map = new LinkedHashMap<>(); map.put("用户名", sysLog.getUsername()); map.put("IP", sysLog.getRequestIp()); map.put("IP来源", sysLog.getAddress()); map.put("描述", sysLog.getDescription()); map.put("浏览器", sysLog.getBrowser()); map.put("请求耗时/毫秒", sysLog.getTime()); map.put("异常详情", new String(ObjectUtil.isNotNull(sysLog.getExceptionDetail()) ? sysLog.getExceptionDetail() : "".getBytes())); map.put("创建日期", sysLog.getCreateTime()); list.add(map); } FileUtil.downloadExcel(list, response); } @Override @Transactional(rollbackFor = Exception.class) public void delAllByError() { logRepository.deleteByLogType("ERROR"); } @Override @Transactional(rollbackFor = Exception.class) public void delAllByInfo() { logRepository.deleteByLogType("INFO"); } }