659-669spring integrated MVC

Posted by jspodisus on Tue, 04 Jan 2022 20:27:26 +0100

659 login case database creation web project construction login page creation

Use Servlet+MVC+Mybatis+Jsp to complete user login

① Create t in mysql_ User user information table (id,name,pwd)

② Use idea to create a new web project named 01 spring IOC mybatis login

③ Import relevant jar packages in the web project (spring IOC jar+Mybatis jar+mysql jar)

④ Create login. In the web project JSP login page and send login request

Set jsp template!
<%
String path=request.getContextPath();
String basePath=request.getScheme()+"://"+request.getServerName()+":"+request
.getServerPort()+path+"/";
%>
...
<base href="<%=basePath%>">

<form action="userLogin" method="post">
    user name:<input type="text" name="uname" value=""><br/>
    password:<input type="password" name="pwd" value=""><br/>
    <input type="submit"  value="Sign in">
</form>

660 complete implementation of login function

⑤ Create UserServlet in the web project and improve the code to handle login requests

package com.bjsxt.controller;

import com.bjsxt.pojo.User;
import com.bjsxt.service.UserService;
import com.bjsxt.service.impl.UserServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet("/userLogin")
public class UserServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //Format request encoding
        req.setCharacterEncoding("utf-8");
        //Set response encoding format
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        //Request data
        String uname = req.getParameter("uname");
        String pwd = req.getParameter("pwd");
        //Processing requests
            //Create business tier objects
        UserService userService = new UserServiceImpl();
        //Calling business layer methods
        User user = userService.userLoginService(uname, pwd);

        //Response results
            //Get session object
        HttpSession session = req.getSession();
        if(user!=null){
            session.setAttribute("user",user);
            resp.sendRedirect(req.getContextPath()+"/main.jsp");//Login succeeded
        }else {
            session.setAttribute("flag","loginFail");
            resp.sendRedirect(req.getContextPath()+"/login.jsp");//Login failed
        }
    }
}

⑥ Create UserService business in web project and improve code processing login business

package com.bjsxt.service;

import com.bjsxt.pojo.User;

import java.io.IOException;

public interface UserService {
    User userLoginService(String uname, String pwd) throws IOException;
}
package com.bjsxt.service.impl;

import com.bjsxt.mapper.UserMapper;
import com.bjsxt.pojo.User;
import com.bjsxt.service.UserService;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class UserServiceImpl implements UserService {
    @Override
    public User userLoginService(String uname, String pwd) throws IOException {
        //Get sqlSession object
        InputStream is = Resources.getResourceAsStream("mybatis.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        //Get mapper interface instantiation object
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //Complete database query
        User user = mapper.userLoginMapper(uname, pwd);
        //return
        return user;
    }
}

⑦ Create UserMapper in the web project and improve the code to query user information according to user name and password

package com.bjsxt.mapper;

import com.bjsxt.pojo.User;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

public interface UserMapper {
    //User login
    @Select("select * from t_user where uname=#{uname} and pwd=#{pwd}")
    User userLoginMapper(@Param("uname") String uname,
                         @Param("pwd") String pwd);
}
login.jsp
<%
    String path = request.getContextPath();
    String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request
            .getServerPort() + path + "/";
%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
    <base href="<%=basePath%>">
</head>
<body>
<h3>Welcome to class 502</h3>
<hr/>
<c:if test="${sessionScope.flag=='loginFail'}">
    <font size="20px" color="red">Wrong user name or password</font>
</c:if>
<c:remove var="flag" scope="session"/>


<form action="userLogin" method="post">
    user name:<input type="text" name="uname" value=""><br/>
    password:<input type="password" name="pwd" value=""><br/>
    <input type="submit"  value="Sign in">
</form>
</body>
</html>

661 mybatis bottom layer analysis spring configuration data source bean

Question:

At present, in the process of developing functions, we will manually create SQLSession objects in the service layer and use SQLSession objects to obtain the instantiation objects of Mapper interface, but we really use the objects of Mapper interface. The current coding method greatly affects the development efficiency, and the coupling between mybatis layer and service layer is very high

solve:

Use Spring IOC technology to decouple the service layer and mybatis layer: in other words, let the Spring container help us obtain the instantiated object of Mapper layer interface, and we can directly obtain it from the Spring container for use

realization:

① Import the jar package of spring IOC

② Create and configure the Spring configuration file under src

mybatis.xml file content – io stream – > becomes a Configuration object - > Configuration has two stores 1 Database data 2 Mapper package scan path

DefaultSqlSessionFactory gets sqlSession from Configuration object!!!

Configure the bean of the DataSource data source

    <!--To create a data source bean-->
<!--    spring Rewritten dataSource because dataSource It's an interface-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/502?characterEncoding=utf8&amp;useSSL=false&amp;serverTimezone=UTC&amp;rewriteBatchedStatements=true"></property>
        <property name="username" value="root"></property>
        <property name="password" value="123456"></property>
    </bean>

662 applicationcontext configuration file configuration factory bean configuration mapper scan bean

Guide package mybatis-spring-2.0.2 The SQLSessionFactory jar is not mybatis, but a bridge between mybatis and spring

Configure the factory bean of SQLSessionFactory (the bean of datasource)

<!--establish SqlSessionFactory of bean-->
<bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"></property>
</bean>

Configure mapper to scan bean object (SQLSessionFactory object, scan path)

③ Create a Spring container object and obtain the instantiated object of Mapper interface to complete the database operation

<!--    to configure mapper scanning bean-->
    <bean id="mapper"
          class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.bjsxt.mapper"></property>
        <property name="sqlSessionFactory" ref="factory"></property>
    </bean>
package com.bjsxt.test;

import javafx.application.Application;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
//After the spring container object completes the creation of mybatis related objects, it will automatically call its
//After completing the mapper layer scanning, the scanning results will be displayed
//That is, the instantiated object of the interface is stored in spring again
//Resource key name in container object: the first letter of the default mapper class is lowercase!!!
public class TestSpring {
    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext(
                "applicationcontext.xml");
        //Returns the names of all key s in the spring container
        String[] names = ac.getBeanDefinitionNames();
        for(String name:names){
            System.out.println(name);
        }
    }
}
dataSource
factory
mapper
userMapper
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory

