在以前的工作中也使用到AOP , 比如记录日志,短信通知;所以在遇见当前的问题时, 首先想到的是使用Spring的核心AOP机制来解决问题;

其实问题处理起来很简单, 但是有一个问题就是,当前的框架已经搭建好, 已经使用在生产线上,最终要的是该功能涉及到整个项目,如果

不适用AOP机制的话,岂不是我要一个一个文件去修改,代码量大不说,并且还容易出线bug,所以想这种情况,肯定是选择AOP机制来处理


问题:在修改数据库的实体数据时, 根据操作人,来查看权限, 是否有权限修改(权限操作上实际是没问题, 主要是后期客户其它需求的权限验证)

框架:ssh2

数据库:mysql


解决方案:使用MethodInterceptor方法拦截器, 在调用Action 的update函数或者addOrUpdate函数之前进行拦截(项目中修改操作都是在Action的update或者

addOrUpdate函数中操作),从中获取需要修改的实体类,获取操作人, 最后再验证权限;但是,这样会有一个问题,前端每一个请求的参数都是不一样的,并且

实体类型都不一样,拦截到的获取不到实际的参数(实体类,操作人);

改变思路,拦截DAO层,数据库操作(当时因为设计框架时没有service层, 只能是DAO层);实际操作后, 方法拦截器拦截不到,至于原因,百度上很多,

 这里就不啰嗦了;

最后只能,新添加service层, action中调用sevice的update函数,并将需要修改的对象当参数传给service,MethodInterceptor方法拦截器去拦截service,通过

MethodInvocation 获取action传递过来的实体类型, 剩下的就是一些业务逻辑了, 下面贴一下代码:


方法拦截器:UpdateInterceptor:

package com.test.utils;

import com.test.bean_new.personnel.Company;
import com.test.bean_new.personnel.Department;
import com.test.bean_new.personnel.Employee;
import com.test.bean_new.personnel.User;
import com.test.dao_new.EmployeeDAO;
import com.test.dao_new.UserDAO;
import net.sf.json.JSONObject;
import org.aopalliance.intercept.MethodInterceptor; 
import org.aopalliance.intercept.MethodInvocation;
import org.apache.poi.ss.formula.functions.T;
import org.apache.struts2.ServletActionContext;
import org.hibernate.*;

import javax.servlet.http.HttpServletResponse;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by Administrator on 2017/4/13 0013.
 */
public class UpdateInterceptor implements MethodInterceptor  {

    private SessionFactory sessionFactory;


