ssm(模板)

Spring

Spring jdbcTemplate

1.1JdbcTemplate概述

​ 它是spring框架中提供的一个对象,是对原始繁琐的JdbcAPI对象的简单封装。spring框架为我们提供了很多的操作模板类。

1.2JdbcTemplate开发步骤

​ ①导入spring-jdbc和spring-tx坐标

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.2.6.RELEASE</version>
        </dependency>

​ ②创建数据库表和实体

此处省略,创建对象和创建一个表相信大家都会,我创建的是一个Account对象,里面有name和money俩个属性,数据类型分别是String类型和Double类型;数据库的表也是account表,表中字段是varchar属性的name,double属性的money

​ ③创建JdbcTemplate对象

    @Test
    //测试JdbcTemplate开发步骤
    public void test1() throws PropertyVetoException {
        //创建数据源对象
        ComboPooledDataSource dataSource=new ComboPooledDataSource();
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
        dataSource.setUser("root");
        dataSource.setPassword("root");
        JdbcTemplate jdbcTemplate=new JdbcTemplate();
        //设置数据源对象  知道数据库在哪里
        jdbcTemplate.setDataSource(dataSource);
        //执行操作
        int tom = jdbcTemplate.update("insert into account values (?,?)", "Tom", 5000);
        System.out.println(tom);
    }
}

​ ④执行数据库操作

        //执行操作
        int tom = jdbcTemplate.update("insert into account values (?,?)", "Tom", 5000);
        System.out.println(tom);

1.3spring容器产生模板对象代码实现

    <!--数据源对象-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
        <property name="user" value="root"></property>
        <property name="password" value="root"></property>
    </bean>

    <!--jdbc模板对象-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    @Test
    //测试Spring产生jdbcTemp;ate对象
    public void test2(){
        ApplicationContext app=new ClassPathXmlApplicationContext("application.xml");
        JdbcTemplate bean = app.getBean(JdbcTemplate.class);
        int count = bean.update("insert into account values (?,?)", "zhangsan", 5000);
        System.out.println(count);
    }

1.4抽取jdbc.properties文件

写一个jdbc.properties文件,在里面写上连接数据库的参数

<?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:context="http://www.springframework.org/schema/context"//引入context命名空间代码
       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命名空间代码

    <!--加载properties-->
    <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
    <!--数据源对象-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${driver}"></property>
        <property name="jdbcUrl" value="${url}"></property>
        <property name="user" value="${user}"></property>
        <property name="password" value="${password}"></property>
    </bean>

    <!--jdbc模板对象-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
</beans>

1.5对数据的更新操作

利用spring提供的内核进行测试

@RunWith(SpringJUnit4ClassRunner.class)//这里RunWith注解代表的是谁来跑这个测试类,这里是用spring提供的内核来跑
@ContextConfiguration("classpath:application.xml")//指定配置文件或配置类
public class TemplateTest {
    @Autowired//使用在字段上用于根据类型依赖注入
    private JdbcTemplate jdbcTemplate;
    @Test
    public void testUpdate(){
        jdbcTemplate.update("update account set money=? where name=?",10000,"tom");//更新数据库
    }
}

1.6对数据的删除操作

    @Test
    public void testDelete(){
        jdbcTemplate.update("delete from account where name=?","tom");
    }

1.7对数据库进行查询操作

①查询全部

    @Test
    public void testQuestAll(){
        List<Account> query = jdbcTemplate.query("select * from account", new BeanPropertyRowMapper<Account>(Account.class));
        System.out.println(query);
    }

②查询表中一个的全部信息

    @Test
    public void testQuestOne(){
        Account tom = jdbcTemplate.queryForObject("select * from account where name=?", new BeanPropertyRowMapper<Account>(Account.class), "lisi");
        System.out.println(tom);
    }

③查询表中的单个数据

    @Test
    public void testQuest(){
        Long count=jdbcTemplate.queryForObject("select count(*) from account",Long.class);
        System.out.println(count);
    }

