SSM框架 -- Spring -- aop&jdbcTemplate

Spring AOP&jdbcTemplate

1 sping的aop
		1:aop的底层--动态代理(理解)
	    2: 使用spring提供好的aop做业务增强(  xml  半xml半注解  )		     			
2 spring提供的dao操作数据库的手段--JDBCTemplate

一 转账案例

​ 业务代码和事务代码进行拆分,通过动态代理的方式,对业务方法进行事务的增强。这样就不会对业务层产生影响,解决了耦合性的问题啦!(在不修该原方法的基础上,对原方法进行增强)

常用的动态代理技术

JDK 代理 : 基于接口的动态代理技术

条件:必须要有接口
生成的动态代理对象和被代理对象是兄弟关系

CGLIB代理:基于父类的动态代理技术

条件:被代理对象不能使用final修饰
导入cglib的坐标(spring坐标整合好了)
生成的动态代理对象是被代理对象的子类

在这里插入图片描述

1)JDK动态代理

在这里插入图片描述

JdkProxy

/**
 * jdk动态代理技术工厂
 */
@Component
public class JdkProxy {

    @Autowired
    @Qualifier("accountServiceImpl")
    private AccountService accountService;

    @Autowired
    private TransactionManager transactionManager;

    @Bean("AccountServiceProxy")
    public Object getProxy(){

        Object objProxy = Proxy.newProxyInstance(accountService.getClass().getClassLoader(),
                accountService.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        Object value=null;
                        try {

                            transactionManager.begin();
                            value = method.invoke(accountService, args);
                            transactionManager.commit();

                        }catch (Exception e){
                            e.printStackTrace();
                            transactionManager.rollback();
                        }finally {
                            transactionManager.close();
                        }
                        return value;
                    }
                });

        return objProxy;

    }
}

SpringJunitTest

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:application.xml")
public class SpringJunitTest2 {

    @Autowired
    @Qualifier("AccountServiceProxy") //代理对象--jdk
    private AccountService accountService;

    @Test
    public void test1() throws SQLException {
        accountService.tranfer();
    }

}
2)Cglib动态代理

spring的jar包,是包含cglib依赖
在这里插入图片描述

CglibProxy

@Component
public class CglibProxy {

    @Autowired
    @Qualifier("accountServiceImpl")
    private AccountServiceImpl accountService;

    @Autowired
    private TransactionManager transactionManager;

    @Bean("accountProxy")
    public Object getCglibProxy(){

        Object object =Enhancer.create(accountService.getClass(), new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

                Object value = null;
                try {

                    transactionManager.begin();
                    value = methodProxy.invoke(accountService, objects);
                    transactionManager.commit();

                } catch (Exception e) {
                    e.printStackTrace();
                    transactionManager.rollback();
                } finally {
                    transactionManager.close();
                }

                return value;
            }
        });

        return object;
    }

}

SpringJunitTest

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:application.xml")
public class SpringJunitTest2 {

    @Autowired
    @Qualifier("accountProxy") //代理对象--cglib
    private AccountServiceImpl accountService;

    @Test
    public void test1() throws SQLException {
        accountService.tranfer();
    }

}

二 Spring的AOP简介

AOP:面向切面编程是软件开发的一种思想

目的:代码之间的解耦,在不破坏源代码的情况下,对源代码实现业务增强。

springAOP的底层:动态代理

springAOP的相关术语

Target(目标对象):  要被增强的对象

Proxy(代理对象) :  对增强对象的封装对象

Joinpoint(连接点):  目标对象的一个一个方法

Pointcut(切入点):   目标对象要被增强的那个方法

Advice(通知/增强): 增强方法 
前置通知
后置通知
异常通知
最终通知
    
环绕通知



Aspect(切面): 切入点+通知=切面 (目标方法和增强方法合成在一起 叫做切面)

Weaving(织入):将切入点集成到切面的这一个过程 我们称为织入过程
将目标方法和增强方法合成在一起的过程 叫织入过程 (底层实现技术就是动态代理)

三 基于XML的AOP开发【重点】

导入坐标

<dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.13</version>
 </dependency>

