转载请注明出处:https://blog.csdn.net/l1028386804/article/details/80295737

1、定义日志类SystemLog

package io.mykit.annotation.spring.log.entity;import java.util.Date;/*** 定义日志实体信息* @author liuyazhuang**/
public class SystemLog {private String id;private String description;private String method;private Long logType;private String requestIp;private String exceptioncode;private String exceptionDetail;private String params;private String createBy;private Date createDate;public String getId() {return id;}public void setId(String id) {this.id = id == null ? null : id.trim();}public String getDescription() {return description;}public void setDescription(String description) {this.description = description == null ? null : description.trim();}public String getMethod() {return method;}public void setMethod(String method) {this.method = method == null ? null : method.trim();}public Long getLogType() {return logType;}public void setLogType(Long logType) {this.logType = logType;}public String getRequestIp() {return requestIp;}public void setRequestIp(String requestIp) {this.requestIp = requestIp == null ? null : requestIp.trim();}public String getExceptioncode() {return exceptioncode;}public void setExceptioncode(String exceptioncode) {this.exceptioncode = exceptioncode == null ? null : exceptioncode.trim();}public String getExceptionDetail() {return exceptionDetail;}public void setExceptionDetail(String exceptionDetail) {this.exceptionDetail = exceptionDetail == null ? null : exceptionDetail.trim();}public String getParams() {return params;}public void setParams(String params) {this.params = params == null ? null : params.trim();}public String getCreateBy() {return createBy;}public void setCreateBy(String createBy) {this.createBy = createBy == null ? null : createBy.trim();}public Date getCreateDate() {return createDate;}public void setCreateDate(Date createDate) {this.createDate = createDate;}@Overridepublic String toString() {return "SystemLog [id=" + id + ", description=" + description + ", method=" + method + ", logType=" + logType+ ", requestIp=" + requestIp + ", exceptioncode=" + exceptioncode + ", exceptionDetail="+ exceptionDetail + ", params=" + params + ", createBy=" + createBy + ", createDate=" + createDate+ "]";}}

2、定义SystemLogService接口

package io.mykit.annotation.spring.log.service;import io.mykit.annotation.spring.log.entity.SystemLog;/*** 日志的Service接口* @author liuyazhuang**/
public interface SystemLogService {int deleteSystemLog(String id);int insert(SystemLog record);int insertTest(SystemLog record);SystemLog selectSystemLog(String id);int updateSystemLog(SystemLog record);
}

3、接口实现类SystemLogServiceImpl

package io.mykit.annotation.spring.log.service.impl;import java.util.Date;
import java.util.UUID;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;import io.mykit.annotation.spring.log.entity.SystemLog;
import io.mykit.annotation.spring.log.service.SystemLogService;@Service("systemLogService")
public class SystemLogServiceImpl implements SystemLogService {private final Logger logger = LoggerFactory.getLogger(SystemLogServiceImpl.class);@Overridepublic int deleteSystemLog(String id) {logger.info("deleteSystemLog===>>>" + id);return 1;}@Overridepublic int insert(SystemLog record) {logger.info("insert===>>>" + record.toString());return 1;}@Overridepublic int insertTest(SystemLog record) {logger.info("insertTest===>>>" + record.toString());return 1;}@Overridepublic SystemLog selectSystemLog(String id) {logger.info("selectSystemLog===>>>" + id);SystemLog log = new SystemLog();  log.setId(UUID.randomUUID().toString());log.setDescription("查询日志");  log.setMethod("selectSystemLog");  log.setLogType((long)0);  log.setRequestIp("127.0.0.1");  log.setExceptioncode( null);  log.setExceptionDetail( null);  log.setParams( null);  log.setCreateBy("刘亚壮");  log.setCreateDate(new Date()); return log;}@Overridepublic int updateSystemLog(SystemLog record) {logger.info("updateSystemLog===>>>" + record.toString());return 1;}
}

4、自定义注解Log

package io.mykit.annotation.spring.log.provider;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 自定义日志注解* @author liuyazhuang**/
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {/** 要执行的操作类型比如:add操作 **/  public String operationType() default "";  /** 要执行的具体操作比如:添加用户 **/  public String operationName() default "";
}

5、实现注解解析器SystemLogAspect