总结:

更新操作:

​ jdbcTempate.update(sql,params)

查询操作:

​ jdbcTemplate.query(sql,Mapper,params)

​ jdbcTemplate.queryForObject(sql,Mapper,params)

SpringMVC拦截器

1.1拦截器(interceptor)的作用

SpringMVC的拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理

将拦截器按一定顺序联结成一条链,这条链称为拦截器(interceptor Chain)。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。拦截器也是AOP思想的具体体现。

在这里插入图片描述

自定义拦截器很简单,只有如下三步:

重点,注意点:千万不要忘记在web.xml里面忘记配置 ,这个是springmvc的核心,不配置这个是找不到注解中的路径的,只能在web里面找路径。

  <!--SpringMVC的前端控制器-->
  <servlet>
    <servlet-name>DispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>DispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

目标方法:

@Controller
public class TargetController {

    @RequestMapping("/target")
    public ModelAndView show(){
        System.out.println("目标程序执行......");
        ModelAndView modelAndView=new ModelAndView();
        modelAndView.addObject("name","itcast");
        modelAndView.setViewName("shu");
        System.out.println("jajja");
        return modelAndView;
    }
}

① 创建拦截器类实现HandlerInterceptor

public class MyInterceptor implements HandlerInterceptor {
    @Override
    //在目标方法执行之前 执行
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle执行了");
        return true;//返回true代表放行,放回felse不放行
    }

    //在目标方法执行之后 视图对象放回之前执行(return modelAndView之前执行)
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle执行了");
        //这里可以改变返回的视图
    }

    //在流程都执行完了 执行
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion执行了");
    }
}

② 配置拦截器

    <!--配置拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.itheima.interceptor.MyInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

③ 测试拦截器的拦截效果

结果:

preHandle执行了
目标程序执行......
jajja
postHandle执行了
afterCompletion执行了

④拦截器的小应用

package com.itheima.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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

public class MyInterceptor implements HandlerInterceptor {
    @Override
    //在目标方法执行之前 执行
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle执行了");
        String param = request.getParameter("param");
        if ("yes".equals(param)){
            return true;//后面有param并且等于yes,继续执行
        }else {
            request.getRequestDispatcher("/shu.jsp").forward(request,response);//如果不满足上面条件就执行转发新的页面,后面程序就不执行了
            return false;
        }
    }

    //在目标方法执行之后 视图对象放回之前执行
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        modelAndView.addObject("name","yangming");//更改模型中的数据
        System.out.println("postHandle执行了");
    }

    //在流程都执行完了 执行
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion执行了");
    }
}

了解:假如写了俩个拦截器,俩个拦截器执行结果:

执行结果:

preHandle执行了
preHandle222执行了
目标程序执行......
jajja
postHandle执行了
postHandle222执行了
afterCompletion执行了
afterCompletion222执行了
哪个拦截器配置在上面哪个先执行第一部分,然后返回执行第二个拦截器的第一部分,按照此顺序依次执行。

SpringMVC异常处理

1.1异常处理的思路

系统中异常包括俩类:编译时异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发,测试等手段减少运行时异常的发生。

系统的Dao,Service,Controller出现都通过throws Exception向上抛出,最后由SpringMVC前端控制器交由异常处理器进行异常处理,如下图:

在这里插入图片描述

1.2

① 使用SpringMVC提供的简单异常处理器SimpleMappingExceptionResolver

② 实现Spring的异常处理接口HandlerExceptionResolver自定义自己的异常处理器

1.3简单异常处理器SimpleMappingException Resolver

在我们的项目运行过程中,无法完全避免出现一些位置的运行时异常(比如NullPointerException ),而恰恰我们并没有对该异常进行处理,那么就会将此异常抛向用户。 当用户浏览页面时突然眼前蹦出一堆看不懂的,可想而知用户的体验度是非常差的,而如果简单的配置一下异常处理的话可以在spring-mvc.xml中进行配置异常后跳转的页面。(在xml里面大部分都是处理运行时异常,编译时异常在程序中就可以处理,不过编译时异常也可以通过上抛,在spring-mvc.xml进行相应的异常配置)。

