`
HotStrong
  • 浏览: 507367 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Spring AOP 完成日志记录

阅读更多

 

Spring AOP 完成日志记录

 

 

1、技术目标

 

 

  • 掌握Spring AOP基本用法
  • 使用Spring AOP完成日志记录功能

 

 

提示:本文所用项目为"影片管理",参看

http://hotstrong.iteye.com/blog/1160153

本文基于"影片管理"项目进行了日志记录功能扩充

 

注意:本文所实现的项目(MyEclipse工程)已提供下载,数据库

脚本可参看《MyBatis 1章 入门(使用MyBatis完成CRUD)》

 

 

2、什么是AOP

 

AOP是Aspect Oriented Programming的缩写,意思是面向方面编程,AOP实际是GoF设计模式的延续

 

注意:关于AOP的详细介绍不是本文重点

 

 

3、关于Spring AOP的一些术语

 

  • 切面(Aspect):在Spring AOP中,切面可以使用通用类或者在普通类中以@Aspect 注解(@AspectJ风格)来实现
  • 连接点(Joinpoint):在Spring AOP中一个连接点代表一个方法的执行
  • 通知(Advice):在切面的某个特定的连接点(Joinpoint)上执行的动作。通知有各种类型,其中包括"around"、"before”和"after"等通知。许多AOP框架,包括Spring,都是以拦截器做通知模型, 并维护一个以连接点为中心的拦截器链
  • 切入点(Pointcut):定义出一个或一组方法,当执行这些方法时可产生通知,Spring缺省使用AspectJ切入点语法。

 

 

4、通知类型

 

  • 前置通知(@Before):在某连接点(join point)之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常)
  • 返回后通知(@AfterReturning):在某连接点(join point)正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回
  • 抛出异常后通知(@AfterThrowing):方法抛出异常退出时执行的通知
  • 后通知(@After):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)
  • 环绕通知(@Around):包围一个连接点(join point)的通知,如方法调用。这是最强大的一种通知类型,环绕通知可以在方法调用前后完成自定义的行为,它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行

 

 

5、@AspectJ风格的AOP配置

 

Spring AOP配置有两种风格:

 

  • XML风格 = 采用声明形式实现Spring AOP 
  • AspectJ风格 = 采用注解形式实现Spring AOP

 

 

注意:本文采用AspectJ风格

 

6、使用准备

闲话少说,下面开始日志记录的准备工作

 

6.1)创建日志记录表(MySQL),

 

 

CREATE TABLE `t_log` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `userid` bigint(20) unsigned NOT NULL,
  `createdate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建日期',
  `content` varchar(8000) NOT NULL DEFAULT '' COMMENT '日志内容',
  `operation` varchar(250) NOT NULL DEFAULT '' COMMENT '用户所做的操作',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 

 

 

6.2)在经过了Spring Security的权限验证后,可以从Security中获取到

登录管理员的帐号,而日志记录表t_log中存储的是管理员id,所以需要通

过管理员的帐号查询出管理员id,创建管理员POJO、Mapper、Service,

代码及配置如下:

 

管理员POJO类:

 

 

package com.xxx.pojo;
public class Admin extends BaseDomain {

	private String nickname;//管理员帐号
	private String passwd;//管理员密码
	private String phoneno;//联系电话

	public String getNickname() {
		return nickname;
	}
	public void setNickname(String nickname) {
		this.nickname = nickname;
	}
	public String getPasswd() {
		return passwd;
	}
	public void setPasswd(String passwd) {
		this.passwd = passwd;
	}
	public String getPhoneno() {
		return phoneno;
	}
	public void setPhoneno(String phoneno) {
		this.phoneno = phoneno;
	}
}

 

 

 

管理员Mapper接口与XML配置文件:

 

 

package com.xxx.dao;

import com.xxx.pojo.Admin;
/**
 * 管理员Mapper接口
 */
public interface AdminMapper {
	/**
	 * 获取指定帐号名的管理员
	 */
	 public Admin findAdminByNickname(String userName);
}

 

 

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xxx.dao.AdminMapper">
	<!-- 通过账号名称查询管理员 -->
	<select id="findAdminByNickname" parameterType="string" resultType="Admin">
	select * from t_admin where nickname=#{userName}
	</select>
</mapper>

 

 

 

管理员Service接口与实现类:

 

 

package com.xxx.service;

import com.xxx.pojo.Admin;

/**
 * 管理员信息业务逻辑接口
 */
public interface AdminService {
	/**
	 * 获取指定帐号名的管理员
	 */
	 public Admin findAdminByNickname(String userName);
}

 

 

