1.SPring概念
2.IOC容器
3Aop
4JDBC Template
5.事务管理
6.Spring 5 新特性
Spring是轻量级的开源的JavaEE框架
Spring可以解决企业应用开发的复杂性
Spring有两个核心部分 : **
IOC 和 AOP
**
IOC:控制反转,把创建对象过程交给SPring管理
Aop:面向切面,不修改源代码的进行功能增强
SPring特点
选取Spring5版本
下载链接
https://repo.spring.io/ui/native/release/org/springframework/spring/
这里下载的是5.2.9 RELEASE稳定版本
导入jar包
public class User {
public void add(){
System.out.println("add..");
}
}
(1)Spring配置文件使用xml格式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fRrojz1u-1639549019989)(1Spring框架概述.assets/image-20211207173650355.png)]
<beans xmlns="http://www.springframework.org/schema/beans"
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">
<bean id="user" class="com.lyp.spring5.User">bean>
beans>
public class TestSpring5 {
@Test
public void testAdd(){
//1.加载spring配置文件
ApplicationContext context =
new ClassPathXmlApplicationContext("bean1.xml");
//2.获取配置创建的对象
User user = context.getBean("user", User.class);
System.out.println(user);
user.add();
}
}
概念和原理
IOC思想基于IOC容器完成,IOC容器底层就是对象工厂
Spring提供IOC容器实现两种方式:(两个接口) 都可以. 加载spring配置文件, 获取配置创建的对象
BeanFactory :IOC容器基本实现,是Spring内部使用接口,不提供开发人员进行使用
//1.加载spring配置文件
// ApplicationContext context =
// new ClassPathXmlApplicationContext("bean1.xml");
BeanFactory context =
new ClassPathXmlApplicationContext("bean1.xml");
//BeanFActory加载配置文件时候不会创建对象,在获取对象(使用) 才去创建对象
//ApplicationContext 加载配置文件时候 会把配置文件的对象进行创建
//2.获取配置创建的对象
User user = context.getBean("user", User.class);
ApplicationContext : BeanFActory 接口的子接口,提供更多更强大的功能,一般是由开发人员进行使用。
ApplicationContext接口有实现类
Bean管理 指的是两个操作
Bean管理操作有两种方式
(基于xml)
(基于注解)
1)在spring配置中,使用bean标签,标签里面添加对应属性,就可以实现对象创建
2)在bean标签里面有很多属性,介绍常用属性
id属性 :唯一标识
**class属性 :**类全路径(包类路径)
3)创建对象时候,默认也是执行无参构造方法
1)DI:依赖注入,就是注入属性
//1.创建类,定义属性和对应的set方法
public class Book {
//1.创建类,定义属性和对应的set方法
private String bname;
public void setBname(String bname) {
this.bname = bname;
}
public static void main(String[] args) {
Book book = new Book();
book.setBname("abc");
}
}
//2.在spring配置文件配置对象创建,配置属性注入
<bean id="book" class="com.lyp.spring5.Book">
<property name="bname" value="水浒传"> property>
<property name="bauthor" value="施耐庵"> property>
bean>
public class Book {
private String bname;
//set方法注入
public void setBname(String bname) {
this.bname = bname;
}
//有参数构造注入
public Book(String bname) {
this.bname = bname;
}
public static void main(String[] args) {
//set方法注入
// Book book = new Book();
// book.setBname("abc");
//有参数构造注入
Book book = new Book("abc");
}
}
1》创建类,定义属性,创建属性对应的有参数构造方法
public class Orders {
private String oname;
private String sddress;
//有参构造
public Orders(String oname, String sddress) {
this.oname = oname;
this.sddress = sddress;
}
}
2》在spring配置文件中进行配置
<bean id="orders" class="com.lyp.spring5.Orders">
<constructor-arg name="oname" value="电脑">constructor-arg>
<constructor-arg name="address" value="China">constructor-arg>
bean>
1》使用p名称空间注入,可以简化基于xml配置方式
第一步 添加p名称空间在配置文件中
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DRxBHgP7-1639549019996)(1Spring框架概述.assets/image-20211208143719712.png)]
第二步 进行属性注入,在bean标签里面进行操作
<bean id="book" class="com.lyp.spring5.Book " p:bname="西游戏" p:bauthor="吴承恩">
bean>
1》字面量
<property name="address" >
<null/>
property>
<property name="address" >
<value>>]]>value>
property>
创建两个类 Service类和Dao类
在service 调用dao里面的方法
在spring配置文件中进行配置
public class UserService {
//创建UserDao类型属性,生成set方法
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void add(){
System.out.println("service add。。。。。");
userDao.update();
//创建UserDao对象 原始方式
// UserDao userDao = new UserDaoImpl(); //接口= new 实现类
// userDao.update();
}
}
public interface UserDao {
public void update();
}
public class UserDaoImpl implements UserDao{
@Override
public void update() {
System.out.println("dao update。。。。.");
}
}
<bean id="userService" class="com.lyp.spring5.service.UserService">
<property name="userDao" ref="userDaoImpl">property>
bean>
<bean id="userDaoImpl" class="com.lyp.spring5.dao.UserDaoImpl">bean>
测试类
public class TestBean {
@Test
public void testAdd(){
//1.加载spring 配置文件
ApplicationContext context =
new ClassPathXmlApplicationContext("bean2.xml");
//2. 获取配置创建对象
UserService userService = context.getBean("userService", UserService.class);
System.out.println(userService);
userService.add();
}
}
1》一对多关系:部门和员工
一个部门有多个员工,一个员工属于一个部门
部门是一,员工是多
2》在实体类之间表示一对多的关系, 员工表示所属部门,使用对象类型属性进行表示
//部门类
public class Dept {
private String name;
public void setName(String name) {
this.name = name;
}
}
//员工类
public class Emp {
private String ename;
private String gender;
//员工属于某一个部门,使用对象形式表示
private Dept dept;
public void setDept(Dept dept) {
this.dept = dept;
}
public void setEname(String ename) {
this.ename = ename;
}
public void setGender(String gender) {
this.gender = gender;
}
}
3》在sping配置文件中进行配置
<bean id="emp" class="com.company.bean.Emp">
<property name="ename" value="lucy">property>
<property name="gender" value="女">property>
<property name="dept">
<bean id="dept" class="com.company.bean.Dept">
<property name="name" value="安保部">property>
bean>
property>
bean>
第一种写法
<bean id="emp" class="com.company.bean.Emp">
<property name="ename" value="lucy">property>
<property name="gender" value="女">property>
<property name="dept" ref="dept"> property>
bean>
<bean id="dept" class="com.company.bean.Dept">
<property name="dname" value="财务部">property>
bean>
第二种写法
<bean id="emp" class="com.company.bean.Emp">
<property name="ename" value="Lili">property>
<property name="gender" value="女">property>
<property name="dept" ref="dept">property>
<property name="dept.dname" value="技术部">property>
bean>
<bean id="dept" class="com.company.bean.Dept">
<property name="dname" value="财务部">property>
bean>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D8C26Jpr-1639549019998)(1Spring框架概述.assets/image-20211208211921390.png)]
1》注入数组类型属性
2》注入List集合类型属性
3》注入Map集合类型属性
第一步创建类,定义数组,list,map,set类型属性,生成对应set方法
public class Stu {
//1 数组类型属性
private String[] courses;
//2 List集合类型属性
private List<String> list;
//3 Map集合类型属性
private Map<String,String> maps;
//4 set集合类型属性
private Set<String> sets;
public void setCourses(String[] courses) {
this.courses = courses;
}
public void setMaps(Map<String, String> maps) {
this.maps = maps;
}
public void setList(List<String> list) {
this.list = list;
}
public void test(){
System.out.println(Arrays.toString(courses));
System.out.println(list);
System.out.println(maps);
System.out.println(sets);
}
}
第二步 在spring配置文件中进行配置
<bean id="stu" class="com.lyp.collectiontype.Stu">
<property name="courses" >
<array>
<value>java课程value>
<value>数据库课程value>
array>
property>
<property name="list">
<list>
<value>张三value>
<value>张四value>
list>
property>
<property name="maps">
<map>
<entry key="JAVA" value="java">entry>
<entry key="PHP" value="php">entry>
map>
property>
<property name="sets">
<set>
<value>MySQLvalue>
<value>Redisvalue>
set>
property>
bean>
第三步 写一个测试类
public class TestSpring5Demo1 {
@Test
public void testCollection(){
ApplicationContext context =
new ClassPathXmlApplicationContext("bean1.xml");
Stu stu = context.getBean("stu", Stu.class);
stu.test();
}
}
4》 在集合里面设置对象类型值
<bean id="course1" class="com.lyp.collectiontype.Course">
<property name="cname" value="Spring5框架">property>
bean>
<bean id="course2" class="com.lyp.collectiontype.Course">
<property name="cname" value="Mybatis框架">property>
bean>
<property name="courseList">
<list>
<ref bean="course1">ref>
<ref bean="course2">ref>
list>
property>
bean>
5》把集合注入部分提取出来
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
beans>
使用util标签完成list集合注入提取
<util:list id="bookList">
<value>水浒传value>
<value>西游记value>
<value>红楼梦value>
util:list>
<bean id="book" class="com.lyp.collectiontype.Book">
<property name="list" ref="bookList">property>
bean>
Spring有两种类型bean,一种普通bean,另外一种工厂bean(factorybean)
第一步 创建类,让这个类作为工厂bean,实现接口FactoryBean
第二步 实现接口里面的方法,在实现方法定义返回的bean类型
//设置的对象类型是MyBean 但是返回的类型是Course
public class MyBean implements FactoryBean<Course> {
//定义返回bean
@Override
public Course getObject() throws Exception {
Course course = new Course();
course.setCname("abc");
return course;
}
@Override
public Class<?> getObjectType() {
return null;
}
@Override
public boolean isSingleton() {
return false;
}
}
@Test
public void testCollection3(){
ApplicationContext context =
new ClassPathXmlApplicationContext("bean3.xml");
Course course = context.getBean("myBean", Course.class);
System.out.println(course);
}
1.在spring里面,设置创建bean实例是单实例还是多实例
2.在Spring里面,默认情况下,bean是一个单实例对象
默认是单实例对象
3.如何 设置单实例还是多实例
在spring配置文件bean标签里面有属性(scope) 用于设置单实例还是多实例 scope
scope属性值
第一个值 默认值 ,singleton,表示单实例对象
第二个值prototype,表示多实例对象
第一 :singleton单实例 prototype多实例
第二:设置scope值是 singleton时候,加载spring配置文件时候就会创建单实例对象
设置scope值是 prototype时候, 不是在加载spring配置文件时候 创建对象 ,在调用getbean方法时候创建多实例对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CcoxOgsV-1639549020002)(1Spring框架概述.assets/image-20211209160533740.png)]
request
session
1 生命周期
2.bean 生命周期
1》 通过构造器创建bean实例(无参数构造)
2》为bean的属性设置值和对其他bean引用(调用set方法)
3》调用bean的初始化的方法(需要进行配置)
4》bean可以使用了(对象获取到了)
5》当容器关闭时候,调用bean的销毁方法(需要进行配置销毁的方法)
3.演示bean生命周期
public class Orders {
//无参数构造
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("第三步 执行初始化的方法");
}
// 创建执行销毁的方法
public void destroyMethod(){
System.out.println("第五步 执行销毁的方法");
}
}
<beans xmlns="http://www.springframework.org/schema/beans"
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">
<bean id="orders" class="com.lyp.bean.Orders" init-method="initMethod" destroy-method="destroyMethod">
<property name="oname" value="手机">property>
bean>
beans>
@Test
public void testBean4(){
// ApplicationContext context =
// new ClassPathXmlApplicationContext("bean4.xml");
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("bean4.xml");
Orders orders = context.getBean("orders", Orders.class);
System.out.println("第四步 获取创建bean实例对象");
System.out.println(orders);
//手动让bean的实例销毁
// ( (ClassPathXmlApplicationContext) context).close();
context.close();
}
4.bean的后置处理器 bean的生命周期有七步
1》 通过构造器创建bean实例(无参数构造)
2》为bean的属性设置值和对其他bean引用(调用set方法)
3》把bean实例传递bean后置处理器的方法 postProcessBeforeInitialization
4》调用bean的初始化的方法(需要进行配置)
5》把把bean实例传递bean后置处理器的方法 postProcessAfterInitialization
6》bean可以使用了(对象获取到了)
7》当容器关闭时候,调用bean的销毁方法(需要进行配置销毁的方法)
5.演示添加后置处理器效果
1》创建类,实现接口BeanPostProcessor , 创建后置处理器
public class MyBeanPost implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在初始化之前执行的方法");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在初始化之后执行的方法");
return bean;
}
}
<bean id="myBeanPost" class="com.lyp.bean.MyBeanPost">bean>
什么是自动装配
根据指定装配规则(属性 名称 或者属性类型), Spring自动将匹配的属性值进行注入
自动装配过程
1》根据属性名称自动注入
!--实现自动装配
bean标签属性autowire,配置自动装配
autowire属性常用两个值:
byName根据属性名称注入 ,注入值bean 的id值和类属性名称一致
byType根据属性类型注入
-->
<bean id="emp" class="com.lyp.autowire.Emp" autowire="byName">
bean>
<bean id="dept" class="com.lyp.autowire.Dept">bean>
2》根据属性类型注入
!--实现自动装配
bean标签属性autowire,配置自动装配
autowire属性常用两个值:
byName根据属性名称注入 ,注入值bean 的id值和类属性名称一致
byType根据属性类型注入
-->
<bean id="emp" class="com.lyp.autowire.Emp" autowire="byType">
bean>
<bean id="dept" class="com.lyp.autowire.Dept">bean>
1.直接配置数据库信息
2 引入外部属性文件配置数据库连接池
1》引入context名称空间
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
2》在spring配置文件使用标签引入外部属性文件
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${prop.driverClass}">property>
<property name="url" value="${prop.url}">property>
<property name="username" value="${prop.userName}">property>
<property name="password" value="${prop.password}">property>
bean>
上面四个注解功能是一样的,都可以用来创建bean实例
第一步 引入依赖
第二步 开启组件扫描
<context:component-scan base-package="com.lyp">context:component-scan>
第三步,创建类,在类上面添加创建对象注解
//在注解里面value属性值可以省略不写
//默认是类的名称,首字母小写
@Component(value = "userService") // public class UserService {
public void add(){
System.out.println("service add....");
}
}
测试类
public class TestSpring5Demo1 {
@Test
public void testdemo1(){
ApplicationContext context =
new ClassPathXmlApplicationContext("bean1.xml");
UserService userService = context.getBean("userService", UserService.class);
System.out.println(userService);
userService.add();
}
}
<context:component-scan base-package="com.lyp" use-default-filters="false">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Component"/>
context:component-scan>
<context:component-scan base-package="com.lyp">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
context:component-scan>
第一步 把service 和dao 对象创建,在service 和dao 类添加创建对象注解
第二步 在service注入 dao 对象,在service类添加dao类型属性,在属性上面使用注解
//在注解里面value属性值可以省略不写
//默认是类的名称,首字母小写
//@Component(value = "userService") // @Service
public class UserService {
//定义dao类型属性D
//不需要添加set方法
//添加注入属性注解
@Autowired //根据类型进行注入
private Userdao userdao;
public void add(){
System.out.println("service add....");
userdao.add();
}
}
这个Qualifier 注解的使用,和上面@Autowired 一起使用
@Service
public class UserService {
//定义dao类型属性D
//不需要添加set方法
//添加注入属性注解
@Autowired //根据类型进行注入
@Qualifier(value = "userDaoImpl1") //根据名称进行注入
private Userdao userdao;
public void add(){
System.out.println("service add....");
userdao.add();
}
}
@Repository(value = "userDaoImpl1")
public class UserDaoImpl implements Userdao{
@Override
public void add() {
System.out.println("dao add ....");
}
}
// @Resource //根据类型进行注入
@Resource(name = "userDaoImpl1") //根据名称注入
private Userdao userdao;
Resource 是javax中的
import javax.annotation.Resource;
@Value(value = "abc")
private String name;
(1) 创建配置类,替代xml配置文件
@Configuration //作为配置类,代替xml配置文件
@ComponentScan(basePackages = {"com.lyp"})
public class SpringConfig {
}
(2)编写测试类
@Test
public void testdemo2(){
//加载配置类
ApplicationContext context =
new AnnotationConfigApplicationContext(SpringConfig.class);
UserService userService = context.getBean("userService", UserService.class);
System.out.println(userService);
userService.add();
}
(1) AOP 为 Aspect Oriented Programming ,(面向切面编程),利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
(2) 通俗描述 : 不通过修改源代码方式,在主干功能里面添加新的功能
(3) 使用登录的例子说明AOP
1.AOP底层使用动态代理
(1) 有两种情况动态代理
第一种 有接口情况,使用JDK动态代理
第二种 没有接口情况 ,使用CGLIB动态代理
(1)调用newProxyInstance方法
方法里面有三个参数:
第一个参数:类加载器
第二个参数:增强方法所在的类,这个类实现的接口,支持多个接口
第三个参数:实现这个接口Interface InvocationHandler,创建代理对象,写增强的方法。
(1) 创建接口,定义方法
package com.lyp;
public interface UserDao {
public int add(int a ,int b);
public String update(String id);
}
(2)创建接口实现类,实现方法
package com.lyp;
public class UserDaoImpl implements UserDao{
@Override
public int add(int a, int b) {
System.out.println("add方法执行了。。。。");
return a+b;
}
@Override
public String update(String id) {
System.out.println("update方法执行了。。。。");
return id;
}
}
(3)使用Proxy类创建接口代理对象
package com.lyp;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
public class JDKProxy {
public static void main(String[] args) {
//创建接口实现类代理对象
Class[] interfaces = {UserDao.class};
// Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new InvocationHandler() {
// @Override
// public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// return null;
// }
// });
UserDaoImpl userDao = new UserDaoImpl();
UserDao dao = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
int result = dao.add(1, 2);
System.out.println("result : "+result);
}
}
//创建代理对象代码
class UserDaoProxy implements InvocationHandler{
//1 把创建的 是谁的代理对象,把谁传递过来
//有参数构造
private Object obj;
public UserDaoProxy(Object obj){
this.obj = obj ;
}
//增强的逻辑
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//方法之前
System.out.println("在方法之前执行。。。。"+method.getName() +"传递的参数。。。" + Arrays.toString(args));
//被增强的方法
Object res = method.invoke(obj, args);
//方法之后
System.out.println("方法之后执行" + obj);
return res;
}
}
1.连接点
类里面哪些方法可以被增强,这些方法称为 连接点。
2.切入点
实际被真正增强的方法,称为切入点。
3.通知(增强)
实际增强的逻辑部分称为通知(增强)
通知有多种类型
4.切面
是动作
把通知应用到切入点的过程
(1)什么是AspectJ
(1)基于xml配置文件
(2) 基于注解方式实现(使用)
(1)切入点表达式作用 : 知道对哪个类里面的哪个方法进行增强
(2)语法结构 :
execution([权限修饰符] [返回类型] [类全路径] [方法名称] [参数列表])
举例1. 对 com.lyp.dao.BookDao类里面的add 进行增强
Execution(* com.lyp.dao.BookDao.add(…))
举例2. 对 com.lyp.dao.BookDao类里面的所有( *)方法进行增强
Execution(* com.lyp.dao.BookDao.*****(…))
举例3.对 com.lyp.dao包里面的类里面的所有类,类里面的所有方法 进行增强
Execution(* com.lyp.dao.*.*****(…))
1、创建类, 在类里面定义方法
//被增强的类
public class User {
public void add(){
System.out.println("add...");
}
}
2.创建增强类(编写增强逻辑)
(1 )在增强类里面,创建方法,让不同方法代表不同通知类型
//增强的类
public class UserProxy {
//前置通知
public void before(){
System.out.println("before..");
}
}
3.进行通知配置
(1)在 spring配置文件中,开启注解扫描
<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: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/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.lyp.aopAnno">context:component-scan>
beans>
(3)在增强类上面添加注解@Aspect
//增强的类
@Component
@Aspect //生成代理对象
public class UserProxy {
(4)在Spring配置文件中开启生成代理对象
<aop:aspectj-autoproxy>aop:aspectj-autoproxy>
4.配置不同类型的通知
(1)在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置
package com.lyp.aopAnno;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
//增强的类
@Component
@Aspect //生成代理对象
public class UserProxy {
//前置通知
//before 注解 表示作为前置通知
@Before(value = "execution(* com.lyp.aopAnno.User.add(..))")
public void before(){
System.out.println("before..。。");
}
//后置通知(返回通知)
@AfterReturning(value = "execution(* com.lyp.aopAnno.User.add(..))")
public void AfterReturning(){
System.out.println("AfterReturning..。。");//在返回值后执行
}
//最终通知
@After(value = "execution(* com.lyp.aopAnno.User.add(..))")
public void After(){
System.out.println("After..。。");//在方法执行后执行
}
//异常通知
@AfterThrowing(value = "execution(* com.lyp.aopAnno.User.add(..))")
public void AfterThrowing(){
System.out.println("AfterThrowing..。。");
}
//环绕通知
@Around(value = "execution(* com.lyp.aopAnno.User.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
System.out.println("环绕之前");
//被增强的方法执行
proceedingJoinPoint.proceed();
System.out.println("环绕之后");
}
}
5.相同的切入点抽取
//相同切入点抽取
@Pointcut(value = "execution(* com.lyp.aopAnno.User.add(..))")
public void pointdemo(){
}
//前置通知
//before 注解 表示作为前置通知
@Before(value = "pointdemo()")
public void before(){
System.out.println("before..。。");
}
6.有多个增强类对同一个方法进行增强,设置增强类优先级
(1)在增强类上面添加注解@Order(数字类型值),数字类型值越小优先级越高
@Component
@Aspect
@Order(1)
public class PersonProxy {
7.完全使用注解开发
(1)创建配置类,不需创建xml配置文件
@Component
@ComponentScan(basePackages = {"com.lyp"}) //扫描
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop {
}
1.创建两个类,增强类和被增强类,创建方法
2.在spring配置文件中创建两个类对象
<bean id="book" class="com.lyp.aopxml.Book">bean>
<bean id="bookProxy" class="com.lyp.aopxml.BookProxy">bean>
3.在spring配置文件中配置切入点
<aop:config>
<aop:pointcut id="p" expression="execution(* com.lyp.aopxml.Book.buy(..))"/>
<aop:aspect ref="bookProxy">
<aop:before method="before" pointcut-ref="p"/>
aop:aspect>
aop:config>
测试
@Test
public void testAopXML(){
ApplicationContext context =
new ClassPathXmlApplicationContext("bean2.xml");
Book book = context.getBean("book", Book.class);
book.buy() ;
}
(1)spring 框架对 JDBC进行封装,使用 JdbcTemplate 方便实现对数据库操作
(2)在spring 配置文件中配置数据库连接池
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
<property name="url" value="jdbc:mysql://localhost:3306/user_db?serverTimezone=GMT%2B8&useSSL=false&useUnicode=true&characterEncoding=UTF-8&allowPublicKeyRetrieval=true">property>
<property name="username" value="root">property>
<property name="password" value="000000">property>
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver">property>
bean>
(3)配置JdbcTemplate 对象,注入DataSource
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource">property>
bean>
(4) 创建service类,创建dao类,在dao类注入jdbcTemplate 对象
<context:component-scan base-package="com.lyp">context:component-scan>
@Service
public class BookService {
//注入dao
@Autowired
private BookDao bookDao;
}
@Repository
public class BookDaoImpl implements BookDao{
//注入JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
}
1.对应数据库创建实体类
遇到的question
如果步对应在查询时会出现jdbcTempalte查询为null的情况
2.编写service和dao
(1)在dao进行数据库添加操作
@Repository
public class BookDaoImpl implements BookDao{
//注入JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
//添加的方法
@Override
public void add(Book book) {
//1 创建sql语句
String sql = "insert into t_book values(?,?,?)";
//2 调用方法实现
Object[] args = {book.getUserId(), book.getUsername(), book.getUstatus()};
int update = jdbcTemplate.update(sql,args);
// int update = jdbcTemplate.update(sql, book.getUserId(), book.getUsername(), book.getUstatus());
System.out.println(update);
}
}
(2)调用JdbcTemplate对象里面update 方法实现添加操作
3.测试类
public class TestBook {
@Test
public void testAdd(){
ApplicationContext context =
new ClassPathXmlApplicationContext("bean1.xml");
BookService bookService = context.getBean("bookService", BookService.class);
Book book = new Book();
book.setUserId("1");
book.setUsername("java");
book.setUstatus("a");
bookService.addBook(book);
}
}
//修改的方法
@Override
public void updateBook(Book book) {
String sql = "update t_book set user_name=?,ustatus=? where user_id=?";
Object[] args = {book.getUsername(), book.getUstatus(), book.getUserId()};
//注意 三者的顺序
int update = jdbcTemplate.update(sql, args);
System.out.println(update);
}
//删除的方法
@Override
public void delete(String id) {
String sql = "delete from t_book where user_id=?";
int update = jdbcTemplate.update(sql, id);
System.out.println(update);
}
测试类
package com.lyp.dao.test;
import com.lyp.entity.Book;
import com.lyp.service.BookService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestBook {
@Test
public void testAdd(){
ApplicationContext context =
new ClassPathXmlApplicationContext("bean1.xml");
BookService bookService = context.getBean("bookService", BookService.class);
// //添加
// Book book = new Book();
// book.setUserId("1");
// book.setUsername("java");
// book.setUstatus("a");
// bookService.addBook(book);
// //修改
// Book book = new Book();
// book.setUserId("1");
// book.setUsername("javaupup");
// book.setUstatus("a");
// bookService.updateBook(book);
//删除
bookService.delete("1");
}
}
1.查询表里面有多少条记录,返回是某个值
2.使用JdbcTemplate 实现查询返回某个值代码
//查询表中记录数
@Override
public int selectCount() {
String sql = "SELECT COUNT(*) FROM t_book";
Integer count = jdbcTemplate.queryForObject(sql, Integer.class);
return count;
}
1.场景:查询图书详情
//查询返回对象值
@Override
public Book findBookInfo(String id) {
String sql = "SELECT * FROM t_book where user_id=?";
//调用方法
Book book = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Book>(Book.class), id);
return book;
}
1.场景:查询图书列表分页。。
2.调用JdbcTemplate 方法实现查询返回集合
1.批量操作:操作表里面多条记录
//批量添加
@Override
public void batchAddBook(List<Object[]> batchArgs) {
String sql = "insert into t_book values(?,?,?)";
int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
System.out.println(Arrays.toString(ints));
}
测试类
//批量添加
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1= {"4","php","b"};
Object[] o2= {"5","c","d"};
Object[] o3= {"6","c++","a"};
batchArgs.add(o1);
batchArgs.add(o2);
batchArgs.add(o3);
//调用批量添加
bookService.batchAdd(batchArgs);
}
//批量修改
@Override
public void batchUpdateBook(List<Object[]> batchArgs) {
String sql = "update t_book set user_name=?,ustatus=? where user_id=?";
int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
System.out.println(ints);
}
//批量删除
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1= {"4"};
Object[] o2= {"5"};
batchArgs.add(o1);
batchArgs.add(o2);
//调用方法实现批量删除
bookService.batchDelete(batchArgs);
(1)事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,如果有一个失败所有操作都失败
(2)典型场景:银行转账
lucy转账100给mary
lucy少100 mary多100
(1)原子性 : 不可分割,要么都失败要么都成功
(2)一致性 :操作之前和操作之后总量是不变的
(3)隔离性:多事务进行操作时,彼此不会产生影响
(4)持久性:事物提交后,表中发生变化
1、创建数据库表,添加记录
2、创建service,创建dao,完成对象创建和注入关系
(1)在 service 注入 dao, 在 dao 注入JdbcTemplate ,在JdbcTemplate 注入DataSource
@Service
public class UserService {
//注入dao
@Autowired
private UserDao userDao;
}
@Repository
public class UserDaoImpl implements UserDao{
//注入JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
}
<context:component-scan base-package="com.lyp">context:component-scan>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
<property name="url" value="jdbc:mysql://localhost:3306/user_db?serverTimezone=GMT%2B8&useSSL=false&useUnicode=true&characterEncoding=UTF-8&allowPublicKeyRetrieval=true">property>
<property name="username" value="root">property>
<property name="password" value="000000">property>
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver">property>
bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource">property>
bean>
3、在dao创建两个方法: 多钱和少钱的方法,在service 创建方法(转账的方法)
//多钱
@Override
public void addMoney() {
String sql = "update t_account set money=money+? where username=?";
jdbcTemplate.update(sql,100,"mary");
}
//lucy转账100给mary
//少钱
@Override
public void reduceMoney() {
String sql = "update t_account set money=money-? where username=?";
jdbcTemplate.update(sql,100,"lucy");
}
@Service
public class UserService {
//注入dao
@Autowired
private UserDao userDao;
//转账的方法
public void accountMoney(){
//lucy少100
userDao.reduceMoney();
//mary多100
userDao.addMoney();
}
}
测试类
@Test
public void testAccount(){
ApplicationContext context =
new ClassPathXmlApplicationContext("bean1.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.accountMoney();
}
4.上面银行转账代码,如果正常执行没有问题,但是如果执行过程中出现异常,有问题
(1)上面的问题如果解决?
(2)事物操作过程
(1)有两种方式:编程式事务管理 和 声明式事务管理(使用)
(1)基于注解方式
(2)基于xml 配置文件方式
(1) 提供一个接口,代表事务管理器,这个接口针对不同的框架提供不同的实现类
1、在Spring 配置文件中 配置事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource">property>
bean>
2、在Spring 配置文件中,开启事务注解
(1)在Spring 配置文件中引入名称空间 tx
<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: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/context http://www.springframework.org/schema/context/spring-context.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">
(2)开启事务注解
<tx:annotation-driven transaction-manager="transactionManager">tx:annotation-driven>
3、在Service类上面 (获取service 类里面方法上面) 添加事务注解
(1)@Transactional ,这个注解添加到类上面,也可以添加到方法上面
(2) 如果把这个注解添加类上面,这个类里面所有的方法都添加事务
(3)如果把这个注解添加方法上面,为这个方法添加事务
@Service
@Transactional
public class UserService {
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O6xYgUAc-1639549020031)(1Spring框架概述.assets/image-20211212192045562.png)]
(1)多事务方法直接进行调用,这个过程中事务时如何进行管理的
以上两种最常见
@Service
@Transactional(propagation = Propagation.REQUIRED)
public class UserService {
(1)**事务有特性称为隔离性,多事务操作之间不会产生影响。**不考虑隔离性产生很多问题。
(2)有三个读问题:脏读、(虚)幻读、不可重复读
(3)脏读:一个未提交事务读取到另一个未提交事务的数据 是一种致命问题
在事务回滚前读到修改的数据
(4)幻读:一个未提交事务读取到另一提交事务添加的数据
(5)不可重复读:一个未提交事务读取到另一个提交事务修改数据 是一种现象
@Service
@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ)
public class UserService {
默认 :REPEATABLE_READ
(1)事务需要在一定时间内进行提交,如果不提交进行回滚
(2)默认值时-1,设置时间以秒为单位进行计算
@Service
@Transactional(timeout = -1,propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ)
public class UserService {
(1)读:查询操作,写:添加修改删除操作
(2)readyOnly 默认值是false,表示可以查询,可以添加修改删除
(3)设置readyOnly 值是true,设置成true后,只能是查询
@Transactional( readOnly = false,timeout = -1,propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ)
(1)设置出现哪些异常进行事务回滚
(1)设置出现哪些异常不进行事务回滚
1、在spring 配置文件 中进行配置
第一步 配置事务管理器
第二步 配置通知
第三步 配置切入点和 切面
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource">property>
bean>
<tx:advice id="txadvice">
<tx:attributes>
<tx:method name="accountMoney"propagation="REQUIRED"/>
tx:attributes>
tx:advice>
<aop:config>
<aop:pointcut id="pt" expression="execution(* com.lyp.service.UserService.*(..))"/>
<aop:advisor advice-ref="txadvice" pointcut-ref="pt"/>
aop:config>
1、创建配置类,使用配置类替代xml 配置文件
@Configuration//配置类
@ComponentScan(basePackages ="com.lyp" ) //开启组件扫描
@EnableTransactionManagement //开启事务
public class TxConfig {
//创建数据库连接池
@Bean
public DruidDataSource getDruidDataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/user_db");
dataSource.setUsername("root");
dataSource.setPassword("000000");
return dataSource;
}
//创建JdbcTemplate 对象
@Bean
public JdbcTemplate getJdbcTemplate(DataSource dataSource){
//到IOC容器中 根据类型找到dataSource
JdbcTemplate jdbcTemplate = new JdbcTemplate();
//注入dataSource
jdbcTemplate.setDataSource( dataSource);
return jdbcTemplate;
}
//创建事务管理器对象
@Bean
public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource){
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
}
测试类
@Test
public void testAccount3(){
ApplicationContext context =
new AnnotationConfigApplicationContext(TxConfig.class);
UserService userService = context.getBean("userService", UserService.class);
userService.accountMoney();
}
(1)Spring5 已经移除Log4jConfigListener,官方Log4j2
(2)Spring5 框架整合Log4j2
第一步 引入jar包
第二步 创建Log4j2.xml配置文件
<configuration status="INFO">
<appenders>
<console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
console>
appenders>
<loggers>
<root level="info">
<appender-ref ref="Console"/>
root>
loggers>
configuration>
(1) @Nullable 注解可以使用在方法上面、属性上面、参数上面,表示方法返回可以为空,属性值可以为空,参数值可以为空
(2)注解用在方法上面,方法返回值可以为空
(3)注解用在方法的参数里面,方法参数可以为空
//函数式风格创建对象,交给spring进行管理
@Test
public void testAccount4(){
//1.创建GenericApplicationContext对象
GenericApplicationContext context = new GenericApplicationContext();
//2.调用context 的方法对象注册
context.refresh();
// context.registerBean( User.class, ()->new User());
context.registerBean( "user1",User.class, ()->new User());
//3 获取在spring 注册的对象
//User user = (User)context.getBean("com.lyp.test.User");
User user = (User)context.getBean("user1");
System.out.println(user);
}
(1)是Spring5台南佳的新模块,用于web开发的,功能类似SpringMVC,WebFlux使用当前比较流行的响应式编程出现的框架
(2)使用传统web框架,比如SpringMVC,这些基于Servlet容器,Webflux是一种异步非阻塞的框架,异步非阻塞的框架在Servlet 3.1以后才支持,核心是基于Reactor 的相关API实现的。
(3)解释什么是异步非阻塞
上面都是针对对象不一样
(4)Webflux 特点:
第一:非阻塞式: 再有限资源下,提高系统吞吐量和伸缩性,以Reactor为基础实现响应式编程
第二:函数式编程:spring5框架基于java8,Webflux使用Java8函数式编程方式实现路由请求
1》两个框架都可以使用注解方式,都运行再Tomcat等容器中
2》SpringMVC采用命令式编程,Webflux采用异步响应式编程
(1)什么是响应式编程
简称RP(Reactive Programming)
响应式编程是一种面向数据流和变化传播的编程范式。这意味着可以在编程语言中很方便地表达静态或动态的数据流,而相关的计算模型会自动将变化的值通过数据流进行传播。
例如,对于 a=b+c 这个表达式的处理,在命令式编程中,会先计算 b+c 的结果,再把此结果赋值给 变量a,因此 b,c 两值的变化不会对 变量a 产生影响。但在响应式编程中,变量a 的值会随时跟随 b,c 的变化而变化。
电子表格程序就是响应式编程的一个例子。单元格可以包含字面值或类似"=B1+C1"的公式,而包含公式的单元格的值会依据其他单元格的值的变化而变化。
响应式编程最初是为了简化交互式用户界面的创建和实时系统动画的绘制而提出来的一种方法,但它本质上是一种通用的编程范式。
例如,在MVC软件架构中,响应式编程允许将相关模型的变化自动反映到视图上,反之亦然。
(2)java8 及其之前版本
提供的观察者模式两个类Observer 和Observable
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.5.7version>
<relativePath/>
parent>
<groupId>com.lypgroupId>
<artifactId>demoreactor8artifactId>
<version>0.0.1-SNAPSHOTversion>
<name>demoreactor8name>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
public class ObserverDemo extends Observable {
public static void main(String[] args) {
ObserverDemo observer =new ObserverDemo();
//添加观察者
observer.addObserver((o,arg)->{
System.out.println("发生了变化");
});
observer.addObserver((o,arg)->{
System.out.println("手动被观察者通知,准备改变");
});
observer.setChanged();//监控数据变化
observer.notifyObservers();//通知
}
}2.响应式编程(**Reactor**实现)
(1)响应式编程操作中,Reactor是满足Reactive 规范框架
(2)Reactor 有两个核心类,Mono和Flux,这两个类实现接口 Publisher ,提供丰富操作符。Flux对象实现发布者,返回N个元素;Mono实现发布者,返回0或者1个元素。
(3)Flux 和 Mono都是数据流的发布者,使用Flux和Mono都可以发出三种数据信号:
元素值,错误信号,完成信号,
错误信号和完成信号都代表终止信号,终止信号用于告诉订阅者数据流结束了,错误信号终止数据流同时把错误 信息传递给订阅者。
(4)代码演示Flux和Mon
第一步 引入依赖
<dependency>
<groupId>io.projectreactorgroupId>
<artifactId>reactor-coreartifactId>
<version>3.1.5.RELEASEversion>
dependency>
第二步 编写代码
public class TestReactor {
public static void main(String[] args) {
//just方法直接声明
Flux.just(1,2,3,4);
Mono.just(1);
//其他的方法
Integer[] array = {1,2,3,4};
Flux.fromArray(array);
List<Integer> list = Arrays.asList(array);
Flux.fromIterable(list);
Stream<Integer> stream = list.stream();
Flux.fromStream(stream);
}
}
(5)三种信号特点
1》错误信号和完成信号都是终止信号,不能共存的,
2》如果没有发送任何元素值,而是直接发送错误或者完成信号,表示是空数据流
3》如果没有错误信号,没有完成信号,表示是无线数据流
(6)调用**just **或者其他方法只是声明数据流,数据流并没有发出,只有进行订阅后才会触发数据流,不订阅什么都不会发生的
(7)操作符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SAooAy87-1639549020049)(1Spring框架概述.assets/image-20211213213527279.png)]
SpringWebflux基于Reactor,默认容器时Netty,Netty是高性能的NIO框架,异步非阻塞的框架
(1)Netty
(2)SpringWebFlux 执行过程和SpingMVC 相似的
(3)SpringWebFlux 里面 DispatchHandler ,负责请求的处理
(4) SpringWebFlux 实现函数式编程,两个接口 :RouterFunction (路由处理) 和HandlerFunction(处理函数)
SpringWebFlux 实现方式有两种:注解编程模型 和 函数式编程模型
使用注解编程模型方式,和之前SpringMVC 使用相似的,只需要把相关依赖配置到项目中,SpringBoot自动配置相关运行容器,默认情况下使用 Netty 服务器
第一步 创建SpringBoot工程 ,引入WebFlux依赖
org.springframework.boot
spring-boot-starter-webflux
第二步配置启动端口号
第三步
package com.lyp.webfluxdemo1.service;
import com.lyp.webfluxdemo1.entity.User;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
//用户操作接口
public interface UserService {
//根据id查询用户
Mono<User> getUserById(int id);
//查询所有用户
Flux<User> getAllUser();
//添加用户
Mono<Void> saveUserInfo(Mono<User> user);
}
接口实现类
public class UserServiceImpl implements UserService{
//创建map集合存储数据
private final Map<Integer,User> users = new HashMap<>();
public UserServiceImpl() {
this.users.put(1,new User("lucy", "男", 20));
this.users.put(2,new User("mary", "女", 21));
this.users.put(3,new User("nana", "男", 24));
}
//根据id查询
@Override
public Mono<User> getUserById(int id) {
return Mono.just(this.users.get(id));
}
//查询多个用户
@Override
public Flux<User> getAllUser() {
return Flux.fromIterable(this.users.values());
}
//添加
@Override
public Mono<Void> saveUserInfo(Mono<User> userMono) {
return userMono.doOnNext(person ->{
//向map集合里面放值
int id = users.size()+1;//防止id值重复
users.put(id,person);
}).thenEmpty(Mono.empty());
}
}
@RestController
public class UserController {
//注入service
@Autowired
private UserService userService;
//id查询
@GetMapping("/user/{id}")
public Mono<User> getUserId(@PathVariable int id){
return userService.getUserById(id);
}
//查询所有
@GetMapping("/user")
public Flux<User> getUsers(){
return userService.getAllUser();
}
//添加
@PostMapping("/saveuser")
public Mono<Void> saveUser(@RequestBody User user){
Mono<User> userMono = Mono.just(user);
return userService.saveUserInfo(userMono);
}
}
SpringMVC方式实现,同步阻塞的方式,基于SpringMVC+Servlet+Tomcat
SpringWebFlux方式实现,异步非阻塞方式,基于SpringWebFlux+Reactor+Netty
RouterFuction(实现路由功能,请求转发给对应的handler) 和 HandleFuction (处理请求生成响应的函数)。核心任务做定义两个函数式接口的实现并且启动需要的服务器
第一步把注解编程模型工程复制一份
第二步 创建Handler(具体实现方法)
public class UserHandler {
private final UserService userService;
public UserHandler(UserService userService){
this.userService = userService;
}
//根据id查询
public Mono<ServerResponse> getUserById(ServerRequest request){
//获取id值
int userId = Integer.valueOf(request.pathVariable("id"));
//空值处理
Mono<ServerResponse> notFound = ServerResponse.notFound().build();
//调用service方法得到数据
Mono<User> userMono = this.userService.getUserById(userId);
//把userMono进行转换返回
//使用Reactor操作符 flatMap
return
userMono.
flatMap(person -> ServerResponse.ok().contentType(MediaType.APPLICATION_JSON)
.body((BodyInserter<?, ? super ServerHttpResponse>) person))
.switchIfEmpty(notFound);
}
//查询所有
public Mono<ServerResponse> getAllUsers(){
//调用service得到结果
Flux<User> users = this.userService.getAllUser();
return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON)
.body(users,User.class);
}
//添加
public Mono<ServerResponse> saveUser(ServerRequest request){
Mono<User> userMono = request.bodyToMono(User.class);
return ServerResponse.ok().build(this.userService.saveUserInfo(userMono));
}
}
第三步初始化服务器,编写Router
//1.创建Router路由
public RouterFunction<ServerResponse> routerFunction(){
UserService userService = new UserServiceImpl();
UserHandler handler = new UserHandler(userService);
return RouterFunctions.route(
GET("/users/id").and(accept(APPLICATION_JSON)),handler::getUserById)
.andRoute(GET("/users").and(accept(APPLICATION_JSON)),handler::getAllUsers);
}
//2.创建服务器 完成适配
public void creatReactorserver(){
//路由和handler适配
RouterFunction<ServerResponse> route= routerFunction();
HttpHandler httpHandler = toHttpHandler(route);
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
//创建服务器
HttpServer httpSever = HttpServer.create();
httpSever.handle(adapter).bindNow();
}
//最终调用
public static void main(String[] args) throws Exception {
Server server =new Server();
server.creatReactorserver();
System.out.println("enter to exiy");
System.in.read();
}
public class Client {
public static void main(String[] args) {
//调用服务器地址
WebClient webClient = WebClient.create("http://127.0.0.1:57994]]");
//根据id查询
String id = "1";
User userresult = webClient.get().uri("]users/id", id).accept(MediaType.APPLICATION_JSON).retrieve().bodyToMono(User.class)
.block();
System.out.println(userresult.getName());
//查询所有
Flux<User> results = webClient.get().uri("/users/")
.accept(MediaType.APPLICATION_JSON).retrieve().bodyToFlux(User.class);
results.map(stu -> stu.getName()).buffer().doOnNext(System.out::println).blockFirst();
}
}
Spring是轻量级的开源的JavaEE框架,解决企业应用开发的复杂性,两个核心部分 : IOC 和 AOP
SPring5.2.9版本
(1)IOC底层原理(工厂 、反射等)
(2)IOC接口 (BeanFactory)
(3)IOC操作Bean管理(基于xml)
(4)IOC操作Bean管理(基于注解)
(1)AOP 底层原理:动态代理,有接口情况(使用JDK动态代理),没有接口(CGLIB动态代理)
(2)术语 切入点、增强(通知),切面
(3)基于AspectJ 实现AOP操作
(1)使用 JdbcTemplate 实现数据库 curd 操作
(2)使用 JdbcTemplate 实现数据库批量操作
(1)事务概念
(2)重要概念 :传播行为和隔离级别
(3)基于注解实现声明式事务管理
(4)完全注解方式实现声明式事务管理
(1)整合日志框架
(2)@Nullable注解
(3)函数式注册对象
(4)整合Junit5 单元测试框架
(5)SpringWebFlux使用
Service.getAllUser();
return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON)
.body(users,User.class);
}
//添加
public Mono saveUser(ServerRequest request){
Mono userMono = request.bodyToMono(User.class);
return ServerResponse.ok().build(this.userService.saveUserInfo(userMono));
}
}
第三步初始化服务器,编写Router
* 创建路由的方法
```java
//1.创建Router路由
public RouterFunction routerFunction(){
UserService userService = new UserServiceImpl();
UserHandler handler = new UserHandler(userService);
return RouterFunctions.route(
GET("/users/id").and(accept(APPLICATION_JSON)),handler::getUserById)
.andRoute(GET("/users").and(accept(APPLICATION_JSON)),handler::getAllUsers);
}
//2.创建服务器 完成适配
public void creatReactorserver(){
//路由和handler适配
RouterFunction<ServerResponse> route= routerFunction();
HttpHandler httpHandler = toHttpHandler(route);
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
//创建服务器
HttpServer httpSever = HttpServer.create();
httpSever.handle(adapter).bindNow();
}
//最终调用
public static void main(String[] args) throws Exception {
Server server =new Server();
server.creatReactorserver();
System.out.println("enter to exiy");
System.in.read();
}
public class Client {
public static void main(String[] args) {
//调用服务器地址
WebClient webClient = WebClient.create("http://127.0.0.1:57994]]");
//根据id查询
String id = "1";
User userresult = webClient.get().uri("]users/id", id).accept(MediaType.APPLICATION_JSON).retrieve().bodyToMono(User.class)
.block();
System.out.println(userresult.getName());
//查询所有
Flux<User> results = webClient.get().uri("/users/")
.accept(MediaType.APPLICATION_JSON).retrieve().bodyToFlux(User.class);
results.map(stu -> stu.getName()).buffer().doOnNext(System.out::println).blockFirst();
}
}
Spring是轻量级的开源的JavaEE框架,解决企业应用开发的复杂性,两个核心部分 : IOC 和 AOP
SPring5.2.9版本
(1)IOC底层原理(工厂 、反射等)
(2)IOC接口 (BeanFactory)
(3)IOC操作Bean管理(基于xml)
(4)IOC操作Bean管理(基于注解)
(1)AOP 底层原理:动态代理,有接口情况(使用JDK动态代理),没有接口(CGLIB动态代理)
(2)术语 切入点、增强(通知),切面
(3)基于AspectJ 实现AOP操作
(1)使用 JdbcTemplate 实现数据库 curd 操作
(2)使用 JdbcTemplate 实现数据库批量操作
(1)事务概念
(2)重要概念 :传播行为和隔离级别
(3)基于注解实现声明式事务管理
(4)完全注解方式实现声明式事务管理
(1)整合日志框架
(2)@Nullable注解
(3)函数式注册对象
(4)整合Junit5 单元测试框架
(5)SpringWebFlux使用