SpringMvc已经定义好了该类型转换器,在使用时可以根据项目情况进行相应异常与视图的映射配置

spring-mvc.xml
<!--配置简单映射异常处理器-->
    <!--配置简单映射异常处理器-->
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <property name="defaultErrorView" value="error"/>//此处是如果下面的异常都没有匹配到发生的异常,就执行默认错误视图
        <property name="exceptionMappings">
            <map>
                <entry key="com.itheima.exception.MyException" value="error"/>//key后面是异常类型,value接的是错误视图
                <entry key="java.lang.ClassCastException" value="error"/>
            </map>
        </property>
    </bean>

1.4自定义异常处理步骤

① 创建异常处理器类实现HandlerExceptionResolver

public class MyExceptionResolver implements HandlerExceptionResolver {

   /*
        参数Exception:异常对象
        返回ModelAndView 跳转到错误视图信息
    */
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) {
        ModelAndView modelAndView=new ModelAndView();
        if (e instanceof MyException){
            modelAndView.addObject("info","自定义异常");
        }else if (e instanceof ClassCastException){
            modelAndView.addObject("info","类转换异常");
        }
        modelAndView.setViewName("error");
        return modelAndView;
    }

② 配置异常处理器

spring-mvc.xml
<!--自定义异常处理器-->
<bean class="com.itheima.resolver.MyExceptionResolver"/>

③ 编写异常页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>通用异常错误提示</h1>
    <h1>${info}</h1>
</body>
</html>

④ 测试异常跳转

@RequextMapping(value="/show")
public String show() throws FileNotFountException,MyException{
	System.out.println("show running.....");
	// demoService.show1();
	demoService.show5();
	return "index";
}

1.SPring的AOP简介

1.1 什么是AOP

AOP为Aspect Oriented Programming的缩写,意思为面向切面编程,是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。

AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各个部分的耦合度降低,提高程序的可重用性,同时提高了开发效率。

1.2AOP的作用及其优势

① 作用:在程序运行期间,在不修改源码的情况下对方法进行功能增强。

② 优势:减少重复代码,提高开发效率,并且便于维护。

1.3 AOP的动态代理技术

常用的动态代理技术

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

​ 使用动态代理有三个要点,

  1. 必须实现 InvocationHandler 接口,表明该类是一个动态代理执行类。
  2. InvocationHandler 接口内有一实现方法如下: public Object invoke(Object proxy, Method method, Object[] args) 。使用时需要重写这个方法
  3. 获取代理类,需要使用 Proxy.newProxyInstance(Clas loader, Class[] interfaces, InvocationHandler h) 这个方法去获取Proxy对象(Proxy 类类型的实例)。

注意到 Proxy.newProxyInstance 这个方法,它需要传入 3 个参数。解析如下:

// 第一个参数,是类的加载器
// 第二个参数是委托类的接口类型,证代理类返回的是同一个实现接口下的类型,保持代理类与抽象角色行为的一致
// 第三个参数就是代理类本身,即告诉代理类,代理类遇到某个委托类的方法时该调用哪个类下的invoke方法
Proxy.newProxyInstance(Class loader, Class<?>[] interfaces, InvocationHandler h)

再来看看 invoke 方法,用户调用代理对象的什么方法,实质上都是在调用处理器的
invoke 方法,通过该方法调用目标方法,它也有三个参数:

// 第一个参数为 Proxy 类类型实例,如匿名的 $proxy 实例
// 第二个参数为委托类的方法对象
// 第三个参数为委托类的方法参数
// 返回类型为委托类某个方法的执行结果
public Object invoke(Object proxy, Method method, Object[] args)

案例:

