1.SpringFramework

loc

ioc中用到了 反射 工厂模式 xml解析

ioC:inversion of control 控制反转

作用:将创建对象的过程交由ioc管理

ioc管理的对象默认都是单例的

Spring提供的两个ioc接口:

1: BeanFactory:ioc容器基本实现,是spring内部使用的接口,不提供开发人员使用,

2: ApplicationContext: BeanFactory接口的子接口,提供的功能更多,提供给开发人员使用

//BeanFactory[Bean工厂]   管理实现类的工厂(懒汉:在第一次使用时实例化对象)
//ApplicationContext 管理实现类的工厂(饿汉:在服务器启动时把所有对象实例化)   extends BeanFactory

Bean管理:

bean管理指的是两个操作
(1)spring创建对象
(2)spring注入属性

ioc操作bean管理:

基于xml方式创建对象:

<bean id="iocService" class="com.javakc.spring.ioc.service.impl.IocServiceImpl"/>

(1) 在spring配置文件中使用bean标签,在bean标签里面添加对应属性就可以实现对象创建

(2)bean标签中常用的属性

  • id 唯一标示(起别名)
  • class 写类的全路径

(3)创建对象时,会默认执行无参构造方法


spring中有两种bean(普通bean和工厂bean(FactoryBean))

1.普通bean:在配置文件中定义bean类型就是返回类型

2.工厂bean:在配置文件定义bean类型可以和返回类型不一样

工厂bean操作

第一步 创建类,让这个类作为工厂 bean,实现接口 FactoryBean
第二步 实现接口里面的方法,在实现的方法中定义返回的 bean 类型

public class MyBean implements FactoryBean<Course> {//定义返回 bean@Overridepublic Course getObject() throws Exception {Course course = new Course();course.setCname("abc");return course;}@Overridepublic Class<?> getObjectType() {return null;}@Overridepublic boolean isSingleton() {return false;} }
1.bean的作用域

Spring 里面,设置创建 bean 实例是单实例还是多实例(单实例表示只有一个对象,多实例表示每次都创建一个新的对象)默认是单实例对象

如何设置单实例还是多实例

(1) 在 spring 配置文件 bean 标签里面有属性(scope)用于设置单实例还是多实例

(2) scope 属性值 第一个值 默认值 singleton 表示是单实例对象

​ 第二个值 prototype,表示是多实例对象

<bean id="book" class="com.atguigu.spring5.bean.Book" scope="prototype"><property name="bname" ref="bookList"/>
</bean>

singleton 和 prototype 区别

第一 singleton 单实例,prototype 多实例

第二 设置 scope 值是 singleton 时候,加载 spring 配置文件时候就会创建单实例对象

设置 scope 值是 prototype 时候,不是在加载 spring 配置文件时候创建 对象,在调用

getBean 方法时候创建多实例对象

2.bean的生命周期

1)通过构造器创建 bean 实例(通过执行无参数构造,把对象创建)

2)为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)

3)后置处理器方法postProcessBeforeInitialization(在初始化方法之前运行)

4)调用 bean 的初始化的方法(需要进行配置初始化的方法)

5)后置处理器方法postProcessAfterInitialization(在初始化方法之后运行)

6 ) bean 可以使用了(对象获取到了)

7 ) 当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)

public Orders(){System.out.println("第一步 执行无参构造创建bean实例");}private String oname;public void setOname(String oname) {this.oname = oname;System.out.println("第二步 调用set方法设置属性值");}//创建初始化方法public void initMethod(){System.out.println("第四步 执行初始化方法"); //需要在xml中配置该方法为初始化方法}//创建销毁方法public void destroyMethod(){System.out.println("第七步 执行销毁方法"); //需要在xml中配置该方法为初始化方法}

xml配置文件代码

<bean id="orders" class="com.atguigu.spring5.bean2.Orders" init-method="initMethod" destroy-method="destroyMethod"><property name="oname" value="手机"/>
</bean><!--配置后置处理器-->
<bean id="mybeanPost" class="com.atguigu.spring5.bean2.MybeanPost"/>

测试代码

@Testpublic void testbean2() {ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");Orders orders = context.getBean("orders", Orders.class);System.out.println("第六步 获取创建bean实例对象");//手动让bean实例销毁((ClassPathXmlApplicationContext)context).close();}//销毁方法二@Testpublic void testbean3(){ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");Orders orders = context.getBean("orders", Orders.class);System.out.println("第六步 获取创建bean实例对象");//手动让bean实例销毁context.close();}

后置处理器方法代码

public class MybeanPost implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("第三步 在初始化方法之前执行");return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("第五步 在初始化方法之后执行");return bean;}
}

后置处理器写法: (1).实现BeanPostProcessor接口 (2).重写后置方法 (3).在xml文件中配置后置处理器(将该类交由ioc容器管理)

后置处理器的作用:会为当前配置文件中所有bean对象添加后置处理器

3.xml自动装配
  1. 什么是自动装配

(1)根据指定装配规则(属性名称或者属性类型),Spring 自动将匹配的属性值进行注入

  1. 实现自动装配

bean 标签属性 autowire,配置自动装配

autowire 属性常用两个值:

byName 根据属性名称注入 ,注入值 bean 的 id 值和类属性名称一样

byType 根据属性类型注入

根据名称装配

<bean id="emp" class="com.atguigu.spring5.autowire.Emp" autowire="byName"/><bean id="dept" class="com.atguigu.spring5.autowire.Dept"/>

根据类型装配

<bean id="emp" class="com.atguigu.spring5.autowire.Emp" autowire="byType"/><bean id="dept" class="com.atguigu.spring5.autowire.Dept"/>
4.外部属性文件

druid

引入外部属性文件配置数据库连接池

(1).引入druid(德鲁伊)jar包

(2).引入mysql驱动Jar包

(3).创建外部属性文件,properties 格式文件,写数据库信息

prop.driverClass=com.mysql.jdbc.Driver
prop.url=jdbc:mysql://127.0.0.1:3306/spring5?serverTimezone=Asia/Shanghai&use Unicode=true&characterEncoding=UTF-8&useSSL=false
prop.userName=root
prop.possword=123456

(4).把外部 properties 属性文件引入到 spring 配置文件中

<!--引入context命名空间-->
<!--引入properties文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>

(5)配置连接池

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${prop.driverClass}"/><property name="url" value="${prop.url}"/><property name="username" value="${prop.userName}"/><property name="password" value="${prop.possword}"/></bean>
从bean管理中获取对象:
  1. 将类写入到ioc容器中

     <bean id="iocService" class="com.javakc.spring.ioc.service.impl.IocServiceImpl"/>
    
  2. 加载xml配置文件 (加载配置文件时,写入到配置文件中的类将会被实例化)

     ApplicationContext context = new ClassPathXmlApplicationContext("spring-ioc.xml");
    

    ClassPathXmlApplicationContext 可以换成 FileSystemXmlApplicationContext

ClassPathXmlApplicationContext : xml文件在src下有这个 (在src目录下可以直接写文件名)

FileSystemXmlApplicationContext : xml文件在盘符路径下用这个 (需要写全路径)

ClassPathXmlApplicationContext 和 FileSystemXmlApplicationContext 都实现了 ApplicationContext接口

  1. 从ioc容器里获取bean对象

    IocService iocservice= context.getBean("iOCService",IocService.class);
    写法二
    context.getBean("iOCService") //返回object类型
    

    或者写 context.getBean(“iocService”,IocService.class); //IocService.class表示转换成该类型,如果不转换返回的是object类型

DI

DI:Dependency Injection 依赖注入