Process finished with exit code 0

663 servlet and decoupling implementation

The Controller layer uses Spring to decouple the service layer

Question:

It is implemented after the business layer uses the Spring container object to obtain the Mapper interface instantiation object

The service layer and mybatis layer are decoupled, but in the controller layer, we are still in the Servlet

Creating Service objects directly in is too coupling

solve:

Configure the service object as a bean object, and extract it from the Spring container in the Servlet

Get the Service object and complete the function development

realization:

① In ApplicationContext Configure the bean of the service in the XML file

<bean id="us" class="com.bjsxt.service.impl.UserServiceImpl" ></bean>

② Create a Spring container object in the service method in the servlet

③ Get the service object from the Spring container in the service method in the servlet

④ Use the service object to complete function processing

 ApplicationContext ac = new ClassPathXmlApplicationContext(
         "applicationcontext.xml");
UserService userService = (UserService) ac.getBean("us");
 //Calling business layer methods
 User user = userService.userLoginService(uname, pwd);

Analysis of resource proportion in 664 SM integration

Question:

In the current integration, after receiving the request, tomcat service will create a thread to process the request, and each thread runs independently of each other The process is as follows:

① The browser initiates a login request

② The tomcat server obtains the request and creates a new thread to process the request

③ Call the service method in the requested Servlet object

If 10 users initiate a login request, tomcat will create 10 threads to process the request Each thread needs to call the service method of UserServlet, and the method call depends on the instantiation object of UserServlet. Then each thread creates a UserServlet object, or is there only one UserServlet object, but it is shared and used by 10 threads?

If we operate in a single thread and call the service method of UserServlet object for 10 consecutive times, the code is as follows:

UserServlet us=new UserServlet()

us.service();

us.service();

us.service();

us.service();

...

In this code, we can declare 10 threads, and each thread runs us independently service(). It is concluded that when tomcat creates a thread to process a request, the Servlet object will only be created once, and the Servlet object is shared by multiple threads So when was the Servlet created?

By default, it is created at the first request and will not be re created in the future. If loadOnStartUp is configured, the initialization creation will be completed when the server starts

④ The service method in the Servlet is executed and the service method is put on the stack

Then create the spring container object, and a spring container object s1 will appear in the memory heap. When s1 is created, the spring configuration file will be loaded and the object (dataSource,factory,mapper,us) will be created according to the configuration file

⑤ Get the business layer object us in the Spring container

⑥ Calling the login business method of the us object

⑦ Logging in to the business method stack will create a new Spring container object s2,

When s2 is created, the Spring configuration file is loaded and parsed, and the bean objects of datasource, factory, US and mapper are created

⑧ Obtain the mapper object in the s2 container object in the business login method, complete the database operation, execute the business processing, log in the business method, complete the processing, return the result to the service method of the controller, and then the business method is out of the stack

⑨ After the service method of the servlet obtains the return value of the business layer, it continues to process, and then responds to the processing result to the browser. The service method ends, the service method comes out of the stack, the request is processed, and the thread is destroyed

Through the above process, it is found that in the current code structure, there will be 10 objects other than Servlet objects in a thread. Once highly concurrent access, it will cause a great waste of memory resources and cause the project to crash

665 SM optimization 1

