The secret of spring 5

Getting to know spring

Due to Spring framework software development Created by the complexity of. Spring uses a basic JavaBean to do this. Previously, it could only be done by EJB Things done. However, the use of Spring is not limited to server-side development. In terms of simplicity, testability and loose coupling, most Java applications can benefit from Spring.

Spring is an open source framework, which is developed by [rod Johnson]( https://baike.baidu.com/item/Rod Johnson). It is created to solve the complexity of enterprise application development. Spring uses basic JavaBean s to do things that previously could only be done by EJB s. However, the use of spring is not limited to server-side development. From the perspective of simplicity, testability and loose coupling, any Java application can benefit from spring.

Quickly build a spring project

It is recommended to use maven to create projects in POM Import dependency under XML

<dependencies>

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

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>

    </dependencies>
    
<!--Prevent packaging from ignoring configuration files-->
 <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

Create configuration file bean1 xml

[the transfer of external chain pictures fails. The source station may have an anti-theft chain mechanism. It is recommended to save the pictures and upload them directly (img-rewu5oib-1650034961139) (first acquaintance with spring.assets/1646806689953.png)]

<?xml version="1.0" encoding="UTF-8"?>
<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 name="user" class="com.wu.domain.User">
        <property name="id" value="123"/>
    </bean>

</beans>

Create entity class User

    public class User {
    
        private Integer id;
        private String name;
    
        public User(){
    
        }
        public User(Integer id, String name) {
            this.id = id;
            this.name = name;
        }
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }

Write test class

public class BeanTest {

    public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext = new 
                ClassPathXmlApplicationContext("bean1.xml");

        User user = (User) applicationContext.getBean("user");

        System.out.println(user.getId());
    }
}

What is a spring container?

We can simply understand spring as a big bathhouse. There are many things and services in this bathhouse

What is IOC?

ioc (inversion of control): it's hard to understand literally. We can simply understand it. In the past, when we called an object, we used to create the object through the new keyword. Now we give the creation right to the spring container. We just need to get the object from getBean () in the container.