<!--通知类-->
        <bean id="adviceConfig" class="cn.itcast.advice.AdviceConfig"></bean>
        <!--spring的aop:
                       关注点1:通知(增强方法)
                       关注点2:织入(将通知和切入点合并成切面的过程) 使用aop标签
                                // 将增强方法和目标方法合同在一起的过程

        -->


        <!--aop的置入-->
         <aop:config>
                 <!--指向通知-->
                 <aop:aspect ref="adviceConfig">
                         <!--
                                before:之前
                                method:通知类中的某个方法
                                pointcut:指向的是切入点(要增强的方法)

                                表达式:
                                    execution(public void cn.itcast.serviceimpl.AccountServiceImpl.save(..))
                                修饰符:可以省略不写
                                返回值:可以使用通配符
                                包名:cn.itcast.serviceimpl
                                         可以使用通配符代替 但是只能代替一个

                                类名:AccountServiceImpl
                                         可以使用通配符代替 但是只能代替一个

                                方法名:save(..)
                                          可以使用通配符代替 但是只能代替一个

                                       通配符:* 可以代替所有
                                        ..:用于方法参数  用于包名
                                        方法参数:代表参数可有可无
                                        包名:cn.. 带表cn下的所有子包 cn.itcast.. 带表是cn.itcast下的所有子包
                         -->
                        <!--抽取切入点-->
                        <aop:pointcut id="pt" expression="execution(* cn.itcast.*.AccountServiceImpl.*(..))"></aop:pointcut>

                        <!--前置 后置  异常 最终 顺序无序 建议单独使用-->
                        <aop:before method="before" pointcut-ref="pt"></aop:before>
                        <aop:after-returning method="afterReturning" pointcut-ref="pt"></aop:after-returning>
                        <aop:after-throwing method="afterThrowing" pointcut-ref="pt"></aop:after-throwing>
                        <aop:after method="after" pointcut-ref="pt"></aop:after>

                        <!--环绕通知-->
                       <!-- <aop:around method="around" pointcut="execution(public void cn.itcast.serviceimpl.AccountServiceImpl.save(..))"></aop:around>-->
                 </aop:aspect>
         </aop:config>

四 基于注解的AOP开发

1 开启aop的注解

 <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

2 在通知类添加注解

@Aspect
public class AdviceConfig {
  ....
}

3 在每个通知方法上添加切入点表达式

public class AdviceConfig {


    /*抽取切入点表达式:
    *       定义无参无返回值无内容的方法
    *               在方法头上加统一注解:@Pointcut("execution(* cn.itcast.*.AccountServiceImpl.save(..))")
    *                谁用谁调方法名
    *
    * */
    @Pointcut("execution(* cn.itcast.*.AccountServiceImpl.save(..))")
    public void pt(){}

    //通知
    //@Before("pt()")
    public void before(){
        System.out.println("之前。。。");
    }

    //通知
    
  	//@AfterReturning("pt()")
    public void afterReturning(){
        System.out.println("之后。。。");
    }

    //通知
    //@AfterThrowing("pt()")
    public void afterThrowing(){
        System.out.println("异常。。。");
    }

    //通知
    //@After("pt()")
    public void after(){
        System.out.println("最终。。。");
    }


    // 通知--给环绕用
    @Around("pt()")
    public void around(ProceedingJoinPoint pj){

        try {
            // 之前
            System.out.println("之前。。。");
            // 原方法
            pj.proceed(); //invoke
            // 之后
            System.out.println("之后。。。");

        }catch (Throwable e){
            e.printStackTrace();
            System.out.println("异常。。。");
        }finally {
            System.out.println("最终。。。");
        }
    }
}

4 抽取切入点表达式

  /*抽取切入点表达式:
    *       定义无参无返回值无内容的方法
    *               在方法头上加统一注解:@Pointcut("execution(* cn.itcast.*.AccountServiceImpl.save(..))")
    *                谁用谁调方法名
    *
    * */
    @Pointcut("execution(* cn.itcast.*.AccountServiceImpl.save(..))")
    public void pt(){}
    
    
     // 通知--给环绕用
    @Around("pt()")
    public void around(ProceedingJoinPoint pj){

        try {
            // 之前
            System.out.println("之前。。。");
            // 原方法
            pj.proceed(); //invoke
            // 之后
            System.out.println("之后。。。");

        }catch (Throwable e){
            e.printStackTrace();
            System.out.println("异常。。。");
        }finally {
            System.out.println("最终。。。");
        }
    }

全注解开发:

@EnableAspectJAutoProxy 配置类上填写该注解  会扫描带有Aspect注解的内容

@Configuration
@ComponentScan(basePackages = "cn.itcast") 
@EnableAspectJAutoProxy  
public class SpringConfig {
}


五 spring的aop优化转账

1 aop的全xml方式

application.xml

 <!--aop的xml方式:
            关注点:通知
            关注点:织入
    -->
    <bean id="transactionManager" class="cn.itcast.utils.TransactionManager"></bean>

    <aop:config>
        <aop:aspect ref="transactionManager">
            <aop:pointcut id="pt" expression="execution(* cn.itcast.serviceimpl.AccountServiceImpl.tranfer(..))"></aop:pointcut>
              <aop:around method="around" pointcut-ref="pt"></aop:around>
        </aop:aspect>
    </aop:config>