依赖注入的两种方式?

  1. setter注入
  2. 构造器注入 (官方推荐)

基于xml方式 手动装配

1.set方法注入属性

(1) 创建类,定义属性和对应的set方法

//创建属性
private String name;
private String age;//创建set方法
public void setName(String name) {this.name = name;
}public void setAge(String age) {this.age = age;
}

(2) 在spring配置文件中 配置属性注入

<bean id="springdi" class="com.atguigu.spring5.SpringDi"><!--使用property完成属性注入name:类里面属性名称value:向属性里注入的值ref:向属性中注入对象,里面写的是bean标签中的id值--><property name="name" value="安鹏"/><property name="age" value="21"/>
</bean>

注入其他类型属性

(1) 注入null值

<property name="age">
<null/>
</property>

(2)属性值包含特殊符号

​ 方法一 将符号转义 &gt …

​ 方法二将内容写到CDATA //了解就行

2.有参构造注入属性

(1)创建属性 , 和属性对应的有参构造方法

//创建属性
private String name;
private int age;
//创建有参构造方法
public SpringDi1(String name,int age){this.name=name;this.age=age;
}

(2) 在spring配置文件中 配置属性注入

<bean id="springdi1" class="com.atguigu.spring5.SpringDi1"><!--使用constructor-arg完成属性注入name:类里面属性名称value:向属性里注入的值ref:注入类index: 表示构造方法里的第n个参数(0表示第一个)--><constructor-arg name="name" value="anpeng"/><constructor-arg name="age" value="21"/>
</bean>

如果要注入对象 用 ref=“类名” //注入的类需要在ioc容器中

3.外部bean-注入属性

(1)创建两个类service和dao

(2)在service中调用dao中的方法

(3)创建属性 和对应的注入方式(set或构造方法)

//创建SpringDiDao类型的属性private SpringDiDao springDiDao;//有参构造 创建SpringDiDao类型的参数public SpringDiService(SpringDiDao springDiDao){this.springDiDao=springDiDao;}

(4)在spring配置文件中进行配置

<!--创建dao和service对象-->
<bean id="springDiDao" class="com.atguigu.spring5.dao.SpringDiDaoImpl"></bean>
<bean id="springDiService" class="com.atguigu.spring5.service.SpringDiService"><!--将dao注入到service中--><constructor-arg ref="springDiDao"/>
</bean>

使用set方法注入:

4.内部bean和级联赋值
<bean id="emp" class="com.atguigu.spring5.bean.Emp"><property name="ename" value="安鹏"/><property name="gender" value="男"/><property name="dept"><bean id="dept" class="com.atguigu.spring5.bean.Dept"><property name="dname" value="财务部"/></bean></property></bean>

在bean标签里嵌套一个bean

5.xml注入数组集合类型属性

(1)定义 数组,set,list,map集合属性,并创建get方法或有参构造

//数组类型属性
private String[] courses;//list集合类型属性
private List<String> list;//set集合属性
private Set<String> sets;//map集合属性
private Map<String,String> maps;public void setCourses(String[] courses) {this.courses = courses;
}public void setSets(Set<String> sets){this.sets=sets;
}public void setList(List<String> list) {this.list = list;
}public void setMaps(Map<String, String> maps) {this.maps = maps;
}

(2)在spring配置文件中进行配置

<bean id="springDi2" class="com.atguigu.spring5.SpringDi2"><!--注入数组类型--><property name="courses"><array><value>java课程</value><value>数据库课程</value></array></property><!--注入list类型--><property name="list"><list><value>张三</value><value>李四</value></list></property><!--注入set类型--><property name="sets"><set><value>Mysql</value><value>Redis</value></set></property><!--注入map集合--><property name="maps"><map><entry key="JAVA" value="java"></entry><entry key="PYTHON" value="python"></entry></map></property>
</bean>

在注入属性标签(property或constructor-arg)里使用对应标签(array,list,set,map)来添加多个值

6.在集合里面设置对象类型的值

(1)在集合里面设置对象类型的值

<bean id="springDi22" class="com.atguigu.spring5.SpringDi2"><property name="courselist"><list><ref bean="course1"/><ref bean="course2"/></list></property></bean>

(2)创建多个coursel对象

<bean id="course1" class="com.atguigu.spring5.bean.Course"><property name="cname" value="Spring5"/><property name="cnumber" value="2022/3/1"/>
</bean>
<bean id="course2" class="com.atguigu.spring5.bean.Course"><property name="cname" value="Mybatis"/><property name="cnumber" value="2022/3/1"/>
</bean>
7.把集合注入部分提取出来
<!--提取list集合类型属性注入--><util:list id="bookList">   //引入命名空间:util<value>苹果</value><value>小米</value><value>华为</value><!--注入对象类型用ref--></util:list><!--提取list集合类型属性使用--><bean id="book" class="com.atguigu.spring5.bean.Book" scope="prototype"><property name="bname" ref="bookList"/></bean>
使用方法 基于xml方式:

1.构造方法注入

  1. 方法注入

    <bean id="iocService" class="com.javakc.spring.ioc.service.impl.IocServiceImpl"><!--        构造方法注入--><constructor-arg ref="iocDao"/>
    </bean>
    
  2. 注入

    IocDao iocDao;
    //构造方法注入
    public IocServiceImpl(IocDao iocDao) {this.iocDao=iocDao;
    }
    

2.set方法注入

  1. 方法注入

     <property name="iocDao123" ref="iocDao"/>
    

Ioc基于注解

使用注解的目的:为了简化xml配置

1.使用注解创建对象

Spring 针对 Bean 管理中创建对象提供注解

1)@Component //通用

2)@Controller //web表现层

3)@Service //service逻辑层

4)@Repository //dao数据层

参数: value=“” 等同于 基于配置里面的bean的id


基于注解方式实现对象创建

(1).注入AOP依赖

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mQ6NOSHb-1654355011641)(spring%E7%AC%94%E8%AE%B0.assets/image-20220302211129213.png)]

(2).开启注解扫描

<context:component-scan base-package="com.atguigu.spring5.comment,com.atguigu.spring5.bean"/>

扫描多个包用逗号分割

(3).创建类,在类上面添加创建对象注解

@Service(value = "userService") //value属性值可以省略不写,默认值是类名 首字母小写

开启注解扫描细节配置(指定扫描注解)

<!--
use-default-filters="false" 表示不使用默认filter, 自己配置filter  (自己指定扫描哪写注解)
context:include-filter  设置扫描那些注解--><context:component-scan base-package="com.atguigu.spring5.comment" use-default-filters="false"><context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/></context:component-scan>

2.使用注解实现属性注入

  1. @AutoWired 根据属性类型进行自动装配

    1. 第一步 把 service 和 dao 对象创建,在 service 和 dao 类添加创建对象注解

      第二步 在 service 注入 dao 对象,在 service 类添加 dao 类型属性,在属性上面使用注解

      @Autowired
      private DiDao diDao;
      
  2. @Qualifier 根据属性名称进行注入

    1. @Qualifier 注解需要和上面@Autowired 一起使用

    2. 在属性上添加注解

      @Autowired  //根据类型注入
      @Qualifier(value = "diDaoImpl")  //根据名称注入   名称默认是类的首字母小写
      private DiDao diDao;
      
  3. @Resource 可以根据属性注入,也可以根据名称注入

    1. 引入jar包[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nn3rgIIB-1654355011644)(spring%E7%AC%94%E8%AE%B0.assets/image-20220304120236575.png)]

    2. 在属性上添加注解

      //@Resource   //根据类型注入
      @Resource(name = "diDaoImpl")   //根据名称注入
      private DiDao diDao;
      
  4. @Value 注入普通类型属性

    1. 在属性上添加注解

      @Value(value = "写要注入的值")
      private String name;
      