(it can also be simply understood that in the past, when we went to the bathhouse to take a bath, we could only take a bath manually. In order to repay everyone, the government has built a bathhouse (spring container) to provide you with bath services, so we don't have to take a bath by ourselves.)

(1) Inversion of control, the creation of objects and the calling process between objects are handed over to Spring for management

(2) Purpose of using IOC: to reduce coupling

(3) An entry-level case is IOC implementation

Implementation principle of ioc bottom layer

xml parsing, factory schema, reflection

In the first step, spring will parse the xml configuration file

In the second step, a factory class will get the class name through the class attribute of the bean tag in xml, and then get its name Class files create instances for users through reflection

BeanFactory interface

1. The IOC idea is based on the IOC container. The bottom layer of the IOC container is the object factory

2. Spring provides two ways to implement IOC container: (two interfaces)

(1) BeanFactory: the basic implementation of IOC container, which is the internal use interface of Spring and is not available for developers to use

*The object will not be created when loading the configuration file, and the object will be created only when the object is obtained (used)

(2) ApplicationContext: the sub interface of BeanFactory interface, which provides more and more powerful functions. It is generally developed by the developer

Use by the operator

*When the configuration file is loaded, the object in the configuration file will be created

How ioc manages bean s

Adding attribute values to bean s

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

    <!--p Namespace injection p:name="wgy"-->
    <bean name="user" class="com.wu.domain.User">
        <!--set Method injection-->
<!--        <property name="id" value="123"/>-->
        <!--Construction method injection-->
<!--        <constructor-arg name="id" value="123"/>-->
<!--        <constructor-arg name="name" value="wgy"/>-->

        <!--Attribute to null-->
        <property name="id">
            <null/>
        </property>

        <!--Attribute values contain special symbols
         1 hold<>Escape &lt; &gt;
         2 Write content with special symbols to CDATA
        -->
        <property name="name">
            <value><![CDATA[<<wgy>>]]></value>
        </property>
    </bean>

</beans>

Property is a reference type

<?xml version="1.0" encoding="UTF-8"?>
<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="userService" class="com.wu.service.UserService">
        <property name="userDao" ref="userDao"/>
    </bean>

    <bean id="userDao" class="com.wu.dao.UserDao"/>


</beans>

One to many assignment

<?xml version="1.0" encoding="UTF-8"?>
<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="emp" class="com.wu.domain.Emp">
        <property name="id" value="2"/>
        <property name="name" value="wgy"/>
        <property name="age" value="18"/>

        <!--Object attribute assignment-->
<!--        <property name="dept">-->
<!--            <bean class="com.wu.domain.Dept">-->
<!--                <property name="id" value="1"/>-->
<!--                <property name="dname" value="development"/>-->
<!--            </bean>-->
<!--        </property>-->

        <!--Cascade assignment-->
        <property name="dept" ref="dept"/>
    </bean>

    <bean id="dept" class="com.wu.domain.Dept">
        <property name="id" value="1"/>
        <property name="dname" value="development"/>
    </bean>


</beans>

Assign a value to a set

 //1 array type properties
    private String[] courses;
    //2 list collection type attribute
    private List<String> list;
    //3 map collection type attribute
    private Map<String,String> maps;
    //4 set set type attribute
    private Set<String> sets;
    private List<Course> listc;
<?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: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 https://www.springframework.org/schema/util/spring-util.xsd">

    <bean id="student" class="com.wu.domain.Student">
        <property name="courses">
            <array>
                <value>mathematics</value>
                <value>English</value>
            </array>
        </property>

        <!--Both methods are OK-->
        <property name="list" ref="list">
<!--            <list>-->
<!--                <value>1</value>-->
<!--                <value>2</value>-->
<!--            </list>-->
        </property>

        <property name="maps">
            <map>
                <entry key="k1" value="wgy"/>
                <entry key="k2" value="why"/>
            </map>
        </property>

        <property name="sets">
            <set>
                <value>MySQL</value>
                <value>Redis</value>
            </set>
        </property>

        <property name="listc">
            <list>
                <ref bean="course1"/>
                <ref bean="course2"/>
            </list>
        </property>
    </bean>

    <bean class="com.wu.domain.Course" id="course1"/>
    <bean class="com.wu.domain.Course" id="course2"/>

    <!--extract list aggregate-->
    <util:list id="list">
        <value>1</value>
        <value>2</value>
    </util:list>
</beans>

IOC operation Bean * * Management (* * FactoryBean)

Spring has two types of beans, one is ordinary * * bean * * and the other is factory * * bean * * (FactoryBean)**

1. Ordinary * * bean * *: the * * bean type defined in the configuration file is the return type

2. Factory * * bean * *: the * * bean type defined in the configuration file can be different from the return type

The first step is to create a class that acts as a factory bean and implements the interface FactoryBean

The second step is to implement the method in the interface and define the returned bean type in the implemented method

Create a factory bean

First, create an object implementation interface

package FactoryBean.factory;

import FactoryBean.domain.User;
import org.springframework.beans.factory.FactoryBean;

/**
 * @Descirption:
 * @create 2022-03-09 16:08
 * @auther: wgy
 */
// Beans are manufactured through factories for further decoupling
public class MyBean implements FactoryBean<User> {

    @Override
    public User getObject() throws Exception {
        User user = new User();
        user.setName("wgy");
        return user;
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }

}

Create the object to be generated

package FactoryBean.domain;

/**
 * @Descirption:
 * @create 2022-03-09 16:07
 * @auther: wgy
 */
public class User {

    private String name;

    public User(String name) {
        this.name = name;
    }

    public User(){
        System.out.println("hello");
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}

xml configuration file

   <bean id="myBean" class="FactoryBean.factory.MyBean"></bean>

Test class

 @Test
    public void TestBean1(){
        ApplicationContext applicationContext = new
                ClassPathXmlApplicationContext("bean5.xml");

        User user =applicationContext.getBean("myBean", User.class);

        System.out.println(user);
    }

Instantiation of Bean

1 . Static factory instantiation

It is to create a factory class and write a static method in it. This method returns an instance instantiated by our factory When we need to use it, we can get it directly through getBean (name of ID)

1 . Create an empty bean object

package com.wu.staic_factory;

public class Bean2 {
}

2 . Create a factory and define a static createBean method to return the instance object

package com.wu.staic_factory;


public class MyBean2Factory {

    public MyBean2Factory() {
        System.out.println("MyBean2Factory Initialize in factory");
    }

    //Create bean2 instance with your own factory
    public static Bean2 createBeanFactory(){
        return new Bean2();
    }
}

3 . Configure in xml file

<bean id="bean2" 
      class="com.wu.staic_factory.MyBean2Factory" factory-method="createBeanFactory"/>

4 . Write test class

package com.wu.staic_factory;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class InstanceTest2 {

    public static void main(String[] args) {
        //Define the path of the configuration file
        String xmlPath="com/wu/staic_factory/bean2.xml";

        //applicationcontext loads the configuration file. Initialize bean
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);

        System.out.println(applicationContext.getBean("bean2"));
    }

}

2 . Example chemical plant instantiation

It is similar to a static factory, but the bean creation method in the factory class is not static, and the configuration file is modified

1 . Create an empty bean object

package com.wu.factory;

public class Bean3 {
}

2 . Create a factory and define a createBean method to return the instance object

package com.wu.factory;


public class MyBean3Factory {

    public MyBean3Factory() {
        System.out.println("MyBean3Factory Initialize in factory");
    }

    //Create bean3 instances using your own factory
    public Bean3 createBeanFactory(){
        return new Bean3(;
    }
}

3 . The configuration file is as follows

 	<!-- Configuration factory-->
    <bean id="myBean3Factory" class="com.wu.factory.MyBean3Factory"/>

    <!-- use factory-bean Specify the configured instance factory   -->
    <!-- use factory-method Specify how to get the configured instance factory   -->
    <bean id="bean3" factory-bean="myBean3Factory" factory-method="createBeanFactory"/>

4 . Test class

package com.wu.factory;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class InstanceTest3 {

    public static void main(String[] args) {
        //Define the path of the configuration file
        String xmlPath="com/wu/factory/bean3.xml";

        //applicationcontext loads the configuration file. Initialize bean
        ApplicationContext applicationContext = new 	      ClassPathXmlApplicationContext(xmlPath);

        System.out.println(applicationContext.getBean("bean3"));
    }

}

Some people say that static factories and example chemical factories are different. There are multiple static methods. Why add more configuration files My understanding is that the static modifier is loaded first, which is more important than the class, so we can use factory method = "createbeanfactory" to specify the static method in static factory instantiation But the instance factory cannot, because its method is non-static, so the loading order must wait for the class to be instantiated before the method can be loaded. Therefore, for the instance factory, we need to instantiate the bean factory first, and then specify its instantiation method Therefore, some configurations are added

Scope of Bean

1 . singleton singleton mode, the bean instance created each time is the same

2 . prototype prototype pattern. Each bean instance created is a new one

You only need to add the scope attribute to the bean attribute to use it

spring uses singleton by default

difference

singleton will instantiate all bean s when loading the configuration file

prototype instantiates bean s when you need them, not when they are loaded

Bean lifecycle

(1) Create bean instance through constructor (no parameter construction)

(2) Set values for bean properties and references to other beans (call the set method)

(3) Call the initialization method of the bean (the method that needs configuration initialization)

(4) The bean is ready to use (the object is obtained)

(5) When the container is closed, call the bean destruction method (the method that needs to be configured for destruction)

package life.domain;

/**
 * @Descirption:
 * @create 2022-03-09 17:05
 * @auther: wgy
 */
public class User {

    private String name;

    public User(){
        System.out.println("First step,The constructor begins to execute");
    }

    public User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        System.out.println("Step two,set Method starts execution");
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }

    public void initialize(){
        System.out.println("Step 3,Initialization method starts execution");
    }

    public void destroy(){
        System.out.println("Last step,Destruction method execution");
    }
}

 <bean id="user" class="life.domain.User" init-method="initialize" destroy-method="destroy">
        <property name="name" value="123"/>
    </bean>

But when we add the post processor, MyPostProcessor will add two steps

package life.postprocessor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * @Descirption:
 * @create 2022-03-09 17:06
 * @auther: wgy
 */
// Post processor. After implementing this interface, all spring bean s will pass through it
public class MyPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Post processor front");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Post processor");
        return bean;
    }
}