    @Override
    public Object invoke(MethodInvocation invo) throws Throwable {
        Object[] args = invo.getArguments();
        Method method = invo.getMethod();
        if (!"update".equals(method.getName())
                && !"addOrUpdate".equals(method.getName())) {
            Object obj = invo.proceed();
            return obj;
        }
        try {
            UserDAO userDAO = (UserDAO) Utils.getBean("userDAO");
            Object obj = ServletActionContext.getRequest().getSession().getAttribute("userSession");
            String personName = "";
            if (obj != null) {
                Object personNameObj = ((Map) obj).get("userName");
                if (personNameObj != null) {
                    personName = personNameObj.toString();
                }
            }
            User user = userDAO.getUser(personName);
            if(user.getUserGroup() == 3){
                obj = invo.proceed();
                return obj;
            }
            if(null != args && args.length>0){
                obj = args[0];
                Class cls = obj.getClass();
                Field[] fields = cls.getDeclaredFields();
                Field field = null;
                //获取Id
                String fieldName="";
                for(int i=0 ; i< fields.length; i++){
                    field = fields[i];
                    fieldName = field.toString().substring(field.toString().lastIndexOf(" "));
                    fieldName = fieldName.substring(fieldName.lastIndexOf(".")+1);
                    if("id".equals(fieldName)){
                        break;
                    }
                }
                boolean flag = checkPermissionByUpdateUser(field, obj, cls, user);
                if(!flag){
                    //返回权限不足给前端
                    JSONObject json = new JSONObject();
                    json.put("success", false);
                    json.put("msg", "权限不足");
                    HttpServletResponse response = ServletActionContext.getResponse();
                    PrintWriter writer = null;
                    response.setCharacterEncoding("UTF-8");
                    response.setContentType("text/html; charset=utf-8");
                    try {

                        writer = response.getWriter();
                        writer.print(json);

                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        if (writer != null)
                            writer.close();
                    }
                    return null;
                }
                Object reObj =invo.proceed();
                return reObj;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return args;
    }

    /**
     *
     * @param field obj中的属性Id字段
     * @param obj 需要保存的实例对象
     * @return
     * @throws Exception
     */
    private boolean checkPermissionByUpdateUser(Field field, Object obj, Class cls, User user) throws Exception {
        String objName = cls.toString();
        String clsName = objName.substring(objName.lastIndexOf(".")+1);
        PropertyDescriptor pd = new PropertyDescriptor(field.getName(),
                obj.getClass());
        Method getMethod = pd.getReadMethod();
        Object o = getMethod.invoke(obj);//执行get方法返回一个Object

        //获取记录操作人字段名称
        String updateUser = getUpdateUser(cls);
        if(null == updateUser || "".equals(updateUser))
            return false;

        //查询数据库中真实的updateUser
        String sql = "SELECT "+updateUser+" FROM "+clsName + " where id = "+(int)o;

        updateUser = (String) getRealEntity(sql);
        EmployeeDAO employeeDAO = (EmployeeDAO) Utils.getBean("employeeDAO");
        Employee employee = employeeDAO.getEmployeeByName(updateUser);
        if(null != employee){//根据公司来做检查
            Department department = employee.getDepartment();
            Company company = department.getCompany();
            employee = employeeDAO.get(user.getEmployeeId());
            Company company2 = null;
            if(null != employee){
                department = employee.getDepartment();
                company2 = department.getCompany();
            }
            if(company.getId().equals(company2.getId())){
                return true;
            }
        }
        return false;
    }

    private Object getRealEntity(String sql){
        Session session = sessionFactory.openSession();
        List<T> entities = new ArrayList<T>();
        try {
            Query query = createSQLQuery(session, sql);
            entities = query.list();
        } catch (Exception e) {
            e.printStackTrace();
            session.close();
        } finally {
            if (session.isOpen()) {
                session.close();
            }
        }
        if(null != entities && !entities.isEmpty()) return entities.get(0);
        return null;
    }

    private String getUpdateUser(Class cls) throws Exception {
        Field[] fields = cls.getDeclaredFields();
        //获取Id
        for(int i=0 ; i< fields.length; i++){
            Field field = fields[i];
            switch (field.getName()){
                case "updateOperator":
                    return "updateOperator";
                case "updateUser":
                    return "updateUser";
                case "operatorName":
                    return "operatorName";
                case "operateMan":
                    return "operateMan";
                case "operateman":
                    return "operateman";
                case "operatePerson":
                    return "operatePerson";
            }
        }
        return "";
    }


    public SQLQuery createSQLQuery(Session session, String sql, final Object... values) {
        SQLQuery query = session.createSQLQuery(sql);
        if (values != null) {
            for (int i = 0; i < values.length; i++) {
                query.setParameter(i, values[i]);
            }
        }
        return query;
    }

    private String getParamStr(String param) {
        String resultStr = "";
        if (null != ServletActionContext.getRequest().getParameter(param)) {
            try {
                resultStr = URLDecoder.decode(ServletActionContext.getRequest().getParameter(param), "utf-8");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return resultStr;
    }



    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }
}


Service:

package com.test.service.fixasset;

import com.test.bean_new.finance.Fixasset;
import com.test.dao_new.FixassetDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * Created by Administrator on 2017/4/15 0015.
 */
@Component //自动扫描注解spring bean
public class FixassetService {
    @Autowired//自动装配
    private FixassetDAO fixassetDAO;

    public boolean update(Fixasset fixasset){
        boolean flag = fixassetDAO.addOrUpdate(fixasset);
        return flag;
    }

    public FixassetDAO getFixassetDAO() {
        return fixassetDAO;
    }

    public void setFixassetDAO(FixassetDAO fixassetDAO) {
        this.fixassetDAO = fixassetDAO;
    }
}


ApplicationContext.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:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	http://www.springframework.org/schema/tx
	http://www.springframework.org/schema/tx/spring-tx-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/context
    http://www.springframework.org/schema/context/spring-context-4.0.xsd
	">
	<import resource="classpath:applicationContext-*.xml" />
	<context:component-scan base-package="com.test.service.*"></context:component-scan>
	<!--数据库配置信息-->
	<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<!-- 标准配置 -->
				<value>classpath:db.properties</value>
			</list>
		</property>
	</bean>
	<!-- <bean id="lobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler"
		lazy-init="true" /> -->

	<!--dataSource-->
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName" value="${jdbc.driver}" />
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
	</bean>

	<!--数据库事务-->
	<bean id="txManage"
		  class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>
	<tx:advice id="txAdvice" transaction-manager="txManage">
		<tx:attributes>
			<tx:method name="insert*" propagation="REQUIRED" />

			<tx:method name="get*" read-only="true" />
			<tx:method name="find*" read-only="true" />
			<tx:method name="search*" read-only="true" />
			<tx:method name="query*" read-only="true" />
			<tx:method name="add*" propagation="REQUIRED" />
			<tx:method name="del*" propagation="REQUIRED" />
			<tx:method name="update*" propagation="REQUIRED" />
			<tx:method name="do*" propagation="REQUIRED" />
			<tx:method name="save*" propagation="REQUIRED" />
			<tx:method name="saveOrUpdate*" propagation="REQUIRED" />
			<tx:method name="*" propagation="REQUIRED" read-only="true" />
		</tx:attributes>
	</tx:advice>
	<aop:config>
		<aop:pointcut expression="execution(* com.test.dao_new*.*(..))"
					  id="serviceMethod" />
		<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod" />
	</aop:config>

	<!--sessionFactory-->
	<bean id="sessionFactory"
		  class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.connection.autocommit">true</prop>
				<prop key="myeclipse.connection.profile">MySQL</prop>
				<!--<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>-->
				<prop key="hibernate.dialect">com.test.dao_new.MySQLLocalDialect</prop>
				<!--<prop key="hibernate.hbm2ddl.auto">create</prop>-->
				<prop key="hibernate.hbm2ddl.auto">update</prop>
				<prop key="hibernate.myeclipse.connection.profile">true</prop>
				<!-- <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop> -->
			</props>
		</property>
		<property name="mappingLocations">
			<list>
			<!-- 省略-->
			</list>
		</property>
	</bean>

	<!--MethodInterceptor-->
	<bean id="myInterceptor"
		  class="com.test.utils.UpdateInterceptor"
		  abstract="false" lazy-init="false"
		  autowire="default">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>
	<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
		<property name="beanNames">
			<list>
				<value>fixassetService</value><!-- 添加需要拦截的service bean-->
			</list>
		</property>

		<property name="interceptorNames">
			<list>
				<value>myInterceptor</value>
			</list>
		</property>
	</bean>



</beans>