3.完全注解开发

目的:为了代替xml配置文件

步骤一:创建配置类

@Configuration  //作为配置类,代替xml配置文件
@ComponentScan(basePackages = {"com.atguigu.spring5"})  //开启注解扫描
public class SpringConfig {}

步骤二:编写测试类

@Test
public void SpringConfigTest() {//加载配置类ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
}

2.AOP

aop的作用:在不修改原有代码的同时,添加一些新的功能

有两种情况动态代理

第一种 有接口情况,使用 JDK 动态代理

​ 创建接口实现类代理对象,增强类的方法

​ [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k6UyayLQ-1654355011646)(spring%E7%AC%94%E8%AE%B0.assets/image-20220304150249675.png)]

第二种 没有接口情况,使用 CGLIB 动态代理

​ 创建子类的代理对象,增强类的方法

​ [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v6u4vG63-1654355011647)(spring%E7%AC%94%E8%AE%B0.assets/image-20220304150336175.png)]

JDK动态代理

  1. 使用 JDK 动态代理,使用 Proxy 类里面的方法创建代理对象

    1. 调用 newProxyInstance 方法

      1. 方法有三个参数:

        第一参数,类加载器

        第二参数,增强方法所在的类,这个类实现的接口,支持多个接口

        第三参数,实现这个接口 InvocationHandler,创建代理对象,写增强的部分

AOP(术语)

  1. 连接点

    类里面可以被增强的方法叫连接点

  2. 切入点

    实际真正被增强的方法,叫切入点

  3. 通知

    1. 实际增强的部分叫通知
    2. 通知有多重类型
      1. 前置通知
      2. 后置通知
      3. 环绕通知
      4. 异常通知
      5. 最终通知
  4. 切面

    把通知应用到切入点的过程

AOP操作(准备工作)

  1. Spring 框架一般都是基于 AspectJ 实现 AOP 操作

(1)AspectJ 不是 Spring 组成部分,独立 AOP 框架,一般把 AspectJ 和 Spirng 框架一起使

用,进行 AOP 操作

  1. 在项目工程里面引入 AOP 相关依赖

    1. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7N7vvl8Y-1654355011648)(spring%E7%AC%94%E8%AE%B0.assets/image-20220308135746784.png)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VJvJGIW4-1654355011649)(spring%E7%AC%94%E8%AE%B0.assets/image-20220308135842300.png)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9QcrrHzF-1654355011650)(spring%E7%AC%94%E8%AE%B0.assets/image-20220308140031614.png)]
  2. 切入点表达式

    1. 切入点表达式作用:知道对哪个类里面的哪个方法进行增强

    2. 语法结构: execution([权限修饰符] [返回类型] [类全路径] 方法名称 ) //返回类型可以省略不写

      1. 举例 1:对 com.atguigu.dao.BookDao 类里面的 add 进行增强

        execution(* com.atguigu.dao.BookDao.add(…))

      2. 举例 2:对 com.atguigu.dao.BookDao 类里面的所有的方法进行增强

        execution(* com.atguigu.dao.BookDao.* (…))

      3. 举例 3:对 com.atguigu.dao 包里面所有类,类里面所有方法进行增强

        execution(* com.atguigu.dao.*.* (…))

      4. 第一个 星号 表示任何权限都可以,

        第二个 星号 表示所有方法

        第三个 星号 表示所有类

        第一个 点点 表示任何类型的任意数量的参数

    3. 2)