The post processor is registered in the xml configuration file, and each bean will be processed after registration

 <!--Configure post processor-->
    <bean id="MyPostProcessor" class="life.postprocessor.MyPostProcessor"/>

So the last step is step 7

(1) Create bean instance through constructor (no parameter construction)

(2) Set values for bean properties and references to other beans (call the set method)

(3) Call the initialization method of the bean (the method that needs configuration initialization)

(4) Postprocessor postProcessBeforeInitialization method

(5) The bean is ready to use (the object is obtained)

(6) Postprocessor postProcessAfterInitialization method

(7) When the container is closed, call the bean destruction method (the method that needs to be configured for destruction)

bean auto assembly

<!--Realize automatic assembly
     bean Label properties autowire,Configure automatic assembly
     autowire Two values are commonly used for attributes:
         byName Inject value according to attribute name bean of id The value is the same as the class attribute name
         byType Inject according to attribute type
    -->
    <bean id="emp" class="autowire.domain.Emp" autowire="byName"></bean>

    <bean id="dep" class="autowire.domain.Dep"/>

Read external files

Import Druid dependency and mysql dependency

<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.8</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>

bean.xml configuration

<!--Import external properties file-->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!-- Configure connection pool -->
    <!-- DruidDataSource dataSource = new DruidDataSource(); -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <!-- dataSource.setDriverClassName("com.mysql.jdbc.Driver");
            set Method injection
        -->
        <!-- obtain properties Document content, according to key Get, use spring Expression acquisition -->
        <property name="driverClassName" value="${jdbc.driverclass}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

What is DI?

di (dependency injection): simply understood as adding the classes we need to the spring container for the caller to call.

(it can be interpreted as a newly-built bathhouse with only a pool and nothing. Then the government approved the money and the person in charge began to release recruitment information. Some talented people came to the bathhouse to apply for massage, bath and ear picking. In this way, people who come to the bathhouse to take a bath can freely choose the services they need.)

Injection conditions?

Must meet:

1. The attribute has a set method: after the spring container instantiates the bean by calling the parameterless constructor or static factory method, it will call the set attribute to inject the instantiated bean

2. Construction method injection: the spring container injects the dependent instance through the construction method. Based on the construction method injection, it is realized by calling the parametric construction method, and each parameter represents a dependency

1 . Define an interface and add a say() method to it

package com.wu.ioc;

public interface UserService {

    void say();
}

2 . Implement an interface implementation class to implement the say method

package com.wu.ioc;

public class UserServiceImpl implements UserService {

    //Declare an object
    private UserDao userDao;

    //Injection methods provided to spring
    public void setUserDao(UserDao userDao){
        this.userDao=userDao;
    }

    //Method of implementing interface
    @Override
    public void say() {
        userDao.say();
        System.out.println("userserviceimpl hello world");
    }
}

3 . The configuration file is as follows

 <bean id="userService" class="com.wu.ioc.UserServiceImpl">
        <property name="userDao" ref="userDao"/>
 </bean>

4 . Test class

package com.wu.ioc;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestDI {

    public static void main(String[] args) {
        //Initialize the spring container and load the configuration file
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //Obtain the instance object of the factory through the container
        UserService userService= (UserService) context.getBean("userService");
        //Call the method in the instance
        userService.say();
    }
}

5 . complete

[the transfer of external chain pictures fails, and the source station may have anti-theft chain mechanism. It is recommended to save the pictures and upload them directly (img-pj6kmvhb-1650034961141) (first acquaintance with spring.assets/1617765936987.png)]

Fully annotated configuration bean

(1) Annotation is a special mark of code, format: @ annotation name (attribute name = attribute value, attribute name = attribute value...)

(2) Use annotations, which act on classes, methods and attributes

(3) Purpose of using annotation: to simplify xml configuration

Spring provides annotations for creating objects in Bean management

(1)@Component

(2)@Service

(3)@Controller

(4)@Repository

*The above four annotation functions are the same and can be used to create bean instances

<!-- Scan all comments under this file -->
<context:component-scan base-package="com.wu"/>

 <!--Scan only with controller Annotated class
            use-default-filters Use default filter true Scan all false Custom scan
        -->
 <context:component-scan base-package="com.wu" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

 <!--Do not scan with controller Annotated class-->
<context:component-scan base-package="com.wu" >
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

Autowired: automatically assemble according to the attribute type

Qualifier: matching according to the name can be used with Autowired

Resource: can be injected according to type or name

Value: inject common type attribute

@Controller
public class UserController {

    @Autowired //Automatic matching according to type
    @Qualifier(value = "userService") //Inject by name
    private UserService userService;

    @Value("123")
    public String key;

    public void add(){
        userService.add();
    }
}


@Service   //By default, it is injected in lowercase according to the initial letter of the class name
public class UserService {

    //@Resource / / inject according to type
    @Resource(name = "userDao") //Inject by name
    private UserDao userDao;

    public void add(){
        System.out.println("userservice  add");
    }
}

Configuration class instead of configuration file

@Configuration  //Declare that this is a configuration class
@ComponentScan(basePackages = {"com.wu"}) //Configure scan package
public class SpringConfig {
}