//TargetInterface接口:
public interface TargetInterface {
    public void save();
}
//Target目标对象:
public class Target implements TargetInterface{
    @Override
    public void save() {
        System.out.println("sava running.....");
    }
}
//增强类
public class Advice {
    public void before(){
        System.out.println("前置增强.....");
    }
    public void after(){
        System.out.println("后置增强.....");
    }
}
//测试类
public class ProxyText {
    public static void main(String[] args) {
        //目标对象
        Target target=new Target();
        //增强对象
        Advice advice=new Advice();
        //返回值 就是动态代理生成的代理对象
        TargetInterface proxy=(TargetInterface) Proxy.newProxyInstance(
                target.getClass().getClassLoader(), //目标对象的类加载器
                target.getClass().getInterfaces(), //目标对象相同的接口字节码对象数组
                new InvocationHandler() {
                    //调用代理对象的任何方法 实质执行的都是invoke方法
                    @Override
                    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                        //前置增强
                        advice.before();
                        Object invoke = method.invoke(target, args);//执行目标方法
                        advice.after();
                        return invoke;
                    }
                }

        );
        proxy.save();
    }
}

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

​ 案例:

//目标类
public class Target{
    public void save() {
        System.out.println("sava running.....");
    }
}
//增强类
public class Advice {
    public void before(){
        System.out.println("前置增强.....");
    }
    public void after(){
        System.out.println("后置增强.....");
    }
}
public class ProxyText {
    public static void main(String[] args) {
        //目标对象
        Target target=new Target();
        //增强对象
        Advice advice=new Advice();
        //返回值 就是动态代理生成的代理对象  基于cglib
        //1.创建增强器
        Enhancer enhancer=new Enhancer();
        //2.设置父类(目标)
        enhancer.setSuperclass(Target.class);
        //3.设置回调
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object proxy, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                advice.before();//执行前置
                Object invoke=method.invoke(target,args);//执行目标
                advice.after();//执行后置
                return invoke;
            }
        });
        //4.创建代理对象
        Target proxy =(Target) enhancer.create();
        //5.调用方法,实际上是执行的目标方法的save()
        proxy.save();
    }
}

Spring的AOP简介

1.4AOP相关概念

(1)横切关注点:对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点
(2)Aspect(切面):通常是一个类,里面可以定义切入点和通知(要点)
(3)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用。被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器
(4)Advice(通知):AOP在特定的切入点上执行的增强处理,有before(前置),after(后置),afterReturning(最终),afterThrowing(异常),around(环绕)(要点)
(5)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式(要点)
(6)weave(织入):将切面应用到目标对象并导致代理对象创建的过程(要点)
(7)introduction(引入):在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段
(8)AOP代理(AOP Proxy):AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类
(9)目标对象(Target Object): 包含连接点的对象。也被称作被通知或被代理对象。POJO

1.5 知识要点

① aop:面向切面编程

② aop底层实现:基于JDK的动态代理和基于Cglib的动态代理

③ aop的重点概念:

	Pointcut(切入点):被增强的方法

​ Advice(通知/增强):封装增强业务逻辑的方法

​ Aspect(切面):切点+通知

​ Weaving(织入):将切点与通知结合的过程

④开发明确事项:

​ 谁是切点(切点表达式配置)

​ 谁是通知(切面类中的增强方法)

​ 将切点和通知进行织入配置

1.6AOP的快速入门

① 导入AOP相关坐标

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

② 创建目标接口和目标类(内部有切点)

接口类:
public interface TargetInterface {
    public void save();
}
目标类:
public class Target implements TargetInterface {
    @Override
    public void save() {
        System.out.println("sava running.....");
    }
}

③ 创建切面类(内部有增强方法)

public class MyAspect {
    public void before(){
        System.out.println("前置增强.....");
    }
}

④ 将目标类和切面类的对象创建权交给spring

<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
//需要导入aop命名空间
<!--配置目标对象-->
    <bean id="target" class="com.itheima.proxy.aop.Target"></bean>

    <!--切面对象-->
    <bean id="myAspect" class="com.itheima.proxy.aop.MyAspect"></bean>