AOP操作(注解)

  1. 创建被增强类,在类里面定义方法

    @Component
    public class User {public void add(){System.out.println("add方法");}
    }
    
  2. 创建增强类(编写增强逻辑)

    @Aspect
    @Component
    public class UserProxy {//前置通知public void before(){System.out.println("before 前置通知");}
    }
    
  3. 进行通知的配置

    1. 在 spring 配置文件中,开启注解扫描

      <context:component-scan base-package="com.atguigu.spring5.AspectJAOP"/>
      
    2. 使用注解创建 User 和 UserProxy 对象

      @Component
      
    3. 在增强类上面添加注解 @Aspect

      @Aspect
      
    4. 在 spring 配置文件中开启生成代理对象

      <!--开启 Aspect 生成代理对象-->
      <aop:aspectj-autoproxy/><!--扫描到Aspect注解后将改类定为代理类-->
      
  4. 配置不同类型的通知

    //增强类
    @Aspect
    @Component
    public class UserProxy {//前置通知@Before(value = "execution(* com.atguigu.spring5.AspectJAOP.User.add(..))")public void before(){System.out.println("before 前置通知");}//后置通知@AfterReturning(value = "execution(* com.atguigu.spring5.AspectJAOP.User.add(..))")public void afterReturning(){System.out.println("后置通知");}//最终通知@After(value = "execution(* com.atguigu.spring5.AspectJAOP.User.add(..))")public void after(){System.out.println("最终通知");}//异常通知@AfterThrowing(value = "execution(* com.atguigu.spring5.AspectJAOP.User.add(..))")public void afterThrowing(){System.out.println("异常通知");}//环绕通知@Around(value = "execution(* com.atguigu.spring5.AspectJAOP.User.add(..))")public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println("环绕通知前");proceedingJoinPoint.proceed();System.out.println("环绕通知后");}}

    相同切入点抽取

    @Pointcut(value = "execution(* com.atguigu.spring5.AspectJAOP.User.add(..))")public void pointdemo(){}//前置通知@Before(value = "pointdemo()")public void before(){System.out.println("before 前置通知");}
    

有多个增强类多同一个方法进行增强,设置增强类优先级

在增强类上面添加注解 @Order(数字类型值),数字类型值越小优先级越高

   @Aspect@Component@Order(1)public class PersonProxy {@Before(value = "execution(* com.atguigu.spring5.AspectJAOP.User.add(..))")public void before(){System.out.println("PersonProxy");}}

完全注解开发

@Configuration  //作为配置类,代替xml配置文件
@ComponentScan(basePackages = {"com.atguigu.spring5"})  //开启注解扫描
@EnableAspectJAutoProxy(proxyTargetClass = true)//开启 Aspect 生成代理对象
public class ConfigAop {}

AOP操作(基于配置)

1、创建两个类,增强类和被增强类,创建方法

2、在spring 配置文件中创建两个类对象

<bean id="book" class="com.atguigu.spring5.AopXml.Book"/>
<bean id="bookProxy" class="com.atguigu.spring5.AopXml.BookProxy"/>

3**、在** spring 配置文件中配置切入点

<!--配置aop增强--><aop:config><!--切入点--><aop:pointcut id="p" expression="execution(* com.atguigu.spring5.AopXml.Book.buy(..))"/><!--配置切面--><aop:aspect ref="bookProxy"><!--ref里面写增强类--><!--增强作用在具体的方法上--><aop:before method="before" pointcut-ref="p"/><!--method写增强的方法  arg-names写切入点--></aop:aspect></aop:config>

2.2动态代理(旧)

2.2.1配置形式

1.以注解为切入点 和 以方法作为切入点

<!--扫描并实例化-->
<context:component-scan base-package="com.javakc.spring"/><!--aop动态代理配置--><aop:config><!--aop切面--><!--ref注入--><aop:aspect ref="loggerAdvice"><!--aop切入点--><!--1.以注解为切入点 (用于整个类)--><!--expression[表达式] . annotation[注解]  .  Controller[控制器][表现层注解]--><!--            <aop:pointcut id="" expression="@annotation(org.springframework.stereotype.Controller)"/>--><!--2.以方法作为切入点--><!--execution[执行]   .   method[方法]  .   methodMethod[方法切入点]--><!--execution(方法的路径),支持正则表达式,id唯一标识符 --><!--<aop:pointcut id="methodPointcut" expression="execution(* com.javakc.spring.aop.service.impl.AopServiceImpl.insert(String, int))"/><aop:pointcut id="methodPointcut" expression="execution(* com.javakc.spring.ioc.service.impl.IocServiceImpl.insert(String, int))"/>--><aop:pointcut id="methodPointcut"expression="execution(* com.javakc.spring.*.service.impl.*ServiceImpl.insert(..))"/><!-- * 表示所有     第一个 * 叫方法返回类型(表示任意的返回类型)--><!-- .. 两个点表示任意的参数个数(包括无参)和任意的参数类型--><!--切入点只负责拦截--><!--建立 连接点 JointPoint 与 通知实现类 方法 映射--><!--after[后来,在...之后]    .   before[以前,在...之前]--><!--after 事后消息处理 , before 预处理--><aop:after method="logger" pointcut-ref="methodPointcut"/></aop:aspect></aop:config><!--注:需要引入aop依赖-->
2.2.2注解形式
<!--扫描并实例化-->
<context:component-scan base-package="com.javakc.spring"/><!--启用aop注解支持-->
<aop:aspectj-autoproxy/>

@Aspect 声明切面 (声明在类上)

@Pointcut 声明切入点(声明在方法上) (注:类上需要有切面注解)

@Pointcut("execution(* com.javakc.spring.*.service.impl.*ServiceImpl.insert(..))")//方法名就是id名,传入要切入的方法的路径

@After 建立 连接点 JointPoint 与 通知实现类 方法 映射 (后置通知) (声明在插入的(如:日志)方法上)

@After("切入点的方法名")
@After("methodPointcut()")

|

@Aspect //声明切面
@Component //通用注解
public class LoggerAdvice {@Pointcut("execution(* com.javakc.spring.*.service.impl.*ServiceImpl.insert(..))")//方法名就是id名public void methodPointcut(){}/*** 记录日志*/@After("methodPointcut()")public void logger() {//输出当前时间System.out.println("LoggerAdivce" + LocalDate.now());}
}
2.2.3.通知类型
  1. @Before 前置通知 (在目标方法执行之前执行的通知)

  2. @AfterReturning 成功通知,后置通知,(在目标方法执行之后执行的通知)(在没有报错时通知)(抓住异常时也通知)

  3. @AfterThrowing 异常通知 (在目标方法抛出异常时执行的通知)

  4. @After 最终通知 (是在目标方法执行之后执行的通知)(报不报错都执行)

  5. @Around 环绕通知 (在目标方法执行之前和之后都可以执行额外代码的通知) //不能没有返回值,且返回值不能为空

    @Around("methodPointcut()")public Object logger(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("环绕前");Object result = joinPoint.proceed();//放行System.out.println("环绕后");return result;}
    

目标方法指的是:调用的insert,update,update等方法

2.2.3.1 JoinPoint

join[连接] , Point[点]

joinPoint[连接点] (被拦截下来的方法)

joinPoint方法:

getTarget() 目标对象(输出拦截下来的方法属于那个类,(输出类的路径))

@After("methodPointcut()")public void logger(JoinPoint joinPoint) {System.out.println("目标对象(委托类)"+joinPoint.getTarget());System.out.println("方法参数"+joinPoint.getArgs()[0]);//返回的是数组类型joinPoint.getSignature().getName();//得到方法名,}

过滤器 filter 优先级最高

拦截器 interceptor

aop

watcher 观察者模式


JdbeTemplate

JdbcTemplate(概念和准备)

  1. 什么是 JdbcTemplate

    Spring 框架对 JDBC 进行封装,使用 JdbcTemplate 方便实现对数据库操作

  2. 准备工作

    1. 引入相关 jar 包

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cV5lM1gh-1654355011651)(spring%E7%AC%94%E8%AE%B0.assets/image-20220309161748151.png)]

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BEFNoOk9-1654355011652)(spring%E7%AC%94%E8%AE%B0.assets/image-20220309161813170.png)]mysql驱动

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HaxDkJJc-1654355011653)(spring%E7%AC%94%E8%AE%B0.assets/image-20220309161951353.png)]底层封装了jdbc

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qDu3EO8Z-1654355011654)(spring%E7%AC%94%E8%AE%B0.assets/image-20220309162041846.png)]针对事务想过操作的依赖

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tM2kKkTn-1654355011656)(spring%E7%AC%94%E8%AE%B0.assets/image-20220309162135901.png)]整合Mybatis或其他框架时使用

    2. 在 spring 配置文件配置数据库连接池

      <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"><property name="url" value="jdbc:mysql:///spring5" /><property name="username" value="root" /><property name="password" value="123456" /><property name="driverClassName" value="com.mysql.jdbc.Driver" /></bean>
      
    3. 配置jdbcTemplate对象,注入数据源

      <!--JdbcTemplate对象--><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><!--注入数据源--><property name="dataSource" ref="dataSource"/>
      </bean>
      
    4. 创建 service 类和 dao 类,在 dao 注入 jdbcTemplate 对象

      扫描包

      <context:component-scan base-package="com.atguigu.jdbeTemplate"/>
      

      注入对象

      @Repository
      public class BookDaoImpl implements BookDao{@Autowiredprivate JdbcTemplate jdbcTemplate;
      }
      

JdbcTemplate操作数据库(添加)

  1. 对应数据库字段创建实体类,并生成get set方法

  2. 编写 service dao

    1. 调用 JdbcTemplate 对象里面 update 方法实现添加操作

      1. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FUwozVz1-1654355011657)(spring%E7%AC%94%E8%AE%B0.assets/image-20220309172013130.png)]

      2. 第一个参数:写sql 语句

        第二个参数:写可变参数,设置 sql 语句值

      3. @Repository
        public class BookDaoImpl implements BookDao {@Autowiredprivate JdbcTemplate jdbcTemplate;@Overridepublic void add(Book book) {//创建sql语句String sql = "insert into jdbctemplate value(?,?,?)";//调用方法实现int update = jdbcTemplate.update(sql, book.getUserId(), book.getUsername(), book.getUstatus());System.out.println(update);}
        }
        
      4. 测试类

        public class JdbcTemplateTest {@Testpublic void test() {ClassPathXmlApplicationContext contest = new ClassPathXmlApplicationContext("dbPool.xml");BookService bookService = contest.getBean("bookService", BookService.class);Book book=new Book();book.setUserId(3);book.setUsername("java");book.setUstatus("a");bookService.add(book);}
        }
        

JdbcTemplate操作数据库(修改,删除)

//修改方法@Overridepublic void updateBook(Book book) {//创建sql语句String sql = "update jdbctemplate set book_name=?,ustatus=?  where book_id=?";int update = jdbcTemplate.update(sql, book.getBookname(), book.getUstatus(), book.getBookId());System.out.println(update);}//删除方法@Overridepublic void deleteBook(String id) {String sql="delete from jdbctemplate where book_id=?";int update= jdbcTemplate.update(sql,id);System.out.println(update);}

JdbcTemplate操作数据库(查询)

查询返回单个值

使用[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3Gg2CpDQ-1654355011658)(spring%E7%AC%94%E8%AE%B0.assets/image-20220313181149861.png)]
方法

第一个参数:sql 语句
第二个参数:返回类型 Class