test method
     @Test
    public void TestBean3(){
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);

        UserController userController = (UserController) applicationContext.getBean("userController");
        userController.add();
        System.out.println(userController.key);
    }

What is aop?

(1) Aspect oriented programming (aspect oriented programming), AOP can isolate all parts of business logic, so that

The coupling degree between various parts of the business logic is reduced, the reusability of the program is improved, and the development efficiency is improved.

(2) Popular Description: add new functions to the main functions without modifying the source code

For example, now I write a login service, but this system has permissions for every login user How to authenticate permissions when accessing specified resources At this time, we can use aop to realize authority authentication This will not change the original business Complete requirements at the same time

aop underlying principle

1. When there is an interface, use jdk dynamic proxy (create the implementation class proxy object of the interface)

2. When there is no interface, use cglib dynamic proxy (create a subclass proxy object of the current class)

Use JDK dynamic Proxy and use the methods in Proxy class to create Proxy objects

Call the newProxyInstance method

Method has three parameters:

First parameter, class loader

The second parameter is the class where the enhancement method is located. The interface implemented by this class supports multiple interfaces

The third parameter is to implement this interface InvocationHandler, create a proxy object and write the enhanced part

aopjdk case

public interface UserDao {

    int add(int a,int b);

    String update(String id);
}

public class UserDaoImpl implements UserDao{
    @Override
    public int add(int a, int b) {
        return a+b;
    }

    @Override
    public String update(String id) {
        return "update method"+id;
    }
}

public class UserDaoProxy implements InvocationHandler {

    //1. Who is the proxy object created and who is passed over
    //Parameter construction transfer
    private Object obj;

    public UserDaoProxy(Object obj) {
        this.obj = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //Before method
        System.out.println("Method...." + method.getName() + " :Passed parameters..." + Arrays.toString(args));
        //Enhanced method execution
        Object res = method.invoke(obj, args);
        //After method
        System.out.println("Execute after method...." + obj);
        return res;
    }
}

public class JDKProxy {

    public static void main(String[] args) {
        // Get all objects that need proxy
        Class[] interfaces = {UserDao.class};

        UserDaoImpl userDao = new UserDaoImpl();

        UserDao userDao1 = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));

        userDao1.add(1,2);
        userDao1.update("1");
    }
}

aop terminology

1. Connection point

The methods in the class can be enhanced. These methods are called join points

2. Entry point

Actually enhanced method

3. Notice

1. The enhanced logical part is called notification

2. Type of notice

Pre notification, post notification, surround notification, exception notification, final notification

4. Section

The act of applying a notification to a pointcut

AspectJ implements aop

AspectJ is not a part of Spring. It is an independent AOP framework. Generally, AspectJ and Spirng framework are used together

AOP operation with

(1) Pointcut expression function: know which method in which class to enhance

(2) Syntax structure: execution([permission modifier] [return type] [full path of class] Method name )

Example 1: com atguigu. dao. add in bookdao class is enhanced

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

Example 2: com atguigu. dao. All methods in the bookdao class are enhanced

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

Example 3: com atguigu. All classes and methods in Dao package are enhanced

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

Implementing aop with annotations

@Component
public class User {

    void add() {
        //int a=10/0;
        System.out.println("add.......");
    }
}

@Component
@Aspect
@Order(1) // The smaller the number, the higher the priority
public class UserProxy {

    // Extract a common tangent point
    @Pointcut(value = "execution(* aopanno.User.add(..))")
    public void pointdemo() {
    }

    //@Before annotation indicates as pre notification
    @Before(value = "pointdemo()")
    public void before() {
        System.out.println("before.........");
    }
    //Post notification (return notification)
    @AfterReturning(value = "execution(* aopanno.User.add(..))")
    public void afterReturning() {
        System.out.println("afterReturning.........");
    }
    //Final notice
    @After(value = "execution(* aopanno.User.add(..))")
    public void after() {
        System.out.println("after.........");
    }
    //Exception notification
    @AfterThrowing(value = "execution(* aopanno.User.add(..))")
    public void afterThrowing() {
        System.out.println("afterThrowing.........");
    }
    //Around Advice 
    @Around(value = "execution(* aopanno.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws
            Throwable {
        System.out.println("Before surround.........");
        //Enhanced method execution
        proceedingJoinPoint.proceed();
        System.out.println("After surround.........");
    }
}


@Configuration
@ComponentScan(basePackages = {"aopanno"})
@EnableAspectJAutoProxy(proxyTargetClass = true) // Enable aop support
public class AopConfig {
}
<?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: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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

    <context:component-scan base-package="aopanno"/>

    <!-- open Aspect Generate proxy object-->
    <aop:aspectj-autoproxy/>
</beans>

Implementing aop with xml

@Component
public class Book {

    void add() {
        //int a=10/0;
        System.out.println("add.......");
    }
}

public class BookProxy {

    @Before(value = "execution(* aopxml.Book.add(..))")
    public void before() {
        System.out.println("before.........");
    }
}


<?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 https://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="book" class="aopxml.Book"/>
    <bean id="bookProxy" class="aopxml.BookProxy"/>

    <!--to configure aop-->
    <aop:config>
        <!--breakthrough point(Class methods that need to be enhanced)-->
        <aop:pointcut id="p" expression="execution(* aopxml.Book.add(..))"/>
        <!--Configuration section(Enhanced class)-->
        <aop:aspect ref="bookProxy">
            <aop:before method="before" pointcut-ref="p"/>
        </aop:aspect>
    </aop:config>
</beans>

spring integrates jdbc

Import dependency

<dependencies>

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

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

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.8</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
        </dependency>
    </dependencies>

Create entity class

package com.wu.domain;

import lombok.*;

import java.io.Serializable;

/**
 * @Descirption:
 * @create 2022-03-28 15:58
 * @auther: wgy
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
@EqualsAndHashCode
public class User implements Serializable {

    private Integer id;
    private String name;
    private String password;
    private String address;
    private String phone;

}

create profile

<?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"
       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">

    <!--Scan package-->
    <context:component-scan base-package="com.wu"/>

    <!-- Database connection pool -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
          destroy-method="close">
        <property name="url" value="jdbc:mysql://localhost:3306/jdbc"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
    </bean>

    <!--to configure jdbctemplate injection datasource-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>




</beans>

dao layer

package com.wu.dao;

import com.wu.domain.User;
import lombok.AllArgsConstructor;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * @Descirption:
 * @create 2022-03-28 16:03
 * @auther: wgy
 */
@Repository
@AllArgsConstructor
public class UserDao {