TransactionManager

 public void around(ProceedingJoinPoint pjp){
        try {
            begin();
            pjp.proceed();
            commit();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            rollback();
        }finally {
            close();
        }
    }

2 aop的半xml半注解方式

application.xml

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

TransactionManager

@Component
@Aspect
public class TransactionManager {

    @Autowired
    private ThreadLocalUtils tl;

    // 开启事务
    public void begin(){
        try {
            tl.getConnection().setAutoCommit(false);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    // 提交事务
    public void commit(){
        try {
            tl.getConnection().commit();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    // 回滚事务
    public void rollback(){
        try {
            tl.getConnection().rollback();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    // 释放资源
    public void close(){
        try {
            tl.getConnection().close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }


    @Pointcut("execution(* cn.itcast.serviceimpl.AccountServiceImpl.tranfer(..))")
    public void pt(){}

    @Around("pt()")
    public void around(ProceedingJoinPoint pjp){

        try {
            begin();
            pjp.proceed();
            commit();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            rollback();
        }finally {
            close();
        }
    }
}

六 spring整合JdbcTemplate

jdbcTemplate:spring提供的用来操作数据库的工具

构造:new JdbcTemplate(连接池)
api:
	update() 增删改
	queryForObject() 单查
	query()多查

整合步骤

1 导入jdbcTemplate的坐标

<!--jdbcTemplate-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.1.5.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>5.1.5.RELEASE</version>
    </dependency>

2 整合jdbcTemplate(application.xml)

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

        <!--开启注解扫描-->
        <context:component-scan base-package="cn.itcast"></context:component-scan>

        <!--第三方的资源-->
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
                <property name="dataSource" ref="druid"></property>
        </bean>
        <!--druid-->
        <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
        <bean id="druid" class="com.alibaba.druid.pool.DruidDataSource">
                <property name="driverClassName" value="${jdbc.driver}"></property>
                <property name="url" value="${jdbc.url}"></property>
                <property name="username" value="${jdbc.username}"></property>
                <property name="password" value="${jdbc.password}"></property>
        </bean>
</beans>

AccountDaoImpl

@Repository
public class AccountDaoImpl implements AccountDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public void save() {
        /*增加
        String sql="insert into account(name,money) values(?,?)";
        jdbcTemplate.update(sql,"老王2",100);*/


        //单查询--返回对象
        /*String sql="select * from account where id=?";
        Account account = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Account>(Account.class), 1);
        System.out.println(account);*/


        //多查--返回list
        String sql="select * from account";
        List<Account> list = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Account>(Account.class));
        for (Account account : list) {
            System.out.println(account);
        }

    }
}

SpringJunitTest1测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:application.xml")
public class SpringJunitTest1 {

    @Autowired
    private AccountService accountService;

    @Test
    public void test(){
        accountService.save();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,需要在项目中添加xxl-sso-client的依赖,可以通过Maven或者手动添加jar包的方式。然后,在Spring配置文件中配置xxl-sso-client的相关信息,如下所示: ``` <!-- 配置xxl-sso-client --> <bean id="xxlSsoClient" class="com.xxl.sso.client.filter.XxlSsoClientFilter"> <property name="serverUrlPrefix" value="${sso.server.url.prefix}" /> <property name="clientId" value="${sso.client.id}" /> <property name="clientSecret" value="${sso.client.secret}" /> <property name="logoutPath" value="${sso.client.logout.path:/logout}" /> <property name="loginPath" value="${sso.client.login.path:/login}" /> <property name="excludes" value="${sso.client.excludes}" /> </bean> <!-- 配置拦截器 --> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**" /> <bean class="com.xxl.sso.client.filter.XxlSsoClientInterceptor"> <property name="xxlSsoClient" ref="xxlSsoClient" /> </bean> </mvc:interceptor> </mvc:interceptors> ``` 其中,`${sso.server.url.prefix}`为xxl-sso-server的地址前缀,`${sso.client.id}`和`${sso.client.secret}`为xxl-sso-client的身份识别信息,`${sso.client.logout.path}`和`${sso.client.login.path}`为退出登录和登录的路径,`${sso.client.excludes}`为不需要拦截的路径。 最后,在Controller中添加`@XxlSsoClient`注解,表示该接口需要进行身份认证。 ``` @Controller public class UserController { @XxlSsoClient @RequestMapping("/user/info") @ResponseBody public String userInfo(HttpServletRequest request) { // 获取用户信息 XxlSsoUser xxlUser = (XxlSsoUser) request.getAttribute(XxlSsoConstant.XXL_SSO_USER); return "user info: " + xxlUser.toString(); } } ``` 以上就是集成xxl-sso到SSM框架中的步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值