The userMapper dependency of the mapper layer is injected into the UserServiceImpl class!

C in B - Dynamic factory mode

A - > b!!!

solve:

realization:

① Imported jar package:

② Create and configure ApplicationContext under src XML file

<!--Configure business layer bean-->
    <bean id="us" class="com.bjsxt.service.impl.UserServiceImpl" >
        <property name="userMapper" ref="userMapper"></property>
    </bean>

③ On the web The configuration file path to configure the Spring container object in the XML file

④ Load the initialization resources in the init method of the Servlet (get the business layer object from the Spring container object)

⑤ Declare the attributes of the mapper layer in the business layer and the corresponding get/set methods

⑥ Function development can be completed normally

UserServiceImpl
package com.bjsxt.service.impl;

import com.bjsxt.mapper.UserMapper;
import com.bjsxt.pojo.User;
import com.bjsxt.service.UserService;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;
import java.io.InputStream;

public class UserServiceImpl implements UserService {
    //Declare mapper layer properties
    private UserMapper userMapper;

    public UserMapper getUserMapper() {
        return userMapper;
    }

    public void setUserMapper(UserMapper userMapper) {
        this.userMapper = userMapper;
    }

    //User login
    @Override
    public User userLoginService(String uname, String pwd) throws IOException {


        //Complete database query
        User user = userMapper.userLoginMapper(uname, pwd);
        //return
        return user;
    }
}

666 SM optimization 2

④ Load the initialization resources in the init method of the Servlet (get the business layer object from the Spring container object)

Just get the required UserServiceImpl class object!
 @WebServlet(value = "/userLogin",loadOnStartup = 1)
public class UserServlet extends HttpServlet {
//Declare variables to record business layer objects
private UserService userService;
 //Initialization method
 @Override
 public void init() throws ServletException {
     ApplicationContext ac = new ClassPathXmlApplicationContext(
             "applicationcontext.xml");
      userService = (UserService) ac.getBean("us");
     
 }
    ...
}

667 SM optimization 3

applicationcontext.xml is dead!!

Optimize the following code:

ApplicationContext ac = new ClassPathXmlApplicationContext(
        "applicationcontext.xml");
web.xml
<!--Configuring global parameters: logging spring Profile name-->
   <context-param>
       <param-name>contextConfigLocation</param-name>
       <param-value>classpath:applicationcontext.xml</param-value>
   </context-param>
<!--    Configure listener-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
public class UserServlet extends HttpServlet {
    //Declare variables to record business layer objects
   private UserService userService;
    //Initialization method
    @Override
    public void init() throws ServletException {
        ApplicationContext ac = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());

         userService = (UserService) ac.getBean("us");
    }

Process summary 668

All jar packages

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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--To create a data source bean-->
<!--    spring Rewritten dataSource because dataSource It's an interface-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/502?characterEncoding=utf8&amp;useSSL=false&amp;serverTimezone=UTC&amp;rewriteBatchedStatements=true"></property>
        <property name="username" value="root"></property>
        <property name="password" value="123456"></property>
    </bean>

    <!--establish SqlSessionFactory of bean-->
    <bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
<!--    to configure mapper scanning bean-->
    <bean id="mapper"
          class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.bjsxt.mapper"></property>
        <property name="sqlSessionFactory" ref="factory"></property>
    </bean>
<!--Configure business layer bean-->
    <bean id="us" class="com.bjsxt.service.impl.UserServiceImpl" >
        <property name="userMapper" ref="userMapper"></property>
    </bean>
</beans>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
        http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
           version="3.0">
<!--Configuring global parameters: logging spring Profile name-->
   <context-param>
       <param-name>contextConfigLocation</param-name>
       <param-value>classpath:applicationcontext.xml</param-value>
   </context-param>
<!--    Configure listener-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>
UserServlet
@Override
public void init() throws ServletException {
    ApplicationContext ac = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());

     userService = (UserService) ac.getBean("us");
}

669 process code implementation

1. Lead the package to build the package structure of src
2 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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--Configure data sources bean-->
    <bean id="dataSource"
          class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/502?characterEncoding=utf8&amp;useSSL=false&amp;serverTimezone=UTC&amp;rewriteBatchedStatements=true"></property>
        <property name="username" value="root"></property>
        <property name="password" value="123456"></property>
    </bean>
<!--   Configuration factory bean-->
    <bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
    </bean>
<!--    to configure mapper scanning bean-->
    <bean id="mapper" 
          class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.bjsxt.mapper"></property>
        <property name="sqlSessionFactory" ref="factory"></property>
    </bean>
<!--   Configure business layer bean-->
</beans>
3 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
        http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
           version="3.0">
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationcontext.xml</param-value>
</context-param>
    
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

Topics: Spring MVC