⑤ 在applicationContext.xml中配置织入关系

 <!--配置织入,告诉spring框架哪些方法(切点)进行哪些方法增强(前置,后置)-->
    <aop:config>
        <!--声明切面-->
        <aop:aspect ref="myAspect">
            <!--切面,切点+通知-->
            <aop:before method="before" pointcut="execution(public void com.itheima.proxy.aop.Target.save())"></aop:before>
        </aop:aspect>
    </aop:config>

⑥ 测试代码

//测试类:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:application.xml")
public class AopTest {

    @Autowired
    private TargetInterface target;
    @Test
    public void test1(){
        target.save();
    }
}

1.切点表达式的语法:

在这里插入图片描述

2.通知的类型:

通知的配置语法:

<app:通知类型 method=“切面类中的方法名” pointcut=“切点表达式”></aop通知类型>

① 前置通知 aop:before 用于配置前置通知。指定增强的方法在切入点方法之前执行。

 <aop:before method="before" pointcut="execution(* com.itheima.proxy.aop.*.*(..))"></aop:before>
public class MyAspect {
    public void before(){
        System.out.println("前置增强.....");
    }

② 后置通知 aop:after-returning 用于配置后置通知。指定增强的方法在切入点方法之后执行。

<aop:after-returning method="afterRunning" pointcut="execution(* com.itheima.proxy.aop.*.*(..))"></aop:after-returning>
    public void afterRunning(){
        System.out.println("后置增强.....");
    }

③ 环绕通知 aop:around 用于配置环绕通知,指定增强的方法在切入点方法之前和之后都执行。

<aop:around method="around" pointcut="execution(* com.itheima.proxy.aop.*.*(..))"></aop:around>
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("环绕前增强......");
        Object proceed=pjp.proceed();
        System.out.println("环绕后增强......");
        return proceed;
    }

④ 异常抛出通知 aop:throwing 用于配置异常抛出通知,指定增强的方法在出现异常时执行。

<aop:after-throwing method="afterThrowing" pointcut="execution(* com.itheima.proxy.aop.*.*(..))"></aop:after-throwing>
    public void afterThrowing(){
        System.out.println("异常抛出增强.......");
    }

⑤ 最终通知 aop:after 用于配置最终通知,无论增强方式执行是否有异常都会执行

<aop:after method="after" pointcut="execution(* com.itheima.proxy.aop.*.*(..))"></aop:after>
    public void after(){
        System.out.println("最后增强......");
    }

3.切点表达式的抽取

<!--抽取切点表达式-->           
<aop:pointcut id="myPointcut" expression="execution(* com.itheima.proxy.aop.*.*(..))"/>
<aop:around method="around" pointcut-ref="myPointcut"></aop:around>

1.7 注解方式实现AOP

基于注解的aop开发步骤:

① 创建目标接口和目标类(内部有切点)

③ 将目标类和切面类的对象创建权交给spring

//目标类:
@Controller("target")
public class Target implements TargetInterface {
    @Override
    public void save() {
        System.out.println("sava running.....");
    }
}
//接口:
public interface TargetInterface {
    public void save();
}

② 创建切面类(内部有增强方法)

④ 在切面类中使用注解配置织入关系

//切面类:
@Controller("myAspect")
@Aspect//这个注解是告诉spring这个类为切面类
public class MyAspect {
    @Before("execution(* com.itheima.proxy.conn.*.*(..))")//<!--切面,切点,通知-->告诉spring这个方法为前置增强方法
    public void before(){
        System.out.println("前置增强.....");
    }

⑤ 在配置文件中开启组件扫描和AOP的自动代理

//上面要引入aop和context的空间 
<!--组件扫描-->
    <context:component-scan base-package="com.itheima.proxy.conn"></context:component-scan>
    <!--aop自动代理-->
    <aop:aspectj-autoproxy/>

⑥ 测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext-conn.xml")
public class AopTest1 {
    @Autowired
    private TargetInterface target;

