访问Controller打印的日志效果如下:
*********************************Request请求*************************************** ClassName : com.xxx.app.xxx.action.xxxx RequestMethod : createURL() RequestParams : ["xxx","789"] RequestType : POST Description : 创建机器二维码图片URL serverAddr : http://localhost:8090 RemoteAddr : 0:0:0:0:0:0:0:1 DeviceName : Unknown BrowserName : Unknown UserAgent : PostmanRuntime/3.0.9 RequestUri : /retail/xxxx/createURL Result : {http://www.test.com/?msg=&mno=xxx&deviceid=789&acid=689277759a7c40ec81a8fb74cd5c153a, success=true}
如何Service抛出异常打印信息如下:
*********************************Service异常*************************************** ClassName : com.quna.app.retail.service.impl.xxx Method : com.quna.app.retail.service.impl.xxxx.goodsSync() Params : [{"deviceId":"123456789","itemId":"1","pictUrl":"1111","reservePrice":"3","title":"2"};] Description : 贩卖机商品同步 ExceptionName : java.lang.ArithmeticException ExceptionMessage : / by zero
步骤如下:
1)创建两个注解,分别用了对Controller和Service实现日志记录
ControllerLogs注解
/** * @version: V1.0 * @author: fendo * @className: ControllerLogs * @packageName: com.xx.commons.web.annotation * @description: Controller日志记录 * @data: 2018-05-21 15:58 **/ @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface ControllerLogs { /** * 描述 */ String description() default ""; }
ServiceLogs注解
/** * @version: V1.0 * @author: fendo * @className: ControllerLogs * @packageName: com.xxxx.commons.web.annotation * @description: Service日志记录 * @data: 2018-05-21 15:58 **/ @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface ServiceLogs { /** * 描述 */ String description() default ""; }
2)创建切面LogAspect
/** * projectName: xxxx * fileName: LogAspect.java * packageName: com.xxxx.logs.aop * date: 2018-05-31 10:15 * copyright(c) xxxxxxxx */ package com.xxxx.utils.logs.aop; import com.alibaba.fastjson.JSON; import com.xxxx.utils.logs.annotation.ControllerLogs; import com.xxxx.utils.logs.annotation.ServiceLogs; import com.xxxx.utils.logs.utils.IpUtils; import com.xxxx.utils.logs.utils.StringUtils; import com.xxxx.utils.logs.utils.UserAgentUtils; import eu.bitwalker.useragentutils.UserAgent; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.context.annotation.Configuration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import java.lang.reflect.Method; import java.util.Arrays; /** * @version: V1.0 * @author: fendo * @className: LogAspect * @packageName: com.xxxx.logs.aop * @description: 日志切点 * @data: 2018-05-31 10:15 **/ @Aspect @Configuration public class LogAspect { /** * 本地异常日志记录对象 */ private final Logger logger = LoggerFactory.getLogger(getClass()); /** * Service层切点 */ @Pointcut("@annotation(com.xxxx.utils.logs.annotation.ServiceLogs)") public void serviceAspect() { } /** * Controller层切点 */ @Pointcut("@annotation(com.xxxx.utils.logs.annotation.ControllerLogs)") public void controllerAspect() { } /** * 前置通知 用于拦截Controller层记录用户的操作 * * @param joinPoint 切点 */ @Before("controllerAspect()") public void doBefore(JoinPoint joinPoint) { try { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); //类名 String className = joinPoint.getTarget().getClass().getName(); //请求方法 String method = joinPoint.getSignature().getName() + "()"; //方法参数 String methodParam = JSON.toJSONString(joinPoint.getArgs()); //方法描述 String methodDescription = getControllerMethodDescription(joinPoint); StringBuilder sb = new StringBuilder(1000); sb.append("\n"); sb.append("*********************************Request请求***************************************"); sb.append("\n"); sb.append("ClassName : ").append(className).append("\n"); sb.append("RequestMethod : ").append(method).append("\n"); sb.append("RequestParams : ").append(methodParam).append("\n"); sb.append("RequestType : ").append(request.getMethod()).append("\n"); sb.append("Description : ").append(methodDescription).append("\n"); sb.append("serverAddr : ").append(request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()).append("\n"); sb.append("RemoteAddr : ").append(IpUtils.getRemoteAddr(request)).append("\n"); UserAgent userAgent = UserAgentUtils.getUserAgent(request); sb.append("DeviceName : ").append(userAgent.getOperatingSystem().getName()).append("\n"); sb.append("BrowserName : ").append(userAgent.getBrowser().getName()).append("\n"); sb.append("UserAgent : ").append(request.getHeader("User-Agent")).append("\n"); sb.append("RequestUri : ").append(StringUtils.abbr(request.getRequestURI(), 255)).append("\n"); logger.info(sb.toString()); } catch (Exception e) { e.printStackTrace(); } } @AfterReturning(returning = "ret", pointcut = "controllerAspect()") public void doAfterReturning(Object ret) throws Throwable { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); //请求方法 String method = StringUtils.abbr(request.getRequestURI(), 255); StringBuilder sb = new StringBuilder(1000); // 处理完请求,返回内容 sb.append("\n"); sb.append("Result : ").append(ret); logger.info(sb.toString()); } /** * 异常通知 用于拦截service层记录异常日志 * * @param joinPoint * @param ex */ @AfterThrowing(pointcut = "serviceAspect()", throwing = "ex") public void doAfterThrowing(JoinPoint joinPoint, Throwable ex) { try { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); //类名 String className = joinPoint.getTarget().getClass().getName(); //请求方法 String method = (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"); //方法参数 String methodParam = Arrays.toString(joinPoint.getArgs()); //方法描述 String methodDescription = getServiceMthodDescription(joinPoint); //获取用户请求方法的参数并序列化为JSON格式字符串 String params = ""; if (joinPoint.getArgs() != null && joinPoint.getArgs().length > 0) { for (int i = 0; i < joinPoint.getArgs().length; i++) { params += JSON.toJSONString(joinPoint.getArgs()[i]) + ";"; } } StringBuilder sb = new StringBuilder(1000); sb.append("\n"); sb.append("*********************************Service异常***************************************"); sb.append("\n"); sb.append("ClassName : ").append(className).append("\n"); sb.append("Method : ").append(method).append("\n"); sb.append("Params : ").append("[" + params + "]").append("\n"); sb.append("Description : ").append(methodDescription).append("\n"); sb.append("ExceptionName : ").append(ex.getClass().getName()).append("\n"); sb.append("ExceptionMessage : ").append(ex.getMessage()).append("\n"); logger.info(sb.toString()); } catch (Exception e1) { e1.printStackTrace(); } } /** * 获取注解中对方法的描述信息 用于service层注解 * * @param joinPoint 切点 * @return 方法描述 * @throws Exception */ public static String getServiceMthodDescription(JoinPoint joinPoint) throws Exception { String targetName = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); Object[] arguments = joinPoint.getArgs(); Class targetClass = Class.forName(targetName); Method[] methods = targetClass.getMethods(); String description = ""; for (Method method : methods) { if (method.getName().equals(methodName)) { Class[] clazzs = method.getParameterTypes(); if (clazzs.length == arguments.length) { description = method.getAnnotation(ServiceLogs.class).description(); break; } } } return description; } /** * 获取注解中对方法的描述信息 用于Controller层注解 * * @param joinPoint 切点 * @return 方法描述 * @throws Exception */ public static String getControllerMethodDescription(JoinPoint joinPoint) throws Exception { String targetName = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); Object[] arguments = joinPoint.getArgs(); Class targetClass = Class.forName(targetName); Method[] methods = targetClass.getMethods(); String description = ""; for (Method method : methods) { if (method.getName().equals(methodName)) { Class[] clazzs = method.getParameterTypes(); if (clazzs.length == arguments.length) { description = method.getAnnotation(ControllerLogs.class).description(); break; } } } return description; } }
3)几个工具类
DateUtils
/** * projectName: xxxx * fileName: DateUtils.java * packageName: utils * date: 2018-05-30 17:29 * copyright(c) xxxx */ package com.xxxx.utils.logs.utils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.FastDateFormat; import java.lang.management.ManagementFactory; import java.text.ParseException; import java.util.Calendar; import java.util.Date; /** * @version: V1.0 * @author: fendo * @className: DateUtils * @packageName: utils * @description: 日期工具类 * @data: 2018-05-30 17:29 **/ public class DateUtils extends org.apache.commons.lang3.time.DateUtils { private static String[] parsePatterns = { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM-dd HH", "yyyy-MM", "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM/dd HH", "yyyy/MM", "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM.dd HH", "yyyy.MM", "yyyy年MM月dd日", "yyyy年MM月dd日 HH时mm分ss秒", "yyyy年MM月dd日 HH时mm分", "yyyy年MM月dd日 HH时", "yyyy年MM月", "yyyy"}; /** * 得到日期字符串 ,转换格式(yyyy-MM-dd) */ public static String formatDate(Date date) { return formatDate(date, "yyyy-MM-dd"); } /** * 得到日期字符串 默认格式(yyyy-MM-dd) pattern可以为:"yyyy-MM-dd" "HH:mm:ss" "E" */ public static String formatDate(long dateTime, String pattern) { return formatDate(new Date(dateTime), pattern); } /** * 得到日期字符串 默认格式(yyyy-MM-dd) pattern可以为:"yyyy-MM-dd" "HH:mm:ss" "E" */ public static String formatDate(Date date, String pattern) { String formatDate = null; if (date != null){ if (StringUtils.isBlank(pattern)) { pattern = "yyyy-MM-dd"; } formatDate = FastDateFormat.getInstance(pattern).format(date); } return formatDate; } /** * 得到日期时间字符串,转换格式(yyyy-MM-dd HH:mm:ss) */ public static String formatDateTime(Date date) { return formatDate(date, "yyyy-MM-dd HH:mm:ss"); } /** * 得到当前日期字符串 格式(yyyy-MM-dd) */ public static String getDate() { return getDate("yyyy-MM-dd"); } /** * 得到当前日期字符串 格式(yyyy-MM-dd) pattern可以为:"yyyy-MM-dd" "HH:mm:ss" "E" */ public static String getDate(String pattern) { return FastDateFormat.getInstance(pattern).format(new Date()); } /** * 得到当前日期前后多少天,月,年的日期字符串 * @param pattern 格式(yyyy-MM-dd) pattern可以为:"yyyy-MM-dd" "HH:mm:ss" "E" * @param amont 数量,前为负数,后为正数 * @param type 类型,可参考Calendar的常量(如:Calendar.HOUR、Calendar.MINUTE、Calendar.SECOND) * @return */ public static String getDate(String pattern, int amont, int type) { Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); calendar.add(type, amont); return FastDateFormat.getInstance(pattern).format(calendar.getTime()); } /** * 得到当前时间字符串 格式(HH:mm:ss) */ public static String getTime() { return formatDate(new Date(), "HH:mm:ss"); } /** * 得到当前日期和时间字符串 格式(yyyy-MM-dd HH:mm:ss) */ public static String getDateTime() { return formatDate(new Date(), "yyyy-MM-dd HH:mm:ss"); } /** * 得到当前年份字符串 格式(yyyy) */ public static String getYear() { return formatDate(new Date(), "yyyy"); } /** * 得到当前月份字符串 格式(MM) */ public static String getMonth() { return formatDate(new Date(), "MM"); } /** * 得到当天字符串 格式(dd) */ public static String getDay() { return formatDate(new Date(), "dd"); } /** * 得到当前星期字符串 格式(E)星期几 */ public static String getWeek() { return formatDate(new Date(), "E"); } /** * 日期型字符串转化为日期 格式 see to DateUtils#parsePatterns */ public static Date parseDate(Object str) { if (str == null){ return null; } try { return parseDate(str.toString(), parsePatterns); } catch (ParseException e) { return null; } } /** * 获取过去的天数 * @param date * @return */ public static long pastDays(Date date) { long t = System.currentTimeMillis()-date.getTime(); return t/(24*60*60*1000); } /** * 获取过去的小时 * @param date * @return */ public static long pastHour(Date date) { long t = System.currentTimeMillis()-date.getTime(); return t/(60*60*1000); } /** * 获取过去的分钟 * @param date * @return */ public static long pastMinutes(Date date) { long t = System.currentTimeMillis()-date.getTime(); return t/(60*1000); } /** * 获取两个日期之间的天数 * * @param before * @param after * @return */ public static double getDistanceOfTwoDate(Date before, Date after) { long beforeTime = before.getTime(); long afterTime = after.getTime(); return (afterTime - beforeTime) / (1000 * 60 * 60 * 24); } /** * 获取某月有几天 * @param date 日期 * @return 天数 */ public static int getMonthHasDays(Date date){ String yyyyMM = FastDateFormat.getInstance("yyyyMM").format(date); String year = yyyyMM.substring(0, 4); String month = yyyyMM.substring(4, 6); String day31 = ",01,03,05,07,08,10,12,"; String day30 = "04,06,09,11"; int day = 0; if (day31.contains(month)) { day = 31; } else if (day30.contains(month)) { day = 30; } else { int y = Integer.parseInt(year); if ((y % 4 == 0 && (y % 100 != 0)) || y % 400 == 0) { day = 29; } else { day = 28; } } return day; } /** * 获取日期是当年的第几周 * @param date * @return */ public static int getWeekOfYear(Date date){ Calendar cal = Calendar.getInstance(); cal.setTime(date); return cal.get(Calendar.WEEK_OF_YEAR); } /** * 获取一天的开始时间(如:2015-11-3 00:00:00.000) * @param date 日期 * @return */ public static Date getOfDayFirst(Date date) { if (date == null){ return null; } Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.set(Calendar.HOUR, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); return calendar.getTime(); } /** * 获取一天的最后时间(如:2015-11-3 23:59:59.999) * @param date 日期 * @return */ public static Date getOfDayLast(Date date) { if (date == null){ return null; } Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.set(Calendar.HOUR, 23); calendar.set(Calendar.MINUTE, 59); calendar.set(Calendar.SECOND, 59); calendar.set(Calendar.MILLISECOND, 999); return calendar.getTime(); } /** * 获取服务器启动时间 * @return */ public static Date getServerStartDate(){ long time = ManagementFactory.getRuntimeMXBean().getStartTime(); return new Date(time); } /** * 格式化为日期范围字符串 * @param beginDate 2018-01-01 * @param endDate 2018-01-31 * @return 2018-01-01 ~ 2018-01-31 */ public static String formatDateBetweenString(Date beginDate, Date endDate){ String begin = DateUtils.formatDate(beginDate); String end = DateUtils.formatDate(endDate); if (StringUtils.isNoneBlank(begin, end)){ return begin + " ~ " + end; } return null; } /** * 解析日期范围字符串为日期对象 * @param dateString 2018-01-01 ~ 2018-01-31 * @return new Date[]{2018-01-01, 2018-01-31} */ public static Date[] parseDateBetweenString(String dateString){ Date beginDate = null; Date endDate = null; if (StringUtils.isNotBlank(dateString)){ String[] ss = StringUtils.split(dateString, "~"); if (ss != null && ss.length == 2){ String begin = StringUtils.trim(ss[0]); String end = StringUtils.trim(ss[1]); if (StringUtils.isNoneBlank(begin, end)){ beginDate = DateUtils.parseDate(begin); endDate = DateUtils.parseDate(end); } } } return new Date[]{beginDate, endDate}; } }
IpUtils类:
/** * projectName: xxxx * fileName: IpUtils.java * packageName: com.xxxx.logs.utils * date: 2018-05-31 10:48 * copyright(c) xxxx */ package com.xxxx.utils.logs.utils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import javax.servlet.http.HttpServletRequest; /** * @version: V1.0 * @author: fendo * @className: IpUtils * @packageName: com.xxxx.logs.utils * @description: IP工具类 * @data: 2018-05-31 10:48 **/ public class IpUtils { /** * 获取客户端IP地址 * @param request * @return */ public static String getRemoteAddr(HttpServletRequest request) { if (request == null) { return "unknown"; } String ip = request.getHeader("X-Forwarded-For"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("X-Real-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } return StringUtils.split(ObjectUtils.toString(ip), ",")[0]; } }
StringUtils类:
/** * projectName: xxxx * fileName: StringUtils.java * packageName: com.xxxx.logs.utils * date: 2018-05-31 10:53 * copyright(c) xxxx */ package com.xxxx.utils.logs.utils; import org.apache.commons.lang3.StringEscapeUtils; import java.io.UnsupportedEncodingException; import java.util.regex.Matcher; import java.util.regex.Pattern; import static org.apache.commons.lang3.StringUtils.isBlank; /** * @version: V1.0 * @author: fendo * @className: StringUtils * @packageName: com.xxxx.logs.utils * @description: 字符串工具类, 继承org.apache.commons.lang3.StringUtils类 * @data: 2018-05-31 10:53 **/ public class StringUtils { /** * 替换掉HTML标签方法 */ public static String stripHtml(String html) { if (isBlank(html)){ return ""; } String regEx = "<.+?>"; Pattern p = Pattern.compile(regEx); Matcher m = p.matcher(html); String s = m.replaceAll(""); return s; } /** * 缩略字符串(不区分中英文字符) * @param str 目标字符串 * @param length 截取长度 * @return */ public static String abbr(String str, int length) { if (str == null) { return ""; } try { StringBuilder sb = new StringBuilder(); int currentLength = 0; for (char c : stripHtml(StringEscapeUtils.unescapeHtml4(str)).toCharArray()) { currentLength += String.valueOf(c).getBytes("GBK").length; if (currentLength <= length - 3) { sb.append(c); } else { sb.append("..."); break; } } return sb.toString(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return ""; } }
TimeUtils类:
/** * projectName: xxxx * fileName: TimeUtils.java * packageName: utils * date: 2018-05-30 17:31 * copyright(c) xxxx */ package com.xxxx.utils.logs.utils; import org.apache.commons.lang3.time.DateFormatUtils; import java.util.Arrays; import java.util.Date; /** * @version: V1.0 * @author: fendo * @className: TimeUtils * @packageName: utils * @description: 时间计算工具类 * @data: 2018-05-30 17:31 **/ public class TimeUtils { /** * 将时间转换为字符串(xx天,xx时,xx分,xx秒,大于360天显示日期时间) */ public static String formatDateAgo(long dateTime) { StringBuilder sb = new StringBuilder(); if (dateTime < 1000){ sb.append(dateTime).append("毫秒"); }else{ TimeUtils t = new TimeUtils(dateTime); int day = t.get(TimeUtils.DAY); int hour = t.get(TimeUtils.HOUR); int minute = t.get(TimeUtils.MINUTE); int second = t.get(TimeUtils.SECOND); if (day > 365){ return DateUtils.formatDate(new Date(dateTime), "yyyy年MM月dd日 HH时mm分ss秒"); } if (day > 0){ sb.append(day).append("天"); } if (hour > 0){ sb.append(hour).append("时"); } if (minute > 0){ sb.append(minute).append("分"); } if (second > 0){ sb.append(second).append("秒"); } } return sb.toString(); } /** * 将过去的时间转为为,刚刚,xx秒,xx分钟,xx小时前、xx天前,大于3天的显示日期 */ public static String formatTimeAgo(String dateTime) { return formatTimeAgo(DateUtils.parseDate(dateTime)); } /** * 将过去的时间转为为,刚刚,xx秒,xx分钟,xx小时前、xx天前,大于3天的显示日期 */ public static String formatTimeAgo(Date dateTime) { String interval = null; // 得出的时间间隔是毫秒 long time = System.currentTimeMillis() - dateTime.getTime(); // 如果时间间隔小于10秒则显示“刚刚”time/10得出的时间间隔的单位是秒 if (time / 1000 < 10 && time / 1000 >= 0) { interval = "刚刚"; } // 如果时间间隔大于24小时则显示多少天前 else if (time / 3600000 < 24*4 && time / 3600000 >= 24) { int d = (int) (time / (3600000*24));// 得出的时间间隔的单位是天 interval = d + "天前"; } // 如果时间间隔小于24小时则显示多少小时前 else if (time / 3600000 < 24 && time / 3600000 >= 1) { int h = (int) (time / 3600000);// 得出的时间间隔的单位是小时 interval = h + "小时前"; } // 如果时间间隔小于60分钟则显示多少分钟前 else if (time / 60000 < 60 && time / 60000 >=1) { int m = (int) ((time % 3600000) / 60000);// 得出的时间间隔的单位是分钟 interval = m + "分钟前"; } // 如果时间间隔小于60秒则显示多少秒前 else if (time / 1000 < 60 && time / 1000 >=10) { int se = (int) ((time % 60000) / 1000); interval = se + "秒前"; } // 大于3天的,则显示正常的时间,但是不显示秒 else { interval = DateUtils.formatDate(dateTime,"yyyy-MM-dd"); } return interval; } /** * 时间字段常量,表示“秒” */ public final static int SECOND = 0; /** * 时间字段常量,表示“分” */ public final static int MINUTE = 1; /** * 时间字段常量,表示“时” */ public final static int HOUR = 2; /** * 时间字段常量,表示“天” */ public final static int DAY = 3; /** * 各常量允许的最大值 */ private final int[] maxFields = { 59, 59, 23, Integer.MAX_VALUE - 1 }; /** * 各常量允许的最小值 */ private final int[] minFields = { 0, 0, 0, Integer.MIN_VALUE }; /** * 默认的字符串格式时间分隔符 */ private String timeSeparator = ":"; /** * 时间数据容器 */ private int[] fields = new int[4]; /** * 无参构造,将各字段置为 0 */ public TimeUtils() { this(0, 0, 0, 0); } /** * 使用时、分构造一个时间 * @param hour 小时 * @param minute 分钟 */ public TimeUtils(int hour, int minute) { this(0, hour, minute, 0); } /** * 使用时、分、秒构造一个时间 * @param hour 小时 * @param minute 分钟 * @param second 秒 */ public TimeUtils(int hour, int minute, int second) { this(0, hour, minute, second); } /** * 使用一个字符串构造时间<br> * Time time = new Time("14:22:23"); * @param time 字符串格式的时间,默认采用“:”作为分隔符 */ public TimeUtils(String time) { this(time, null); } /** * 使用时间毫秒构建时间 * @param time */ public TimeUtils(long time){ this(new Date(time)); } /** * 使用日期对象构造时间 * @param date */ public TimeUtils(Date date){ this(DateFormatUtils.formatUTC(date, "HH:mm:ss")); } /** * 使用天、时、分、秒构造时间,进行全字符的构造 * @param day 天 * @param hour 时 * @param minute 分 * @param second 秒 */ public TimeUtils(int day, int hour, int minute, int second) { initialize(day, hour, minute, second); } /** * 使用一个字符串构造时间,指定分隔符<br> * Time time = new Time("14-22-23", "-"); * @param time 字符串格式的时间 */ public TimeUtils(String time, String timeSeparator) { if(timeSeparator != null) { setTimeSeparator(timeSeparator); } parseTime(time); } /** * 设置时间字段的值 * @param field 时间字段常量 * @param value 时间字段的值 */ public void set(int field, int value) { if(value < minFields[field]) { throw new IllegalArgumentException(value + ", time value must be positive."); } fields[field] = value % (maxFields[field] + 1); // 进行进位计算 int carry = value / (maxFields[field] + 1); if(carry > 0) { int upFieldValue = get(field + 1); set(field + 1, upFieldValue + carry); } } /** * 获得时间字段的值 * @param field 时间字段常量 * @return 该时间字段的值 */ public int get(int field) { if(field < 0 || field > fields.length - 1) { throw new IllegalArgumentException(field + ", field value is error."); } return fields[field]; } /** * 将时间进行“加”运算,即加上一个时间 * @param time 需要加的时间 * @return 运算后的时间 */ public TimeUtils addTime(TimeUtils time) { TimeUtils result = new TimeUtils(); int up = 0; // 进位标志 for (int i = 0; i < fields.length; i++) { int sum = fields[i] + time.fields[i] + up; up = sum / (maxFields[i] + 1); result.fields[i] = sum % (maxFields[i] + 1); } return result; } /** * 将时间进行“减”运算,即减去一个时间 * @param time 需要减的时间 * @return 运算后的时间 */ public TimeUtils subtractTime(TimeUtils time) { TimeUtils result = new TimeUtils(); int down = 0; // 退位标志 for (int i = 0, k = fields.length - 1; i < k; i++) { int difference = fields[i] + down; if (difference >= time.fields[i]) { difference -= time.fields[i]; down = 0; } else { difference += maxFields[i] + 1 - time.fields[i]; down = -1; } result.fields[i] = difference; } result.fields[DAY] = fields[DAY] - time.fields[DAY] + down; return result; } /** * 获得时间字段的分隔符 * @return */ public String getTimeSeparator() { return timeSeparator; } /** * 设置时间字段的分隔符(用于字符串格式的时间) * @param timeSeparator 分隔符字符串 */ public void setTimeSeparator(String timeSeparator) { this.timeSeparator = timeSeparator; } private void initialize(int day, int hour, int minute, int second) { set(DAY, day); set(HOUR, hour); set(MINUTE, minute); set(SECOND, second); } private void parseTime(String time) { if(time == null) { initialize(0, 0, 0, 0); return; } String t = time; int field = DAY; set(field--, 0); int p = -1; while((p = t.indexOf(timeSeparator)) > -1) { parseTimeField(time, t.substring(0, p), field--); t = t.substring(p + timeSeparator.length()); } parseTimeField(time, t, field--); } private void parseTimeField(String time, String t, int field) { if(field < SECOND || t.length() < 1) { parseTimeException(time); } char[] chs = t.toCharArray(); int n = 0; for(int i = 0; i < chs.length; i++) { if(chs[i] <= ' ') { continue; } if(chs[i] >= '0' && chs[i] <= '9') { n = n * 10 + chs[i] - '0'; continue; } parseTimeException(time); } set(field, n); } private void parseTimeException(String time) { throw new IllegalArgumentException(time + ", time format error, HH" + this.timeSeparator + "mm" + this.timeSeparator + "ss"); } @Override public String toString() { StringBuilder sb = new StringBuilder(16); sb.append(fields[DAY]).append(',').append(' '); buildString(sb, HOUR).append(timeSeparator); buildString(sb, MINUTE).append(timeSeparator); buildString(sb, SECOND); return sb.toString(); } private StringBuilder buildString(StringBuilder sb, int field) { if(fields[field] < 10) { sb.append('0'); } return sb.append(fields[field]); } @Override public int hashCode() { final int PRIME = 31; int result = 1; result = PRIME * result + Arrays.hashCode(fields); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final TimeUtils other = (TimeUtils) obj; if (!Arrays.equals(fields, other.fields)) { return false; } return true; } }
UserAgentUtils类:
/** * projectName: xxxx * fileName: UserAgentUtils.java * packageName: com.xxxx.logs.utils * date: 2018-05-31 10:49 * copyright(c) xxxx */ package com.xxxx.utils.logs.utils; import eu.bitwalker.useragentutils.Browser; import eu.bitwalker.useragentutils.DeviceType; import eu.bitwalker.useragentutils.UserAgent; import javax.servlet.http.HttpServletRequest; /** * @version: V1.0 * @author: fendo * @className: UserAgentUtils * @packageName: com.xxxx.logs.utils * @description: 用户代理 * @data: 2018-05-31 10:49 **/ public class UserAgentUtils { /** * 获取用户代理对象 * @param request * @return */ public static UserAgent getUserAgent(HttpServletRequest request){ return UserAgent.parseUserAgentString(request.getHeader("User-Agent")); } /** * 获取设备类型 * @param request * @return */ public static DeviceType getDeviceType(HttpServletRequest request){ return getUserAgent(request).getOperatingSystem().getDeviceType(); } /** * 是否是PC * @param request * @return */ public static boolean isComputer(HttpServletRequest request){ return DeviceType.COMPUTER.equals(getDeviceType(request)); } /** * 是否是手机 * @param request * @return */ public static boolean isMobile(HttpServletRequest request){ return DeviceType.MOBILE.equals(getDeviceType(request)); } /** * 是否是平板 * @param request * @return */ public static boolean isTablet(HttpServletRequest request){ return DeviceType.TABLET.equals(getDeviceType(request)); } /** * 是否是手机和平板 * @param request * @return */ public static boolean isMobileOrTablet(HttpServletRequest request){ DeviceType deviceType = getDeviceType(request); return DeviceType.MOBILE.equals(deviceType) || DeviceType.TABLET.equals(deviceType); } /** * 获取浏览类型 * @param request * @return */ public static Browser getBrowser(HttpServletRequest request){ return getUserAgent(request).getBrowser(); } /** * 是否IE版本是否小于等于IE8 * @param request * @return */ public static boolean isLteIE8(HttpServletRequest request){ Browser browser = getBrowser(request); return Browser.IE5.equals(browser) || Browser.IE6.equals(browser) || Browser.IE7.equals(browser) || Browser.IE8.equals(browser); } }
4)POM.XML文件
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>1.5.6.RELEASE</version> <type>pom</type> <scope>provided</scope> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <scope>provided</scope> <version>1.8.8</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.0.5.RELEASE</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.21</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.21</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.6</version> <scope>provided</scope> </dependency> <dependency> <groupId>eu.bitwalker</groupId> <artifactId>UserAgentUtils</artifactId> <version>1.20</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.46</version> <scope>provided</scope> </dependency> </dependencies>
5)使用方式
@PostMapping("/createURL") @ControllerLogs(description = "创建机器二维码图片URL") public Map<String,Object> createURL(@NotEmpty(message = "mno is required") String mno, @NotEmpty(message = "deviceid is required") String deviceid){ return eightStatesService.createURL(mno,deviceid); } @Override @ServiceLogs(description = "商品同步") public Map<String, Object> goodsSync(GoodsRequestDTO data) { int a = 0/0; MachineGoods machineGoods = new MachineGoods(); BeanUtils.copyProperties(data,machineGoods); machineGoods.setId(Identities.uuid2()); machineGoods.setCt(new Date()); machineGoods.setMt(new Date()); activityTemplate.save(machineGoods); return ResultFactory.getSuccess(); }