//查询表中有多少条记录@Overridepublic int findCount() {String sql = "select count(*) from jdbctemplate";Integer count = jdbcTemplate.queryForObject(sql, Integer.class);//第二个参数是 返回类型.classreturn count;}
查询返回对象

使用[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bDWR67Hd-1654355011660)(spring%E7%AC%94%E8%AE%B0.assets/image-20220313181305484.png)]
方法

第一个参数:sql 语句
第二个参数:RowMapper 是接口,针对返回不同类型数据,使用这个接口里面实现类完成数据封装
第三个参数:sql 语句值

//查询返回对象@Overridepublic Book findOne(String id) {String sql = "select * from jdbctemplate where book_id=?";Book book = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Book>(Book.class), id);return book;}

查询返回集合

//查询返回集合(查询全部数据)
@Override
public List<Book> findAll() {String sql = "select * from jdbctemplate";List<Book> list = jdbcTemplate.query(sql,new BeanPropertyRowMapper<Book>(Book.class));return list;
}

JdbcTemplate操作数据库(批量添加)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FRQZAUkL-1654355011661)(spring%E7%AC%94%E8%AE%B0.assets/image-20220315184953944.png)]

第一个参数:sql 语句
第二个参数:List 集合,添加多条记录数据

添加方法

//批量添加@Overridepublic void batchAdd(List<Object[]> batchArgs) {String sql="insert into jdbctemplate value(?,?,?)";jdbcTemplate.batchUpdate(sql,batchArgs);}

测试方法

//批量添加List<Object[]> list=new ArrayList<>();Object[] o1={6,"ppp","aaa"};Object[] o2={7,"ooo","acccaa"};Object[] o3={8,"qqq","nnn"};list.add(o1);list.add(o2);list.add(o3);bookService.batchAdd(list);

JdbcTemplate操作数据库(批量修改)

//批量修改@Overridepublic void batchUpdate(List<Object[]> batchArgs) {String sql = "update jdbctemplate set book_name=?,ustatus=? where book_id=?";int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);System.out.println(Arrays.toString(ints));}

JdbcTemplate操作数据库(批量删除)

//批量删除@Overridepublic void batchDelete(List<Object[]> batchArgs) {String sql="delete from jdbctemplate where book_id=?";int[] ints=jdbcTemplate.batchUpdate(sql,batchArgs);System.out.println(Arrays.toString(ints));}

事务操作

事务概念

事务是数据库操作最基本单元,操作一条或多条sql语句时,要么都成功,要么都失败

事务的四个特性:

2、事务四个特性(ACID)

1)原子性 一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成
2)一致性 在事务开始之前和事务结束以后,数据库的完整性没有被破坏
3)隔离性 事务和事务之间相互隔离
4)持久性 事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失

搭建实务操作环境

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GmNpFKfZ-1654355011662)(spring%E7%AC%94%E8%AE%B0.assets/image-20220316104132732.png)]

  1. 创建 service,搭建dao,完成对象创建和注入关系
    (1)service 注入 dao,在 dao 注入 JdbcTemplate,在 JdbcTemplate 注入 DataSource

  2. dao 创建两个方法:多钱和少钱的方法,在 service 创建方法(转账的方法)

    @Repository
    public class UserDaoImpl implements UserDao{@Autowiredprivate JdbcTemplate jdbcTemplate;//添加钱@Overridepublic void addMoney() {String sql="update account set money=money+? where username=?";jdbcTemplate.update(sql,100,"lucy");}//减少钱@Overridepublic void reduceMoney() {String sql="update account set money=money-? where username=?";jdbcTemplate.update(sql,100,"mary");}
    }
    
  3. 在service中添加 转账方法

    @Service
    public class UserService {@Autowiredprivate UserDao userDao;//转账方法public void accountMoney() {//加钱userDao.addMoney();//少钱userDao.reduceMoney();}
    }
    
  4. 添加事务

事务的操作过程

@Service
public class UserService {@Autowiredprivate UserDao userDao;//转账方法public void accountMoney() {try{//第一步 开启事务//第二步 进行也不操作//加钱userDao.addMoney();//模拟异常int i=10/0;//少钱userDao.reduceMoney();//第三步 没有异常提交事务}catch (Exception e){//第四步 出现异常事务回滚}}
}

事务管理介绍

  1. 事务添加到 逻辑层

  2. 在Spring 进行事务管理操作

    1. 有两种方式:

      1. 编程式事务管理
      2. 声明式事务管理(使用)
  3. 声明式事务管理

    1. 基于注解方式(使用)
    2. 基于 xml 配置文件方式
  4. 在Spring进行声明式事务管理,底层使用AOP原理

  5. Spring事务管理API

    1. 提供一个接口,代表事务管理器,这个接口针对不同的框架提供不同的实现类

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yzCedEzq-1654355011663)(spring%E7%AC%94%E8%AE%B0.assets/image-20220317151116873.png)]

事务操作(注解)

  1. 在spring配置文件配置事务管理器

    <!--创建事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!--不同框架的事务管理器不同如Mybaties用的是DataSourceTransactionManagerHibernate用的是HibernateTransactionManager--><!--注入数据源--><property name="dataSource" ref="dataSource"/>
    </bean>
    
  2. 在spring配置文件,开启事务注解

    1. 在 spring 配置文件引入名称空间 tx

    2. 开启事务注解

      <!--开启事务注解-->
      <tx:annotation-driven transaction-manager="transactionManager"/>
      
    3. 在service类上面(或者在方法上面)添加事务注解

      1. @Transactional,这个注解添加到类上面,也可以添加方法上面

      2. 如果把这个注解添加类上面,这个类里面所有的方法都添加事务

      3. 如果把这个注解添加方法上面,只为这个方法添加事务

      4. @Service
        @Transactional
        public class UserService {}
        

事务参数配置

事务传播行为
  1. propagation:事务传播行为

    1. 多事务方法之间进行调用,这个过程中事务 是如何进行管理的(如:有事务的调用没事务的)

    2. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hFdf0Qu7-1654355011665)(spring%E7%AC%94%E8%AE%B0.assets/image-20220317174903537.png)]

    3. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2zlm7ysM-1654355011666)(spring%E7%AC%94%E8%AE%B0.assets/image-20220317174943719.png)]

    4. @Service
      @Transactional(propagation = Propagation.REQUIRED)
      public class UserService {}
      
    5. PROPAGATION_REQUIRED (默认值)

事务隔离级别

ioslation事务隔离级别

  1. 脏读: 事务读取到了另一个未提交的事务

  2. 不可重复度: 一个未提交的事务读取到一个已提交的事务

  3. 幻读: 一个未提交事务读取到另一提交事务添加数据

  4. 解决方法: 使用 隔离级别

    1. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5ENt5p4P-1654355011666)(spring%E7%AC%94%E8%AE%B0.assets/image-20220317210445990.png)]

      mysql默认是可重复读

    2. 如何使用格林级别

      @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ)
      
超时时间

timeout:超时时间

  1. 事务如果未在指定时间内提交,则进行回滚

  2. 默认值:-1(-1表示不超时),设置时间以秒为单位

  3. timeout = -1

    @Transactional(timeout = -1, propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ)
    
是否只读

readOnly:是否只读

1)读:查询操作,写:添加修改删除操作

2)readOnly 默认值 false,表示可以查询,可以添加修改删除操作

3)设置 readOnly 值是 true,设置成 true 之后,只能查询

readOnly = false

@Transactional(readOnly = false, timeout = -1, propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ)
回滚

设置出现哪些异常进行事务回滚

不回滚

设置出现哪些异常不进行事务回滚