package io.mykit.annotation.spring.log.aspect;import java.lang.reflect.Method;
import java.util.Date;
import java.util.UUID;import javax.annotation.Resource;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;import com.alibaba.fastjson.JSONObject;import io.mykit.annotation.spring.log.entity.SystemLog;
import io.mykit.annotation.spring.log.entity.User;
import io.mykit.annotation.spring.log.provider.Log;
import io.mykit.annotation.spring.log.service.SystemLogService;/*** 具体切片类的实现* @author liuyazhuang**/
@Aspect
@Component
public class SystemLogAspect {//注入Service用于把日志保存数据库  @Resource  //这里我用resource注解,一般用的是@Autowired,他们的区别如有时间我会在后面的博客中来写private SystemLogService systemLogService;  private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect. class);  //Controller层切点  @Pointcut("execution (* io.mykit.annotation.spring.log.user.service..*.*(..))")  public  void controllerAspect() {  }  /** * 前置通知 用于拦截Controller层记录用户的操作 * * @param joinPoint 切点 */ @Before("controllerAspect()")public void doBefore(JoinPoint joinPoint) {System.out.println("==========执行controller前置通知===============");if(logger.isInfoEnabled()){logger.info("before " + joinPoint);}}    //配置controller环绕通知,使用在方法aspect()上注册的切入点@Around("controllerAspect()")public void around(JoinPoint joinPoint){System.out.println("==========开始执行controller环绕通知===============");long start = System.currentTimeMillis();try {((ProceedingJoinPoint) joinPoint).proceed();long end = System.currentTimeMillis();if(logger.isInfoEnabled()){logger.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms!");}System.out.println("==========结束执行controller环绕通知===============");} catch (Throwable e) {long end = System.currentTimeMillis();if(logger.isInfoEnabled()){logger.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms with exception : " + e.getMessage());}}}/** * 后置通知 用于拦截Controller层记录用户的操作 * * @param joinPoint 切点 */  @SuppressWarnings("rawtypes")@After("controllerAspect()")  public  void after(JoinPoint joinPoint) {  /* HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();  HttpSession session = request.getSession();  *///读取session中的用户  // User user = (User) session.getAttribute("user");  //请求的IP  //String ip = request.getRemoteAddr();User user = new User();user.setId(1);user.setName("刘亚壮");String ip = "127.0.0.1";try {  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 operationType = "";String operationName = "";for (Method method : methods) {  if (method.getName().equals(methodName)) {  Class[] clazzs = method.getParameterTypes();  if (clazzs.length == arguments.length) {  if(method.isAnnotationPresent(Log.class)){operationType = method.getAnnotation(Log.class).operationType();operationName = method.getAnnotation(Log.class).operationName();break;  }}  }  }//*========控制台输出=========*//  System.out.println("=====controller后置通知开始=====");  System.out.println("请求方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")+"."+operationType);  System.out.println("方法描述:" + operationName);  System.out.println("请求人:" + user.getName());  System.out.println("请求IP:" + ip);  //*========数据库日志=========*//  SystemLog log = new SystemLog();  log.setId(UUID.randomUUID().toString());log.setDescription(operationName);  log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")+"."+operationType);  log.setLogType((long)0);  log.setRequestIp(ip);  log.setExceptioncode( null);  log.setExceptionDetail( null);  log.setParams( null);  log.setCreateBy(user.getName());  log.setCreateDate(new Date());  //保存数据库  systemLogService.insert(log);  System.out.println("=====controller后置通知结束=====");  }  catch (Exception e) {  //记录本地异常日志  logger.error("==后置通知异常==");  logger.error("异常信息:{}", e.getMessage());  }  } //配置后置返回通知,使用在方法aspect()上注册的切入点@AfterReturning("controllerAspect()")public void afterReturn(JoinPoint joinPoint){System.out.println("=====执行controller后置返回通知=====");  if(logger.isInfoEnabled()){logger.info("afterReturn " + joinPoint);}}/** * 异常通知 用于拦截记录异常日志 * * @param joinPoint * @param e */  @AfterThrowing(pointcut = "controllerAspect()", throwing="e")  public  void doAfterThrowing(JoinPoint joinPoint, Throwable e) {  /*HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();  HttpSession session = request.getSession();  //读取session中的用户  User user = (User) session.getAttribute(WebConstants.CURRENT_USER);  //获取请求ip  String ip = request.getRemoteAddr(); */ //获取用户请求方法的参数并序列化为JSON格式字符串  User user = new User();user.setId(1);user.setName("刘亚壮");String ip = "127.0.0.1";String params = "";  if (joinPoint.getArgs() !=  null && joinPoint.getArgs().length > 0) {  for ( int i = 0; i < joinPoint.getArgs().length; i++) {
//                params += JsonUtil.getJsonStr(joinPoint.getArgs()[i]) + ";";  params += JSONObject.toJSONString(joinPoint.getArgs()[i]) + ";"; }  }  try {  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 operationType = "";String operationName = "";for (Method method : methods) {  if (method.getName().equals(methodName)) {  Class[] clazzs = method.getParameterTypes();  if (clazzs.length == arguments.length) {  if(method.isAnnotationPresent(Log.class)){operationType = method.getAnnotation(Log.class).operationType();operationName = method.getAnnotation(Log.class).operationName();break;  }}  }  }/*========控制台输出=========*/  System.out.println("=====异常通知开始=====");  System.out.println("异常代码:" + e.getClass().getName());  System.out.println("异常信息:" + e.getMessage());  System.out.println("异常方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")+"."+operationType);  System.out.println("方法描述:" + operationName);  System.out.println("请求人:" + user.getName());  System.out.println("请求IP:" + ip);  System.out.println("请求参数:" + params);  /*==========数据库日志=========*/  SystemLog log = new SystemLog();log.setId(UUID.randomUUID().toString());log.setDescription(operationName);  log.setExceptioncode(e.getClass().getName());  log.setLogType((long)1);  log.setExceptionDetail(e.getMessage());  log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));  log.setParams(params);  log.setCreateBy(user.getName());  log.setCreateDate(new Date());  log.setRequestIp(ip);  //保存数据库  systemLogService.insert(log);  System.out.println("=====异常通知结束=====");  }  catch (Exception ex) {  //记录本地异常日志  logger.error("==异常通知异常==");  logger.error("异常信息:{}", ex.getMessage());  }  /*==========记录本地异常日志==========*/  logger.error("异常方法:{}异常代码:{}异常信息:{}参数:{}", joinPoint.getTarget().getClass().getName() + joinPoint.getSignature().getName(), e.getClass().getName(), e.getMessage(), params);  }  }

6、实现User实体类

package io.mykit.annotation.spring.log.entity;/*** 测试AOP切面的类* @author liuyazhuang**/
public class User {private Integer id;private String name;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "User [id=" + id + ", name=" + name + "]";}
}