    @Test
    public void go(){
        target.save();
    }
}

在这里插入图片描述

注解抽取切点表达式:

@Controller("myAspect")
@Aspect
public class MyAspect {
    @Before("pointcut()")
    //通过pointcut()方法拿到注入里面的execution(* com.itheima.proxy.conn.*.*(..))
    public void before(){
        System.out.println("前置增强.....");
    }

    @Pointcut("execution(* com.itheima.proxy.conn.*.*(..))")
   //这里的注解表示,将execution(* com.itheima.proxy.conn.*.*(..))注入到pointcut()方法中
    public void pointcut(){

    }

Spring 的事务控制

一.基于xml的声明方式

声明事物的控制要点:

pom.xml文件配置:

 <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>5.2.6.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.8.4</version>
    </dependency>

① 平台事物管理器配置

  <!--配置平台事务管理器-->
    <bean id="transactionManger" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

② 事物通知的配置

<!--通知 事务的增强-->
    <tx:advice id="txAdvice" transaction-manager="transactionManger">
        <tx:attributes>
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>

③ 事物aop织入的配置

 <!--配置事务的aop织入-->
    <aop:config>
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.itheima.service.impl..*.*(..))"></aop:advisor>
    </aop:config>

完整案例:

AccountController控制类:

public class AccountController {
    public static void main(String[] args) {
        ApplicationContext app=new ClassPathXmlApplicationContext("applicationContext.xml");
        AccountService accountService=app.getBean(AccountService.class);
        accountService.transfer("zhangsan","lisi",500);
    }
}

domain包下的Account类:

public class Account {
    private String name;
    private double money;
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }
}

service包下的AccountService接口类:

public interface AccountService {
    public void transfer(String outMan,String inMan,double money);
}

service包下的子包impl下的AccountServiceImpl类:

public class AccountServiceImpl implements AccountService {
    private AccountDao accountDao;
    public void setAccountDao(AccountDao accountDao){
        this.accountDao=accountDao;
    }
    @Override
    public void transfer(String outMan, String inMan, double money) {
        accountDao.out(outMan,money);
        accountDao.in(inMan,money);
    }
}

dao包下的AccountDao接口类:

public interface AccountDao {
    public void out(String outMan,double money);
    public void in(String inMan,double money);
}

dao包下的子包的impl包下的AccountDaoImpl:

public class AccountDaoImpl implements AccountDao {
    private JdbcTemplate jdbcTemplate;
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate){
        this.jdbcTemplate=jdbcTemplate;
    }

    @Override
    public void out(String outMan, double money) {
        jdbcTemplate.update("update account set money=money-? where name=?",money,outMan);
    }

    @Override
    public void in(String inMan, double money) {
        jdbcTemplate.update("update account set money=money+? where name=?",money,inMan);
    }
}

resources包下的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: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.xsd
        http://www.springframework.org/schema/aop  http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
//引入top和tx命名空间

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"/>
        <property name="user" value="root"/>
        <property name="password" value="root"/>
    </bean>

    <bean id="AccountDao" class="com.itheima.proxy.dao.impl.AccountDaoImpl">
        <property name="jdbcTemplate" ref="jdbcTemplate"></property>
    </bean>

    <bean id="AccountService" class="com.itheima.proxy.Service.impl.AccountServiceImpl">
        <property name="accountDao" ref="AccountDao"></property>
    </bean>
    <!--目标对象 内部的方法就是切点-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--配置平台事务管理器-->
    <bean id="transactionManger" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--通知 事务的增强-->
    <tx:advice id="txAdvice" transaction-manager="transactionManger">
        <tx:attributes>
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>

    <!--配置事务的aop织入-->
    <aop:config>
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.itheima.service.impl..*.*(..))"></aop:advisor>
    </aop:config>
</beans>

当然还需要自己准备一张表,表中俩个属性一个String类型的name,一个double类型的age。

