Spring aop +自定义annotation

Spring aop +自定义注解

一.所需的jar 包

<!-- 导入java ee jar 包 --> 
<dependency>  
      <groupId>javax</groupId>  
      <artifactId>javaee-api</artifactId>  
      <version>7.0</version>  
</dependency>  
<!--spring ,springmvc-->
<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>4.2.6.RELEASE</version>
</dependency>
<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>4.2.6.RELEASE</version>
      </dependency>
<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>4.2.6.RELEASE</version>
</dependency>
<dependency>  
      <groupId>org.springframework</groupId>  
      <artifactId>spring-core</artifactId>  
      <version>4.2.6.RELEASE</version>  
</dependency> 
<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>4.2.6.RELEASE</version>
</dependency>
<dependency>  
      <groupId>org.springframework</groupId>  
      <artifactId>spring-tx</artifactId>  
      <version>4.2.6.RELEASE</version>  
</dependency>
<pre name="code" class="html"><!--spring jdbc-->
<dependency>  
      <groupId>org.springframework</groupId>  
      <artifactId>spring-jdbc</artifactId>  
      <version>4.2.6.RELEASE</version>  
</dependency>
<!--mybatis-->
<dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.2.8</version>
      </dependency>
 <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>1.2.3</version>
</dependency>
<!-- 导入Mysql数据库链接jar包 -->  
<dependency>  
      <groupId>mysql</groupId>  
      <artifactId>mysql-connector-java</artifactId>  
      <version>5.1.30</version>  
</dependency>  
<!-- dbcp -->  
<dependency>  
      <groupId>commons-dbcp</groupId>  
      <artifactId>commons-dbcp</artifactId>  
      <version>1.2.2</version>  
</dependency>
<!--c3p0--> 
<dependency>
      <groupId>com.mchange</groupId>
      <artifactId>c3p0</artifactId>
      <version>0.9.5.2</version>
</dependency>
<!-- json -->  
<dependency>  
      <groupId>org.codehaus.jackson</groupId>  
      <artifactId>jackson-mapper-asl</artifactId>  
      <version>1.9.13</version>  
</dependency> 
<!-- jackson -->
<dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.7.4</version>
</dependency>
<dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.7.4</version>
</dependency>
<!-- 上传组件包 -->  
<dependency>  
      <groupId>commons-fileupload</groupId>  
      <artifactId>commons-fileupload</artifactId>  
      <version>1.3.1</version>  
</dependency>  
<dependency>  
      <groupId>commons-io</groupId>  
      <artifactId>commons-io</artifactId>  
      <version>2.4</version>  
</dependency>  
<dependency>  
      <groupId>commons-codec</groupId>  
      <artifactId>commons-codec</artifactId>  
      <version>1.9</version>  
</dependency> 
<!-- c标签 -->
<dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
</dependency>
<!--aop: aspect -->
<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>4.2.6.RELEASE</version>
</dependency>
<dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>1.8.6</version>
</dependency>
<dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.8.6</version>
</dependency>

二 xml 配置
1.web.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
    <context-param>
        <param-name>webAppRootKey</param-name>
        <param-value>springmaven.root</param-value>
    </context-param>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-mybatis.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
    </listener>
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:dispatcher-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

</web-app>