7、定义UserService接口

package io.mykit.annotation.spring.log.user.service;/*** 日志切面的UserService* @author liuyazhuang**/
public interface UserService {void addUser();
}

8、接口实现类UserServiceImpl

我们在这个类上加上了注解@Log(operationType="add操作", operationName = "添加用户")

package io.mykit.annotation.spring.log.user.service.impl;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;import io.mykit.annotation.spring.log.provider.Log;
import io.mykit.annotation.spring.log.user.service.UserService;@Service("logUserService")
public class UserServiceImpl implements UserService {private final Logger logger  = LoggerFactory.getLogger(UserServiceImpl.class);@Override@Log(operationType="add操作", operationName = "添加用户")public void addUser() {logger.info("执行了添加用户的操作");}
}

9、spring-log-annotation.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:cache="http://www.springframework.org/schema/cache"xmlns:task="http://www.springframework.org/schema/task"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsdhttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsdhttp://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.0.xsdhttp://www.springframework.org/schema/task  http://www.springframework.org/schema/task/spring-task-4.0.xsd"default-autowire="byName"><mvc:annotation-driven /><!-- 激活组件扫描功能,在包io.mykit.annotation.spring.log及其子包下面自动扫描通过注解配置的组件 --><context:component-scan base-package="io.mykit.annotation.spring.log" /> <!-- 启动对@AspectJ注解的支持 --><!-- proxy-target-class等于true是强制使用cglib代理,proxy-target-class默认是false,如果你的类实现了接口 就走JDK代理,如果没有走cglib代理  --><!-- 注:对于单利模式建议使用cglib代理,虽然JDK动态代理比cglib代理速度快,但性能不如cglib --><aop:aspectj-autoproxy proxy-target-class="true"/><context:annotation-config /><bean id="systemLogAspect" class="io.mykit.annotation.spring.log.aspect.SystemLogAspect"/>
</beans>

