在以前的工作中也使用到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>