完全注解开发

  1. 创建配置类,使用配置类替代 xml 配置文件

  2. 配置类

    @Configuration //定义该类为配置类
    @ComponentScan(basePackages = "com.atguigu") //扫描包
    @EnableTransactionManagement //开启事务
    public class TxConfig {//创建数据库连接池@Beanpublic DruidDataSource getDataSource(){DruidDataSource dataSource = new DruidDataSource();dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/spring5?serverTimezone=Asia/Shanghai&use Unicode=true&characterEncoding=UTF-8&useSSL=false");dataSource.setUsername("root");dataSource.setPassword("123456");return dataSource;}//创建jdbcTemplate对象@Beanpublic JdbcTemplate getJdbcTemplate(DataSource dataSource){JdbcTemplate jdbcTemplate=new JdbcTemplate();//注入DataSourcejdbcTemplate.setDataSource(dataSource);return jdbcTemplate;}//创建事务管理器对象@Beanpublic DataSourceTransactionManager getTransactionManager(DataSource dataSource){DataSourceTransactionManager transactionManager=new DataSourceTransactionManager();transactionManager.setDataSource(dataSource);return transactionManager;}
    }
  3. 测试类

    @Testpublic void test2() {ApplicationContext context = new AnnotationConfigApplicationContext(TxConfig.class);UserService userService = context.getBean("userService", UserService.class);userService.accountMoney();}
    

xml代码

    <!--扫描包--><context:component-scan base-package="com.atguigu"/><!--引入properties--><context:property-placeholder location="classpath:dataSource.properties"/><!--创建数据源--><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"><property name="url" value="${prop.url}" /><property name="username" value="${prop.userName}" /><property name="password" value="${prop.password}" /><property name="driverClassName" value="${prop.driverClass}" /></bean><!--创建JdbcTemplate对象--><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><!--注入数据源--><property name="dataSource" ref="dataSource"/></bean><!--创建事务管理器--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!--不同框架的事务管理器不同如Mybaties用的是DataSourceTransactionManagerHibernate用的是HibernateTransactionManager--><!--注入数据源--><property name="dataSource" ref="dataSource"/></bean><!--开启事务注解--><tx:annotation-driven transaction-manager="transactionManager"/>

之后 学 spring5新特性

spring5整合Junit4

  1. 引入依赖

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Un2powid-1654355011667)(spring%E7%AC%94%E8%AE%B0.assets/image-20220318095616696.png)]

  2. 创建测试类 添加注解@RunWith和@ContextConfiguration

    @RunWith(SpringJUnit4ClassRunner.class)//定义Junit框架版本
    @ContextConfiguration("classpath:Transaction.xml")//加载配置文件
    public class JTest4 {@Autowiredprivate UserService userService;@Testpublic void test1(){userService.accountMoney();}
    }
    

原测试文件

public class accountTest {@Testpublic void test1() {ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("Transaction.xml");UserService userService = context.getBean("userService", UserService.class);userService.accountMoney();}
}


2.SpringMVC

执行流程

  1. DispatcherServlet接收请求并拦截请求
  2. 把请求转交给处理器映射器
  3. 通过映射器将请求的url和Handler进行映射,然后返回给DispatcherServlet
  4. 根据HandlerAdapter(适配器)去找对应Controller类
  5. 在调用逻辑层调数据层
  6. 数据层返回数据到表现层
  7. 表现层携带数据(模型)和跳转的视图返回给HandlerAdapter(适配器)
  8. HandlerAdapter(适配器)在返回给DispatcherServlet
  9. DispatcherServlet再去调用视图解析器,将视图和模型传给视图解析器
    1. 视图解析器的任务

      1. 获取ModeAndView(模型和视图)
      2. 解析ModeAndView(模型和视图)的视图名字
      3. 拼接视图名字
      4. 将数据渲染到视图上
  10. 视图解析器将解析后的视图传给DispatcherServlet
  11. DispatcherServlet去找对应的视图
  12. 最终将视图返回给用户
  1. 用户通过浏览器发起 HttpRequest 请求到前端控制器 (DispatcherServlet)。

  2. DispatcherServlet 将用户请求发送给处理器映射器 (HandlerMapping)。

  3. 处理器映射器 (HandlerMapping)会根据请求,找到负责处理该请求的处理器,并将其封装为处理器执行链 返回 (HandlerExecutionChain) 给 DispatcherServlet

  4. DispatcherServlet 会根据 处理器执行链 中的处理器,找到能够执行该处理器的处理器适配器(HandlerAdaptor) --注,处理器适配器有多个

  5. 处理器适配器 (HandlerAdaptoer) 会调用对应的具体的 Controller

  6. Controller 将处理结果及要跳转的视图封装到一个对象 ModelAndView 中并将其返回给处理器适配器 (HandlerAdaptor)

  7. HandlerAdaptor 直接将 ModelAndView 交给 DispatcherServlet ,至此,业务处理完毕

  8. 业务处理完毕后,我们需要将处理结果展示给用户。于是DisptcherServlet 调用 ViewResolver,将 ModelAndView 中的视图名称封装为视图对象

  9. ViewResolver 将封装好的视图 (View) 对象返回给 DIspatcherServlet

  10. DispatcherServlet 调用视图对象,让其自己 (View) 进行渲染(将模型数据填充至视图中),形成响应对象 (HttpResponse)

  11. 前端控制器 (DispatcherServlet) 响应 (HttpResponse) 给浏览器,展示在页面上。

使用步骤

  1. 创建maven项目

  2. 右击项目 选择

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QEt39GMW-1654355011668)(spring笔记.assets/image-20220325170749072.png)]
    定义成web项目

  3. 在web.xml文件中注册DispatchServlet (注意修改 要关联springmvc的配置文件名 )

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><!--注册DispatchServlet--><servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!--关联springmvc的配置文件--><!--classpath: 只会到你的class路径中查找文件。classpath*: 不仅包含class路径,还包括jar文件中(class路径)进行查找--><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc-servlet.xml</param-value></init-param><!--启动级别 表示服务器启动时跟着启动--><load-on-startup>1</load-on-startup></servlet><!-- / 匹配所有请求: (不包含.jsp)--><!-- /* 匹配所有请求: (包含.jsp)--><servlet-mapping><servlet-name>springmvc</servlet-name><url-pattern>/</url-pattern></servlet-mapping>
    </web-app>
    
  4. 创建springmvc-servlet.xml文件 (在resources中创建)

    <?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"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"><!--扫描包--><context:component-scan base-package="com.kuang.controller"/><!--让springmvc不处理静态资源(过滤资源,不交给视图解析器处理)(如 .css  .js   .html   .mp3    .mp4    ...)--><mvc:default-servlet-handler/><!--注册映射器和适配器 注册之后才能使@RequestMapping注解生效--><mvc:annotation-driven/><!--视图解析器--><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver"><!--前缀--><property name="prefix" value="/WEB-INF/jsp/"/><!--后缀--><property name="suffix" value=".jsp"/></bean>
    </beans>
    
  5. 创建表现层

    @Controller
    @RequestMapping("/hello")   //父接收请求
    public class HelloMVC {@RequestMapping("/h1")   //接收请求public String Hello(Model model){//调用逻辑层//封装数据//model添加的值,可以再jsp页面中取出并渲染model.addAttribute("msg","Hello123123123123");//如果返回值是String,并且有具体页面可以跳转,就会被视图解析器处理,返回就是视图,return "hello";}
    }
    
  6. 创建要返回的jsp文件

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head><title>Title</title>
    </head>
    <body>${msg}<%--接收后端传来的参数--%>
    </body>
    </html>
    
  7. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FRZ9Qm1h-1654355011669)(spring笔记.assets/image-20220325171418552.png)]

RestFul风格

@RequestMapping 能够处理HTTP请求的方法,比如 get; put; post; delete; ratch

地址栏请求默认是get请求

@GetMapping

@PostMapping

@PutMapping

@DeleteMapping

@PatchMapping

用法:@GetMapping(“/add/{参数a}/{参数b}”)

@PathVariable 接收请求路径中占位符的值
通过 @PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中

http://localhost:8080/book/allBook

表现层代码

@Controller
public class ResFul {/** @PathVariable 接收请求路径中占位符的值* */@GetMapping("/get/{a}/{b}")public String GetUser(@PathVariable int a,@PathVariable int b, Model model){int msg=a+b;model.addAttribute("msg",msg);return "test";}
}

