Spring learning record 01

Java EE overview

Phase 1: Java 2 Version 0 proposes that Java is divided into three platforms;

JavaSE: Standard Edition (desktop application: eclipse, Navicat, IDEA)

JavaME: mini version (mobile application)

Java EE: Enterprise Edition (developing large enterprise applications)

Application requirements of large enterprises

1. High concurrency (it can support tens of thousands to millions of users online at the same time);

2. Large amount of data (the data of a single table may reach tens of millions);

3. Support distributed transactions;

4. Support cluster and load balancing;

Note: a single tomcat can support 0-500 concurrent requests within 1s per unit time;

Required technology

Lightweight framework + POJOS;

POJOS

Is an ordinary Java class, is an ordinary JavaBean;

The so-called ordinary Java class means that there is no mandatory requirement for a Java class to inherit any class or implement any interface method;

Role of POJOS: transmitting data and processing business;

Lightweight framework

Lightweight framework is defined relative to heavyweight framework. We don't need to learn heavyweight framework (EJB);

Lightweight framework features:

1. It separates the business from other framework tasks, and the business is handed over to POJOS for processing; The management of components, the implementation of AOP aspects and the access of databases are handled by lightweight frameworks;

2. Its intrusiveness to the code is not high (even some frameworks can't see the code in the code);

3. It advocates "Object-Oriented Programming";

4. It does not rely on some external special servers, and can directly use the test framework of main() or Junit to complete the function test;

Classification of lightweight frameworks:

Presentation layer: struts 1 / 2, spring MVC

Business layer: (object-oriented programming, process oriented programming);

Persistence layer: hibernate, mybatis, spring data JPA (orm)

Note: spring framework is used for overall control;

Heavyweight framework (understand)

Features of heavyweight framework:

It can not only process business, but also transmit data, but also provide cluster support and distributed transactions;

However:

1. It advocates "process oriented programming";

2. It relies too much on some API classes, such as Servlet inheriting HTTPServlet;

3. Relying too much on the server (very troublesome for development, testing and deployment);

4. It is highly intrusive to code;

That's why there is a lightweight framework;

Spring

spring: integration framework, management of components (java classes) at all levels, maintenance of relationships between components, AOP (transactions, logs);

spring derived frameworks: springioc, springMVC, springboot, springdata, springcloud;

Preparatory work 1

– configure maven environment

effect:

Automatically download jar packages and manage jar packages;

Manage the dependencies between jar packages;

It can help us test, launch, deploy and package (java is jar, web is war package);

maven: it's a project management tool

maven is a free open source project on apache open source platform;

1. Download: http://maven.apache.org/download.cgi

2. Installation: first, in the D:\Program Files directory, unzip apache-maven-3.6.3-bin zip;

Record the location above the bin directory: D:\software\apache-maven-3.6.3-bin\apache-maven-3.6.3

3. Configuration:

In the system variable, add M2_HOME

M2_HOME=D:\Program Files\apache-maven-3.6.0-bin\apache-maven-3.6.0

Find the path variable and add it in the path (in win10 system, do not add it;)

%M2_HOME%\bin

Save environment variables

4. Test whether the configuration is OK:

Open the DOC command and enter: mvn -v. if the version information appears, it indicates that the installation is correct.

5. maven principle

6. Configure local warehouse

Open settings under the installation directory conf XML file

Modification:

Then create a directory repo in disk D.

7. Replace foreign maven sources with domestic ones

Replace the foreign source with the domestic Ali acceleration source!

In settings In the mirrors node of XML, add the following content:

<mirror>
        <id>nexus-aliyun</id>
        <mirrorOf>central</mirrorOf>
        <name>Nexus aliyun</name>
        <url>http://maven.aliyun.com/nexus/content/groups/public</url> 
    </mirror>

Preparatory work 2

– replace idea.

Just follow the installation documentation.

JavaBean programming specification

JavaBean is a domain object, which comes from the analysis of customer requirements. This object has both behavior and attributes.

requirement:

1. All JavaBean s must implement the serialization interface;

2. All properties in Java must be private, and getter and setter methods are provided on demand;

3. If you need to define a parametric constructor, you need to provide a nonparametric constructor first;

4. toString can or cannot be provided;

Java programming principles

All development programs need to meet the requirements of "high cohesion and low coupling";

How can we do it?

A: at this time, it is necessary to meet the following requirements at the design level: 7 design principles and 23 design modes;

Seven principles

1. Single principle: a class does only one thing;

2. Opening and closing principle: when new requirements come, the expansion of new functions needs to be open, while the modification of old functions needs to be closed.

3. Interface isolation principle: the principle of interface minimization. When designing the interface, the methods in the interface should be as few as possible;

4. Dependency Inversion Principle: the interdependence between layers should be that the upper layer depends on the abstraction of the lower layer rather than the specific implementation of the lower layer. The lower layer should be ignorant of the upper layer (do not know any code of the upper layer);

5. Richter substitution principle: wherever the parent class appears, the child class can be replaced; (it means that the subclass should not override the methods implemented by the parent class);

6. Demeter's rule: the least known principle. When defining a class, it only interacts with the parameters of the method, the return of the method, member variables and other related classes.

7. Principle of combination and aggregation: encountering the problem of duplicate code.

Previous solutions: in the past, it was through inheritance, but inheritance will destroy encapsulation and increase the redundancy of inheritance;

Current methods: solve the problems of previous methods;

Directory structure of Maven project

Agreement on Maven project

src/main/java core code;

Location of src/main/resources configuration file;

src/test/java test code;

Location of src/test/resources test configuration file;

pom.xml: project object model. This configuration file is mainly used to describe how the project is composed.

pom.xml

Each project consists of three parts:

<!--Coordinates of the project-->
  <groupId>org.example</groupId>         //It's called organization
  <artifactId>springIoc</artifactId>     //Is your project name
  <version>1.0-SNAPSHOT</version>        //Current version of the project

Project global configuration information:

<!--Global configuration information-->
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

Define dependencies:

 <!--Specify dependencies-->
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <!-- <scope>test</scope>  Indicates that jar The package is only valid during the test phase-->
    <!-- <scope>compile</scope>  Indicates that jar Packages are only valid at compile time-->
    <!-- <scope>runtime</scope>  Indicates that jar The package is valid during operation-->
  </dependencies>

Define plug-in relationships (almost without modification):

<build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
        <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
        <plugin>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.7.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <version>3.0.0</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>

Spring framework

definition

spring framework was created by Rod Johnson in 2003. The main function of the framework is to make our applications meet the requirements of "high cohesion and low coupling", and always follow the idea of interface oriented programming to achieve loose coupling, which mainly solves the problem of loose coupling between business logic layer and other layers.

Spring core framework

The core of Spring framework: IOC (container), AOP (aspect oriented programming);

Characteristics of Spring framework

1. Facilitate program decoupling and simplify development (high cohesion and low coupling);

– its bottom layer is implemented by factory + reflection + configuration file.

(1) It can help programmers to create instances of components;

(2) It allows programmers to manage dependencies between components;

2. AOP programming support

– Spring provides aspect oriented programming, which can easily realize the functions of permission interception and operation of programs.

3. Declarative transaction support

– transaction management can be completed through configuration without manual programming.

4. Facilitate program testing

– Spring supports Junit4 (unit testing), which makes it easy to test Spring programs through annotations.

5. Convenient integration of various excellent frameworks

– Spring does not exclude various excellent open source frameworks. It provides direct support for various excellent frameworks (such as Struts, Hibernate, MyBatis, Quartz, etc.).

6. Reduce the difficulty of using Java EE API.

– Spring provides encapsulation for some APIs (JDBC, JavaMail, remote call, etc.) that are very difficult to use in Java EE development, which greatly reduces the difficulty of applying these APIs.

Spring Architecture - 7 functional modules (key)

– the Spring framework is a layered architecture consisting of seven well-defined modules. The Spring module is built on the core container, which defines the way to create, configure and manage bean s, as shown in the figure:

1. Spring Core

– the core container provides the basic functions of the Spring framework. The main component of the core container is BeanFactory, which is the implementation of the factory pattern. BeanFactory uses the forced inversion (IOC) pattern to separate the configuration and dependency specifications of the application from the actual application code.

2. Spring Context

– Spring context is a configuration file that provides context information to the Spring framework. The Spring context includes enterprise services such as JNDI, EJB, email, internationalization, validation, and scheduling capabilities.

3,Spring AOP

– through the configuration management feature, the Spring AOP module directly integrates aspect oriented programming functions into the Spring framework. Therefore, you can easily make any object managed by the Spring framework support AOP. The Spring AOP module provides transaction management services based on the objects in the Spring application. By using Spring AOP, declarative transaction management can be integrated into applications without relying on EJB components

4,Spring Dao

– the JDBC DAO abstraction layer provides a meaningful exception hierarchy that can be used to manage exception handling and error messages thrown by different database vendors. The exception hierarchy simplifies error handling and greatly reduces the amount of exception code that needs to be written (such as opening and closing connections). The JDBC oriented exceptions of Spring DAO follow the general DAO exception hierarchy.

5,Spring ORM

– the Spring framework inserts several ORM frameworks to provide ORM object relationship tools, including JDO, Hibernate and iBatis SQL Map. All transactions follow the common DAO hierarchy of Spring.

6. Spring Web module

– the Web context module is built on the application context module and provides context for web-based applications. Therefore, the Spring framework supports the integration of Jakarta Struts. The web also simplifies processing multipart requests and binding request parameters to domain objects.

7. Spring MVC framework

– MVC framework is a fully functional MVC implementation for building Web applications. Through the policy interface, the MVC framework becomes highly configurable. MVC accommodates a large number of view technologies, including JSP, Velocity, Tiles, iText and POI.

The core class of Spring container

1. BeanFactory interface;

2. ApplicationContext interface;

——The ApplicationContext interface inherits the BeanFactory interface, and their two implementation classes can become Spring containers.

——Spring container is actually a super large factory. Its bottom layer: Factory + reflection.

——BeanFactory provides all the functions of containers, but ApplicationContext is still required for the following reasons:

When BeanFactory generates an instance, it generates an instance only when getBean() is called;

While ApplicationContext starts to initialize and create instances of all components when creating container instances.

——We generally use ApplicationContext as a container (because of high efficiency).

——In addition to realizing all the functions of BeanFactory, ApplicationContext also extends many other kinetic energy: support I18N (internationalization), support task scheduling, support mail service, support WebSocket, etc.

ApplicationContext interface

Implementation classes: (1) ClassPathXmlApplicationContext, (2) FileSystemXmlApplicationContext, (3) AnnotationConfigApplicationContext (annotation).

difference:

——ClassPathXmlApplicationContext loads ApplicationContext using a relative path XML configuration file;

——FileSystemXmlApplicationContext loads ApplicationContext using an absolute path XML configuration file;

——AnnotationConfigApplicationContext provides annotation support.

——Note: however, the three are the same in the way of managing and maintaining components, and there is no difference.

How to start a container in code

//Open a Spring container
 ApplicationContext context = new AnnotationConfigApplicationContext("classpath:applicationContext.xml");

Spring framework development steps

Text flow

1. Create a Maven project;

2. In. POM Import the dependency package of spring with XML;

<!--Import spring Dependency package of framework-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.9.RELEASE</version>
    </dependency>

3. Define the required JavaBean s;

4. Define the interfaces of each layer of the three-tier architecture for the business;

5. Write the implementation class for the interface, and complete the interface oriented programming.

6. Skate ApplicationContext XML configuration file, in which tags are used to declare the components that need to be managed by the container.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
        <bean id="userService" class="com.woniuxy.springIoc.service.impl.UserServiceImpl"></bean>
        <bean id="userController" class="com.woniuxy.springIoc.controller.UserController">
                <property name="userService" ref="userService"></property>
        </bean>
</beans>

Note: id is the unique identification of the component in the container, and class is the full path of the class of the component in the container.

7. Testing.

Graphic flow

After creating the Maven project, import the dependencies.

    <!--Import spring Dependency package of framework-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.9.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>

Writing JavaBean s

package com.woniuxy.bean;
import java.io.Serializable;
public class StudentBean implements Serializable {
    private Long id;
    private String stuName;
    private Integer age;
    /**
     * 0 female
     * 1 male
     * -1 unknown
     */
    private Integer gender;
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getStuName() {
        return stuName;
    }
    public void setStuName(String stuName) {
        this.stuName = stuName;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public Integer getGender() {
        return gender;
    }
    public void setGender(Integer gender) {
        this.gender = gender;
    }
    @Override
    public String toString() {
        return "StudentBean{" +
                "id=" + id +
                ", stuName='" + stuName + '\'' +
                ", age=" + age +
                ", gender=" + gender +
                '}';
    }
}

Write interfaces of each layer

(1) The presentation layer has no interface;

(2) The business layer has interfaces: IStudentService;

(3) The persistence layer has an interface: StudentMapper;

(4) And provide corresponding abstract methods in the interface;

Business layer (IStudentService):

package com.woniuxy.service;
import com.woniuxy.bean.StudentBean;
import java.util.List;
public interface IStudentService {
    /**
     * New students
     * @param studentBean
     */
    void saveStudentBean(StudentBean studentBean);
    /**
     * Modify student
     * @param studentBean
     */
    void updateStudentBean(StudentBean studentBean);
    /**
     * Delete student
     * @param studentBean
     */
    void deleteStudentBean(StudentBean studentBean);
    /**
     * Query students by ID
     * @param id
     * @return
     */
    StudentBean getOne(Long id);
    /**
     * According to the student name, fuzzy query all student information
     * @param studentName
     * @return
     */
    List<StudentBean> findAllByStuName(String studentName);

Persistence layer (StudentMapper.java):

package com.woniuxy.mapper;
import com.woniuxy.bean.StudentBean;
import java.util.List;
public interface StudentMapper {
    /**
     * New students
     * @param studentBean
     */
    void saveStudentBean(StudentBean studentBean);
    /**
     * Modify student
     * @param studentBean
     */
    void updateStudentBean(StudentBean studentBean);
    /**
     * Delete student
     * @param studentBean
     */
    void deleteStudentBean(StudentBean studentBean);
    /**
     * Query students by ID
     * @param id
     * @return
     */
    StudentBean getOne(Long id);
    /**
     * According to the student name, fuzzy query all student information
     * @param studentName
     * @return
     */
    List<StudentBean> findAllByStuName(String studentName);
}

Persistence layer (StudentMapper.java):

package com.woniuxy.mapper;
import com.woniuxy.bean.StudentBean;
import java.util.List;
public interface StudentMapper {
    /**
     * New students
     * @param studentBean
     */
    void saveStudentBean(StudentBean studentBean);
    /**
     * Modify student
     * @param studentBean
     */
    void updateStudentBean(StudentBean studentBean);
    /**
     * Delete student
     * @param studentBean
     */
    void deleteStudentBean(StudentBean studentBean);
    /**
     * Query students by ID
     * @param id
     * @return
     */
    StudentBean getOne(Long id);
    /**
     * According to the student name, fuzzy query all student information
     * @param studentName
     * @return
     */
    List<StudentBean> findAllByStuName(String studentName);
}

Layered implementation of interfaces of each layer:

– write StudentMapper for StudentMapper xml
For IStudentService, nothing more than writing its implementation class StudentServiceImpl.

-StudentServiceImpl.java

package com.woniuxy.service.impl;
import com.woniuxy.bean.StudentBean;
import com.woniuxy.service.IStudentService;
import java.util.List;
public class StudentServiceImpl implements IStudentService {
    @Override
    public void saveStudentBean(StudentBean studentBean) {
    }
    @Override
    public void updateStudentBean(StudentBean studentBean) {
    }
    @Override
    public void deleteStudentBean(StudentBean studentBean) {
    }
    @Override
    public StudentBean getOne(Long id) {
        return null;
    }
    @Override
    public List<StudentBean> findAllByStuName(String studentName) {
        return null;
    }
}

——Give the implementation class to the Spring container

——The implementation classes are managed by the Spring container

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--Give the implementation class to Spring Container, and its identification is defined as: studentServiceImpl-->
    <bean id="studentServiceImpl"
          class="com.woniuxy.service.impl.StudentServiceImpl"></bean>
</beans>

——Testing

package com.woniuxy.service.impl;
import com.woniuxy.service.IStudentService;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import static org.junit.Assert.*;
public class StudentServiceImplTest {
    /**
     * Create container object
     */
    private ApplicationContext context;
    private IStudentService studentService;
    @Before
    public void setUp() throws Exception {
        context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        studentService = (IStudentService) context.getBean("studentServiceImpl");
        System.out.println(context.getBean("studentServiceImpl") == context.getBean("studentServiceImpl") );
    }
    @Test
    public void saveStudentBean() {
        System.out.println(studentService);
    }
    @Test
    public void updateStudentBean() {
    }
    @Test
    public void deleteStudentBean() {
    }
    @Test
    public void getOne() {
    }
    @Test
    public void findAllByStuName() {
    }
}

SpringIOC

——Spring framework can help us manage components and reduce the workload of programmers.

IOC Inversion Of Control (interview question)

——If there is no Spring container, the program needs to create its own instances when using some component instances, that is, the control of creating component instances is an "active relationship", but with the Spring container, it is now created by the container, and then passed to us. The program now has the right to create objects, from the previous initiative to passive: passive acceptance.

Benefits of inversion of control

1. Reduce the coupling degree between programs, and let the container help us loosen the coupling relationship between components.

2. Can let us really achieve: Abstract oriented programming. (dependency inversion principle)

Note: only with this reverse mechanism can Spring containers achieve "loose coupling between programs";

DI Dependency Injection (interview question)

DI and IOC are actually the same thing, there is no difference, but their descriptions are different.

Dependency injection (interview questions)

——When there is no Spring container, the program needs to directly rely on an instance when completing a business. With the Spring container, the dependency relationship changes from directly relying on the instance to relying on the container. Let the container create the instance and re inject the instance into the program.

Difference between IOC and DI (interview questions)

——In fact, there is no difference, but the concerns are different. IOC focuses on the control of creating objects (from active creation to passive acceptance), and DI focuses on dependencies (from directly relying on objects to relying on Spring containers).

Two ways for containers to pass instances to programs

1. Set point injection

——In fact, it means that you provide a setter () method, which is called by the Spring container to inject the instances in the container into the program.

package com.woniuxy.controller;
import com.woniuxy.bean.StudentBean;
import com.woniuxy.service.IStudentService;
import com.woniuxy.service.impl.StudentServiceImpl;
public class StudentController {
    private IStudentService studentService;
    public void setStudentService(IStudentService studentService) {
        this.studentService = studentService;
    }
    /**
     * Save students
     * @param studentBean
     */
    public void saveStudentBean(StudentBean studentBean){
        studentService.saveStudentBean(studentBean);
    }
}

Specific operation mode:

(1) Provide setter () for the property;

(2) In the configuration file of the spring container, use the property tag to complete the assembly between components.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--Give the implementation class to Spring Container, and its identification is defined as: studentServiceImpl-->
    <bean id="studentServiceImpl"
          class="com.woniuxy.service.impl.StudentServiceImpl"></bean>
    <bean id="studentController" class="com.woniuxy.controller.StudentController">
        <!--adopt property call setter() Complete assembly of components-->
        <property name="studentService" ref="studentServiceImpl"></property>
    </bean>
</beans>

2. Structural injection

——The program needs to provide a constructor, and the Spring container assigns values to the attributes by calling the constructor.

Specific code:

(1) Create a parameterized constructor in the program;

package com.woniuxy.controller;
import com.woniuxy.bean.StudentBean;
import com.woniuxy.service.IStudentService;
public class StudentController {
    private IStudentService studentService;
    public StudentController(IStudentService studentService) {
        this.studentService = studentService;
    }
    /**
     * Save students
     * @param studentBean
     */
    public void saveStudentBean(StudentBean studentBean){
        studentService.saveStudentBean(studentBean);
    }
}

(2) In the configuration file of Spring container, use constructor Arg to complete the construction assembly.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--Give the implementation class to Spring Container, and its identification is defined as: studentServiceImpl-->
    <bean id="studentServiceImpl"
          class="com.woniuxy.service.impl.StudentServiceImpl"></bean>
    <bean id="studentController" class="com.woniuxy.controller.StudentController">
        <constructor-arg name="studentService" ref="studentServiceImpl"></constructor-arg>
    </bean>
</beans>

3. Difference between structure injection and set value injection (interview question)

(1) The principle of injection is different. One is assembled through the constructor and the other is assembled through the setter.

(2) The injection sequence of setting injection is as follows: the Spring container creates the object first, and then calls setter () to inject the content; Construction injection is to inject content when an object is generated.

Note: neither of them is good or bad, but the use scenarios are different:

– 1: set value injection is easy to be accepted by java programmers,

– 2: if there are strict requirements on the injection sequence, it is more suitable for structural injection;

– 3: if the order of creating objects is required by, it is also suitable for construction injection.

*Singleton mode:

Singleton pattern: it is one of 23 design patterns. Its common usage scenario: this pattern can be used when a program needs only a unique instance of a class.

(1) Lazy mode:

package com.woniuxy.bean;
public class Calendar {
    private static Calendar calendar;
    /**
     * Private constructor
     */
    private Calendar(){}
    /**
     * Lazy mode
     * @return
     */
    public static Calendar getInstance(){
        if(calendar != null){
            return calendar;
        }else{
           synchronized (Calendar.class){
                   if(calender == null){
                     calendar = new Calendar();
                }
            }
        }
        return calendar;
    }
}

(2) Hungry man model

package com.woniuxy.bean;
public class Calendar {
    private static Calendar calendar = new Calendar();
    /**
     * Private constructor
     */
    private Calendar(){}
    /**
     * Hungry man model
     * @return
     */
    public static Calendar getInstance(){
        return calendar;
    }
}

Hungry man mode: when the class is loaded, the instance itself has been generated!
Lazy mode: the instance is generated by calling the method of the class

Hungry man mode is inherently thread safe!!

*Clone mode (prototype mode)

– cloning mode: a way to generate new objects in batches based on something as a prototype

– clone mode, which not only generates new objects, but also copies the data of the objects to the new objects;

– applicable scenario of clone mode: when an object has a large number of attributes and all attributes have values; You now need a large number of objects of the same type

– specific implementation: a clonable interface needs to be implemented

package com.woniuxy.bean;
import java.io.Serializable;
public class StudentBean implements Serializable,Cloneable {
    private Long id;
    private String stuName;
    private Integer age;
    /**
     * 0 female
     * 1 male
     * -1 unknown
     */
    private Integer gender;
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getStuName() {
        return stuName;
    }
    public void setStuName(String stuName) {
        this.stuName = stuName;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public Integer getGender() {
        return gender;
    }
    public void setGender(Integer gender) {
        this.gender = gender;
    }
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    @Override
    public String toString() {
        return "StudentBean{" +
                "id=" + id +
                ", stuName='" + stuName + '\'' +
                ", age=" + age +
                ", gender=" + gender +
                '}';
    }
}
package com.woniuxy.bean;
import org.junit.Test;
public class StudentBeanTest {
    @Test
    public void testClone(){
        StudentBean studentBean = new StudentBean();
        studentBean.setStuName("Kurosaki Ichigo");
        studentBean.setAge(18);
        studentBean.setGender(1);
        //clone
        try {
            StudentBean studentBean1 = (StudentBean) studentBean.clone();
            studentBean1.setStuName("Naruto");
            System.out.println(studentBean);
            System.out.println(studentBean1);
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}

(1) Shallow cloning

package com.woniuxy.bean;
import java.io.Serializable;
public class StudentBean implements Serializable,Cloneable {
    private Long id;
    private String stuName;
    private Integer age;
    /**
     * 0 female
     * 1 male
     * -1 unknown
     */
    private Integer gender;
    private GirlFriendBean girlFriendBean;
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getStuName() {
        return stuName;
    }
    public void setStuName(String stuName) {
        this.stuName = stuName;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public Integer getGender() {
        return gender;
    }
    public void setGender(Integer gender) {
        this.gender = gender;
    }
    public GirlFriendBean getGirlFriendBean() {
        return girlFriendBean;
    }
    public void setGirlFriendBean(GirlFriendBean girlFriendBean) {
        this.girlFriendBean = girlFriendBean;
    }
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    @Override
    public String toString() {
        return "StudentBean{" +
                "id=" + id +
                ", stuName='" + stuName + '\'' +
                ", age=" + age +
                ", gender=" + gender +
                ", girlFriendBean=" + girlFriendBean +
                '}';
    }
}
package com.woniuxy.bean;
import java.io.Serializable;
public class GirlFriendBean implements Serializable {
    private Long id;
    private String girlName;
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getGirlName() {
        return girlName;
    }
    public void setGirlName(String girlName) {
        this.girlName = girlName;
    }
}
package com.woniuxy.bean;
import org.junit.Test;
public class StudentBeanTest {
    @Test
    public void testClone(){
        StudentBean studentBean = new StudentBean();
        studentBean.setStuName("Kurosaki Ichigo");
        studentBean.setAge(18);
        studentBean.setGender(1);
        GirlFriendBean girlFriendBean = new GirlFriendBean();
        girlFriendBean.setGirlName("Inoue");
        studentBean.setGirlFriendBean(girlFriendBean);
        //clone
        try {
            StudentBean studentBean1 = (StudentBean) studentBean.clone();
            studentBean1.setStuName("Naruto");
            System.out.println(studentBean);
            System.out.println(studentBean1);
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}

(2) Deep cloning

Deep cloning not only clones the object itself, but also clones the associated objects of the object

package com.woniuxy.bean;
import java.io.Serializable;
public class GirlFriendBean implements Serializable ,Cloneable{
    private Long id;
    private String girlName;
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getGirlName() {
        return girlName;
    }
    public void setGirlName(String girlName) {
        this.girlName = girlName;
    }
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
package com.woniuxy.bean;
import java.io.Serializable;
public class StudentBean implements Serializable,Cloneable {
    private Long id;
    private String stuName;
    private Integer age;
    /**
     * 0 female
     * 1 male
     * -1 unknown
     */
    private Integer gender;
    private GirlFriendBean girlFriendBean;
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getStuName() {
        return stuName;
    }
    public void setStuName(String stuName) {
        this.stuName = stuName;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public Integer getGender() {
        return gender;
    }
    public void setGender(Integer gender) {
        this.gender = gender;
    }
    public GirlFriendBean getGirlFriendBean() {
        return girlFriendBean;
    }
    public void setGirlFriendBean(GirlFriendBean girlFriendBean) {
        this.girlFriendBean = girlFriendBean;
    }
    @Override
    public Object clone() throws CloneNotSupportedException {
        StudentBean studentBean = (StudentBean) super.clone();
        GirlFriendBean girlFriendBean = (GirlFriendBean) this.girlFriendBean.clone();
        studentBean.setGirlFriendBean(girlFriendBean);
        return studentBean;
    }
    @Override
    public String toString() {
        return "StudentBean{" +
                "id=" + id +
                ", stuName='" + stuName + '\'' +
                ", age=" + age +
                ", gender=" + gender +
                ", girlFriendBean=" + girlFriendBean +
                '}';
    }
}
package com.woniuxy.bean;
import org.junit.Test;
public class StudentBeanTest {
    @Test
    public void testClone(){
        StudentBean studentBean = new StudentBean();
        studentBean.setStuName("Kurosaki Ichigo");
        studentBean.setAge(18);
        studentBean.setGender(1);
        GirlFriendBean girlFriendBean = new GirlFriendBean();
        girlFriendBean.setGirlName("Inoue");
        studentBean.setGirlFriendBean(girlFriendBean);
        //clone
        try {
            StudentBean studentBean1 = (StudentBean) studentBean.clone();
            studentBean1.setStuName("Naruto");
            System.out.println(studentBean);
            System.out.println(studentBean1);
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}

The lifecycle (SCOPE) of the instance created by the Spring container

1. singleton: when a single instance (default) Spring container generates a component by default, the component has only one unique instance in the Spring container. The Spring container is responsible for the whole life cycle of component instances. When the container is created, it generates component instances. When the container is destroyed, the component instances are destroyed

2. Prototype: prototype mode (clone mode)

<bean id="studentController" class="com.woniuxy.controller.StudentController" scope="prototype">
        <constructor-arg name="studentService" ref="studentServiceImpl"></constructor-arg>
    </bean>

The instance of the component is created by the Spring container, but the Spring container is not responsible for the use of the component after it is created and when it is destroyed. The programmer is responsible for it (JVM garbage collection);

3. The instance of the request component is related to the root HttpRequest. It can be within the same HttpRequest range, and there is only one instance of the component! Different httprequests have different component instances.

<bean id="studentController" class="com.woniuxy.controller.StudentController" scope="request">
        <constructor-arg name="studentService" ref="studentServiceImpl"></constructor-arg>
    </bean>

4. The instance of the session component is related to the root HttpSession. It can be in the same HttpSession range, and there is only one instance of the component! Different httpsessions have different component instances.

<bean id="studentController" class="com.woniuxy.controller.StudentController" scope="session">
        <constructor-arg name="studentService" ref="studentServiceImpl"></constructor-arg>
    </bean>

5. The instance of the application component is related to the root ServletContext. It can be within the same ServletContext, and there is only one instance of the component! The life cycle of ServletContext is usually related to the WEB container

<bean id="studentController" class="com.woniuxy.controller.StudentController" scope="application">
        <constructor-arg name="studentService" ref="studentServiceImpl"></constructor-arg>
    </bean>

6. The instance of the websocket component is related to the connection created by the root websocket. It can only have one instance of the component within the same connection range!

<bean id="studentController" class="com.woniuxy.controller.StudentController" scope="websocket">
        <constructor-arg name="studentService" ref="studentServiceImpl"></constructor-arg>
    </bean>

Of the above six scopes, the most important one is singleton prototype, and the others are only for understanding!

automatic assembly

Through the programmer to define the relationship between components, we call it: manual assembly

<bean id="studentServiceImpl"
          class="com.woniuxy.service.impl.StudentServiceImpl"></bean>
    <bean id="studentController" class="com.woniuxy.controller.StudentController">
        <constructor-arg name="studentService" ref="studentServiceImpl"></constructor-arg>
    </bean>

However, the above method is very troublesome. The Spring container provides us with an automatic assembly mode.

byName byType contructor default

ByName

<bean id="studentController" class="com.woniuxy.controller.StudentController" autowire="byName">
    </bean>

Assemble according to the attribute name. When the Spring container generates a component instance, if it finds that the component needs to assemble other components, and the assembly method defines byName, the Spring container will find the names of all the attributes of the component and return to the Spring container to ask whether they exist. If they exist, they will be assembled normally. If they do not exist, the Spring container will not throw an exception, but the program will throw a NullPointerException during code execution

byName needs to define a setter() for the property

ByType

<bean id="studentController" class="com.woniuxy.controller.StudentController" autowire="byType">
    </bean>

If there are multiple instances of Spring dependency defined by this component, the query will be returned to the container of Spring dependency type. If there are multiple instances of Spring dependency defined by this component, the query will be generated according to the assembly method. If there are multiple instances of Spring dependency defined by this component, the query will be returned to the container of Spring dependency type; If none is found, the Spring container will not throw an exception, but the program will throw a NullPointerException during code execution

byName needs to define a setter() for the property

constructor (construction assembly)

<bean id="studentController" class="com.woniuxy.controller.StudentController" autowire="constructor">
    </bean>

Construction assembly: call the constructor to complete the assembly of components. During assembly, the construction parameters are carried out according to the ByType mode!

Be sure to provide constructors!

no or default

It's manual assembly.

annotation

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--Give the implementation class to Spring Container, and its identification is defined as: studentServiceImpl-->
    <bean id="studentService"
          class="com.woniuxy.service.impl.StudentServiceImpl"></bean>
    <bean id="studentController" class="com.woniuxy.controller.StudentController" autowire="constructor">
    </bean>
</beans>

Is it OK to declare more than 1000 components through the configuration file?

Agreement is better than configuration

Agreement: what can define the agreement in the procedure? Interface annotation

Configuration needs to maintain both Java code and configuration code, while annotation only needs to maintain Java code!

Role of annotations

1. Annotation has the function of annotation and explains the code
2. Reach certain agreement with the third party:
@Override Make a reservation with the compiler that this is a rewriting method
@Deprecated Make a reservation with the compiler that this is an outdated method
3. The code in the annotation can be used again in the program

Common annotations of Spring framework

@Component

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {
    String value() default "";
}

This component: usually used for ordinary Java classes, indicating that it is a component that needs to be managed by the Spring container

@Component
public class StudentServiceImpl implements IStudentService{} 
===
<bean id="studentService"
class="com.woniuxy.service.impl.StudentServiceImpl"></bean>

@Controller

The class used to describe the presentation layer, saying that this class needs to be managed by the Spring container!

Effect=== @Component

@Service

The class used to describe the business layer, saying that this class needs to be managed by the Spring container!

Effect=== @Component

@Repository

The class used to describe the persistence layer, saying that this class needs to be managed by the Spring container!

Effect=== @Component

Turn on the automatic scanning function of Spring container

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
        <!-- Turn on the automatic scanning function of the container-->
        <context:component-scan base-package="com.woniuxy"></context:component-scan>
</beans>

Base package benchmark package: Based on this package, scan whether the package and all sub package Java classes are used @Component @Service @Controller @Repository This Java class needs to be included in the Spring container

By default, the class name of the class will be lowercase as the instance of the class and the ID in the container

You can view it through the following methods:

 context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        System.out.println(Arrays.toString(context.getBeanDefinitionNames()));

If you want a name, write it yourself

@Controller("sc")

2 ways to assemble components

@Autowired

Automatic assembly is provided by the Spring framework. Its assembly rule is: byType first and then byName

@Resource

Automatic assembly is provided by Java. Its assembly rule is byName first and then byType

First, assemble accurately according to the name. If the assembly is unsuccessful, then go back to assemble according to the type

However, if the name attribute is specified, it can only be assembled according to byName

@Resource(name="studentServiceImpl")

Classroom exercises (1)

Said: now there are two tables_ info goods_ Info all need to implement CRUD

Now we need to: define their own JavaBean s, define the interfaces and implementations of each layer according to the thinking of three-tier architecture
The implementation of each layer is annotated and managed by the Spring container. The persistence pool can not be written temporarily

In the business layer method, output the passed parameter content!

And write the test code!

Steps:
1. First define userbean (ID, username, age) and goodsbean (ID, goodsname, price)
2. Define business interface IUserService (CRUD) IGoodsService (CRUD)
3. Define business implementation UserServiceImpl GoodsServiceImpl
4. Define presentation layer code UserController GoodsController
5. The presentation layer calls the business and completes the business logic
6. In the Spring configuration file, turn on the automatic scanning of components
7. Add on business implementation class @Service
8. On the presentation layer code, add @Controller
9. On the properties of presentation layer, add @Resource perhaps @Autowired
10. Write test classes and test the code

Spring compatible Junit framework

First step

In POM XML file, import the compatibility package of Spring Junit framework

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
    <!-- Define a global variable -->
    <spring.version>5.2.9.RELEASE</spring.version>
  </properties>
    <!--Import spring Dependency package of framework-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${spring.version}</version>
      <scope>test</scope>
    </dependency>

The second step is to modify the test class

package com.woniuxy.controller;
import com.woniuxy.bean.StudentBean;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
import java.util.Arrays;
import static org.junit.Assert.*;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value={"classpath:applicationContext.xml"})
public class StudentControllerTest {
    @Resource
    private StudentController controller;
    @Test
    public void saveStudentBean() {
        StudentBean studentBean = new StudentBean();
        studentBean.setStuName("Kurosaki Ichigo");
        controller.saveStudentBean(studentBean);
    }
}

@RunWith (SpringJUnit4ClassRunner.class) / / start a Spring container in JUnit unit test
@ContextConfiguration (value = {"classpath:applicationContext.xml"}) / / put ApplicationContext XML to the above Spring container

@Scope Scope annotation

@Scope(value="prototype")
@Controller
public class StudentController {
    ......
}

This annotation is used to modify the scope of the component. The default is singleton

Expand 2, not commonly used annotations

@PostConstruct Initialization code to be executed when instantiating a component
@PreDestroy The closing code to be executed when the component instance is destroyed

These two methods can be written into any Spring managed component:

/**
     * Initialization code to be executed when instantiating a component
     * Instead, the instance initialization block {}
     */
    @PostConstruct
    public void init(){
        System.out.println("Mom, I'm ready!!!!");
    }
    /**
     * The closing code to be executed when the component instance is destroyed
     */
    @PreDestroy
    public void destroy(){
        System.out.println("Mom, I'm out!!!!");
    }

proxy pattern

concept

Usage scenario: if we want to hide ourselves and let other classes help us with tasks, we can use it;

Real life: Star + agent, let others send love letters.

classification

Static proxy

See the proxy mode of the proxy class;

give an example:

1. Ding Li likes Feng Chengcheng very much, but Ding Li has a poor background and is a burden bearer.

2. Ding Li wrote a love letter and asked Xu Wenqiang to give it to Feng Chengcheng. Feng Chengcheng was very happy after reading the letter, but thought it was written by Xu Wenqiang.

3. So Feng Chengcheng communicated with Ding Li again through Xu Wenqiang.

analysis:

1. Feng Chengcheng is Ding Li's goal.

2. Xu Wenqiang is Ding Li's agent.

3. Xu Wenqiang has the same ability as Ding Li.

package com.woniuxy.proxy.statics;
public interface IProxy {
    void sendLetter();
}
package com.woniuxy.proxy.statics;
/**
 * Real object
 */
public class RealObject implements IProxy{
    private GrilBean grilBean;
    public RealObject() {
    }
    public RealObject(GrilBean grilBean) {
        this.grilBean = grilBean;
    }
    /**
     * Send a letter to a girl
     */
    public void sendLetter(){
        System.out.println("to[" + grilBean.getGirlName() + "]" + "Send a letter!!!");
    }
    public void getLetter(){
        System.out.println("dear["+grilBean.getGirlName()+"],I like you!");
    }
}
package com.woniuxy.proxy.statics;
/**
 * Proxy object
 */
public class ProxyObject implements IProxy{
    private GrilBean grilBean;
    private RealObject realObject;
    public ProxyObject(GrilBean grilBean) {
        this.grilBean = grilBean;
        //Proxy object, must know the real object
        realObject = new RealObject(grilBean);
    }
    /**
     * Sending behavior of proxy object
     */
    @Override
    public void sendLetter() {
        realObject.getLetter();
        //Before delivering the letter
        System.out.println("Change the signature of the letter to that of the proxy object!!!!");
        //Send a letter
        realObject.sendLetter();
        //After delivering the letter
    }
}

package com.woniuxy.proxy.statics;
import java.io.Serializable;
/**
 * Target object
 */
public class GrilBean implements Serializable {
    private String girlName;
    public GrilBean() {
    }
    public GrilBean(String girlName) {
        this.girlName = girlName;
    }
    public String getGirlName() {
        return girlName;
    }
    public void setGirlName(String girlName) {
        this.girlName = girlName;
    }
}
package com.woniuxy.proxy;
import com.woniuxy.proxy.statics.GrilBean;
import com.woniuxy.proxy.statics.IProxy;
import com.woniuxy.proxy.statics.ProxyObject;
public class Main {
    public static void main(String[] args) {
    // write your code here
        GrilBean grilBean = new GrilBean("Feng Chengcheng");
        //Give the girl to the delegate
        IProxy proxy = new ProxyObject(grilBean);
        //The proxy object sends a message to it
        proxy.sendLetter();
    }
}

Dynamic agent

The proxy mode of the proxy class is not visible

1. JDK agent

Definition: JDK proxy belongs to the interface proxy mode. There must be an interface on the real class. There is a brotherhood between the proxy class and the real class. But it's not appropriate. There's no interface to real classes.

package com.woniuxy.proxy.auto.jdk;
public interface IUserService {
    void saveUserBean();
    void updateUserBean();
}
package com.woniuxy.proxy.auto.jdk;
public class UserServiceImpl implements IUserService{
    @Override
    public void saveUserBean() {
        System.out.println("I'm saving!!!!");
    }
    @Override
    public void updateUserBean() {
        System.out.println("I'm updating!!!!");
    }
}
package com.woniuxy.proxy.auto.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JdkProxyFactory {
    private Object target;
    public void setTarget(Object target) {
        this.target = target;
    }
    public  Object getProxyIntance(){
        //Returns the proxy object of a target object
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                //How to implement the interface method when calling
                new InvocationHandler() {
                    /**
                     *
                     * @param proxy Proxy object
                     * @param method Executing method
                     * @param args Method parameters
                     * @return
                     * @throws Throwable
                     */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //Call the proxy object to execute the target method
                return method.invoke(target,args);
            }
        });
    }
}
package com.woniuxy.proxy.auto.jdk;
public class MainEnter {
    public static void main(String[] args) {
        JdkProxyFactory proxyFactory = new JdkProxyFactory();
        //Real object
        IUserService userService = new UserServiceImpl();
        proxyFactory.setTarget(userService);
        //Generate a proxy object
        IUserService proxyInstance = (IUserService)proxyFactory.getProxyIntance();
        //The proxy method is called through the proxy object
        proxyInstance.saveUserBean();
        proxyInstance.updateUserBean();
        //Returns the parent class of the object's class
        System.out.println(userService.getClass().getSuperclass());
        System.out.println(proxyInstance.getClass().getSuperclass());
    }
}

2. Cglib agent

cglib code, which is no longer a brother proxy method of the interface, but a subclass proxy

The function of cglib is in spring core There is a complete implementation in the jar package, so you need to introduce:

 <!--Import spring Dependency package of framework-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.9.RELEASE</version>
    </dependency>
package com.woniuxy.springaop.bean;
public class UserBean {
}
package com.woniuxy.springaop.service.impl;
import com.woniuxy.springaop.bean.UserBean;
public class UserServiceImpl {
    /**
     * New user
     * @param userBean
     */
    public void saveUserBean(UserBean userBean){
        System.out.println("saveUserBean()" + userBean);
    }
    /**
     * Modify user
     * @param userBean
     */
    void updateUserBean(UserBean userBean) {
        System.out.println("updateUserBean()" + userBean);
    }
}
package com.woniuxy.springaop.proxy.cglib;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxyFactory implements MethodInterceptor {
    /**
     * Target object
     */
    private Object target;
    public void setTarget(Object target) {
        this.target = target;
    }
    public Object getProxyInstance(){
        //1. Tools
        Enhancer en = new Enhancer();
        //2. Set parent class
        en.setSuperclass(target.getClass());
        //3. Set callback function
        en.setCallback(this);
        //4. Create subclasses (proxy objects)
        return en.create();
    }
    /**
     *
     * @param o              Proxy object
     * @param method        Target method
     * @param objects      Target parameters
     * @param methodProxy  Agent method
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        //Before the target method is executed (operation transaction, logging...)
        //Formal implementation of agency method
        Object obj = methodProxy.invoke(target,objects);
        //Release and authorize this class to access non-public elements of other classes
        method.setAccessible(true);
        //After the target method is executed
        return obj;
    }
}
package com.woniuxy.springaop.service.impl;
import com.woniuxy.springaop.bean.UserBean;
import com.woniuxy.springaop.proxy.cglib.CglibProxyFactory;
import org.junit.Test;
import static org.junit.Assert.*;
public class UserServiceImplTest {
    @Test
    public void saveUserBean() {
        UserServiceImpl userService = new UserServiceImpl();
        CglibProxyFactory proxyFactory = new CglibProxyFactory();
        proxyFactory.setTarget(userService);
        //Generate proxy instance
        UserServiceImpl proxyInstance = (UserServiceImpl)proxyFactory.getProxyInstance();
        //Call the method of the proxy instance
        UserBean userBean = new UserBean();
        proxyInstance.saveUserBean(userBean);
    }
    @Test
    public void updateUserBean() {
    }
}

It should be noted that real classes cannot use the final keyword to modify classes or methods because they use subclass proxy

Difference between JDK agent and Cglib agent (interview question)

1. The principles of the two agents are different. JDK agent belongs to interface agent, and the relationship between agent class and real class is friend relationship; The Cglib agent is a subclass agent. The relationship between the proxy class and the real class is parent-child relationship (the real class is the parent and the proxy class is the child).

2. Cglib converts bytecode and generates new classes through ASM, a bytecode processing framework, while JDK dynamically generates a proxy instance in memory according to the interface through the bottom layer of JVM.

Role of agency model

1. Hide the real object itself;

2. For real object methods, some other methods can be enhanced before or after execution.

SpringAOP

Aspect oriented programming with spring;

The code we wrote before is generally the presentation layer calling the business layer, and the business layer calling the persistence layer. The execution order of the code is from top to bottom, that is to say: we usually pay attention to the code vertically before. AOP is a horizontal focus on code.

Concept map

effect

AOP's greatest function: adopt the core code mode to separate the core business from non core business and pay attention to the core business. We pay attention to the core business vertically instead of the core business. We pay attention to the core business horizontally!

Core business: we use vertical focus instead of core business. We use horizontal focus!!

Cross business: businesses owned by different functional modules (almost all non core functions).

Common concepts:

1. Facets are also called aspects. Each facet is actually our non core function. Generally, a non core function is a facet;

2. Cut in point cut in point according to the conditions, the function points that can be adapted are all cut in points. This entry point can be a method, the end of the method, or even an exception of the method;

3. When the connection point aspect formally enters the entry point on a function point, the point is the connection point;

4. Notification, also known as enhancement, is defined on the aspect. Before or after the execution of the target method, new methods need to be added, that is, functions provided on the aspect (pre notification, post notification, post return notification, post exception notification, surround notification);

5. The target object refers to the object whose cut surface needs to be enhanced;

6. The proxy object is a proxy instance generated dynamically for the target object from the AOP perspective. This instance is often generated by JDK proxy and CGLIB proxy (if the target object has an interface, JDK proxy is used, and if the target object has no interface, BGLIB proxy is used);

7. Weaving weaving is the process of applying AOP facets to proxy objects, which is called weaving;

Spring provides two ways to cut

Format of pointcut expression

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern)
                throws-pattern?)

Modifiers pattern access modifiers can be omitted.

ret - type - pattern return type cannot be omitted.

The classpath of the declaring - type - pattern class can be omitted.

Name - the name of the pattern method cannot be omitted.

param - pattern parameter list cannot be omitted.

throws- pattern ? Exception expressions can be omitted.

//Block com woniuxy. All methods of all classes under the service package
execution(*com.woniuxy.service.*.*(..))        
//Block all public methods
execution(public * *(..))
//Method starting with save
execution(* save*(..))
//Intercept the specified method of the specified class. When intercepting, you must locate the method
execution(public com.woniuxy.g_pointcut.OrderDao.save(..))
//Intercepts all methods of the specified class
execution(* com.woniuxy.g_pointcut.UserDao.*(..))
//Intercept all methods of the specified package and all classes under its sub package
execution(* com..*.*(..))
//Multiple expressions
// ||And or indicate that one of the two expressions can be satisfied, and the union of the two expressions can be taken
execution(* com.woniuxy.g_pointcut.UserDao.save()) || execution(* com.woniuxy.g_pointcut.OrderDao.save())
execution(* com.woniuxy.g_pointcut.UserDao.save()) or execution(* com.woniuxy.g_pointcut.OrderDao.save())
// && amp; And and means that both are satisfied at the same time. Take the intersection
//The following two are related and meaningless
execution(* com.woniuxy.g_pointcut.UserDao.save()) &amp;&amp; execution(* com.woniuxy.g_pointcut.OrderDao.save())
execution(* com.woniuxy.g_pointcut.UserDao.save()) and execution(* com.woniuxy.g_pointcut.OrderDao.save())
//Take non value! And not denote the point of tangency that is not within the range
!execution(* com.woniuxy.g_pointcut.OrderDao.save())
not execution(* com.woniuxy.g_pointcut.OrderDao.save())

Mode 1

Spring's own schema based configuration file (understand)

1. Import the required Jar package

 <dependencies>
    <!--Import spring Dependency package of framework-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.9.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.6</version>
      <scope>runtime</scope>
    </dependency>
    <!--spring compatible Junit4-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>5.2.9.RELEASE</version>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>runtime</scope>
    </dependency>
  </dependencies>

2. Create Bean file

package com.woniuxy.springaop.bean;
public class GoodsBean {
}

package com.woniuxy.springaop.bean;
public class UserBean {
}

3. Create business layer interface

package com.woniuxy.springaop.service;
import com.woniuxy.springaop.bean.UserBean;
public interface IUserService {
    /**
     * New user
     * @param userBean
     */
    void saveUserBean(UserBean userBean);
    /**
     * Modify user
     * @param userBean
     */
    void updateUserBean(UserBean userBean);
}



package com.woniuxy.springaop.service;
import com.woniuxy.springaop.bean.GoodsBean;
public interface IGoodsService {
    void saveGoodsBean(GoodsBean goodsBean);
}

4. Business layer interface implementation class

package com.woniuxy.springaop.service.impl;
import com.woniuxy.springaop.bean.GoodsBean;
import com.woniuxy.springaop.service.IGoodsService;
import org.springframework.stereotype.Service;
@Service
public class GoodsServiceImpl implements IGoodsService {
    @Override
    public void saveGoodsBean(GoodsBean goodsBean) {
        System.out.println("saveGoodsBean()" + goodsBean);
    }
}





package com.woniuxy.springaop.service.impl;
import com.woniuxy.springaop.bean.UserBean;
import com.woniuxy.springaop.service.IUserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements IUserService {
    /**
     * New user
     * @param userBean
     */
    public void saveUserBean(UserBean userBean){
        System.out.println("saveUserBean()" + userBean);
    }
    /**
     * Modify user
     * @param userBean
     */
    public void updateUserBean(UserBean userBean) {
        System.out.println("updateUserBean()" + userBean);
    }
}

5. Contents of the configuration file

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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
        https://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">
        <!--Turn on automatic scanning of containers-->
        <context:component-scan base-package="com.woniuxy"></context:component-scan>
        <!--Configure a section-->
        <aop:config>
            <!--execution(public * com.woniuxy.springaop.service.impl.UserServiceImpl.*(..) throws NullPointerException)
            Entry point conditions:
            Method must be public Decorated, the return type doesn't matter,
            Must be com.woniuxy.springaop.service.impl.UserServiceImpl Method under
            Must throw throws NullPointerException
            -->
           <aop:pointcut id="poincutOne" expression="execution(* com.woniuxy.springaop.service.impl.*ServiceImpl.*(..))"/>
           <aop:advisor advice-ref="beforAdvice"  pointcut-ref="poincutOne"></aop:advisor>
           <aop:advisor advice-ref="afterRuturningAvice" pointcut-ref="poincutOne"></aop:advisor>
        </aop:config>
</beans>

6. Testing

7. Summary: Spring comes with its own facet technology. 1. It needs to implement a set of interfaces. 2. Write configuration files

Very troublesome.

Mode 2

Spring compatible with AspectsJ

Need to use a third-party facet Technology: AspectsJ;

Take transaction control as an example;

Recommended reasons:

1. There is no need to inherit or implement any interface;

2. It does not rely too much on configuration. It advocates the use of annotations.

step

1. First, import the third-party Jar file

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.9.6</version>
</dependency>

2. Turn on the aspect proxy mode of Spring

<!--Enable dynamic proxy support for facets: jdk as well as cglib-->
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

3. Notifications (pre, post, post return, post exception) are defined on the section, and other codes remain unchanged

package com.woniuxy.springaop.aspects;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import java.util.Arrays;
/**
 * Transaction aspect
 */
@Component  //Give the cut to the Spring container
@Aspect     //Declare this class as a faceted class
public class TransactionAspect {
    /**
     * Define pointcuts
     */
    @Pointcut("execution(* com.woniuxy.springaop.service.impl.*ServiceImpl.*(..))")
    public void pointcut(){}
    /**
     * Before advice 
     * @param joinPoint Connection point
     */
    @Before(value = "pointcut()")
    public void beforeAdvice(JoinPoint joinPoint){
        System.out.println("My number: 9527 is called pre notification. I execute before the execution of the target method!!!");
        Object target = joinPoint.getTarget();
        System.out.println("Target object" + target);
        String methodName  = joinPoint.getSignature().getName();
        System.out.println("Target method" + methodName);
        Object[] args = joinPoint.getArgs();
        System.out.println("Parameters received by the target method:" + Arrays.toString(args));
        //Open transaction
    }
    /**
     * Post return notification
     * @param joinPoint  Connection point
     * @param result Return result of the target method
     */
    @AfterReturning(value = "pointcut()",returning = "result")
    public void afterReturningAdvice(JoinPoint joinPoint,Object result){
        System.out.println("I am a post return notification. I execute after the target method returns the result normally!!!");
        System.out.println("The return of the target method is:" + result);
    }
    /**
     * Post exception notification
     * @param joinPoint Connection point
     * @param throwable   Exception thrown by target method
     */
    @AfterThrowing(value = "pointcut()",throwing = "throwable")
    public void afterThrowingAdvice(JoinPoint joinPoint,Throwable throwable){
        System.out.println("I am a post exception notification. I execute after the target method throws an exception!!!");
        System.out.println("The exception thrown is:" + throwable.getMessage());
    }
    /**
     * Post notification
     * @param joinPoint Connection point
     */
    @After(value="pointcut()")
    public void afterAdvice(JoinPoint joinPoint){
        System.out.println("I am a post notification, and I execute before the end of the target method, similar to try-catch-fanally Medium fanally()");
    }
    /**
     * Define more entry points
     */
//    @Pointcut("execution(* com.woniuxy.springaop.service.impl.*ServiceImpl.*(..))")
//    public void pointcut01(){}
//    @Pointcut("execution(* com.woniuxy.springaop.service.impl.*ServiceImpl.*(..))")
//    public void pointcut02(){}
}

Surround notification @ Around

– surround notification: it is the most powerful of the five solute types, because it can: modify parameters, modify returns, and even determine whether the target method needs to continue to execute.

It is approximately equal to @ Before + @After, that is, pre notification and post notification;

Remember: if you can use @ Before + After, don't use @ Around.

Not recommended!

 /**
     * Surround notification is approximately equal to Before + After
     * NB:
     * 1,Modify the parameters of the target method execution
     * 2,Modify the return of the target method execution
     * 3,You can even control whether the target method needs to be executed
     *
     *
     *
     * @param joinPoint
     * @return
     */
    @Around(value="pointcut()")
    public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("I am a circular notice, and I am approximately equal to:@Before + @After");
        //parameter
       Object[] args =  joinPoint.getArgs();
       args[0] = null; //Modify the first parameter of the target method to NULL
        //This method is equivalent to method invoke(obj,args);
       Object obj = joinPoint.proceed(args);
       obj = 1;//For all methods, the return result is fixed to 1
       return obj;
    }

Application of AOP in projects (interview questions)

1. Transaction control;

2. Log record;

3. Exception handling;

4. Sensitive word filtering;

SM integration

Explicit dependent packages:

Various Spring dependency packages, including Mybatis dependency package, mysql database connection dependency package, Junit dependency package, Lombok dependency package and Log4J dependency package.

Various Spring dependency packages

<!--Import spring Dependency package of framework-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.9.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.6</version>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>1.9.6</version>
    </dependency>
    <!--spring compatible Junit4-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>5.2.9.RELEASE</version>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.2.9.RELEASE</version>
      <scope>runtime</scope>
    </dependency>

Dependency package of Mybatis

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.3</version>
</dependency>
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>2.0.3</version>
</dependency>

Dependent package for connecting to Mysql database

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

Log4J dependency package

<dependency>
     <groupId>log4j</groupId>
     <artifactId>log4j</artifactId>
     <version>1.2.17</version>
  </dependency>

Integration steps

First step

Import dependencies;

Step two

Prepare the project structure;

Step 3

Write the configuration file of Spring framework (key);

applicationContext.xml

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

Steps of Spring framework configuration file

1. Configure database connection pool and provide JDBC connection;

– data source: it is the source of data. There may be many sources: database, NOSQL, Excel and other systems
Of course, in our case, it usually refers to: relational database;

– business connection pool:
C3p0, DBCP (APACHE), Druid (ALI Druid)

–DBCP

Configuration document of DBCP
http://commons.apache.org/proper/commons-dbcp/configuration.html

- (1) introduce DBCP dependency package

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-dbcp2</artifactId>
    <version>2.7.0</version>
</dependency>

- (2) create mysql Properties file

jdbc.url=jdbc:mysql://localhost:3306/sm?characterEncoding=UTF8
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.username=root
jdbc.password=123456

– (3) in ApplicationContext XML, configure the data source;

<!--take properties Profiles, importing to Spring In container-->
        <context:property-placeholder location="mysql.properties"></context:property-placeholder>
        <!--to configure DataSource Data source connection pool-->
        <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
            <!--to configure JDBC Connect to the database, the most basic connection information-->
            <property name="url" value="${jdbc.url}"></property>
            <property name="driverClassName" value="${jdbc.driverClassName}"></property>
            <property name="username" value="${jdbc.username}"></property>
            <property name="password" value="${jdbc.password}"></property>
            <!--Additional configuration-->
            <!--The default number of connections set in the connection pool is 5-->
            <property name="initialSize" value="5"></property>
            <!--In the connection pool, the maximum number of connections is 50-->
            <property name="maxTotal" value="50"></property>
            <!--In the connection pool, the maximum number of connections in the free area is 10-->
            <property name="maxIdle" value="10"></property>
            <!--Set whether precompiling is supported-->
            <property name="poolPreparedStatements" value="true"></property>
            <!--Set the precompiled object. The default value is 20-->
            <property name="maxOpenPreparedStatements" value="20"></property>
            <!--Verify whether the connection is valid when it is created-->
            <property name="testOnCreate" value="true"></property>
            <!--Set verification statement-->
            <property name="validationQuery" value="select now() from dual"></property>
            <!--Cancel auto submit-->
            <property name="defaultAutoCommit" value="false"></property>
            <!--Cancel connection read only-->
            <property name="defaultReadOnly" value="false"></property>
            <!--set up SQL The query timeout is: 2 S Clock, usually more than 2 S All the above statements will report errors!!!-->
            <property name="defaultQueryTimeout" value="2"></property>
        </bean>
2. Configure SessionFactory SQLsession;

SQL session: generate data according to the factory session object;

<!--to configure SessionFactory-->
        <bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"></property>
            <!--to JavaBean Define alias: place JavaBean Directory of-->
            <property name="typeAliasesPackage" value="com.woniuxy.sm.bean"></property>
            <!--Additional configuration-->
            <property name="configuration">
                <bean class="org.apache.ibatis.session.Configuration">
                    <!--Turn on delayed loading-->
                    <property name="lazyLoadingEnabled" value="true"></property>
                    <property name="aggressiveLazyLoading" value="false"></property>
                </bean>
            </property>
        </bean>
3. Configure MapperScanner to scan SQL mapping files;

MapperScanner scanner: scan * mapper XML configuration file;

<!--to configure MapperScanner Scanner-->
        <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <!--place Mapper Interface and the path where the configuration file is located. If there are multiple paths, you can use , or ; Split-->
            <property name="basePackage" value="com.woniuxy.sm.mapper"></property>
            <!-- Map files and SessionFactory Connect through jdk Agent for Mapper Interface to dynamically generate proxy classes -->
            <property name="sqlSessionFactoryBeanName" value="sessionFactory"></property>
        </bean>
4. Configure the transaction manager to provide transaction management;

Transaction manager: a container / tool dedicated to managing things;

In the learning stage, we use DAO to manually control transactions, but that way can not guarantee that the business logic is under transaction control.

 <!--Transaction manager-->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"></property>
        </bean>
5. Use AOP aspect technology to manage transactions and control the management scope of transactions.

(1) Transaction control using XML

<!--Define notifications on transaction aspects-->
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <tx:attributes>
                <!--Query methods and other illegal naming methods, unified connection, read-only-->
                <tx:method name="*" read-only="true"></tx:method>
                <tx:method name="save*" rollback-for="java.lang.Exception" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
                <tx:method name="add*" rollback-for="java.lang.Exception" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
                <tx:method name="insert*" rollback-for="java.lang.Exception" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
                <tx:method name="update*" rollback-for="java.lang.Exception" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
                <tx:method name="modify*" rollback-for="java.lang.Exception" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
                <tx:method name="delete*" rollback-for="java.lang.Exception" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
                <tx:method name="remove*" rollback-for="java.lang.Exception" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
            </tx:attributes>
        </tx:advice>
        <!--Define section-->
        <aop:config>
            <aop:pointcut id="pointcut1" expression="execution(* com.woniuxy.sm.service.impl.*ServiceImpl.*(..))"/>
            <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"></aop:advisor>
        </aop:config>

(2) Transaction control using annotations

Step 4

Install Lombok plug-in

It is best to use local disk installation. The installed package is lombok-plugin-0.32-2020-1 zip;

In setting - > plugins - > Settings - > install plugin from disk

After installation, restart IEDA.

In POM The Lombok plug-in is introduced into XML.

<dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.12</version>
      <scope>provided</scope>
    </dependency>

@Data This annotation is defined on the JavaBean. Its functions: generate getter() and setter() methods, parameterless constructor, toString(), hashCode(), equals();

@NoArgsConstructor() generates a parameterless constructor;

@Getter generates getter();

@Setter() generates setter();

@ToString generates toString();

@Requireargsconstructor + @ nonnull can be used to define parameterless constructors;

package com.woniuxy.sm.bean;
import lombok.*;
import java.io.Serializable;
import java.util.Date;
/**
 * User instance class
 */
@Data
@RequiredArgsConstructor
public class UserBean implements Serializable {
    private Integer id;
    @NonNull
    private String userName;
    @NonNull
    private String loginName;
    @NonNull
    private String password;
    private int age;
    private Date birthday;
    private RoleBean roleBean;
}
package com.woniuxy.sm.bean;
import lombok.Data;
import java.io.Serializable;
/**
 * Role entity class
 */
@Data
public class RoleBean implements Serializable {
    private Integer id;
    private String roleName;
}

Step 5

Define business layer interfaces and provide implementation classes

package com.woniuxy.sm.service;
import com.woniuxy.sm.bean.UserBean;
public interface IUserService {
    /**
     * New user
     * @param userBean
     */
    void saveUserBean(UserBean userBean);
    /**
     * Modify user
     * @param userBean
     */
    void updateUserBean(UserBean userBean);
    /**
     * Query user by ID
     * @param id
     * @return
     */
    UserBean getOneById(Integer id);
}
package com.woniuxy.sm.service.impl;
import com.woniuxy.sm.bean.UserBean;
import com.woniuxy.sm.service.IUserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements IUserService {
    @Override
    public void saveUserBean(UserBean userBean) {
    }
    @Override
    public void updateUserBean(UserBean userBean) {
    }
    @Override
    public UserBean getOneById(Integer id) {
        return null;
    }
}

Step 6

Turn on the automatic scanning function of the container

<!--Turn on the automatic container scanning function-->
<context:component-scan base-package="com.woniuxy.sm"></context:component-scan>

Step 7

Writing persistence layer code

package com.woniuxy.sm.mapper;
import com.woniuxy.sm.bean.UserBean;
import org.apache.ibatis.annotations.Param;
public interface UserMapper {
    /**
     * New user
     * @param userBean
     */
    void saveUserBean(@Param("u") UserBean userBean);
    /**
     * Modify user
     * @param userBean
     */
    void updateUserBean(@Param("u")UserBean userBean);
    /**
     * Query user by ID
     * @param id
     * @return
     */
    UserBean getOneById(@Param("id")Integer id);
}

Write the configuration file usermapper xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.woniuxy.sm.mapper.UserMapper">
    <insert id="saveUserBean" useGeneratedKeys="true" keyProperty="u.id">
        insert into user_info(user_name,login_name,password,age,birthday)
        values (#{u.userName},#{u.loginName},#{u.password},#{u.age},#{u.birthday})
    </insert>
    <update id="updateUserBean">
        update user_info
        <set>
            <if test="u.userName != null">
                user_name = #{u.userName},
            </if>
            <if test="u.loginName != null">
                login_name = #{u.loginName},
            </if>
            <if test="u.password != null">
                password = #{u.password},
            </if>
            <if test="u.age != null">
            age = #{u.age},
            </if>
            <if test="u.birthday != null">
                birthday = #{u.birthday},
            </if>
        </set>
        <where>
            id = #{u.id}
        </where>
    </update>
    <select id="getOneById" resultType="UserBean">
       select id,user_name as userName,login_name as loginName,age,birthday from user_info where id = #{id}
    </select>
</mapper>

Step 8

In POM XML, add the configuration path;

  <!--Specify the location of the configuration file-->
    <resources>
      <resource>
        <directory>src/main/java</directory>
        <includes>
            <include>**/*.xml</include>
        </includes>
        <filtering>true</filtering>
      </resource>
    </resources>

affair

Transaction: a sequence with clear boundaries and orderly execution order.

Eg: Zhang San, Li Si transferred money;

Eg: one HTTP request;

Four characteristics

Atomicity: a transaction is a complete individual and cannot be separated again (either unity succeeds or unity fails);

Isolation: transactions and transactions are isolated from each other and do not affect each other.

Consistency: within the same transaction submission scope, the accuracy and integrity of data need to be guaranteed (Conservation of mass);

Persistence: once a transaction is committed, the result is permanent.

Isolation level of transaction

Transaction isolation level and database level mean the same thing. There are four database isolation levels (mysql):

The isolation domain is reduced. In addition to the unexpected conditions of phantom reading, non repeatable reading and dirty reading, two kinds of data update loss problems may also be caused.

Update lost

Lost update:

If multiple threads operate to modify the records in the table based on the same query structure, the later modified records will overwrite the previous modified records, and the previous modifications will be lost, which is called Update loss. This is because the system does not perform any lock operations, so concurrent transactions are not isolated.

Update the missing solution: lock the database.

The first type of update is lost

When transaction A cancels, it overwrites the updated data of committed transaction B.

The second type of update is lost

Transaction A overwrites the data submitted by transaction B, resulting in the loss of operations performed by transaction B.

Isolation level and loss of updates

Because the read has been submitted, which may lead to the loss of the second type of update and non repeatable reading, the problem of data consistency is higher than that of repeatable reading. Therefore, we generally use repeatable reading as our default isolation level.

Propagation characteristics of transactions

Transaction propagation: how to control or propagate transactions when multiple methods with transaction capability call each other.

Remember two things:

1. Generally, it must be used for cuird, no matter what the transaction is;

2. SUPPORTS: if there is a transaction, it SUPPORTS the transaction. If there is no transaction, it is executed in a non transaction manner.

Transaction processing scheme provided by Spring framework (interview question)

Programming transaction solution

In the code of the business layer, the transaction template and the functions provided by the platform transaction manager are used to manage the practice.

public class SimpleService implements Service {
    // single TransactionTemplate shared amongst all methods in this instance
    private final TransactionTemplate transactionTemplate;
    // use constructor-injection to supply the PlatformTransactionManager
    public SimpleService(PlatformTransactionManager transactionManager) {
        this.transactionTemplate = new TransactionTemplate(transactionManager);
    }
    public Object someServiceMethod() {
        return transactionTemplate.execute(new TransactionCallback() {
            // the code in this method executes in a transactional context
            public Object doInTransaction(TransactionStatus status) {
                updateOperation1();
                return resultOfUpdateOperation2();
            }
        });
    }
}

Note: this method was abandoned a long time ago. The reason for abandonment is that it re couples the transaction control code with the core code.

Declarative transaction solution

Using the idea of AOP, transaction control is defined in the aspect, and there is no transaction logic code in the core code.

1. In apploicationcontext XML.

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

2. Replace Maven dependency

Replace spring JDBC with spring ORM dependencies.

  <!--Spring Provision of JDBC Connection support and transaction management dependency package-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-orm</artifactId>
      <version>5.2.9.RELEASE</version>
      <scope>runtime</scope>
    </dependency>

3. Add a dependency

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

4. The @ Transactional annotation is used to complete the declaration of transactions.

package com.woniuxy.sm.service.impl;
import com.woniuxy.sm.bean.UserBean;
import com.woniuxy.sm.mapper.UserMapper;
import com.woniuxy.sm.service.IUserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
@Transactional(readOnly = true)
@Service
public class UserServiceImpl implements IUserService {
    @Resource
    private UserMapper userMapper;
    @Transactional(isolation = Isolation.REPEATABLE_READ,rollbackFor = Exception.class)
    @Override
    public void saveUserBean(UserBean userBean) {
        userMapper.saveUserBean(userBean);
    }
    @Transactional(isolation = Isolation.REPEATABLE_READ,rollbackFor = Exception.class)
    @Override
    public void updateUserBean(UserBean userBean) {
        userMapper.updateUserBean(userBean);
    }
    @Override
    public UserBean getOneById(Integer id) {
        return userMapper.getOneById(id);
    }
}

Log4J log framework

1. Import dependency

<dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
    </dependency>

2. Write log4j Properties configuration file

log4j.rootLogger=DEBUG, console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%5p [%t] - %m%n
#Print OUT SQL 
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG

3. In ApplicationContext XML, enable logging

<!--to configure SessionFactory-->
        <bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"></property>
            <!--to JavaBean Define alias: place JavaBean Directory of-->
            <property name="typeAliasesPackage" value="com.woniuxy.sm.bean"></property>
            <!--Additional configuration-->
            <property name="configuration">
                <bean class="org.apache.ibatis.session.Configuration">
                    <!--Turn on delayed loading-->
                    <property name="lazyLoadingEnabled" value="true"></property>
                    <property name="aggressiveLazyLoading" value="false"></property>
                    <!--open Log4j Logging of-->
                    <property name="logImpl" value="org.apache.ibatis.logging.log4j.Log4jImpl"></property>
                </bean>
            </property>
        </bean>

Key configuration

<property name="logImpl" value="org.apache.ibatis.logging.log4j.Log4jImpl"></property>

lock

We all know that reducing the isolation level will lead to data inconsistency. The lower the isolation, the worse the accuracy!
How to solve it?

Scheme: pessimistic lock, optimistic lock.

Pessimistic lock

Pessimistic lock is a very strict row level lock in the database. The concept of pessimistic lock is: the program pessimistically believes that when a user is operating the data in the database, there must be other users operating the same batch of data with him, and at the same time,
So in order to solve this problem, the program directly locks the data at the bottom of the database. The effect after locking is that when user A locks some data, other users cannot view the same data, and the operation effect is equivalent to using synchronized in the code.

Specific steps: add in your query statement

for update;

Statement example:

select * from user_info for update;

The above statement will make other users unable to view user_info, unless the current user has committed the transaction, rolled back the transaction and closed the transaction

In this way, the accuracy is high, but the efficiency is too low! Usually applicable to: purchase train tickets.

Optimistic lock

Optimistic lock: it is the most frequent lock to solve the problem of data consistency. It is not aimed at the underlying locking of the database. On the contrary, it can be understood as a logical lock.

Concept of optimistic lock: the program is optimistic that when a user is operating a batch of data, no one must operate the same batch of data with him at the same time.

Solution of optimistic lock: add version control;

After adding version control, each submission will add its own version+1,

Then compare with the database version number to see if it is greater than the database version number. If it is greater than, it will be submitted normally. If it is not greater than, it will not be submitted successfully!

Of course, there is no optimistic lock in Mybatis. Programmers need to define their own logic. If it is Hibernate or SpringDataJPA, they all provide optimistic lock support by default.

Concrete implementation of optimistic lock

Create JavaBean: commodity class

package com.woniuxy.sm.bean;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
@Data
public class GoodsBean implements Serializable {
    private Integer id;
    private String goodsName;
    private BigDecimal price;
    /**
     * Inventory
     */
    private Integer storeNum;
    /**
     * Version number
     */
    private Integer version;
}

Order class

package com.woniuxy.sm.bean;
import lombok.Data;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import java.io.Serializable;
@Data
@RequiredArgsConstructor
public class OrderBean implements Serializable {
    private Integer id;
    @NonNull
    private String orderNo;
    /**
     * commodity
     */
    @NonNull
    private GoodsBean goodsBean;
    /**
     * purchaser
     */
    @NonNull
    private UserBean userBean;
}

Create business layer interface

package com.woniuxy.sm.service;
import com.woniuxy.sm.bean.GoodsBean;
import com.woniuxy.sm.bean.OrderBean;
import com.woniuxy.sm.bean.UserBean;
public interface IGoodsService {
    /**
     * Query goods by ID
     * @param id
     * @return
     */
    GoodsBean getOneById(Integer id);
    /**
     * Purchase goods and generate orders
     * @param orderBean
     */
    String buyGoods(OrderBean orderBean);
}

Create an interface between two persistence layers

package com.woniuxy.sm.mapper;
import com.woniuxy.sm.bean.GoodsBean;
import org.apache.ibatis.annotations.Param;
public interface GoodsMapper {
    /**
     * Query goods by ID
     * @param id
     * @return
     */
    GoodsBean getOneById(Integer id);
    /**
     * Update item (inventory, and version number)
     * @param goodsBean
     * @return Number of rows affected by the database
     */
    int updateGoodsBean(@Param("g") GoodsBean goodsBean);
}
package com.woniuxy.sm.mapper;
import com.woniuxy.sm.bean.OrderBean;
import org.apache.ibatis.annotations.Param;
public interface OrderMapper {
    /**
     * Save order
     * @param orderBean
     * @return
     */
    int saveOrderBean(@Param("o") OrderBean orderBean);
}

And write corresponding configuration files:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.woniuxy.sm.mapper.GoodsMapper">
    <select id="getOneById" resultType="GoodsBean">
        select id,goods_name as goodsName,price,store_num as storeNum,version
         from goods_info where id = #{id}
    </select>
    <update id="updateGoodsBean">
        update goods_info
        <set>
            <if test="g.storeNum != null">
                store_num = #{g.storeNum} - 1,
            </if>
            <if test="g.version != null">
                version = #{g.version} + 1,
            </if>
        </set>
        <where>
            id = #{g.id} and version = #{g.version}
        </where>
    </update>
</mapper>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.woniuxy.sm.mapper.OrderMapper">
    <insert id="saveOrderBean">
        insert into order_info (order_no,fk_goods_id,fk_user_id) values
        (#{o.orderNo},#{o.goodsBean.id},#{o.userBean.id})
    </insert>
</mapper>

Write the code of the business layer implementation class

package com.woniuxy.sm.service.impl;
import com.woniuxy.sm.bean.GoodsBean;
import com.woniuxy.sm.bean.OrderBean;
import com.woniuxy.sm.mapper.GoodsMapper;
import com.woniuxy.sm.mapper.OrderMapper;
import com.woniuxy.sm.service.IGoodsService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
@Transactional(readOnly = true)
@Service
public class GoodsServiceImpl implements IGoodsService {
    @Resource
    private GoodsMapper goodsMapper;
    @Resource
    private OrderMapper orderMapper;
    @Override
    public GoodsBean getOneById(Integer id) {
        return goodsMapper.getOneById(id);
    }
    /**
     * Logic of optimistic lock
     * @param orderBean
     * @return
     */
    @Transactional(isolation = Isolation.REPEATABLE_READ,rollbackFor = Exception.class)
    @Override
    public String buyGoods(OrderBean orderBean) {
        //First query the version information in the database and the inventory > 0
        GoodsBean goodsBean = goodsMapper.getOneById(orderBean.getGoodsBean().getId());
        if(goodsBean.getStoreNum() > 0){
            int currentVersion = orderBean.getGoodsBean().getVersion() + 1;
            int dbVersion = goodsBean.getVersion();
            //When the inventory is > 0, judge whether the current version number is > the version number in the database
            if(currentVersion > dbVersion){
                //Update the data and return the number of rows affected
               int rows = goodsMapper.updateGoodsBean(goodsBean);
               if(rows > 0){
                   return "Congratulations on your successful purchase!!!";
               } else{
                   throw new RuntimeException("Hand speed is too slow, please operate again!!!");
               }
            }else{
                throw new RuntimeException("Hand speed is too slow, please operate again!!!");
            }
        }else{
            return "You are cold and the goods have been sold out!";
        }
    }
}

Writing test classes

package com.woniuxy.sm.service.impl;
import com.woniuxy.sm.bean.GoodsBean;
import com.woniuxy.sm.bean.OrderBean;
import com.woniuxy.sm.bean.UserBean;
import com.woniuxy.sm.service.IGoodsService;
import com.woniuxy.sm.service.IUserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
import static org.junit.Assert.*;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = {"classpath:applicationContext.xml"})
public class GoodsServiceImplTest {
    @Resource
    private IGoodsService goodsServiceImpl;
    @Resource
    private IUserService userServiceImpl;
    @Test
    public void getOneById() {
    }
    @Test
    public void buyGoods() {
        //Select 1 item
        GoodsBean goodsBean = goodsServiceImpl.getOneById(2);
        //Select 1 user
        UserBean userBean = userServiceImpl.getOneById(1);
        //Generate order
        OrderBean orderBean = new OrderBean("567567",goodsBean,userBean);
        //purchase
        String result = goodsServiceImpl.buyGoods(orderBean);
        System.out.println(result);
        System.out.println("----------------------------------------------");
         //Select 1 user
        UserBean userBean02 = userServiceImpl.getOneById(2);
        //Generate order
        OrderBean orderBean02 = new OrderBean("456789",goodsBean,userBean02);
        //purchase
        String result02 = goodsServiceImpl.buyGoods(orderBean02);
        System.out.println(result02);
    }
}

Compensation mechanism of optimistic lock

Optimistic lock is a version control method to solve the problem of data inconsistency caused by reducing the isolation level. Because it is solving the problem, it may throw out: your operation speed is too slow and you need to operate again!

So it needs to be compensated!

Compensation code:

/**
     * Buy again
     * @param orderBean
     * @return true Indicates that the purchase is successful, and false indicates that the goods have been sold out
     */
    public boolean reBuy(OrderBean orderBean){
        GoodsBean goodsBean = goodsMapper.getOneById(orderBean.getGoodsBean().getId());
        if(goodsBean.getStoreNum() > 0){
            int rows = goodsMapper.updateGoodsBean(goodsBean);
            if(rows > 0){
                //Generate order
                orderMapper.saveOrderBean(orderBean);
                return true;
            } else{
                reBuy(orderBean);
            }
        }else{
            return false;
        }
        return false;
    }

Optimistic lock logic code:

/**
     * Logic of optimistic lock
     * @param orderBean
     * @return
     */
    @Transactional(isolation = Isolation.REPEATABLE_READ,rollbackFor = Exception.class)
    @Override
    public String buyGoods(OrderBean orderBean) {
        //First query the version information in the database and the inventory > 0
        GoodsBean goodsBean = goodsMapper.getOneById(orderBean.getGoodsBean().getId());
        if(goodsBean.getStoreNum() > 0){
            int currentVersion = orderBean.getGoodsBean().getVersion() + 1;
            int dbVersion = goodsBean.getVersion();
            //When the inventory is > 0, judge whether the current version number is > the version number in the database
            if(currentVersion > dbVersion){
                //Update the data and return the number of rows affected
               int rows = goodsMapper.updateGoodsBean(goodsBean);
               if(rows > 0){
                   //Generate order
                   orderMapper.saveOrderBean(orderBean);
                   return "Congratulations on your successful purchase!!!";
               } else{
//                   throw new RuntimeException("hand speed is too slow, please operate again!!!");
                  boolean flag = reBuy(orderBean);
                  if (flag) return "Congratulations on your successful purchase!!!";else return "You are cold and the goods have been sold out!";
               }
            }else{
//                throw new RuntimeException("hand speed is too slow, please operate again!!!");
                boolean flag = reBuy(orderBean);
                if (flag) return "Congratulations on your successful purchase!!!";else return "You are cold and the goods have been sold out!";
            }
        }else{
            return "You are cold and the goods have been sold out!";
        }
    }

Log section

System log aspect

<!--Log bridge frame-->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.30</version>
    </dependency>
     <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.7.30</version>
      <scope>test</scope>
    </dependency>

In ApplicationContext In XML, enable the dynamic proxy support of aspect

<!--Enable dynamic proxy support for facets-->
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

Define a section and annotate it in @Slf4 the section

package com.woniuxy.sm.aspects;
import lombok.extern.slf4j.Slf4j;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@Slf4j
@Component
@Aspect
public class SystemLogAspect {
    @Pointcut("execution(* com.woniuxy.sm.service.impl.*ServiceImpl.*(..))")
    public void pointcut(){}
    /**
     * Before advice 
     * Record: receiving parameters of the target method
     * @param joinPoint
     */
    @Before(value="pointcut()")
    public void beforeAdvice(JoinPoint joinPoint){
        Object target = joinPoint.getTarget();
        //Target method
        String meth = joinPoint.getSignature().getName();
        //Received parameters
        Object[] args = joinPoint.getArgs();
        log.info(target + "--" + meth + "()---args:{} ",Arrays.toString(args));
    }
    /**
     * Post return
     * Record: return result of target method
     * @param joinPoint
     * @param result
     */
    @AfterReturning(value = "pointcut()",returning = "result")
    public void afterReturningAdvice(JoinPoint joinPoint,Object result){
        Object target = joinPoint.getTarget();
        //Target method
        String meth = joinPoint.getSignature().getName();
        log.info(target + "--" + meth + "()---result:{}",result);
    }
    /**
     * Post exception notification
     * Record: exception information thrown by the target method
     * @param joinPoint
     * @param exception
     */
    @AfterThrowing(value = "pointcut()",throwing = "exception")
    public void afterThrowingAdvice(JoinPoint joinPoint,Exception exception){
        Object target = joinPoint.getTarget();
        //Target method
        String meth = joinPoint.getSignature().getName();
        log.error(target + "--" + meth + "()---exception:{}",exception);
    }
}

Record operation log

Operation log: record what kind of things a person has done at a certain time and in a certain module, and what data it has affected. All places that will affect the database need to be recorded! CUD operation, except R.

Define a JavaBean

package com.woniuxy.sm.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class OptLogBean implements Serializable {
    private Integer id;
    private String userName;
    private Date optTime;
    private String menuName;
    private Integer optType;
    private String data;
}

Define business layer interface

package com.woniuxy.sm.service;
import com.woniuxy.sm.bean.OptLogBean;
public interface IOptLogService {
    /**
     * Save operation log
     * @param logBean
     */
    void saveLogBean(OptLogBean logBean);
}

Define interface implementation classes

package com.woniuxy.sm.service.impl;
import com.woniuxy.sm.bean.OptLogBean;
import com.woniuxy.sm.service.IOptLogService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional(readOnly = true)
public class OptLogServiceImpl implements IOptLogService {
    //Assemble Mapper yourself
    @Transactional(isolation = Isolation.REPEATABLE_READ,rollbackFor = Exception.class)
    @Override
    public void saveLogBean(OptLogBean logBean) {
        System.out.println("OptLogServiceImpl ----> " + logBean);
    }
}

Define log enumeration

package com.woniuxy.sm.enums;
import lombok.Getter;
@Getter
public enum OptTypeEnum {
   SAVE(0),UPDATE(1),DELETE(2);
    /**
     * Type properties (enumeration for external use)
     */
   private int type;
   private OptTypeEnum(int type){
       this.type = type;
   }
}

Define log annotations:

package com.woniuxy.sm.annos;
import com.woniuxy.sm.enums.OptTypeEnum;
import java.lang.annotation.*;
/**
 * Define three meta annotations
 */
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {
    /**
     * Menu name
     * @return
     */
    String menuName();
    /**
     * Operation type
     * 0-newly added
     * 1-modify
     * 2-delete
     * @return
     */
    OptTypeEnum optType();
}

Operation log section

package com.woniuxy.sm.aspects;
import com.woniuxy.sm.annos.MyLog;
import com.woniuxy.sm.bean.OptLogBean;
import com.woniuxy.sm.service.IOptLogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Date;
@Component
@Aspect
public class OptLogAspect {
    @Resource
    private IOptLogService logServiceImpl;
    /**
     * Post return notification
     * Record: operation log
     * @param joinPoint
     * @param result
     * @param log Where @ MyLog is used, it is the entry point of this section
     */
    @AfterReturning(value = "@annotation(log)",returning = "result")
    public void afterReturningAdvice(JoinPoint joinPoint, Object result, MyLog log){
        Object[] args = joinPoint.getArgs();
        OptLogBean optLogBean = new OptLogBean
                (null,"Lao Pu",new Date(),log.menuName(),log.optType().getType(), Arrays.toString(args));
        logServiceImpl.saveLogBean(optLogBean);
    }
}

On the method of business layer, log annotation is used

package com.woniuxy.sm.service.impl;
import com.woniuxy.sm.annos.MyLog;
import com.woniuxy.sm.bean.UserBean;
import com.woniuxy.sm.enums.OptTypeEnum;
import com.woniuxy.sm.mapper.UserMapper;
import com.woniuxy.sm.service.IUserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
@Transactional(readOnly = true)
@Service
public class UserServiceImpl implements IUserService {
    @Resource
    private UserMapper userMapper;
    @MyLog(menuName = "user management ",optType = OptTypeEnum.SAVE)
    @Transactional(isolation = Isolation.REPEATABLE_READ,rollbackFor = Exception.class)
    @Override
    public  void saveUserBean(UserBean userBean) {
        userMapper.saveUserBean(userBean);
    }
    @MyLog(menuName = "user management ",optType = OptTypeEnum.UPDATE)
    @Transactional(isolation = Isolation.REPEATABLE_READ,rollbackFor = Exception.class)
    @Override
    public void updateUserBean(UserBean userBean) {
        userMapper.updateUserBean(userBean);
    }
    @Override
    public UserBean getOneById(Integer id) {
        return userMapper.getOneById(id);
    }
}
package com.woniuxy.sm.service.impl;
import com.woniuxy.sm.annos.MyLog;
import com.woniuxy.sm.bean.GoodsBean;
import com.woniuxy.sm.bean.OrderBean;
import com.woniuxy.sm.enums.OptTypeEnum;
import com.woniuxy.sm.mapper.GoodsMapper;
import com.woniuxy.sm.mapper.OrderMapper;
import com.woniuxy.sm.service.IGoodsService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
@Transactional(readOnly = true)
@Service
public class GoodsServiceImpl implements IGoodsService {
    @Resource
    private GoodsMapper goodsMapper;
    @Resource
    private OrderMapper orderMapper;
    @Override
    public GoodsBean getOneById(Integer id) {
        return goodsMapper.getOneById(id);
    }
    /**
     * Logic of optimistic lock
     * @param orderBean
     * @return
     */
    @MyLog(menuName = "Commodity management",optType = OptTypeEnum.SAVE)
    @Transactional(isolation = Isolation.REPEATABLE_READ,rollbackFor = Exception.class)
    @Override
    public String buyGoods(OrderBean orderBean) {
        //First query the version information in the database and the inventory > 0
        GoodsBean goodsBean = goodsMapper.getOneById(orderBean.getGoodsBean().getId());
        if(goodsBean.getStoreNum() > 0){
            int currentVersion = orderBean.getGoodsBean().getVersion() + 1;
            int dbVersion = goodsBean.getVersion();
            //When the inventory is > 0, judge whether the current version number is > the version number in the database
            if(currentVersion > dbVersion){
                //Update the data and return the number of rows affected
               int rows = goodsMapper.updateGoodsBean(goodsBean);
               if(rows > 0){
                   //Generate order
                   orderMapper.saveOrderBean(orderBean);
                   return "Congratulations on your successful purchase!!!";
               } else{
//                   throw new RuntimeException("hand speed is too slow, please operate again!!!");
                  boolean flag = reBuy(orderBean);
                  if (flag) return "Congratulations on your successful purchase!!!";else return "You are cold and the goods have been sold out!";
               }
            }else{
//                throw new RuntimeException("hand speed is too slow, please operate again!!!");
                boolean flag = reBuy(orderBean);
                if (flag) return "Congratulations on your successful purchase!!!";else return "You are cold and the goods have been sold out!";
            }
        }else{
            return "You are cold and the goods have been sold out!";
        }
    }
    /**
     * Buy again
     * @param orderBean
     * @return true Indicates that the purchase is successful, and false indicates that the goods have been sold out
     */
    public boolean reBuy(OrderBean orderBean){
        GoodsBean goodsBean = goodsMapper.getOneById(orderBean.getGoodsBean().getId());
        if(goodsBean.getStoreNum() > 0){
            int rows = goodsMapper.updateGoodsBean(goodsBean);
            //Judge whether the submission is successful
            if(rows > 0){
                //Generate order
                orderMapper.saveOrderBean(orderBean);
                return true;
            } else{
                reBuy(orderBean);
            }
        }else{
            return false;
        }
        return false;
    }
}

In the log aspect, a new method of defining pointcuts is used, which is defined by annotations.

@Annotation means to use annotation, which must be defined above the method.

@within indicates the use of annotations, which must be defined above the class.

SpringMVC

MVC

1. Model, view, controller

2. It is a kind of architecture pattern and an architecture pattern of presentation layer.

3. MVC source (Development): HTML (information display of enterprise websites) - > CGI (public gateway interface, which is a process level technology, so it consumes a lot of resources) - > servlet ----- > JSP (view display + controller) + MODEL(JavaBean). This stage is called WEB layer architecture mode phase I ----- > WEB layer architecture mode phase II (MVC).

MVC benefits:

1. The coupling relationship of loose presentation layer adopts the form of classification and attention of three modules to loose the relationship of presentation layer. For example:

MODEL only focuses on data transmission and the realization of business functions;

View (VIEM) only focuses on the display of the page;

The Controller only focuses on the receipt of the request and the return of the response of the page.

2. Low cost and fast deployment. Programmers only need to pay attention to Java code, not the front end. The front and rear ends are deployed separately and do not interfere with each other.

3. High maintainability, because MVC is 3 modules, which are independent of each other, so they can be maintained separately.

Spring MVC definition

It is a presentation layer framework under MVC architecture mode.

Like Servlet, it follows the request response mode;

Similarly, the HTTP communication protocol is used to complete the data interaction between the front and back ends.

Request response pattern definition

Controller, in the previous two phases, your Servlet assumed this role.

Servlet defect

1. Relying too much on Servlet API, it is mandatory to inherit HTTPServlet;

2. Relying too much on tomcat container leads to very troublesome development or testing;

3. Too dependent on specific pages, remember, for example: jsp;

But now in this framework, it perfectly solves the above problems.

Spring MVC controller

1. Core (front-end controller)

The controller is located at the front end of the whole framework. It is actually a Servlet. Its function is:

(1) Receive the request of the page;

(2) Dispatch requests to different controllers;

2. Application controller

Processing mapper, view parser, file upload parser, processing adapter

These application controllers are provided by spring MVC and do not require programmer operation. Each of them has its own responsibility:

(1) Process mapper: complete the mapping relationship between the page request and the page controller, which is equivalent to what @ WebServlet does;

(2) View parser: complete the back-end parsing task of returning the view name to the specific view resources;

(3) File upload parser: complete the task of file upload;

(4) Processing adapter: complete the adaptation relationship between the page request and the page controller.

In addition to adopting MVC, the spring MVC framework also adopts a mode called "service to worker". Every step of the request reaching the framework, there is a Controller to complete the corresponding task.

3. Page controller

Detailed architecture diagram of spring MVC (key points)

Execution process of spring MVC framework:

Steps:

1. The front end gives up the HTTP request and goes to the core controller.

2. The core controller forwards the request to the processing mapper and inquires about the mapping relationship (some return the relationship and none return 404);

3. The core controller forwards the request to the processing adapter to do the adaptation work;

4. After the adaptation, the request will be forwarded to the page controller to process the business process and return to ModelAndView;

5. When the response reaches the core controller, the core controller gives the viewName in ModelAndView to the view parser to parse it into real view resources;

6. The core controller fills and renders the Model data to the real view resources;

7. The core controller returns the rendered view to the front end for display.

Getting started with spring MVC framework (configuration version - understand)

Log in to the home page!!!

Import dependency

<dependencies>
    <!-- Import springmvc Framework related JAR package -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.2.9.RELEASE</version>
    </dependency>
    <!-- Lombok Introduction of -->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.12</version>
      <scope>provided</scope>
    </dependency>
    <!-- introduce Servlet API -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

Spring MVC validation

Format validation

Judge whether an input box has a value, whether an input has a telephone number, and whether an input has an ID card (you can rely on js + regular expression);

Content verification

Judge whether an account already exists (by JS + backend server).

Note: the validation of spring MVC belongs to format validation.

Spring MVC validation

As a content of understanding upward, (depending on the situation of the company)

Spring MVC itself does not have any verification framework. It adopts the verification framework of Hibernate

Hibernate framework is a pure object-oriented framework. All its operations are completed for Bean objects, so the verification here can also be called Bean Validate

Specific use

1. Import Hibernate authentication dependency

<!-- Import hibernate Validation framework -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.4.1.Final</version>
        </dependency>

2. Modify spring MVC XML, so that the spring MVC framework supports Hibernate authentication services.

<!--open SpringMVC Annotation driven support for framework-->
    <mvc:annotation-driven conversion-service="conversionServiceFactoryBean" validator="localValidatorFactoryBean"></mvc:annotation-driven>
    <!--to configure Spring Framework validation factory-->
    <bean id="localValidatorFactoryBean" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
        <!--Configure authentication service: Hibernate Framework provision-->
        <property name="providerClass" value="org.hibernate.validator.HibernateValidator"></property>
    </bean>

3. Use annotations to validate Bean format constraints.

Note: please refer to for more specifications( https://docs.jboss.org/hibernate/validator/5.4/reference/en-US/html_single/#section-builtin-constraints).

package com.woniuxy.springmvc.bean;
import lombok.Data;
import org.hibernate.validator.constraints.NotEmpty;
import javax.validation.constraints.*;
import java.io.Serializable;
import java.util.Date;
@Data
public class UserBean implements Serializable {
    private Long id;
    @NotNull(message = "User name cannot be null null!")
    @NotEmpty(message = "User name must have value!")
    @Size(min = 2,max = 8,message = "Length of user name:[2,8]Bit!")
    private String userName;
    @NotEmpty(message = "Login name must have value!")
    @Size(min = 6,max = 8,message = "Length of login name:[6,8]Bit!")
    private String loginName;
    @NotEmpty(message = "Password must have value!")
    @Size(min = 6,max = 12,message = "Password length:[6,12]Bit!")
    private String password;
    @Max(value = 60,message = "Too old to register!")
    @Min(value = 18,message = "Minors, can not register!")
    private Integer age;
    /**
     * Marriage or not
     */
    @AssertFalse(message = "Your uncle's, you are married, still come?")
    private boolean marray;
    /**
     * personal income
     */
    @Digits(integer = 10,fraction = 2,message = "You have too much money. Don't blow it NB It's over!")
    @Min(value = 50000,message = "Ask your parents for more money, or come to snail training for a period of time!")
    private double income;
    /**
     * Personal hobbies
     */
    private String[] hobbys;
    /**
     * date of birth
     */
    @Past(message = "Unborn baby, fuck off!")
    private Date birthday;
}

4. Writing method of page controller

package com.wnxy.springmvc.controller;

import com.wnxy.springmvc.bean.UserBean;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.validation.Valid;
import java.util.List;

@Controller
@RequestMapping("/user")
public class UserController {

    @RequestMapping(value = "/register")
    public String register(UserBean userBean){
        System.out.println(userBean);
        return "sysmag/main";
    }

    /**
     * springMVC verification
     * @param userBean
     * @param result Judge the verification results
     * @return
     * @param model
     */
    @RequestMapping(value = "/validator")
    public String validator(@Validated UserBean userBean, BindingResult result, Model model){
        //Determine whether the format is wrong
        if(result.hasErrors()){
            List<ObjectError> errs = result.getAllErrors();//Get all errors
            //What attribute errors are entered, what errors are made, and what prompt codes are there (lamba expression)
            errs.forEach((e)->{
                System.out.println(e.getObjectName());
                System.out.println(e.getDefaultMessage());
                System.out.println(e.getCode());
            });

            //If there is an error, go to the error page
            model.addAttribute("errs",errs);
            return "validator";
        }
        //Registration is successful. Return to the login page
        System.out.println(userBean);
        return "index";
    }
}

Json

How to handle JSON data when front and back ends are separated

Front end and back-end interaction: data format is adopted, and the common ones are XML and JSON;

Ready made JSON framework: Jackson (default support) fastjason (Alibaba);

1. Import JSON dependencies

<!-- introduce Json Tool class for Jar package -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.11.1</version>
        </dependency>

2. Write JSON JSP page

Jquery-1.8.3 Min.js is placed in webapp/static/js Directory:

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2020/11/23
  Time: 14:15
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@include file="header.jsp"%>
<html>
<head>
    <title>Title</title>
    <script type="text/javascript" src="static/js/jquery-1.8.3.min.js"></script>
    <script>
        /*Code to be executed after the page is loaded*/
        $(function () {
            $('#btn01').click(function () {
                /*Send Ajax request*/
                $.ajax({
                    type: "POST",
                    url: "stus/add",
                    data: {
                        stuName:"Yihu",
                        stuNo:"4578",
                        age:"50"
                    },
                    success: function(msg){
                       console.info(msg);
                    }
                });
            });
        });
    </script>
</head>
<body>
    <button id="btn01">newly added</button>
    <button></button>
    <button></button>
</body>
</html>

3. In mvc-spring Freeing static resources in XML

<!--Release static resources-->
    <mvc:resources mapping="/static/**" location="/static/"></mvc:resources>

4. Writing JavaBean s

package com.woniuxy.springmvc.bean;
import lombok.Data;
import java.io.Serializable;
@Data
public class StudentBean implements Serializable {
    private Long id;
    private String stuName;
    private String stuNo;
    private Integer age;
}

5. Object return authoring

package com.woniuxy.springmvc.bean;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import java.io.Serializable;
@Data
@NoArgsConstructor
@RequiredArgsConstructor
public class ResultMsg<T> implements Serializable {
    /**
     * Status code
     */
    @NonNull
    private String code;
    /**
     * Prompt information
     */
    @NonNull
    private String msg;
    /**
     * Return to user data
     */
    private T data;
}

6. Write page controller

@ResponseBody The function of is to complete the serialization operation from back-end Java objects to JSON objects through MappingJackson2HttpMessageConverter. The serialized results are transmitted through the response body.

package com.woniuxy.springmvc.controller;
import com.woniuxy.springmvc.bean.ResultMsg;
import com.woniuxy.springmvc.bean.StudentBean;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@RequestMapping("stus")
@Controller
public class StudentController {
    /**
     * New students
     * But don't jump to the page
     * @param studentBean
     * @return
     *
     *  @ResponseBody Function: serialize Java objects into JSON objects
     *  And complete the data transmission through the response body
     */
    @RequestMapping(value="/add",produces = {"application/json;charset=utf-8"})
    @ResponseBody
    public ResultMsg saveStudentBean(StudentBean studentBean){
        ResultMsg resultMsg = new ResultMsg("200","Saved successfully");
        System.out.println(studentBean);
        return resultMsg;
    }
}

7. Send JSON data from the front end

You need to introduce jquery.xml under webapp/static/js json. js

8. Modify JSON JSP page

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2020/11/23
  Time: 14:15
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@include file="header.jsp"%>
<html>
<head>
    <title>Title</title>
    <script type="text/javascript" src="static/js/jquery-1.8.3.min.js"></script>
    <script type="text/javascript" src="static/js/jquery.json.js"></script>
    <script>
        /*Code to be executed after the page is loaded*/
        $(function () {
            //Back end response JSON data
            $('#btn01').click(function () {
                /*Send Ajax request*/
                $.ajax({
                    type: "POST",
                    url: "stus/add",
                    data: {
                        stuName:"Yihu",
                        stuNo:"4578",
                        age:"50"
                    },
                    success: function(msg){
                       console.info(msg);
                    }
                });
            });
            //Send JSON data from the front end
            $('#btn02').click(function () {
                var user = {
                    stuName:"Yihu",
                    stuNo:"4578",
                    age:"50"
                };
                //Convert JS object to JSON object
                var json = $.toJSON(user);
                /*Send Ajax request*/
                $.ajax({
                    type: "POST",
                    url: "stus/update",
                    contentType:"application/json;charset=utf-8",//Tell the backend that the data passed is JSON
                    data: json,
                    success: function(msg){
                        console.info(msg);
                    }
                });
            });
        });
    </script>
</head>
<body>
    <button id="btn01">newly added(return JSON)</button>
    <button id="btn02">newly added(send out&return JSON)</button>
    <button></button>
</body>
</html>

9. Modify the page controller and use @ RequestBody to receive JSON data

@RestController === @ResponseBody + @Controller
@RequestBody Complete the conversion from page JSON data to back-end Java object data through MappingJackson2HttpMessageConverter.

package com.woniuxy.springmvc.controller;
import com.woniuxy.springmvc.bean.ResultMsg;
import com.woniuxy.springmvc.bean.StudentBean;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("stus")
@RestController  //@ResponseBody + @Controller
public class StudentController {
    /**
     * Modify student
     * @param studentBean
     * @return
     * @RequestBody Function: deserialize the JSON object in the message body into a Java object
     */
    @RequestMapping(value="/update",produces = {"application/json;charset=utf-8"})
    public ResultMsg updateStudentBean(@RequestBody StudentBean studentBean){
        ResultMsg resultMsg = new ResultMsg("200","Saved successfully");
        System.out.println(studentBean);
        return resultMsg;
    }
    /**
     * New students
     * But don't jump to the page
     * @param studentBean
     * @return
     *
     *  @ResponseBody Function: serialize Java objects into JSON objects
     *  And complete the data transmission through the response body
     */
    @RequestMapping(value="/add",produces = {"application/json;charset=utf-8"})
    public ResultMsg saveStudentBean(StudentBean studentBean){
        ResultMsg resultMsg = new ResultMsg("200","Saved successfully");
        System.out.println(studentBean);
        return resultMsg;
    }
}

PostMan postman

After the front and back ends are separated, the front end is not the task of Java programmers. You don't need to write pages? How do you test your interface?

Postman is a testing tool that can simulate a page to complete the sending of HTTP requests.

Double click Run and skip login!

Send get request:

Send Post request (form data):

Send Post request (JSON data):

Rest FUL style

Rest ful (representative state transfer) descriptive state transfer style

This style is neither a technology nor a framework. It is just a change in the way of submission

Previously, you can only use GET/POST submission for resource operations: users/add users/update users/delete

HTTP protocol: the protocol provides N ways to CRUD resources

URI (Universal Resource Identifier): uniform resource identifier. Function: use the name to identify resources uniformly and uniquely

summary

In 2000, it was proposed by Roy Fielding, the manufacturer of HTTP protocol

Resources: in real life, we can make a nominal description of everything!
Resources can be large or small, and they can be in a certain set or group: for example, users orders goods

Small can also be reduced to a specific thing, such as users/1 orders/2020-11-23/9856
users / Zhang San / 18 / female

How to describe resources? The answer is: use URI

How to operate resources

Four standard methods of HTTP:
GET: the query of resources is yes or no
POST: adding resources from scratch
PUT: the modification of resources is yes
DELETE: the deletion of resources is always null

Idempotency: that is, the results of one request or multiple requests initiated by the user for the same operation are consistent.
GET PUT DELETE

POST non idempotent

Descriptive state transition: the transition is the state of the resource

Why do I need to use Rest Full

1. Projects that facilitate the separation of front and back ends (no matter what type of front end is, the back end only provides a unified access entrance)
2. There is only one interface for the same resource
3. It is convenient for server cluster (after the horizontal expansion of tomcat, it is the same to obtain data in Tomcat)

Implementation steps

1. First define the RestController interface

package com.woniuxy.springmvc.controller;
import com.woniuxy.springmvc.bean.ResultMsg;
import com.woniuxy.springmvc.bean.StudentBean;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@RequestMapping("students")
@RestController
public class RestFulController {
    /**
     * newly added
     * @param studentBean
     * @return
     */
    @PostMapping(value = "/more",produces = {"application/json;charset=utf-8"})
    public ResultMsg saveStudentBean(StudentBean studentBean){
        ResultMsg resultMsg = new ResultMsg("200","Operation successful");
        System.out.println(studentBean);
        return resultMsg;
    }
    /**
     * front end: http://localhost:8080/mvc/students/1 Students / 2 1 2 stands for id
     *
     * modify
     * @param studentBean
     * @param id
     * @return
     */
    @PutMapping(value="/{id}",produces = {"application/json;charset=utf-8"})
    public ResultMsg updateStudentBean(StudentBean studentBean,@PathVariable("id") Long id){
        ResultMsg resultMsg = new ResultMsg("200","Operation successful");
        System.out.println(studentBean);
        return resultMsg;
    }
    /**
     * delete
     * @param id
     * @return
     */
    @DeleteMapping(value="/{id}",produces = {"application/json;charset=utf-8"})
    public ResultMsg deleteStudentBean(@PathVariable("id") Long id){
        ResultMsg resultMsg = new ResultMsg("200","Operation successful");
        System.out.println(id);
        return resultMsg;
    }
    /**
     * query
     * @param id
     * @return
     */
    @GetMapping(value="/{id}",produces = {"application/json;charset=utf-8"})
    public ResultMsg getStudentBeanById(@PathVariable("id") Long id){
        ResultMsg resultMsg = new ResultMsg("200","Operation successful");
        System.out.println(id);
        StudentBean studentBean = new StudentBean();
        studentBean.setStuName("waiter");
        resultMsg.setData(studentBean);
        return resultMsg;
    }
    /**
     *  uri === students/all/Zhang San / 18 / 4578
     * @param stuName
     * @return
     */
    @GetMapping(value="/all/{stuName}/{age}/{stuNo}",produces = {"application/json;charset=utf-8"})
    public ResultMsg findAllStudents(@PathVariable("stuName") String stuName,
                                     @PathVariable("age")Integer age,
                                     @PathVariable("stuNo") String stuNo){
        ResultMsg resultMsg = new ResultMsg("200","Operation successful");
        System.out.println(stuName);
        System.out.println(age);
        System.out.println(stuNo);
        StudentBean studentBean = new StudentBean();
        studentBean.setStuName("waiter");
        StudentBean studentBean02 = new StudentBean();
        studentBean02.setStuName("waiter");
        List<StudentBean> datas = new ArrayList<>();
        Collections.addAll(datas,studentBean,studentBean02);
        //Transfer the collection to the data return object and return to the page
        resultMsg.setData(datas);
        return resultMsg;
    }
}

2. On the web It is configured in XML and supports PUT and DELETE request filters (it supports data transmission in form mode);

<!-- solve PUT,DELETE A filter that cannot pass data using the message body -->
  <!-- From: spring-web.jar -->
  <filter>
    <filter-name>formContentFilter</filter-name>
    <filter-class>org.springframework.web.filter.FormContentFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>formContentFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

3. Write restful JSP page to complete the interaction of front and rear data

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2020/11/23
  Time: 14:15
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@include file="header.jsp"%>
<html>
<head>
    <title>Title</title>
    <script type="text/javascript" src="static/js/jquery-1.8.3.min.js?version=1.1"></script>
    <script type="text/javascript" src="static/js/jquery.json.js?version=1.0"></script>
    <script>
        /*Code to be executed after the page is loaded*/
        $(function () {
            //Query students by name
            $('#btn05').click(function () {
                /*Send Ajax request*/
                $.ajax({
                    type: "GET",
                    url: "students/all/Zhang San/18/4578",
                    success: function(msg){
                        console.info(msg);
                    }
                });
            });
            //Query data by ID
            $('#btn04').click(function () {
                /*Send Ajax request*/
                $.ajax({
                    type: "GET",
                    url: "students/1",
                    success: function(msg){
                        console.info(msg);
                    }
                });
            });
            //delete
            $('#btn03').click(function () {
                /*Send Ajax request*/
                $.ajax({
                    type: "DELETE",
                    url: "students/1",
                    success: function(msg){
                        console.info(msg);
                    }
                });
            });
            //modify
            $('#btn02').click(function () {
                /*Send Ajax request*/
                $.ajax({
                    type: "PUT",
                    url: "students/1",
                    data: {
                        stuName:"Yihu",
                        stuNo:"4578",
                        age:"50"
                    },
                    success: function(msg){
                        console.info(msg);
                    }
                });
            });
            //newly added
            $('#btn01').click(function () {
                /*Send Ajax request*/
                $.ajax({
                    type: "POST",
                    url: "students/more",
                    data: {
                        stuName:"Yihu",
                        stuNo:"4578",
                        age:"50"
                    },
                    success: function(msg){
                       console.info(msg);
                    }
                });
            });
        });
    </script>
</head>
<body>
    <button id="btn01">New students</button>
    <button id="btn02">Modify student</button>
    <button id="btn03">Delete student</button>
    <button id="btn04">according to ID Query students</button>
    <button id="btn05">Query students by name</button>
</body>
</html>

Exception handling

How to handle exceptions in the past: throw and grab.

How to handle exceptions

All anomalies: the bottom layer in turn, throw to the upper layer, and throw until the performance layer. Adopt AOP aspect to handle exceptions in a unified way (instead of throwing the exception directly to the page, the exception is converted into friendly prompt information, for example, the current system is busy, please try again later.)

Exception: problems thrown out during the development and operation of the system.

Each layer may throw exceptions. The bottom layer should not catch exceptions. On the contrary, it should constantly throw them upward until they reach the performance layer.

Note: exceptions cannot be thrown on the page.

Tomcat container handling system exception

System abnormality: 405, 404, 403, 400;

405: method is not allowed;

404: resource not found;

400: parameter error;

403: no authorization;

Solve the status code error message prompted by the system

Solution steps:

1. Write the error page corresponding to the status code;

2. On the web Configure error page prompt information in XML.

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2020/11/24
  Time: 10:29
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    Request method error, please contact the administrator!(Miss Pu 13398199549)
</body>
</html>

The spring MVC framework handles exceptions

1. Handling exceptions using xml configuration files (understand)

<!--Configure exception parser-->
    <bean id="simpleMappingExceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
      <!--Default exception page-->
      <property name="defaultErrorView" value="errors/exception"></property>
      <!--On the exception page, you can use ex To get the data-->
      <property name="exceptionAttribute" value="ex"></property>
      <property name="exceptionMappings">
          <props>
              <!--Exception, corresponding page-->
              <prop key="java.lang.NullPointerException">errors/npException</prop>
              <!--If there is anything else, continue-->
          </props>
      </property>
    </bean>

Use AOP aspect programming idea to solve problems (Master)

The first scheme: display the exception information in the exception page;

The second scheme: do not display exception information in the exception page.

Note: choose one of two schemes. If defined at the same time, the first scheme will overwrite the second scheme.

1. The first scheme (suitable for page skipping system)

Exception page:

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2020/11/24
  Time: 10:46
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    This is SpringMVC The default exception page of the framework. The exceptions thrown are: ${ex}
</body>
</html>

For the exception part, use @ ControllerAdvice + @ExceptionHandler:

package com.woniuxy.springmvc.exception;
import com.woniuxy.springmvc.bean.ResultMsg;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
@ControllerAdvice
public class ExceptionHanlder {
    /**
     * @ExceptionHandler Mark the following method, which is an exception handling method
     * @param e
     * @return
     */
    @ExceptionHandler
    public ModelAndView hanlder(Exception e){
        ResultMsg msg = new ResultMsg("10000","unknown error");
        ModelAndView mv = new ModelAndView();
        if(e instanceof NullPointerException){
            msg.setCode("10001");
            msg.setMsg("The system is busy, please try again later!");
        }
        //Next, you can continue to judge the types of exceptions and modify the prompt information
        mv.addObject("ex",msg);
        mv.setViewName("errors/exception");
        return mv;
    }
}

2. The second scheme (there is no jump page, which is applicable to the system with separate front and rear ends)

Note: the exception page is the same as the first scheme.

Use @ RestControllerAdvice + @Exception:

package com.woniuxy.springmvc.exception;
import com.woniuxy.springmvc.bean.ResultMsg;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
 * Don't jump to page
 */
@RestControllerAdvice
public class ExceptionHanlder {
    @ExceptionHandler
    public ResultMsg hanlder(Exception e){
        ResultMsg msg = new ResultMsg("10000","unknown error");
        if(e instanceof NullPointerException){
            msg.setCode("10001");
            msg.setMsg("The system is busy, please try again later!");
        }
        //Continue to make abnormal judgment
        return msg;
    }
}

Summary: the idea of handling exceptions in spring MVC framework: it is completed by using AOP aspect oriented idea, and its entry point is defined on the method of Controller.

Spring MVC framework is a little (interview question)

1. Spring MVC adopts the MVC architecture mode and the service to worker architecture mode. Through a variety of built-in components, the presentation layer is more clearly defined and the page control is more refined.

2. Since Spring MVC is the MVC module function among the seven functions of the Spring framework, it naturally supports the Spring framework.

3. Although there are many configurations of spring MVC, they are relatively simple and independent (you can choose what you need).

4. The code is highly reusable (usually the configuration file of spring MVC, which hardly supports the configuration of any system).

{
console.info(msg);
}
});
});
//Add
$('#btn01').click(function () {
/Send Ajax request/
$.ajax({
type: "POST",
url: "students/more",
data: {
stuName: "Yihu",
stuNo:"4578",
age:"50"
},
success: function(msg){
console.info(msg);
}
});
});
});

Add student modify student delete student query student by ID query student by name```

Exception handling

How to handle exceptions in the past: throw and grab.

How to handle exceptions

All anomalies: the bottom layer in turn, throw to the upper layer, and throw until the performance layer. Adopt AOP aspect to handle exceptions in a unified way (instead of throwing the exception directly to the page, the exception is converted into friendly prompt information, for example, the current system is busy, please try again later.)

Exception: problems thrown out during the development and operation of the system.

Each layer may throw exceptions. The bottom layer should not catch exceptions. On the contrary, it should constantly throw them upward until they reach the performance layer.

Note: exceptions cannot be thrown on the page.

Tomcat container handling system exception

System abnormality: 405, 404, 403, 400;

405: method is not allowed;

404: resource not found;

400: parameter error;

403: no authorization;

[external chain picture transferring... (img-WH8FCF2V-1607306797675)]

Solve the status code error message prompted by the system

Solution steps:

1. Write the error page corresponding to the status code;

2. On the web Configure error page prompt information in XML.

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2020/11/24
  Time: 10:29
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    Request method error, please contact the administrator!(Miss Pu 13398199549)
</body>
</html>

The spring MVC framework handles exceptions

1. Handling exceptions using xml configuration files (understand)

<!--Configure exception parser-->
    <bean id="simpleMappingExceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
      <!--Default exception page-->
      <property name="defaultErrorView" value="errors/exception"></property>
      <!--On the exception page, you can use ex To get the data-->
      <property name="exceptionAttribute" value="ex"></property>
      <property name="exceptionMappings">
          <props>
              <!--Exception, corresponding page-->
              <prop key="java.lang.NullPointerException">errors/npException</prop>
              <!--If there is anything else, continue-->
          </props>
      </property>
    </bean>

Use AOP aspect programming idea to solve problems (Master)

The first scheme: display the exception information in the exception page;

The second scheme: do not display exception information in the exception page.

Note: choose one of two schemes. If defined at the same time, the first scheme will overwrite the second scheme.

1. The first scheme (suitable for page skipping system)

Exception page:

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2020/11/24
  Time: 10:46
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    This is SpringMVC The default exception page of the framework. The exceptions thrown are: ${ex}
</body>
</html>

For the exception part, use @ ControllerAdvice + @ExceptionHandler:

package com.woniuxy.springmvc.exception;
import com.woniuxy.springmvc.bean.ResultMsg;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
@ControllerAdvice
public class ExceptionHanlder {
    /**
     * @ExceptionHandler Mark the following method, which is an exception handling method
     * @param e
     * @return
     */
    @ExceptionHandler
    public ModelAndView hanlder(Exception e){
        ResultMsg msg = new ResultMsg("10000","unknown error");
        ModelAndView mv = new ModelAndView();
        if(e instanceof NullPointerException){
            msg.setCode("10001");
            msg.setMsg("The system is busy, please try again later!");
        }
        //Next, you can continue to judge the types of exceptions and modify the prompt information
        mv.addObject("ex",msg);
        mv.setViewName("errors/exception");
        return mv;
    }
}

2. The second scheme (there is no jump page, which is applicable to the system with separate front and rear ends)

Note: the exception page is the same as the first scheme.

Use @ RestControllerAdvice + @Exception:

package com.woniuxy.springmvc.exception;
import com.woniuxy.springmvc.bean.ResultMsg;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
 * Don't jump to page
 */
@RestControllerAdvice
public class ExceptionHanlder {
    @ExceptionHandler
    public ResultMsg hanlder(Exception e){
        ResultMsg msg = new ResultMsg("10000","unknown error");
        if(e instanceof NullPointerException){
            msg.setCode("10001");
            msg.setMsg("The system is busy, please try again later!");
        }
        //Continue to make abnormal judgment
        return msg;
    }
}

Summary: the idea of handling exceptions in spring MVC framework: it is completed by using AOP aspect oriented idea, and its entry point is defined on the method of Controller.

Spring MVC framework is a little (interview question)

1. Spring MVC adopts the MVC architecture mode and the service to worker architecture mode. Through a variety of built-in components, the presentation layer is more clearly defined and the page control is more refined.

2. Since Spring MVC is the MVC module function among the seven functions of the Spring framework, it naturally supports the Spring framework.

3. Although there are many configurations of spring MVC, they are relatively simple and independent (you can choose what you need).

4. The code is highly reusable (usually the configuration file of spring MVC, which hardly supports the configuration of any system).

5. Extensibility (spring MVC is still a free and open source product. If the function is not enough, you can modify its source code).

Posted by sulin on Tue, 03 May 2022 11:39:26 +0300