基于注解的声明控制事物的方式

基于上面的代码进行改进:

//首先将自己自定义的类,进行注解配置Dao类:
  @Repository("accountDao")
public class AccountDaoImpl implements AccountDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;  
Service:
@Service("accountService")
public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountDao accountDao;
    
      @Transactional(isolation= Isolation.DEFAULT)
    public void transfer(String outMan, String inMan, double money) {
        accountDao.out(outMan,money);
        accountDao.in(inMan,money);
    }
}
    <!--通知 事务的增强-->
    <tx:advice id="txAdvice" transaction-manager="transactionManger">
        <tx:attributes>
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>

    <!--配置事务的aop织入-->
    <aop:config>
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.itheima.service.impl..*.*(..))"></aop:advisor>
    </aop:config>
这上面的配置可以直接在方法上面用 @Transactional注解来代替
 @Transactional(isolation= Isolation.DEFAULT)
    public void transfer(String outMan, String inMan, double money) {
        accountDao.out(outMan,money);
        accountDao.in(inMan,money);
    }
}
这里表示为这个方法开启了事物
要想上面的@Transactional注解能够使用,必须引入aop命名空间,然后进行事务的注解驱动
    <tx:annotation-driven transaction-manager="transactionManger"></tx:annotation-driven>
当然其他的自定义要被识别也需要引入context类,进行组件扫描:
<!--配置组件扫描-->
    <context:component-scan base-package="com.itheima"></context:component-scan>
@Transactional(isolation= Isolation.DEFAULT)
public void transfer(String outMan, String inMan, double money) {
    accountDao.out(outMan,money);
    accountDao.in(inMan,money);
}

}