    // Add the configured JDBC template
    private final JdbcTemplate jdbcTemplate;

    // add to
    public boolean addUser(User user) {
        Object[] args = {user.getName(), user.getPassword(), user.getAddress(), user.getPhone()};
        int update = jdbcTemplate.update("insert into user values(null,?,?,?,?)", args);
        return update > 0;
    }

    // delete
    public boolean deleteUser(Integer id) {
        int update = jdbcTemplate.update("delete from user where id=?", id);
        return update > 0;
    }

    // modify
    public boolean updateUser(User user) {
        Object[] args = {user.getName(), user.getPassword(), user.getAddress(), user.getPhone(), user.getId()};
        int update = jdbcTemplate.update("update user set name=?,password=?,address=?,phone=? where id=?", args);
        return update > 0;
    }

    // How many pieces of data are queried
    public int selectUserClount() {
        Integer count = jdbcTemplate.queryForObject("select count(*) from user", Integer.class);
        return count;
    }

    // Query an object
    public User selectUserById(Integer id) {
        User user = jdbcTemplate.queryForObject("select * from user where id=?", new BeanPropertyRowMapper<User>(User.class), id);
        return user;
    }

    // Query multiple items
    public List<User> selectUsers() {
        List<User> userList = jdbcTemplate.query("select * from user", new BeanPropertyRowMapper<User>(User.class));
        return userList;
    }

    // Batch modification
    public boolean batchUpdate(List<Object[]> args) {
        int[] ints = jdbcTemplate.batchUpdate("update user set name=?,password=?,address=?,phone=? where id=?", args);
        for (int anInt : ints) {
            if (anInt <= 0) return false;
        }
        return true;
    }

    // Batch delete
    public boolean batchDelete(List<Object[]> args) {
        int[] ints = jdbcTemplate.batchUpdate("delete from user where id=?", args);
        for (int anInt : ints) {
            if (anInt <= 0) return false;
        }
        return true;
    }

    // Batch add
    public boolean batchAdd(List<Object[]> args) {
        int[] ints = jdbcTemplate.batchUpdate("insert into user values(null,?,?,?,?)", args);
        for (int anInt : ints) {
            if (anInt <= 0) return false;
        }
        return true;
    }
}

service layer

package com.wu.service;

import com.wu.dao.UserDao;
import com.wu.domain.User;
import lombok.AllArgsConstructor;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @Descirption:
 * @create 2022-03-28 16:02
 * @auther: wgy
 */
@Service
@AllArgsConstructor
public class UserService {

    private final UserDao userDao;

    public Boolean addUser(User user) {
        return userDao.addUser(user);
    }

    public boolean deleteUser(Integer id) {
        return userDao.deleteUser(id);
    }

    public boolean updateUser(User user) {
        return userDao.updateUser(user);
    }

    public int selectUserCount(){
        return userDao.selectUserClount();
    }

    public User selectUserById(Integer id){
        return userDao.selectUserById(id);
    }

    public List<User> selectUsers(){
        return userDao.selectUsers();
    }

    public boolean batchUpdate(List<Object[]> args){
        return userDao.batchUpdate(args);
    }

    public boolean batchDelete(List<Object[]> args){
        return userDao.batchDelete(args);
    }

    public boolean batchAdd(List<Object[]> args) {
        return userDao.batchAdd(args);
    }
}

Test class

package com.wu.test;

import com.wu.domain.User;
import com.wu.service.UserService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.ArrayList;
import java.util.List;

/**
 * @Descirption:
 * @create 2022-03-28 16:12
 * @auther: wgy
 */
public class JdbcTest {


    @Test
    public void test1() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");

        UserService userService = context.getBean("userService", UserService.class);

        User user = new User(null, "wgy", "123", "Wuhan", "123456789");

        System.out.println(userService.addUser(user));
    }

    @Test
    public void test2() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");

        UserService userService = context.getBean("userService", UserService.class);


        System.out.println(userService.deleteUser(6));
    }

    @Test
    public void test3() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");

        UserService userService = context.getBean("userService", UserService.class);

        User user = new User(7, "wgy", "456", "Wuhan", "123456789");

        System.out.println(userService.updateUser(user));
    }


    @Test
    public void test4() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");

        UserService userService = context.getBean("userService", UserService.class);


        System.out.println(userService.selectUserCount());
    }

    @Test
    public void test5() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");

        UserService userService = context.getBean("userService", UserService.class);


        System.out.println(userService.selectUserById(7));
    }

    @Test
    public void test6() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");

        UserService userService = context.getBean("userService", UserService.class);


        List<User> userList = userService.selectUsers();

        userList.forEach(System.out::println);
    }


    @Test
    public void test7() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");

        UserService userService = context.getBean("userService", UserService.class);


        Object[] obj1 = {"json", "123456", "usa", "123456", "4"};
        Object[] obj2 = {"wgy", "123456", "wl", "123456", "5"};
        List<Object[]> objects = new ArrayList<>();
        objects.add(obj1);
        objects.add(obj2);

        System.out.println(userService.batchUpdate(objects));
    }

    @Test
    public void test8() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");

        UserService userService = context.getBean("userService", UserService.class);


        Object[] obj1 = {"4"};
        Object[] obj2 = {"5"};
        List<Object[]> objects = new ArrayList<>();
        objects.add(obj1);
        objects.add(obj2);

        System.out.println(userService.batchDelete(objects));
    }

    @Test
    public void test9() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");

        UserService userService = context.getBean("userService", UserService.class);


        Object[] obj1 = {"json", "123456", "usa", "123456"};
        Object[] obj2 = {"wgy", "123456", "wl", "123456"};
        List<Object[]> objects = new ArrayList<>();
        objects.add(obj1);
        objects.add(obj2);

        System.out.println(userService.batchAdd(objects));
    }
}