10、测试类LogAnnotationTest

package io.mykit.annotation.spring.log.provider;import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;import io.mykit.annotation.spring.log.user.service.UserService;/*** 测试日志注解信息* @author liuyazhuang**/
public class LogAnnotationTest {@SuppressWarnings("resource")@Testpublic void testLogAnnotation(){ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"spring/spring-log-annotation.xml"});UserService userService = (UserService) context.getBean("logUserService");userService.addUser();}
}

11、pom.xml的Jar包依赖

<properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><skip_maven_deploy>false</skip_maven_deploy><jdk.version>1.8</jdk.version><spring.version>4.1.0.RELEASE</spring.version>
</properties><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-expression</artifactId><version>${spring.version}</version></dependency>    <dependency><groupId>org.springframework</groupId><artifactId>spring-messaging</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jms</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjtools</artifactId><version>1.9.1</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.0.1</version></dependency><dependency>  <groupId>org.slf4j</groupId>  <artifactId>slf4j-log4j12</artifactId>  <version>1.7.2</version>  </dependency> <dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.1.1</version></dependency><dependency><groupId>cglib</groupId><artifactId>cglib-nodep</artifactId><version>2.1_3</version></dependency></dependencies>

12、log4j.properties

log4j.rootCategory=INFO,stdout,file,ERROR
#log4j.rootCategory=ERROR,stdout,file
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
#log4j.appender.stdout=org.apache.log4j.FileAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[mykit-annotation-spring-provider]%d %p [%t] %C{1}.%M(%L) | %m%n#log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
#log4j.appender.file.MaxFileSize=100KB
#log4j.appender.file.DatePattern = '.'yyyy-MM-dd'.log'log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.File=/home/mykit/logs/mykit-annotation-spring-provider/mykit-annotation-spring-provider
log4j.appender.file.DatePattern='.'yyyy-MM-dd'.log'
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%-d{yyyy-MM-dd HH\:mm\:ss} [%c-%L]-[%t]-[%p] %m%n

13、测试结果

==========开始执行controller环绕通知===============
==========执行controller前置通知===============
[mykit-annotation-spring-provider]2018-05-12 22:58:19,617 INFO [main] SystemLogAspect.doBefore(59) | before execution(void io.mykit.annotation.spring.log.user.service.impl.UserServiceImpl.addUser())
[mykit-annotation-spring-provider]2018-05-12 22:58:19,629 INFO [main] UserServiceImpl.addUser(16) | 执行了添加用户的操作
[mykit-annotation-spring-provider]2018-05-12 22:58:19,629 INFO [main] SystemLogAspect.around(72) | around execution(void io.mykit.annotation.spring.log.user.service.impl.UserServiceImpl.addUser())    Use time : 14 ms!
==========结束执行controller环绕通知===============
=====controller后置通知开始=====
请求方法:io.mykit.annotation.spring.log.user.service.impl.UserServiceImpl.addUser().add操作
方法描述:添加用户
请求人:刘亚壮
请求IP:127.0.0.1
[mykit-annotation-spring-provider]2018-05-12 22:58:19,912 INFO [main] SystemLogServiceImpl.insert(26) | insert===>>>SystemLog [id=dfc4415f-0151-4e3e-8268-9397ab264288, description=添加用户, method=io.mykit.annotation.spring.log.user.service.impl.UserServiceImpl.addUser().add操作, logType=0, requestIp=127.0.0.1, exceptioncode=null, exceptionDetail=null, params=null, createBy=刘亚壮, createDate=Sat May 12 22:58:19 CST 2018]
=====controller后置通知结束=====
=====执行controller后置返回通知=====
[mykit-annotation-spring-provider]2018-05-12 22:58:19,912 INFO [main] SystemLogAspect.afterReturn(155) | afterReturn execution(void io.mykit.annotation.spring.log.user.service.impl.UserServiceImpl.addUser())

备注:

本实例中我们在具体切面实现类SystemLogAspect中打印出了相关操作日志,具体项目业务中,大家可以根据具体业务需求将日志存储到相关的数据库或者分布式文件系统中。