package com.xxx.service;

import org.springframework.beans.factory.annotation.Autowired;
import com.xxx.dao.AdminMapper;
import com.xxx.pojo.Admin;

public class AdminServiceImpl implements AdminService {
	@Autowired
	private AdminMapper adminMapper;//Mapper接口
	
	public Admin findAdminByNickname(String userName) {
		return adminMapper.findAdminByNickname(userName);
	}
}

 

 

6.3)创建日志记录POJO、Mapper、Service,代码及配置如下:

 

日志记录POJO类:

 

 

package com.xxx.pojo;

import java.io.Serializable;
import java.util.Date;

/**
 * 日志记录POJO
 */
public class Log extends BaseDomain implements Serializable{
	
	private static final long serialVersionUID = 1024792477652984770L;

	private Long userid;//管理员id
	private Date createdate;//日期
	private String content;//日志内容
	private String operation;//操作(主要是"添加"、"修改"、"删除")
	
	//getter、setter,此处省略N字(你懂的)
}

 

 

 

日志记录Mapper接口与XML配置文件:

 

 

package com.xxx.dao;

import com.xxx.pojo.Log;

/**
 * 日志记录Mapper
 */
public interface LogMapper {
	
	public void insert(Log log);//添加日志记录
}

 

 

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xxx.dao.LogMapper">
	<!-- 添加日志记录 -->
	<insert id="insert" parameterType="Log">
		INSERT INTO t_log(userid,createdate,operation,content)
		VALUES(#{userid},NOW(),#{operation},#{content});
	</insert>
</mapper>

 

 

日志记录Service接口与实现类:

 

 

package com.xxx.service;

import org.springframework.transaction.annotation.Transactional;
import com.xxx.pojo.Log;

/**
 * 日志记录业务逻辑接口
 */
public interface LogService {
	
	/**
	 * 日志记录
	 * @param log
	 */
	@Transactional
	public void log(Log log);
	
	/**
	 * 获取登录管理员ID
	 */
	public Long loginUserId();
}

 

 

package com.xxx.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import com.xxx.dao.LogMapper;
import com.xxx.pojo.Admin;
import com.xxx.pojo.Log;

/**
 * 日志记录业务逻辑接口实现类
 * @author HotStrong
 */
public class LogServiceImpl implements LogService{
	
	@Autowired
	private AdminService adminService;
	
	@Autowired
	private LogMapper logMapper;
	
	public void log(Log log) {
		logMapper.insert(log);
	}
	
	/**
	 * 获取登录管理员ID
	 * 
	 * @return
	 */
	public Long loginUserId() {

		if(SecurityContextHolder.getContext() == null){
			return null;
		}
		
		if(SecurityContextHolder.getContext().getAuthentication() == null){
			return null;
		}
		
		UserDetails userDetails = (UserDetails) SecurityContextHolder
				.getContext().getAuthentication().getPrincipal();
		
		if(userDetails == null){
			return null;
		}
		
		//获取登录管理员帐号名
		String userName = userDetails.getUsername();
		
		if(userName == null || userName.equals("")){
			return null;
		}
		
		// 根据管理员帐号名获取帐号ID
		Admin admin = this.adminService.findAdminByNickname(userName);
		
		if(admin == null){
			return null;
		}
		
		return admin.getId();
	}
}

 

 

 

7、在MyBatis配置文件mybatis-config.xml中配置POJO,如下:

 

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<settings>
		<!-- changes from the defaults -->
		<setting name="lazyLoadingEnabled" value="false" />
	</settings>
	<typeAliases>
		<typeAlias alias="Film" type="com.xxx.pojo.Film"/>
		<typeAlias alias="Admin" type="com.xxx.pojo.Admin"/>
		<typeAlias alias="Log" type="com.xxx.pojo.Log"/>
	</typeAliases>
</configuration>

 

 

 

 

8、创建aop包,在aop包下创建切面类LogAspect

 

 

package com.xxx.aop;

import java.lang.reflect.Method;
import java.util.Date;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;

import com.xxx.pojo.Film;
import com.xxx.pojo.Log;
import com.xxx.service.FilmService;
import com.xxx.service.LogService;

/**
 * 日志记录,添加、删除、修改方法AOP
 * @author HotStrong
 * 
 */
@Aspect
public class LogAspect {
	
	@Autowired
	private LogService logService;//日志记录Service
	
	@Autowired
	private FilmService filmService;//影片Service
	
	/**
	 * 添加业务逻辑方法切入点
	 */
    @Pointcut("execution(* com.xxx.service.*.insert*(..))")
    public void insertServiceCall() { }
    
    /**
	 * 修改业务逻辑方法切入点
	 */
    @Pointcut("execution(* com.xxx.service.*.update*(..))")
    public void updateServiceCall() { }
    
    /**
	 * 删除影片业务逻辑方法切入点
	 */
    @Pointcut("execution(* com.xxx.service.FilmService.deleteFilm(..))")
    public void deleteFilmCall() { }
    
    /**
     * 管理员添加操作日志(后置通知)
     * @param joinPoint
     * @param rtv
     * @throws Throwable
     */
	@AfterReturning(value="insertServiceCall()", argNames="rtv", returning="rtv")
    public void insertServiceCallCalls(JoinPoint joinPoint, Object rtv) throws Throwable{
		
		//获取登录管理员id
		Long adminUserId = logService.loginUserId();
		
		if(adminUserId == null){//没有管理员登录
			return;
		}
		
		//判断参数
		if(joinPoint.getArgs() == null){//没有参数
			return;
		}
		
		//获取方法名
		String methodName = joinPoint.getSignature().getName();
		
		//获取操作内容
		String opContent = adminOptionContent(joinPoint.getArgs(), methodName);
		
		//创建日志对象
		Log log = new Log();
		log.setUserid(logService.loginUserId());//设置管理员id
		log.setCreatedate(new Date());//操作时间
		log.setContent(opContent);//操作内容
		log.setOperation("添加");//操作
		
		logService.log(log);//添加日志
	}
	
	 /**
     * 管理员修改操作日志(后置通知)
     * @param joinPoint
     * @param rtv
     * @throws Throwable
     */
	@AfterReturning(value="updateServiceCall()", argNames="rtv", returning="rtv")
    public void updateServiceCallCalls(JoinPoint joinPoint, Object rtv) throws Throwable{
		
		//获取登录管理员id
		Long adminUserId = logService.loginUserId();
		
		if(adminUserId == null){//没有管理员登录
			return;
		}
		
		//判断参数
		if(joinPoint.getArgs() == null){//没有参数
			return;
		}
		
		//获取方法名
		String methodName = joinPoint.getSignature().getName();
		
		//获取操作内容
		String opContent = adminOptionContent(joinPoint.getArgs(), methodName);
		
		//创建日志对象
		Log log = new Log();
		log.setUserid(logService.loginUserId());//设置管理员id
		log.setCreatedate(new Date());//操作时间
		log.setContent(opContent);//操作内容
		log.setOperation("修改");//操作
		
		logService.log(log);//添加日志
	}
	
	/**
     * 管理员删除影片操作(环绕通知),使用环绕通知的目的是
     * 在影片被删除前可以先查询出影片信息用于日志记录
     * @param joinPoint
     * @param rtv
     * @throws Throwable
     */
	@Around(value="deleteFilmCall()", argNames="rtv")
	public Object deleteFilmCallCalls(ProceedingJoinPoint pjp) throws Throwable {
		
		Object result = null;
	     //环绕通知处理方法
	     try {
	    	
	    	//获取方法参数(被删除的影片id)
	    	Integer id = (Integer)pjp.getArgs()[0];
	 		Film obj = null;//影片对象
	    	if(id != null){
	    		//删除前先查询出影片对象
	    		obj = filmService.getFilmById(id);
	    	}
	 		
	    	//执行删除影片操作
	    	result = pjp.proceed();
	    	
	    	if(obj != null){
	    		
		        //创建日志对象
		    	Log log = new Log();
				log.setUserid(logService.loginUserId());//用户编号
				log.setCreatedate(new Date());//操作时间
				
				StringBuffer msg = new StringBuffer("影片名 : ");
				msg.append(obj.getFname());
				log.setContent(msg.toString());//操作内容
				
				log.setOperation("删除");//操作
				
				logService.log(log);//添加日志
	    	}
	    	
	     }
	     catch(Exception ex) {
	        ex.printStackTrace();
	     }
	     
	     return result;
	}
	
	/**
	 * 使用Java反射来获取被拦截方法(insert、update)的参数值,
	 * 将参数值拼接为操作内容
	 */
	public String adminOptionContent(Object[] args, String mName) throws Exception{

		if (args == null) {
			return null;
		}
		
		StringBuffer rs = new StringBuffer();
		rs.append(mName);
		String className = null;
		int index = 1;
		// 遍历参数对象
		for (Object info : args) {
			
			//获取对象类型
			className = info.getClass().getName();
			className = className.substring(className.lastIndexOf(".") + 1);
			rs.append("[参数" + index + ",类型:" + className + ",值:");
			
			// 获取对象的所有方法
			Method[] methods = info.getClass().getDeclaredMethods();
			
			// 遍历方法,判断get方法
			for (Method method : methods) {
				
				String methodName = method.getName();
				// 判断是不是get方法
				if (methodName.indexOf("get") == -1) {// 不是get方法
					continue;// 不处理
				}
				
				Object rsValue = null;
				try {
					
					// 调用get方法,获取返回值
					rsValue = method.invoke(info);
					
					if (rsValue == null) {//没有返回值
						continue;
					}
					
				} catch (Exception e) {
					continue;
				}
				
				//将值加入内容中
				rs.append("(" + methodName + " : " + rsValue + ")");
			}
			
			rs.append("]");
			
			index++;
		}
		
		return rs.toString();
	}
	
}

 

 

 

9、对管理员登录操作进行日志记录

 

还记得《使用Spring Security实现权限管理》一文中第7步提到的两个类吗?其中LoginSuccessHandler类中可以记录管理员的登录操作,代码如下:

 

 

package com.xxx.security;

import java.io.IOException;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;

import com.xxx.pojo.Log;
import com.xxx.service.LogService;

/**
 * 处理管理登录日志
 *
 */
public class LoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler{
	
	@Autowired
	private LogService logService;//日志记录Service
	
	@Override
	public void onAuthenticationSuccess(HttpServletRequest request,
			HttpServletResponse response, Authentication authentication) throws IOException,
			ServletException {
		
		UserDetails userDetails = (UserDetails)authentication.getPrincipal();
		
		//创建日志对象
		Log log = new Log();
		log.setUserid(logService.loginUserId());//设置管理员id
		log.setCreatedate(new Date());//操作时间
		log.setContent("管理员 " + userDetails.getUsername());//操作内容
		log.setOperation("登录");//操作
		
		logService.log(log);//添加日志
		
		super.onAuthenticationSuccess(request, response, authentication);
	}
	
}

 

 

 

10、在applicationContext-services.xml中加入新的配置

 

applicationContext-services.xml中加入了Aspectj配置以及新增的管理员Service、日志记录Service配置:

 

 

<?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:aop="http://www.springframework.org/schema/aop"
		xmlns:tx="http://www.springframework.org/schema/tx"
		xsi:schemaLocation="
			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
			http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
		
		<!-- 加入Aspectj配置 -->
		<aop:aspectj-autoproxy />
		<bean id="logAspect" class="com.xxx.aop.LogAspect" />
		
		<!-- 电影业务逻辑对象 -->
		<bean id="filmService" class="com.xxx.service.FilmServiceImpl"></bean>	
		
		<!-- 管理员业务逻辑对象 -->
		<bean id="adminService" class="com.xxx.service.AdminServiceImpl"></bean>
		
		<!-- 日志记录业务逻辑对象 -->
		<bean id="logService" class="com.xxx.service.LogServiceImpl"></bean>
		
</beans>

 

 

 

11、配置成功后分别进行登录、添加、修改、删除影片操作,日志记录表的内容如下:

 

 

 

 

参考文章:

MyBatis 1章 入门(使用MyBatis完成CRUD)

使用Spring Security实现权限管理

使用ajax gson增强用户体验

 

 

 

24
5
分享到:
评论
30 楼 nlilewy 2016-11-28  
布置好了项目和数据库弄好了,但是登录就报这个错org.springframework.security.access.AccessDeniedException: 不允许访问 怎么解决呀?
29 楼 it1990eye0920 2016-11-03  
    
28 楼 明明如月 2016-10-31  
楼主,求一份代码,上面给的不能解压,邮箱1141188190@qq.com,十分感谢
27 楼 Mr_Fan 2016-09-20  
楼主,能下载但是不能解压,求楼主发到我邮箱谢谢。楼主787776253@qq.com
26 楼 dewffgqd 2016-08-04  
擦 不加引号就能创建,干鸡毛非要加个引号,擦
25 楼 dewffgqd 2016-08-04  
你那sql语句里的单引号咋打出来的?怎么我的sqlyog打不出来呀?
24 楼 谈笑间 2016-07-28  
楼主大哥,你好!小弟是在校学生,初学Mybatis,研究楼主大哥的项目已经好几天了,可是小弟愚笨,至今还未将项目运行出来,日志管理很重要,所以恳请楼主大哥发一份完整的项目源码,谢谢哥了    小弟邮箱:13014627018@163.com
23 楼 songce 2016-07-22  
  
22 楼 谈笑间 2016-07-14  
21 楼 liuhaixiabj 2016-06-08  
无法运行啊
20 楼 whc321 2016-06-06  
送上一份SQL


DROP TABLE IF EXISTS `film`;
CREATE TABLE `film` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `fname` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

#
# Data for table "film"
#

INSERT INTO `film` VALUES (1,'3'),(2,'2');

#
# Structure for table "t_admin"
#

DROP TABLE IF EXISTS `t_admin`;
CREATE TABLE `t_admin` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `nickname` varchar(255) DEFAULT NULL,
  `passwd` varchar(255) DEFAULT NULL,
  `phoneno` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

#
# Data for table "t_admin"
#

INSERT INTO `t_admin` VALUES (1,'123','123','123');

#
# Structure for table "t_group"
#

DROP TABLE IF EXISTS `t_group`;
CREATE TABLE `t_group` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `groupname` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

#
# Data for table "t_group"
#

INSERT INTO `t_group` VALUES (1,'超级管理员');

#
# Structure for table "t_group_role"
#

DROP TABLE IF EXISTS `t_group_role`;
CREATE TABLE `t_group_role` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `roleid` int(11) DEFAULT NULL,
  `groupid` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

#
# Data for table "t_group_role"
#

INSERT INTO `t_group_role` VALUES (1,1,1);

#
# Structure for table "t_group_user"
#

DROP TABLE IF EXISTS `t_group_user`;
CREATE TABLE `t_group_user` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `groupid` int(11) DEFAULT NULL,
  `userid` int(11) DEFAULT NULL,
  PRIMARY KEY (`Id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

#
# Data for table "t_group_user"
#

INSERT INTO `t_group_user` VALUES (1,1,1);

#
# Structure for table "t_log"
#

DROP TABLE IF EXISTS `t_log`;
CREATE TABLE `t_log` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `userid` int(11) DEFAULT NULL,
  `createdate` datetime DEFAULT NULL,
  `content` varchar(255) DEFAULT NULL,
  `operation` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

#
# Data for table "t_log"
#

INSERT INTO `t_log` VALUES (1,1,'2016-06-06 13:22:08','管理员 123','登录'),(2,1,'2016-06-06 13:23:20','管理员 123','登录'),(3,1,'2016-06-06 13:25:08','管理员 123','登录'),(4,1,'2016-06-06 13:42:12','管理员 123','登录'),(5,1,'2016-06-06 13:44:51','insertFilm[参数1,类型:Film,值:(getFname : 1)]','添加'),(6,1,'2016-06-06 13:47:13','insertFilm[参数1,类型:Film,值:(getFname : 2)]','添加'),(7,1,'2016-06-06 13:48:43','updateFilm[参数1,类型:Film,值:(getFname : 3)]','修改');

#
# Structure for table "t_role"
#

DROP TABLE IF EXISTS `t_role`;
CREATE TABLE `t_role` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `role` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

#
# Data for table "t_role"
#

INSERT INTO `t_role` VALUES (1,'老板');

#
# Structure for table "t_user_role"
#

DROP TABLE IF EXISTS `t_user_role`;
CREATE TABLE `t_user_role` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `userid` int(11) DEFAULT NULL,
  `roleid` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

#
# Data for table "t_user_role"
#

INSERT INTO `t_user_role` VALUES (1,1,1);

19 楼 zhaojiacan 2016-05-10  
大哥提供一份sql 嘛
18 楼 sql_aries 2016-03-02  
sdsdsdsdsdd
17 楼 xiaobadi 2016-03-01  
这是个web项目吗?为啥server里无法找到。。
16 楼 u014392175 2015-11-22  
楼主,能下载但是不能解压,求楼主发到我邮箱谢谢。楼主1156886879@qq.com
15 楼 chenchunlin526 2015-11-21  
数据库和表的sql语句呢,没提供啊
14 楼 mefly 2015-11-04  
86132587 写道
楼主,拦截insert方法不会引起循环拦截日志的insert操作吗,这个如何避免,我没看明白?


他方法名是log 不是insertXXX ,所以绕过了这问题
13 楼 86132587 2015-10-29  
楼主,拦截insert方法不会引起循环拦截日志的insert操作吗,这个如何避免,我没看明白?
12 楼 869642759 2015-09-08  
/mysit7/login.jsp
这个是项目入口
11 楼 kongjianqingwa 2015-06-12  
我邮箱kongjianqingwa@163.com.谢谢了!

相关推荐

Global site tag (gtag.js) - Google Analytics