.jsp页面代码

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>${msg}
</body>
</html>

出现问题,检查tomcat和引包情况

转发和重定向

SpringMVC 默认是转发

重定向不能

如果要改成重定向需要添加redirect:

@GetMapping("/get")
public String GetUser1(Model model){String msg="123123";model.addAttribute("msg",msg);return "redirect:index.jsp";
}

接收参数及数据回显

接收的参数和方法参数名一致

接收的参数名和方法参数名一致时可以直接接收到

@GetMapping("/user1")
public String User1(String name,Model model){//接收前端参数String msg=name;//将返回结果传递给前端model.addAttribute("msg",msg);//视图跳转return "test";
}

接收的参数和方法参数名不一致

需要用@RequestParam() 里面写接收的参数名

@GetMapping("/user2")
public String User2(@RequestParam("username") String name, Model model){//接收前端参数String msg=name;//将返回结果传递给前端model.addAttribute("msg",msg);//视图跳转return "test";
}

接收对象参数

接收的参数名需要和对象中的属性名一致,否则接收不到(会得到null值)

@GetMapping("/user3")
public String User3(User user){/*//接收前端参数String msg=user;//将返回结果传递给前端model.addAttribute("msg",msg);*/System.out.println(user);//视图跳转return "test";
}

测试路径 localhost:8080/user?id=1&name=an&age=3
? 号后 写接收的参数
& 号后 分割多个参数

返回字符串类型

使用@ResponseBody //他就不会走视图解析器,会直接返回一个字符串

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mB8YHeqD-1654355011670)(spring笔记.assets/image-20220328172348036.png)]

使用@RestController //他会将所有方法都返回一个字符串,不走视图解析器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cYiAdFAH-1654355011671)(spring笔记.assets/image-20220328173046181.png)]

乱码问题

在web.xml文件中添加过滤器

<!--乱码过滤器-->
<filter><filter-name>encoding</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>
</filter>
<filter-mapping><filter-name>encoding</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>

Json

[]表示一个集合

{}表示对象

json解析工具 Jackson和阿里巴巴fastjson等等

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.13.2.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.75</version>
</dependency>

springmvc解决json乱码(添加到sping配置文件中)

<!--springmvc解决json乱码-->
<mvc:annotation-driven><mvc:message-converters register-defaults="true"><bean class="org.springframework.http.converter.StringHttpMessageConverter"><constructor-arg value="UTF-8"/></bean><bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"><property name="objectMapper"><bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean"><property name="failOnEmptyBeans" value="false"/></bean></property></bean></mvc:message-converters>
</mvc:annotation-driven>

Ajax

使用步骤:

  1. 引入ajax

    <script src="${pageContext.request.contextPath}/statics/jsp/jquery-3.6.0.js"></script>
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iWGuMjjL-1654355011672)(spring笔记.assets/image-20220506172632145.png)]

  2. 在xml配置文件中添加静态资源过滤

    <!--让springmvc不处理静态资源(过滤资源,不交给视图解析器处理)(如 .css  .js   .html   .mp3    .mp4    ...)-->
    <mvc:default-servlet-handler/>
    
  3. 用事件触发js函数,然后运行ajax

  4. <script>function a(){$.post({/*请求的地址*/url:"${pageContext.request.contextPath}/a1",/*键值对存储,key为后端接收的值,value为输入框的值*/data:{"name":$("#username").val()},/*请求成功,data为后端返回的数据*/success:function (data){alert(data);},/*请求失败*/error:function (){}})}
    </script>
    

拦截器

使用拦截器:

  1. 实现HandlerInterceptor接口,并重写方法

    package com.kuang.config;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 {//return true; 执行下一个拦截器,放行@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("=========处理前=========");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("=========处理后=========");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("=========清理=========");}
    }
    
  2. 在spring配置文件中配置拦截器

    <!--配置拦截器-->
    <mvc:interceptors><mvc:interceptor><!-- /** 拦截包括这个请求下面的所有请求--><mvc:mapping path="/**"/><bean class="com.kuang.config.MyInterceptor"/></mvc:interceptor>
    </mvc:interceptors>
    

SpringBoot

创建springBoot

  1. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2jZMRdyz-1654355011672)(spring笔记.assets/image-20220513104640241.png)]
  2. 删掉无用文件
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PiKMTlvU-1654355011673)(spring笔记.assets/image-20220513105402364.png)]

springboot原理1

springboot原理2

  • Pom.xml启动器:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
  • 主启动类

    //主程序
    // @SpringBootApplication 标注这个类是一个springboot应用
    @SpringBootApplication
    public class HelloworldApplication {public static void main(String[] args) {//将springboot启动SpringApplication.run(HelloworldApplication.class, args);}
    }
    

Yaml语法

配置文件

SpringBoot使用一个全局的配置文件 , 配置文件名称是固定的

  • application.properties

    • 语法结构 : key=value
  • application.yml
    • 语法结构 :key:空格 value

**配置文件的作用 :**修改SpringBoot自动配置的默认值,因为SpringBoot在底层都给我们自动配置好了;

yaml语法

properties只能保存键值对

yaml能存键值对,对象,数组,集合

# 普通key: value
name: peng# 对象
student:name: pengage: 3# 对象行内写法
student1: {name: peng,age: 3}# 数组
pets:- cat- dog- pig# 数组行内写法
pets1: [cat,dog,pig]

给属性赋值的几种方式

yaml可以直接给实体类赋值

实体类:

@Component
@Data
public class Person {private String name;private Integer age;private Boolean happy;private Date birth;private Map<String,Object> maps;private List<Object> lists;private Dog dog;
}
@Component
@Data
public class Dog {private String name;private Integer age;
}

spring传统赋值方式: 用@Value

@Component
@Data
public class Dog {@Value("peng")private String name;@Value("3")private Integer age;
}

yaml方式赋值:

  1. 引入依赖(不引入对代码也没影响,只是idea会报红,官方建议引入)

    <!--用yaml文件给属性赋值注解依赖-->
    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional>
    </dependency>
    
  2. 在类上添加注解@ConfigurationProperties(prefix = “”)

    /*
    @ConfigurationProperties注解的作用:
    将配置文件中的每一个属性的值,映射到这个组件中
    告诉springboot将本类中的所有属性和配置文件中的相关配置进行绑定
    参数prefix = "person1" : 将配置文件中的person1下的所有属性一一对应只有这个组件是容器中的组件,才能使用容器提供的@ConfigurationProperties功能*/
    @Component  //注册到bean
    @Data
    @ConfigurationProperties(prefix = "person1")
    public class Person {private String name;private Integer age;private Boolean happy;private Date birth;private Map<String,Object> maps;private List<Object> lists;private Dog dog;
    }
  3. yaml文件

    person1:name: pengage: 3happy: falsebirth: 2022/5/14maps: {k1: v1,k2: v2}lists:- code- music- girldog:name: 旺财age: 3
    