spring integration transaction

1. What business

(1) Transaction is the most basic unit of database operation. Logically, a group of operations will either succeed. If one fails, all operations will fail

All failed

(2) Typical scenario: bank transfer

*lucy transfers 100 yuan to mary

*lucy is 100 less and mary is 100 more

2. Four characteristics of transaction (ACID)

(1) Atomicity

(2) Consistency

(3) Isolation

(4) Persistence

Operational transactions

1. Add transactions to the Service layer (business logic layer) in the three-tier structure of Java EE

2. Transaction management in Spring

(1) There are two ways: programmed transaction management and declarative transaction management (use)

3. Declarative transaction management

**(* * 1) annotation based method (use)

(2) xml based configuration file mode

4. Carry out declarative transaction management in Spring, and the underlying layer uses AOP principle

Open transaction annotation Version (if the data source needs to be injected)

  <!--Configure transaction manager-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--Injection data source-->
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--Open transaction annotation-->
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

Add the annotation @ Transactional on the method or class that needs to be transacted

@Transactional annotation

[the transfer of external chain pictures fails. The source station may have an anti-theft chain mechanism. It is recommended to save the pictures and upload them directly (img-xe76neio-1650034961143) (first acquaintance with spring.assets/1649084389017.png)]

Propagation: transaction propagation behavior

[the transfer of external chain pictures fails. The source station may have an anti-theft chain mechanism. It is recommended to save the pictures and upload them directly (img-fakzziuy-1650034961144) (first acquaintance with spring.assets/1649084427922.png)]

ioslation: transaction isolation level

(1) Transactions have the characteristics of isolation, and multi transaction operations will not have an impact. Without considering isolation, many problems arise

(2) There are three reading problems: dirty reading, unrepeatable reading and unreal reading

(3) Dirty read: data read from one uncommitted transaction to another uncommitted transaction

(4) Non repeatable reading: one uncommitted transaction reads the modified data from another committed transaction

(5) Phantom read: an uncommitted transaction reads data from another committed transaction and adds data

[the transfer of external chain pictures fails, and the source station may have anti-theft chain mechanism. It is recommended to save the pictures and upload them directly (img-kuotzcrl-1650034961146) (first acquaintance with spring.assets/1649084634451.png)]

Timeout: timeout

(1) The transaction needs to be committed within a certain period of time. If it is not committed, it will be rolled back

(2) The default value is - 1, and the set time is calculated in seconds

readOnly: read only

(1) Read: query, write: add, modify, delete

(2) The default value of readOnly is false, which means that you can query, add, modify and delete operations

(3) Set the readOnly value to true. After it is set to true, you can only query

Rollback for: rollback

(1) Set which exceptions occur for transaction rollback

noRollbackFor: no rollback

(1) Set which exceptions occur without transaction rollback

Open the transaction xml Version (if the data source is imported)

 <!--to configure jdbctemplate injection datasource-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--Configure transaction manager-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--Injection data source-->
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--2 Configure notifications-->
    <tx:advice id="txadvice">
        <!--Configure transaction parameters-->
        <tx:attributes>
            <!--Specify which rule method to add transactions to-->
            <tx:method name="accountMoney" propagation="REQUIRED"/>
            <!--<tx:method name="account*"/>-->
        </tx:attributes>
    </tx:advice>

    <!--3 Configure pointcuts and facets-->
    <aop:config>
        <!--Configure pointcuts-->
        <aop:pointcut id="pt" expression="execution(* com.wu.service.UserService.*(..))"/>
        <!--Configuration section-->
        <aop:advisor advice-ref="txadvice" pointcut-ref="pt"/>
    </aop:config>

New features of spring 5

1,log4j

log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--Log level and prioritization: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration hinder status Used to set log4j2 The internal information output can not be set when it is set to trace When, you can see log4j2 Various internal detailed outputs-->
<configuration status="INFO">
    <!--Define all first appender-->
    <appenders>
        <!--Output log information to console-->
        <console name="Console" target="SYSTEM_OUT">
            <!--Controls the format of log output-->
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </console>
    </appenders>
    <!--Then define logger,Only defined logger And introduced appender,appender Will take effect-->
    <!--root: Used to specify the root log of the project, if not specified separately Logger,Will be used root As default log output-->
    <loggers>
        <root level="info">
            <appender-ref ref="Console"/>
        </root>
    </loggers>
</configuration>

pox.xml

<dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.25</version>
        </dependency>

test case

package log;

import org.apache.log4j.Logger;

/**
 * @Descirption:
 * @create 2022-04-15 11:20
 * @auther: wgy
 */
public class TestLog {

    // journal
    private static Logger logger = Logger.getLogger(TestLog.class);

    public static void main(String[] args) {
        logger.info("info");
        logger.debug("debug");
        logger.error("error");
    }
}

2,@Nullable

public class TestNullAble {

    // Property can be null
    @Nullable
    private String name;

    // The return value can be null
    @Nullable
    public String get(){
        return "123";
    }

    // Method parameter can be null
    public String getHello(@Nullable String name){
        return "123";
    }
}

3. Function declaration registration bean

 // Functionally registered bean s enter the spring container
    @Test
    public void testBean(){
        //1 create GenericApplicationContext object
        GenericApplicationContext context = new GenericApplicationContext();
        //2. Call the method object registration of context
        context.refresh();
        context.registerBean("user1",User.class,() -> new User());
        //3 get the object registered in spring
        // User user = (User)context.getBean("com.atguigu.spring5.test.User");
        User user = (User)context.getBean("user1");
        System.out.println(user);
    }