2.dispatcher-servlet 配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc" 
    xmlns:tx="http://www.springframework.org/schema/tx" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 
    http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.0.xsd 
    http://www.springframework.org/schema/mvc 
    http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd 
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

    <!-- 自动扫描包 -->
    <context:component-scan base-package="org.com.order.controller" />
    <context:component-scan base-package="org.com.order.service.impl" />

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/view/" />
        <property name="suffix" value=".jsp" />
    </bean>
     <!-- 资源文件 -->
    <mvc:resources location="/css/" mapping="/css/**"/>
    <mvc:resources location="/js/" mapping="/js/**"/>
    <mvc:resources location="/images/" mapping="/images/**"/>
    <mvc:resources location="/fonts/" mapping="/fonts/**"/>
    <!-- 注解 -->
    <mvc:annotation-driven/>
    <!-- 配置拦截器 -->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/type/*" />
            <mvc:mapping path="/operate/*" />
            <mvc:mapping path="/term/*" />
            <mvc:mapping path="/system/*" />
            <bean class="org.com.order.interceptor.MyLoginInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>
    <!-- aop配置 -->
    <aop:aspectj-autoproxy proxy-target-class="true"/> 
    <bean id="systemlogaspect" class="org.com.order.aop.SystemLogAspect"></bean>
</beans>
  1. spring-mybatis.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-3.0.xsd   
    http://www.springframework.org/schema/context   
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/aop        
    http://www.springframework.org/schema/aop/spring-aop-3.2.xsd" 
    default-autowire="byName" default-lazy-init="false">

    <!-- 创建SqlSessionFactory,同时指定数据源 -->  
    <bean id="mySqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  
        <property name="dataSource" ref="dataSource" />  
        <!-- 自动扫描entity目录, 省掉Configuration.xml里的手工配置 
        <property name="mapperLocations" value="classpath*:maper/*.map.xml" />-->

        <!-- 手动配置map.xml -->
        <property name="configLocation" value="classpath:mybatis-config.xml">
        </property>
    </bean> 

    <!-- DAO接口所在包名,Spring会自动查找其下的类   --> 
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">  
        <property name="basePackage" value="org.com.order.dao" />
        <property name="sqlSessionFactoryBeanName" value="mySqlSessionFactory" />
    </bean>

    <!-- c3p0连接池 -->
    <!-- 引入jdbc配置文件 -->  
    <context:property-placeholder location="classpath:jdbc.properties" /> 
    <bean id="dataSource"  
        class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">  
        <property name="driverClass" value="${jdbc.driverClass}"></property>  
        <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>  
        <property name="user" value="${jdbc.user}"></property>  
        <property name="password" value="${jdbc.password}"></property>  
        <property name="minPoolSize" value="${jdbc.minPoolSize}"></property>
        <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
        <property name="initialPoolSize" value="${jdbc.initialPoolSize}"></property>
        <property name="maxIdleTime" value="${jdbc.maxIdleTime}"></property>
        <property name="acquireIncrement" value="${jdbc.acquireIncrement}"></property>
    </bean>  

    <!-- aop -->
    <!-- 方式一 交给ProxyFactoryBean管理 -->
    <!-- 
    <bean id="human" class="org.com.order.aop.Human"></bean>
    <bean id="sleepHelper" class="org.com.order.aop.SleepHelper"></bean>
    <bean id="spleepPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
        <property name="pattern" value=".*sleep"/>
    </bean>
    <bean id="sleepHelperAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
        <property name="advice" ref="sleepHelper"/>
        <property name="pointcut" ref="spleepPointcut"/>
    </bean>
    <bean id="humanProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="human"/>
        <property name="interceptorNames" value="sleepHelperAdvisor" />
        <property name="proxyInterfaces" value="org.com.order.aop.Sleepable" />
    </bean>
     -->
    <!-- 方式二 apsect注解 (这个要放在dispatcher-servlet.xml里面)-->
    <aop:aspectj-autoproxy proxy-target-class="true"/>  
    <bean id="systemlogaspect" class="org.com.order.aop.SystemLogAspect"></bean>
    -->

    <!--方式三 apsect xml配置,不需要注解 -->
    <!--  
    <bean id="sleepHelper" class="org.com.order.aop.SleepHelper"></bean>
    <bean id="human" class="org.com.order.aop.Human"></bean>
    <aop:config>
        <aop:aspect ref="sleepHelper">
            <aop:before method="beforeSleep" pointcut="execution(* *.sleep(..))&&@annotation(log)"/>
            <aop:after method="afterSleep" pointcut="execution(* *.sleep(..))"/>
        </aop:aspect>
    </aop:config>
    -->

    <!-- (事务管理)transaction manager, use JtaTransactionManager for global tx -->  
    <bean id="transactionManager"  
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
        <property name="dataSource" ref="dataSource" />  
    </bean> 

    <!-- 开启事务管理注解配置   -->
    <tx:annotation-driven transaction-manager="transactionManager"/> 
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="find*" propagation="REQUIRED" read-only="true"/>
            <tx:method name="get*" propagation="REQUIRED" read-only="true"/>
            <tx:method name="add*" propagation="REQUIRED" />
            <tx:method name="delete*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED" />
            <tx:method name="save*" propagation="REQUIRED" />
          </tx:attributes>
    </tx:advice>
</beans>
  1. mybatis-config.xml配置
<?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>  
    <mappers>  
        <mapper resource="org/com/order/map/ordermapper.xml"/> 
    </mappers> 
</configuration>
  1. jdbc.properties
#mysql c3p0
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql://127.0.0.1:3306/mqtttest?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true
jdbc.user=root
jdbc.password=123456
#最小连接数
jdbc.minPoolSize=5
#定义最大连接数  
jdbc.maxActive=20 
#定义最大空闲  
jdbc.maxIdle=20  
#连接池中保留的最大连接数。Default: 15
jdbc.maxPoolSize=30
#初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3
jdbc.initialPoolSize=10
#最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0
jdbc.maxIdleTime=60
#当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 
jdbc.acquireIncrement=5
jdbc.initialSize=0  
#定义最小空闲  
jdbc.minIdle=1  
#定义最长等待时间  
jdbc.maxWait=60000 

三.java 代码
1.首先定义自定义注解类

package org.com.order.aop;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import org.springframework.stereotype.Component;
import java.lang.annotation.ElementType;   
import java.lang.annotation.RetentionPolicy;   
/**
 * @author admin
 * 自定义注解类
 */
@Target({ElementType.METHOD,ElementType.TYPE})   
@Retention(RetentionPolicy.RUNTIME)   
@Documented 
@Component
public @interface MyLogAnnotation {
    //自定义注解的属性,default是设置默认值
    String desc() default "";   
    String msg() default "";   
}