```xml
    <!--通知 事务的增强-->
    <tx:advice id="txAdvice" transaction-manager="transactionManger">
        <tx:attributes>
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>

    <!--配置事务的aop织入-->
    <aop:config>
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.itheima.service.impl..*.*(..))"></aop:advisor>
    </aop:config>
这上面的配置可以直接在方法上面用 @Transactional注解来代替
 @Transactional(isolation= Isolation.DEFAULT)
    public void transfer(String outMan, String inMan, double money) {
        accountDao.out(outMan,money);
        accountDao.in(inMan,money);
    }
}
这里表示为这个方法开启了事物
要想上面的@Transactional注解能够使用,必须引入aop命名空间,然后进行事务的注解驱动
    <tx:annotation-driven transaction-manager="transactionManger"></tx:annotation-driven>
当然其他的自定义要被识别也需要引入context类,进行组件扫描:
<!--配置组件扫描-->
    <context:component-scan base-package="com.itheima"></context:component-scan>
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 文献综述是一种对特定主题进行文献收集、整理和分析的方法。在计算机科学领域,特定主题可以是指定的算法、软件开发模型或技术框架。而SSM是一种常用的Java Web开发框架,它由Spring、SpringMVC和MyBatis三个框架组成。 在编写计算机领域中的SSM文献综述时,可以按照下面的模板来进行组织: 1. 引言:简要介绍SSM框架的背景和重要性,并概述本文综述的目的。 2. Spring框架综述:介绍Spring框架的特点和功能,包括依赖注入、AOP等核心概念。详细描述Spring框架在Web开发中的应用和优势。 3. SpringMVC框架综述:解释SpringMVC框架的基本原理和架构。说明SpringMVC在Web应用中的角色,包括处理请求、响应和视图解析等。列举一些在实际项目中使用SpringMVC的优点和用例。 4. MyBatis框架综述:介绍MyBatis框架的基本原理和主要特性,包括SQL映射、对象关系映射等。详细描述MyBatis在数据库访问中的应用和性能优势。同时,探讨在SSM框架中如何将MyBatis与Spring集成。 5. SSM框架的应用案例:列举一些实际项目中应用SSM框架的成功案例,包括一些著名的开源项目。逐个案例分析其采用SSM框架的原因、优势和实现方法。 6. SSM框架的发展趋势:对当前SSM框架进行总结和评价,展望未来的发展趋势。讨论可能的扩展和改进方向,以及在新技术浪潮下的应用前景。 7. 结论:总结SSM框架的主要特点和应用场景。强调SSM框架在计算机科学领域中的重要性,并给出进一步研究和应用SSM框架的建议。 这些模板内容旨在对计算机领域中SSM框架的相关文献进行梳理和总结,帮助读者更好地了解和应用SSM框架。当然,具体综述的内容和结构还需要根据实际情况和个人需求进行调整和修改。 ### 回答2: 文献综述模板是在研究某个特定领域或主题的相关文献之后,对这些文献进行综合分析、总结和评价的一种学术写作方式。计算机领域中,SSM(Spring+SpringMVC+MyBatis)是一种流行的开发框架,下面将用300字中文对其进行简要综述。 SSM框架是一种通过集成Spring、SpringMVC和MyBatis的方式来进行Web开发的架构模式。这种框架的出现主要是为了解决传统Web开发中代码冗余、耦合度高等问题。通过整合这三个组件,SSM框架可以更好地利用各自的优势,提供了一种灵活、高效、可扩展的开发方式。 在文献综述中,研究者对SSM框架进行了深入的调研和分析。首先,研究者总结了SSM框架的优点。它具有良好的模块化和可重用性,可以实现代码的低耦合和高内聚,提高开发效率和代码质量。其次,SSM框架支持AOP(面向切面编程),可以在业务逻辑和非功能性需求方面提供更好的支持。此外,SSM框架还提供了多种常用的技术,如事务管理、缓存管理等,方便开发人员进行系统开发和维护。 然而,研究者也指出了SSM框架存在的一些问题。首先,对于初学者来说,学习和掌握SSM框架需要一定的时间和精力。此外,对于大型复杂的项目,SSM框架的配置和调试可能会比较繁琐。此外,SSM框架对于性能的支持还有待改进,可能需要进一步优化和调整。 综上所述,SSM框架在计算机领域得到了广泛的应用和研究。它通过整合Spring、SpringMVC和MyBatis的优势,提供了一种高效、灵活和可扩展的Web开发方式。然而,研究者也指出了SSM框架存在的一些问题,并表示有待进一步的改进和优化。未来,我们可以通过深入研究和实践,进一步完善和推广SSM框架,以满足不断变化的计算机领域需求。 ### 回答3: 文献综述模板是一种分析、总结和评价研究领域内已有文献的方法。在计算机科学中,SSM(Spring + SpringMVC + MyBatis)是一种常用的Java企业级开发框架。下面是一个针对计算机SSM架构的文献综述模板示例: 1. 引言:介绍SSM框架在计算机领域中的应用和重要性,概述当前的研究热点和挑战。 2. SSM框架的主要特点和优势:详细介绍Spring、SpringMVC和MyBatis的核心特点和优势,包括依赖注入、面向切面编程、容器管理、模块化设计、数据持久化等方面。 3. SSM框架在企业级应用开发中的应用:评估和总结SSM框架在构建企业级应用程序中的优势和挑战,包括开发效率、可维护性、扩展性、安全性和性能等方面。 4. SSM框架在特定领域的研究和应用:探讨SSM框架在特定领域的应用案例和研究成果,例如电子商务、社交网络、物联网等。 5. SSM框架的改进和优化方法:综述和比较不同研究者对SSM框架改进和优化的方法,包括性能优化、安全性增强、开发效率提升等方面。 6. SSM框架的未来发展方向:分析和展望SSM框架的未来发展方向,包括与大数据、人工智能、云计算等新兴技术的结合。 7. 结论:总结文献综述的主要内容,强调当前的研究挑战和未来的研究方向。 通过以上文献综述模板,可以系统性地总结和分析SSM框架在计算机领域中的实践应用和研究进展,为相关研究者和开发者提供有价值的参考和指导。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值