4. Junt4 integration

pom.xml

<dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
@RunWith(SpringJUnit4ClassRunner.class) //Unit test framework
@ContextConfiguration("classpath:bean1.xml") //Load profile
public class TestJuint4 {

    // You can inject objects internally
}

4. Junt5 integration

pox.xml

<dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.7.0</version>
        </dependency>
@ExtendWith(SpringExtension.class)
@ContextConfiguration("classpath:bean1.xml")

// Compound annotation
//@SpringJUnitConfig(locations = "classpath:bean1.xml")
public class TestJunt5 {
}

spring-webflux

1. Spring 5 adds a new module for web development. The function is similar to that of spring MVC, and Webflux is used

At present, a framework for comparing process responsive programming appears**

2. Using traditional web frameworks, such as spring MVC, which are based on Servlet containers, Webflux is an asynchronous non blocking

Plug framework, asynchronous non blocking framework in servlet3 1 later. The core is the implementation of relevant API s based on Reactor

of

3. Explain what asynchronous non blocking is

*Asynchronous and synchronous

*Non blocking and blocking

****The above is for different objects**

**Asynchronous and synchronous are for the caller. The caller sends a request. If he waits for the other party to respond before doing anything else, it is the same

Next, if you do something else after sending a request without waiting for a response from the other party, it is asynchronous

****Blocking and non blocking are for the callee. The callee gives feedback after receiving the request and completing the request task, which is blocking**

Plug, giving feedback immediately after receiving a request and then doing something is non blocking

4. First, non blocking: improve system throughput and scalability under limited resources, and realize responsive programming based on Reactor

Second, functional programming: the spring 5 framework is based on Java8, and Webflux uses Java8 functional programming to realize routing requests

Responsive programming

Responsive programming (implemented by Reactor)

(1) In Reactive programming operations, Reactor is a framework that meets the Reactive specification

(2) Reacto has two core classes, Mono and Flux. These two classes implement the interface Publisher and provide rich operations

Symbol. The Flux object implements the publisher and returns N elements; Mono implements the publisher and returns 0 or 1 elements

(3) Flux and Mono are both publishers of data flow. Using flux and Mono, three data signals can be sent:

Element value, error signal, completion signal, error signal and completion signal all represent termination signal, and termination signal is used to tell

When the subscriber data stream ends, the error signal terminates the data stream and transmits the error message to the subscriber

Three signal characteristics

*Both error signal and completion signal are termination signals and cannot coexist

*If no element value is sent, but an error or completion signal is sent directly, it indicates that it is an empty data stream

*If there is no error signal and no completion signal, it indicates infinite data flow

Calling just or other methods only declares the data flow. The data flow is not sent out and will be triggered only after subscription

Send a data stream and nothing will happen without subscribing

Operator

The data flow is operated one by one to become an operator, such as a factory pipeline

Spring Webflux is based on Reactor. The default container is netty. Netty is a high-performance NIO framework, asynchronous and non blocking

Plug frame

The execution process of spring Webflux is similar to that of spring MVC

*The spring Webflux core controller DispatchHandler implements the interface WebHandler

*Interface WebHandler has a method

DispatcherHandler in spring Webflux is responsible for the processing of requests

*HandlerMapping: the processing method of the request query

*HandlerAdapter: really responsible for request processing

*HandlerResultHandler: response result processing

Spring Webflux implements functional programming with two interfaces: RouterFunction (routing processing)

And HandlerFunction

Spring MVC is implemented in the way of synchronous blocking, which is based on spring MVC + servlet + Tomcat

It is implemented in spring Webflux mode, asynchronous and non blocking mode, based on spring Webflux + reactor + netty

Annotation implementation

There are two ways to implement spring Webflux: annotation programming model and functional programming model

The annotation programming model is similar to that used by spring MVC before. It only needs to configure the relevant dependencies into the project,

SpringBoot automatically configures related running containers, and Netty server is used by default

pom.xml dependency

<?xml version="1.0" encoding="UTF-8"?>
<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.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.wu</groupId>
    <artifactId>spring5-webflux</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring5-webflux</name>
    <description>spring5-webflux</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>


        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-core</artifactId>
            <version>3.4.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

controller

@RestController
public class UserController {

    //Spring MVC is implemented in the way of synchronous blocking, which is based on spring MVC + servlet + Tomcat
    //It is implemented in spring Webflux mode, asynchronous and non blocking mode, based on spring Webflux + reactor + netty

    //Inject service
    @Autowired
    private UserService userService;

    //id query
    @GetMapping("/user/{id}")
    public Mono<User> geetUserId(@PathVariable int id) {
        return userService.getUserById(id);
    }

    //Query all
    @GetMapping("/user")
    public Flux<User> getUsers() {
        return userService.getAllUser();
    }

    //add to
    @PostMapping("/saveuser")
    public Mono<Void> saveUser(@RequestBody User user) {
        Mono<User> userMono = Mono.just(user);
        return userService.saveUserInfo(userMono);
    }
}

service

public interface UserService {

    // Find users by id
    Mono<User> getUserById(Integer id);

    // Query all users
    Flux<User> getAllUser();

    // Add user
    Mono<Void> saveUserInfo(Mono<User> user);
}

@Service
public class UserServiceImpl implements UserService {

    //Create a map collection to store data
    private final List<User> users = new ArrayList<>();

    public UserServiceImpl() {
        this.users.add(new User(1, "nan", 20));
        this.users.add(new User(2, "nv", 30));
        this.users.add(new User(3, "nv", 50));
    }

    @Override
    public Mono<User> getUserById(Integer id) {
        return Mono.justOrEmpty(this.users.stream().filter(user -> user.getId().equals(id)).findFirst().orElse(null));
    }