用properties配置文件赋值:

  1. 编写properties

    name=peng
    
  2. @PropertySource **:**加载指定的配置文件;

    @confifigurationProperties:默认从全局配置文件中获取值;

  3. 再用spel表达式取出配置文件中的值

    @Component
    @Data
    //加载指定的配置文件
    @PropertySource(value = "classpath:peng.properties")
    public class Dog {//spel表达式取出配置文件中的值@Value("${name}")private String name;private Integer age;
    }
    

yaml扩展:

spring的el表达式

person1:# ${random.uuid}获得一个uuidname: peng${random.uuid}# {random.int}获得随机数age: ${random.int}hello: aaaadog:# 引用person.hello 的值,如果不存在就用 :后面的值,即 other,然后拼接上_旺财name: ${person1.hello:other}_旺财age: 3

松散绑定:

yaml支持松散绑定:松散绑定指的是 符合驼峰命名规范时,可以绑定到一起

jsr-303校验

使用步骤:

  1. 引入依赖

    <!--数据校验依赖-->
    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId><version>2.6.7</version>
    </dependency>
    
  2. 在类上面添加注解@Validated

  3. 在属性上添加指定校验规则注解

    @Component  //注册到bean
    @Data
    @Validated //数据校验
    @ConfigurationProperties(prefix = "person1")
    public class Person {@Email(message = "邮箱格式错误")private String email;@NotNull(message="名字不能为空")private String name;
    }
    

常用的一些校验规则

@NotNull(message="名字不能为空")
private String userName; @Max(value=120,message="年龄最大不能超过120")
private int age; @Email(message="邮箱格式错误")
private String email; //空检查
@Null 验证对象是否为null
@NotNull 验证对象是否不为null, 无法查检长度为0的字符串
@NotBlank 检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格. @NotEmpty 检查约束元素是否为NULL或者是EMPTY.//Booelan检查
@AssertTrue 验证 Boolean 对象是否为 true
@AssertFalse 验证 Boolean 对象是否为 false//长度检查
@Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内 @Length(min=, max=) string is between min and max included.//日期检查
@Past 验证 Date 和 Calendar 对象是否在当前时间之前
@Future 验证 Date 和 Calendar 对象是否在当前时间之后
@Pattern 验证 String 对象是否符合正则表达式的规则.......等等 除此以外,我们还可以自定义一些数据校验规则

配置文件在不同目录下执行顺序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2ttDVJa5-1654355011674)(spring笔记.assets/image-20220514164333213.png)]

多环境切换

我们在主配置文件编写的时候,文件名可以是 application-{profifile}.properties/yml , 用来指定多个环境版本

例如:application-test.properties 代表测试环境配置 application-dev.properties 代表开发环境配置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3Jpfjshr-1654355011675)(spring笔记.assets/image-20220514213425769.png)]

使用spring.profiles.active=dev 来切换到指定环境

# springboot的多环境配置,可以选择激活某一个配置文件
spring:profiles:active: dev;

yaml实现不需要创建多个配置文件,创建出多套环境

server:port: 8081#来激活指定的配置文件
spring:profiles:active: dev# 用 --- 分割创建多个配置环境
---server:port: 8082
#spring.profiles给当前环境起名
spring:profiles: dev---server:port: 8083
spring:profiles: test

Kuang_spring笔记相关推荐

  1. 【读书笔记】知易行难,多实践

    前言: 其实,我不喜欢看书,只是喜欢找答案,想通过专业的解答来解决我生活的困惑.所以,我听了很多书,也看了很多书,但看完书,没有很多的实践,导致我并不很深入在很多时候. 分享读书笔记: <高效1 ...

  2. 【运维学习笔记】生命不息,搞事开始。。。

    001生命不息,搞事不止!!! 这段时间和hexesdesu搞了很多事情! 之前是机械硬盘和固态硬盘的测速,我就在那默默的看着他一个硬盘一个机械测来测去. 坐在他后面,每天都能看到这位萌萌的小男孩,各 ...

  3. SSAN 关系抽取 论文笔记

    20210621 https://zhuanlan.zhihu.com/p/353183322 [KG笔记]八.文档级(Document Level)关系抽取任务 共指id嵌入一样 但是实体嵌入的时候 ...

  4. pandas以前笔记

    # -*- coding: utf-8 -*- """ Created on Sat Jul 21 20:06:20 2018@author: heimi "& ...

  5. PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 call

    您的位置 首页 PyTorch 学习笔记系列 PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 发布: 2017年8月4日 7,195阅读 ...

  6. 容器云原生DevOps学习笔记——第三期:从零搭建CI/CD系统标准化交付流程

    暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...

  7. 容器云原生DevOps学习笔记——第二期:如何快速高质量的应用容器化迁移

    暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...

  8. 王道考研 计算机网络笔记 第六章:应用层

    本文基于2019 王道考研 计算机网络: 2019 王道考研 计算机网络 个人笔记总结 第一章:王道考研 计算机网络笔记 第一章:概述&计算机网络体系结构 第二章:王道考研 计算机网络笔记 第 ...

  9. 王道考研 计算机网络笔记 第五章:传输层

    本文基于2019 王道考研 计算机网络: 2019 王道考研 计算机网络 个人笔记总结 第一章:王道考研 计算机网络笔记 第一章:概述&计算机网络体系结构 第二章:王道考研 计算机网络笔记 第 ...

最新文章

  1. 免费下载!200+讲者核心观点公布!2021最强AI学术会议视频全部回放
  2. 免费的新一代私有云平台Nano v0.3.1发布:云主机快照及媒体管理
  3. arm64的适配问题,这次真醉了
  4. 清理mysql创建的游戏_Linux定时清理游戏log及mysql定时任务删除游戏日志数据的步骤...
  5. python 为什么没有重载_python是否支持重载
  6. java中日期与字符串之间的转换
  7. 第三课 泛型+反射封装数据库访问层 2019-04-02
  8. Linux命令之ifconfig
  9. 前端学习(760):对象导读
  10. var和function谁先优先执行_js函数和变量的执行顺序【易错】
  11. Selenium select-下拉列表处理
  12. 【软件安装】IDM安装并扩展到FireFox和Google Chrome
  13. 在Realview MDK中添加自己的FLASH编程算法
  14. 【HAVENT原创】Spring RestTemplate 工具类
  15. 一个200左右的数字 四个四个的数多一 六个六个的数少一 七个七个的数多六 问此数为多少。。。
  16. ThinkPHP5.0+PHPMailer 实现qq邮箱验证码
  17. MATLAB曲线绘制
  18. 插画素材哪里找?5个超级实用的插画素材库推荐
  19. Mysql导出数据的几种方式
  20. 带蒙版的安卓剪辑软件_视频剪辑必备:5款完全免费的良心剪辑App

热门文章

  1. 【技巧】windows11任务栏无法打开任务管理器的解决办法
  2. 干货 | 诚迈科技联合联发科技、Linaro推出《Make it happen!联发科技曦力X20开发板技术公开课(上海站)》精彩回顾
  3. 关于更新win11后校园网卡顿问题(WLAN上网)
  4. python --003--流程控制while,for
  5. 蚂蚁金服蒋国飞:区块链商用时代正在加速到来
  6. 如何选择正确的RF连接器
  7. 微信用手机号注册利与弊
  8. ||、、!的使用与区别
  9. KanKan甄选,BaseAdapter我要对你说,ViewHolder你懂得,性能优化必读
  10. 搭建hadoop 集群,出现 Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).