Java之——Spring AOP自定义注解实现日志管理相关推荐

  1. spring AOP自定义注解方式实现日志管理

    转:spring AOP自定义注解方式实现日志管理 今天继续实现AOP,到这里我个人认为是最灵活,可扩展的方式了,就拿日志管理来说,用Spring AOP 自定义注解形式实现日志管理.废话不多说,直接 ...

  2. spring aop 自定义注解配合swagger注解保存操作日志到mysql数据库含(源码)

    spring aop 自定义注解保存操作日志到mysql数据库 一.思路 二.自定义注解 三.编写操作日志 四.编写操作日志切面\增强 五.使用 六.`注意` 一.思路 利用spring aop 对方 ...

  3. Spring AOP自定义注解并获取注解的参数

    环境 springboot:1.5 Intellij IDEA:2021.1 序言 最近有个需求,要做方法层面的权限控制.以前在公司使用的是spring security,然后使用注解 如下: @Pr ...

  4. java @around,Spring AOP基于注解的Around通知

    是一种建议类型,可确保方法执行前后的通知可以运行. 以下是通知的语法: 语法 @Pointcut("execution(* com.yiibai.Student.getAge(..))&qu ...

  5. Spring AOP 自定义注解记录操作日志

    1.自定义注释 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface ...

  6. 使用Spring AOP自定义注解方式实现用户操作日志记录

    1,开发环境 操作系统:Windows 7 JDK:1.8.0_161 Eclipse:Mars.2 Release (4.5.2) 2,自定义注解类UserLog @Target({ElementT ...

  7. spring中自定义注解(annotation)与AOP中获取注解___使用aspectj的@Around注解实现用户操作和操作结果日志

    spring中自定义注解(annotation)与AOP中获取注解 一.自定义注解(annotation) 自定义注解的作用:在反射中获取注解,以取得注解修饰的类.方法或属性的相关解释. packag ...

  8. Java AOP自定义注解

    一.背景 在之前文章:Java注解详解中,主要介绍了注解的含义.作用.以及常用的各类注解.今天主要介绍在Springboot中如何实现一个自定义注解,通过自定义注解去实现一些定制化的需求. 二.了解元 ...

  9. java 外部覆盖内部配置,Spring 与自定义注解、外部配置化的结合使用

    Spring 与自定义注解.外部配置化的结合使用 一.Java注解的简单介绍 注解,也叫Annotation.标注,是 Java 5 带来的新特性. 可使用范围 类.字段.方法.参数.构造函数.包等, ...

最新文章

  1. .net项目发布到本地IIS
  2. 如何快速重置打印队列
  3. 【Hibernate】getHibernateTemplate与getSession的区别以及优缺点
  4. 用Windows组件库文件快速部署Visual C
  5. 牛客挑战赛47 A 一道GCD问题
  6. java shirofilter_Spring项目集成ShiroFilter简单实现权限管理
  7. linux设备驱动中的并发控制
  8. 【华为云技术分享】《跟唐老师学习云网络》—router路咋走啊
  9. 力扣141.环形链表
  10. php自定义tcp协议,如何实现自定义协议?
  11. sharepoint_wf 启动窗口设计,支配给自由域用户
  12. arcgis 批量计算几何_ArcGIS数据统计
  13. 【Flask】flask不能访问静态文件问题
  14. spring cloud入门组件教程
  15. 【设计模式】模板模式
  16. 两年制大专计算机网络技术,湖南都市五年制大专_计算机网络技术专业_2021年报名...
  17. python显示日历_Python 程序显示日历
  18. 借助智能手机应用程序和可穿戴设备在夏季塑造身材
  19. 西安财经大学计算机考研科目,西安财经大学2020年硕士研究生考试复试科目与参考书目...
  20. 2019电商生意经(三):内容化,跨界与反击

热门文章

  1. 10 个必须下载的 Google Chrome 插件
  2. uboot使用命令整理(2016.03)
  3. leetcode 212:单词搜索II
  4. 惠普HP Color LaserJet CP6015 打印机驱动
  5. Go语言适用于Web开发吗
  6. 字符、字节、字符串之间的相互转换
  7. 项目出现红色叹号或红叉
  8. 在Matlab中调整函数和输出图片的位置关系(print)
  9. windows 8 设置
  10. html如何清理缓存图片,H5案例分享:js、css和图片等静态文件更新时如何避免浏览器缓存...