    @Override
    public Flux<User> getAllUser() {
        return Flux.fromIterable(this.users);
    }

    @Override
    public Mono<Void> saveUserInfo(Mono<User> user) {
        //Put values into the map set
        return user.doOnNext(this.users::add).thenEmpty(Mono.empty());
    }
}

domain

private Integer id;
    private String name;
    private Integer age;

Functional implementation

(1) When using the functional programming model to operate, you need to initialize the server yourself

(2) Based on the functional programming model, there are two core interfaces: RouterFunction

To the corresponding handler and HandlerFunction. The core task defines two functions

The implementation of the interface and start the required server.

(3) Spring Webflux requests and responses are no longer ServletRequest and ServletResponse, but

ServerRequest and ServerResponse

pom.xml is the same as above

Create handler

package com.wu.spring5webflux2.handler;


import com.wu.spring5webflux2.domain.User;
import com.wu.spring5webflux2.service.UserService;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import static org.springframework.web.reactive.function.BodyInserters.fromObject;

/**
 * @Descirption:
 * @create 2022-04-15 22:01
 * @auther: wgy
 */
public class UserHandler {

    private final UserService userService;

    public UserHandler(UserService userService) {
        this.userService = userService;
    }


    //Query by id
    public Mono<ServerResponse> getUserById(ServerRequest request) {
        //Get id value
        int userId = Integer.parseInt(request.pathVariable("id"));
        //Null value processing
        Mono<ServerResponse> notFound = ServerResponse.notFound().build();
        //Call the service method to get the data
        Mono<User> userMono = this.userService.getUserById(userId);
        //Convert userMono to return
        //Using the Reactor operator flatMap
        return userMono.flatMap(person ->
                        ServerResponse.ok().contentType(MediaType.APPLICATION_JSON)
                                .body(fromObject(person)))
                .switchIfEmpty(notFound);
    }

    //Query all
    public Mono<ServerResponse> getAllUsers(ServerRequest request) {
        //Call service to get the result
        Flux<User> users = this.userService.getAllUser();
        return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(users, User.class);
    }

    //add to
    public Mono<ServerResponse> saveUser(ServerRequest request) {
        //Get user object
        Mono<User> userMono = request.bodyToMono(User.class);
        return ServerResponse.ok().build(this.userService.saveUserInfo(userMono));
    }

}

service and domain are copied directly without change

Create server

package com.wu.spring5webflux2;

import com.wu.spring5webflux2.handler.UserHandler;
import com.wu.spring5webflux2.service.UserService;
import com.wu.spring5webflux2.service.impl.UserServiceImpl;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.netty.http.server.HttpServer;

import java.io.IOException;

import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.RequestPredicates.accept;
import static org.springframework.web.reactive.function.server.RouterFunctions.toHttpHandler;

/**
 * @Descirption:
 * @create 2022-04-15 22:29
 * @auther: wgy
 */
public class Server {

    public static void main(String[] args) throws IOException {
        Server server = new Server();
        server.createReactorServer();
        System.out.println("enter to exit");
        System.in.read();
    }


    //1 create a Router route
    public RouterFunction<ServerResponse> routingFunction() {
        //Create a handler object
        UserService userService = new UserServiceImpl();
        UserHandler handler = new UserHandler(userService);
        //Set route
        return RouterFunctions.route(
                        GET("/users/{id}").and(accept(APPLICATION_JSON)), handler::getUserById)
                .andRoute(GET("/users").and(accept(APPLICATION_JSON)), handler::getAllUsers);
    }


    //2. Create the server to complete the adaptation
    public void createReactorServer() {
        //Routing and handler adaptation
        RouterFunction<ServerResponse> route = routingFunction();
        HttpHandler httpHandler = toHttpHandler(route);
        ReactorHttpHandlerAdapter adapter = new
                ReactorHttpHandlerAdapter(httpHandler);
        //Create server
        HttpServer httpServer = HttpServer.create();
        httpServer.handle(adapter).bindNow();
    }
}

().build(this.userService.saveUserInfo(userMono));
}

}

service and domain Direct copy unchanged



establish server

```java
package com.wu.spring5webflux2;

import com.wu.spring5webflux2.handler.UserHandler;
import com.wu.spring5webflux2.service.UserService;
import com.wu.spring5webflux2.service.impl.UserServiceImpl;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.netty.http.server.HttpServer;

import java.io.IOException;

import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.RequestPredicates.accept;
import static org.springframework.web.reactive.function.server.RouterFunctions.toHttpHandler;

/**
 * @Descirption:
 * @create 2022-04-15 22:29
 * @auther: wgy
 */
public class Server {

    public static void main(String[] args) throws IOException {
        Server server = new Server();
        server.createReactorServer();
        System.out.println("enter to exit");
        System.in.read();
    }


    //1 create a Router route
    public RouterFunction<ServerResponse> routingFunction() {
        //Create a handler object
        UserService userService = new UserServiceImpl();
        UserHandler handler = new UserHandler(userService);
        //Set route
        return RouterFunctions.route(
                        GET("/users/{id}").and(accept(APPLICATION_JSON)), handler::getUserById)
                .andRoute(GET("/users").and(accept(APPLICATION_JSON)), handler::getAllUsers);
    }


    //2. Create the server to complete the adaptation
    public void createReactorServer() {
        //Routing and handler adaptation
        RouterFunction<ServerResponse> route = routingFunction();
        HttpHandler httpHandler = toHttpHandler(route);
        ReactorHttpHandlerAdapter adapter = new
                ReactorHttpHandlerAdapter(httpHandler);
        //Create server
        HttpServer httpServer = HttpServer.create();
        httpServer.handle(adapter).bindNow();
    }
}

``Follow the notes of Shang Silicon Valley,Don't say anything yyds





Tags: Java Back-end Spring Java framework

Posted by NeMoD on Fri, 15 Apr 2022 23:49:21 +0930