2.定义切面方法

package org.com.order.aop;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.com.order.model.SystemOplog;
import org.com.order.service.SystemLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Aspect
@Component
public class SystemLogAspect{

    @Autowired
    private SystemLogService systemlogservice;

     /*
     * execution(* org.com.order.controller..*.*(..))&&@annotation(log)
     * 表示切点关联表达式,位于org.com.order.controller包下的 并且添加自定义注解 的方法运行
     * @Aspect 表示切面类
     */ 

    /*
     * 切点方法之后切面处理
     */
    @AfterReturning("execution(* org.com.order.controller..*.*(..))&&@annotation(log)")
    public void  aftermethod(JoinPoint jp,MyLogAnnotation log){
        //获取httprequest
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();
        //获取session
        HttpSession session = request.getSession();
        String username = (String) session.getAttribute("user");
        if(username!=null && !"".equals(username)){
            String ip = request.getRemoteAddr();
            try{
                Object[] args = jp.getArgs();
                List<String> arglist = new ArrayList<String>();
                //获取第一个参数值
                String str = args[0].tostring();
                String content = log.msg() + ", 关键字:"+str;
                SystemOplog sol = new SystemOplog();
                sol.setAct_method(log.desc());
                sol.setIpaddress(ip);
                sol.setDate_created(new Date());
                sol.setUsername(username);
                sol.setRetroaction(content);
                systemlogservice.savetoSystemlog(sol);
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }   
    /*
     * 切点方法异常处理
     */
    @AfterThrowing("execution(* org.com.order.controller..*.*(..))&&@annotation(log)")
    public void  mythrowing(JoinPoint jp,MyLogAnnotation log){
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();
        HttpSession session = request.getSession();
        String username = (String) session.getAttribute("user");
        if(username!=null && !"".equals(username)){
            String ip = request.getRemoteAddr();
            String content = "操作异常";
            SystemOplog sol = new SystemOplog();
            sol.setAct_method(log.desc());
            sol.setIpaddress(ip);
            sol.setDate_created(new Date());
            sol.setUsername(username);
            sol.setRetroaction(content);
            systemlogservice.savetoSystemlog(sol);
        }
    }
}

3.切点方法添加注解

package org.com.order.controller;

import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpSession;
import org.com.order.aop.MyLogAnnotation;
import org.com.order.model.User;
import org.com.order.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author admin
 * 登录页面
 */
@Controller
public class LoginController {
    @Autowired
    private UserService userservice;
    /*
     * 登录验证
     */
    @RequestMapping(value="/login.do")
    @MyLogAnnotation(desc="登录",msg="用户登录操作")
    public String login(String username,String password,HttpSession session){
        String pwd = "";
        int privilege_id = 0;
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("username", username);
        User user = null;
        try{
            user = userservice.getUser(map);
            pwd = user.getPassword().trim();
            privilege_id = user.getPrivilege_id();
            if(password.equals(pwd) && 1==privilege_id){
                session.setAttribute("user", username);
                return "redirect:/term/orderlist.do";
            }else{
                return "login";
            }
        }catch(Exception e){
            e.printStackTrace();
            return "error/error500";
        }
    }
}

四.当执行到切点方法时,切面方法就会执行(切点方法执行前后)。关于切点切面的概念.可以类比高数的左右极限。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
首先,我们需要定义一个自定义注解 `@RequiresPermissions`,用于标识需要授权访问的方法,例如: ```java @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface RequiresPermissions { String[] value(); // 权限值 } ``` 然后,我们需要实现一个切面,用于拦截被 `@RequiresPermissions` 标识的方法,并进行权限校验,例如: ```java @Component @Aspect public class PermissionCheckAspect { @Autowired private AuthService authService; @Around("@annotation(requiresPermissions)") public Object checkPermission(ProceedingJoinPoint joinPoint, RequiresPermissions requiresPermissions) throws Throwable { // 获取当前用户 User user = authService.getCurrentUser(); if (user == null) { throw new UnauthorizedException("用户未登录"); } // 获取当前用户的权限列表 List<String> permissions = authService.getUserPermissions(user); // 校验权限 for (String permission : requiresPermissions.value()) { if (!permissions.contains(permission)) { throw new ForbiddenException("没有访问权限:" + permission); } } // 执行目标方法 return joinPoint.proceed(); } } ``` 在切面中,我们首先通过 `AuthService` 获取当前用户及其权限列表,然后校验当前用户是否拥有被 `@RequiresPermissions` 标识的方法所需的所有权限,如果没有则抛出 `ForbiddenException` 异常,如果有则继续执行目标方法。 最后,我们需要在 Spring 配置文件中启用 AOP 自动代理,并扫描切面所在的包,例如: ```xml <aop:aspectj-autoproxy /> <context:component-scan base-package="com.example.aspect" /> ``` 这样,我们就通过 Spring AOP自定义注解模拟实现了类似 Shiro 权限校验的功能。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值