SSM integration -- crazy God said Java learning notes

Keywords: Java Eclipse

SSM integration

Bili Bili crazy God says Java learning website
The article is only for sharing learning experience and reviewing. It is more effective to check the formal video website and official documents


Make a book query project using SSM framework

Simple core axis of the project

The eclips e development tool I use may be different from the anchor's operation

1, Environmental requirements

Environmental Science:

  • IDEA
  • MySQL 5.7.19
  • Tomcat 9
  • Maven 3.6

requirement:

  • Need to master MySQL database, Spring, JavaWeb and MyBatis knowledge, simple front-end knowledge;

2, Database environment

Create a database table for storing book data

CREATE DATABASE `ssmbuild`;
 
USE `ssmbuild`;
 
DROP TABLE IF EXISTS `books`;
 
CREATE TABLE `books` (
  `bookID` INT(10) NOT NULL AUTO_INCREMENT COMMENT 'book id',
  `bookName` VARCHAR(100) NOT NULL COMMENT 'title',
  `bookCounts` INT(11) NOT NULL COMMENT 'quantity',
  `detail` VARCHAR(200) NOT NULL COMMENT 'describe',
  KEY `bookID` (`bookID`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
 
INSERT  INTO `books`(`bookID`,`bookName`,`bookCounts`,`detail`)VALUES 
(1,'Java',1,'From getting started to giving up'),
(2,'MySQL',10,'From deleting the library to running away'),
(3,'Linux',5,'From entering the door to entering the prison');

90% of programmers' business is CRUD (addition, deletion, modification and query)

3, Basic environment construction

Maven basic project needs to complete at least two things, dependency and static resource export.

Dependency:

  • junit
  • Database driven
  • Connection pool
  • servlet
  • jsp
  • mybatis
  • mabattis-spring
  • spring

1. Create a new Maven project! ssmbuild, add web support

eclipse, create Maven web project

2. Import related pom dependencies!

<dependencies>
    <!--Junit-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <!--Database driven-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>
    <!-- Database connection pool -->
    <dependency>
        <groupId>com.mchange</groupId>
        <artifactId>c3p0</artifactId>
        <version>0.9.5.2</version>
    </dependency>
 
    <!--Servlet - JSP -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.2</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
 
    <!--Mybatis-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.2</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>2.0.2</version>
    </dependency>
 
    <!--Spring-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.1.9.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.1.9.RELEASE</version>
    </dependency>
</dependencies>

3. Maven resource filtering settings

<build>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>false</filtering>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>false</filtering>
        </resource>
    </resources>
</build>

4. Establish the basic structure and configuration framework!

  • com.kuang.pojo (data object prototype)

  • com.kuang.dao (connect data layer)

  • com.kuang.service (business logic layer)

  • com.kuang.controller (receiving the front business layer)

  • mybatis-config.xml (mybatis configuration file)

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
     
    </configuration>
    
  • applicationContext.xml (spring configuration file)

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

4, Written by Mybatis layer

1. Database configuration file database.properties

jdbc.driver=com.mysql.jdbc.Driver
# If you use MySQL 8.0 +, you need to add a time zone configuration& serverTimezone=Asia/Shanghai
jdbc.url=jdbc:mysql://localhost:3306/ssmbuild?useSSL=true&useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=123456

It is found here that the Chinese of eclipse's. properties file is garbled. Solution - 11.1

2. IDEA associated database

(I use the eclipse tool, but I can't find the method to associate the database. I'll study it later.)

3. Write the core configuration file for MyBatis

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    
    	<!-- Add log -->
	<settings>
		<setting name="logImpl" value="STDOUT_LOGGING"/>
	</settings>
    
	<!-- Configure the data source and give it to Spring Do it -->
	<typeAliases>
		<package name="com.kuang.pojo"/>
	</typeAliases>
	
	<mappers>
		<mapper resource="com/kuang/dao/BookMapper.xml"/>
	</mappers>
 
</configuration>

The teacher video uses: < mapper class = "com. Kuang. Dao. Bookmapper. XML" / >

But I can't find it using class, so I use resource

4. Write the entity class com.kuang.pojo.Books corresponding to the database

lombok dependency

But I use the eclips e tool. lombok can't be used directly. I'll study it later

<!-- Lombok -->
	<dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombpk</artifactId>
        <version>1.16.10</version>
    </dependency>
package com.kuang.pojo;
 
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
 
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Books {
    
    private int bookID;
    private String bookName;
    private int bookCounts;
    private String detail;
    
}

5. Write Mapper interface of Dao layer!

package com.kuang.dao;
 
import com.kuang.pojo.Books;
import java.util.List;
 
public interface BookMapper {
 
    //Add a Book
    int addBook(Books book);
 
    //Delete a Book by id
    int deleteBookById(@Param("bookId") int id);
 
    //Update Book
    int updateBook(Books books);
 
    //According to the id query, a Book is returned
    Books queryBookById(@Param("bookId") int id);
 
    //Query all books and return the list set
    List<Books> queryAllBook();
 
}

6. Write the Mapper.xml file corresponding to the interface. The package of MyBatis needs to be imported;

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kuang.dao.BookMapper">
    
	<insert id="addBook" parameterType="Books">
		insert into ssmbuild.books (bookName,bookCounts,detail) 
		values(#{bookName},#{bookCounts},#{detail});
	</insert>
	
	<delete id="deleteBookById" parameterType="int">
		delete from ssmbuild.books 
		where bookID=#{bookId};
	</delete>
	
	<update id="updateBook" parameterType="Books">
		update ssmbuild.books
		set bookName=#{bookName},bookCounts=#{bookCounts},detail=#{detail} 
		where bookID=#{bookId};
	</update>
	
	<select id="queryBookById" resultType="Books">
		select * from ssmbuild.books 
		where bookID=#{bookId};
	</select>
	
	<select id="queryAllBook" resultType="Books">
		select * from ssmbuild.books;
	</select>
	
	<!-- After entering, the first thing is to register the core configuration file -->
	
	
</mapper>

7. Write the interface and implementation class of Service business layer

Interface

package com.kuang.service;

import java.util.List;

import com.kuang.pojo.Books;

public interface BookService {
	
    //Add a Book
    int addBook(Books book);
 
    //Delete a Book by id
    int deleteBookById(int id);
 
    //Update Book
    int updateBook(Books books);
 
    //According to the id query, a Book is returned
    Books queryBookById(int id);
 
    //Query all books and return the list set
    List<Books> queryAllBook();	

}

Implementation class

package com.kuang.service;

import java.util.List;

import com.kuang.dao.BookMapper;
import com.kuang.pojo.Books;

public class BookServiceImpl implements BookService {
	//service business layer: dao layer: composite dao layer
	
	private BookMapper bookMapper;
	
	public void setBookMapper(BookMapper bookMapper) {
		this.bookMapper = bookMapper;
	}

	@Override
	public int addBook(Books book) {
		return bookMapper.addBook(book);
	}

	@Override
	public int deleteBookById(int id) {
		return bookMapper.deleteBookById(id);
	}

	@Override
	public int updateBook(Books books) {
		return bookMapper.updateBook(books);
	}

	@Override
	public Books queryBookById(int id) {
		return bookMapper.queryBookById(id);
	}

	@Override
	public List<Books> queryAllBook() {
		return bookMapper.queryAllBook();
	}

}

The core of the Mybatis layer is the simple action of writing the bottom layer, building the database, pojo data entity class, dao layer and service layer

5, Spring layer writing

1. Configure Spring to integrate MyBatis. Here, the data source uses c3p0 connection pool;

2. Let's write the configuration file related to Spring integration Mybatis; spring-dao.xml

There are many kinds of database connection pools

  • dbcp: semi-automatic operation, unable to connect automatically
  • c3p0: automatic operation (automatic loading of configuration files and automatic setting into objects)
  • druid
  • hikari
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       
       xmlns:context="http://www.springframework.org/schema/context"   
           
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        ">
        
        <!-- 1.Associated database profile -->
    	<context:property-placeholder location="classpath:database.properties"/>        
        
        <!-- 2.Database connection pool -->
   		<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        
        <!-- c3p0 Private properties of connection pool -->
        <property name="maxPoolSize" value="30"/>
        <property name="minPoolSize" value="10"/>
        <!-- Not automatically after closing the connection commit -->
        <property name="autoCommitOnClose" value="false"/>
        <!-- Get connection timeout -->
        <property name="checkoutTimeout" value="10000"/>
        <!-- Number of retries when getting connection failed -->
        <property name="acquireRetryAttempts" value="2"/>
 		
   		</bean>    

	    <!-- 3.to configure SqlSessionFactory object -->
	    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
	        <!-- Inject database connection pool -->
	        <property name="dataSource" ref="dataSource"/>
	        <!-- to configure MyBaties Global profile:mybatis-config.xml -->
	        <property name="configLocation" value="classpath:mybatis-config.xml"/>
	    </bean>
	    
	    <!-- 4.Configure scan Dao Interface package, dynamic implementation Dao Interface injection into spring In container -->
	    <!--Explanation: https://www.cnblogs.com/jpfss/p/7799806.html-->
	    
	    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
	        <!-- injection sqlSessionFactory -->
	        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
	        <!-- Give the information that needs to be scanned Dao Interface package -->
	        <property name="basePackage" value="com.kuang.dao"/>
	    </bean>

 
</beans>

3. Spring integration service layer

spring-service.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
    
    <!-- Can pass import relation
    	<import resource="classpath:spring-dao.xml"/>
    	You can also applicationContext.xml All in import relation
     -->
 
    <!-- 1.scanning service My bag -->
    <context:component-scan base-package="com.kuang.service" />
 
    <!-- 2.All our business classes, BookServiceImpl Inject into spring,It can be implemented through configuration or annotation-->
    <bean id="BookServiceImpl" class="com.kuang.service.BookServiceImpl">
        <property name="bookMapper" ref="bookMapper"/>
    </bean>
    <!-- 3.Configure transaction manager -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- Inject database connection pool data source -->
        <property name="dataSource" ref="dataSource" />
    </bean>
    <!-- Another word is 4.aop Transaction support -->
</beans>

You can also inject annotations into spring

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">
        
        <import resource="classpath:spring-dao.xml"/>
        <import resource="classpath:spring-service.xml"/>
 
</beans>

Spring layer done! Once again, spring is a hodgepodge, a container

6, Written by Spring MVC layer

1,web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.5" 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_2_5.xsd">

	<!-- DispatchServlet -->
	<servlet>
		<servlet-name>springmvc</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
            <!--Be careful:What we load here is the total configuration file, which was previously damaged here!--> 
			<param-value>classpath:spring-mvc.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
	</servlet-mapping>

	<!-- Random code filtering -->
	<filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>
            org.springframework.web.filter.CharacterEncodingFilter
        </filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
     </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!--Session Expiration time-->
    <session-config>
        <session-timeout>15</session-timeout>
    </session-config>
 
</web-app>

2,spring-mvc.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:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        ">
        
	<!-- 1.Annotation driven -->
	<mvc:annotation-driven/>
	<!-- 2.Static resource filtering -->
	<mvc:default-servlet-handler/>
	<!-- 3.Scan package: controller -->
	<context:component-scan base-package="com.kuang.controller"/>
	<!-- 4.view resolver  -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />      
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>

</beans>

3. Spring configuration integration file, 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">
        
        <import resource="classpath:spring-dao.xml"/>
        <import resource="classpath:spring-service.xml"/>
    	<import resource="classpath:spring-mvc.xml"/>
 
</beans>

Both acquisition methods can be used

<import resource="spring-dao.xml"/>

<import resource="spring-service.xml"/>

<import resource="spring-mvc.xml"/>

Most of these underlying businesses can be used in the future, and it is best to save them

Configuration file, end temporarily! Controller and view layer writing

7, Controller and view layer writing

1. First, write a simple code to test whether the back-end underlying code is correct

1.1. It is written by com.kuang.controller.BookController class. Method 1: query all books

package com.kuang.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.kuang.pojo.Books;
import com.kuang.service.BookService;

@Controller
@RequestMapping("/book")
public class BookController {
	//Controller service layer
	@Autowired
	@Qualifier("BookServiceImpl")
	private BookService bookService;
	
	//Query all the books and return to a book display page
	@RequestMapping("/allBook")
	public String list(Model model) {
		List<Books> list = bookService.queryAllBook();
		model.addAttribute("list", list);
		return "allbook";
	}
	
}

1.2. Compile the homepage index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>home page</title>
</head>
<body>
<h3>
	<a href="${pageContext.request.contextPath}/book/allBook">Enter the book page</a>
</h3>
</body>
</html>

1.3. Book list page allbook.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Book display</title>
</head>
<body>
<h1>Book display</h1>
</body>
</html>

The first underlying test found an error

Error: the problem bean does not exist

Analysis steps:

  1. Check whether the bean injection is successful

  2. Junit unit test to see if our code can query the results

    public class MyTest {
    	@Test
    	public void test() {
    		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    		BookServiceImpl bookServiceImpl = (BookServiceImpl) context.getBean("BookServiceImpl");
    		for (Books books : bookServiceImpl.queryAllBook()) {
    			System.out.println(books);
    		}
    	}
    }
    

    The results can be obtained through the query, and the underlying code must be OK.

  3. There must be something wrong with Spring

  4. Spring MVC, the bean s of our sevice layer are not electrophoretic during integration

    • Does applicationContext.xml inject bean s (integrated)

    • In web.xml, configuration files have also been bound

      We found the problem. We configured Spring-mvc.xml. There is no service bean in it. All null pointer exceptions are reported

      This is the summarized applicationContext.xml, and it can run normally.

2. The beginning is to write the front end

2.1. Beautify the homepage index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>home page</title>
<style>
	a{
		text-decoration:none;
		color:black;
		font-size:18px;
	}
	h3{
		width:180px;
		height:38px;
		margin:100px auto;
		text-align:center;
		line-height:38px;
		background:deepskyblue;
		border-radius:5px;
	}
</style>
</head>
<body>

<h3>
    <a href="${pageContext.request.contextPath}/book/allBook">Click to enter the list page</a>
</h3>

</body>
</html>

2.2 beautify the book display interface allBook.jsp

Beautify the interface with BootStrap, official website: https://www.bootcss.com/

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Book display</title>

<%-- BootStrap Beautify interface --%>
<link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">

</head>
<body>
<%-- container A format border --%>
<div class="container">
	<%-- Clear float --%>
	<div class="row clearfix">
		<%-- Split the screen horizontally into 12 parts,md Screen size, 12 for all 12 copies --%>
		<div class="col-md-12 column">
			<%-- head --%>
			<div class="page-header">
				<%-- small label --%>
				<h1>
					<small>Book list - displays all books</small>
				</h1>
			</div>
		</div>
	</div>
	

	
	<div class="row clearfix">
		<div class="col-md-12 column">
			<table class="table table-hover table-striped">
				<thead>
					<tr>
						<th>Book number</th>
						<th>Book name</th>
						<th>Number of books</th>
						<th>Book details</th>
					</tr>
				</thead>
				<%-- Books are queried from the database list Traversal from: forEach(Note header references) --%>
				<tbody>
				<%-- get data --%>
					<c:forEach var="book" items="${list}">
						<tr>
							<td>${book.bookID}</td>
							<td>${book.bookName}</td>
							<td>${book.bookCounts}</td>
							<td>${book.detail}</td>
						</tr>
					</c:forEach>
				</tbody>
			</table>
		
		</div>
	</div>

</div>
</body>
</html>

3. Add books

3.1. Add function to allBook.jsp book display interface: add books

	<div class="row clearfix">
		<div class="col-md-4 column">
			<%-- toAddBook --%>
			<a href="${pageContext.request.contextPath}/book/toAddBook">New books</a>
		</div>
	</div>

3.2. BookController class writing method: add books

    //Jump to the page where the book is added
    @RequestMapping("/toAddBook")
    public String toAddPaper() {
    	return "addBook";
    }
    
    //Request to add books
    @RequestMapping("/addBook")
    public String addPaper(Books books) {
    	System.out.println("addBook=>"+books);
    	bookService.addBook(books);
    	return "redirect:/book/allBook";//redirect
    }

3.3. Add book page addBook.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Add books</title>
<link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
	<div class="row clearfix">
		<div class="col-md-12 column">
			<div class="page-header">
				<h1>
					<small>New books</small>
				</h1>
			</div>
		</div>
	</div>
	
    <form action="${pageContext.request.contextPath}/book/addBook" method="post">
        Book Name:<input type="text" name="bookName" required><br><br><br>
        Number of books:<input type="text" name="bookCounts" required><br><br><br>
        Book details:<input type="text" name="detail" required><br><br><br>
        <input type="submit" value="add to">
    </form>
</div>

</body>
</html>

4. Modify and delete books

4.1. Add function of allbook.jsp: modify and delete

<td>
<%-- Send a modification message and find the of the modified object id,Let you see the object value when modifying --%>
<a href="${pageContext.request.contextPath}/book/toUpdate?id=${book.bookID}">modify</a>
|
<a href="${pageContext.request.contextPath}/book/deleteBook/${book.bookID}">delete</a>
</td>

(the teacher used & nbsp; for spaces, but my program only read the string and did not convert it to spaces, so I didn't use it)

4.2. BookController class preparation method 3: modify books

    //Jump to the modification page
    @RequestMapping("/toUpdate")
    	//Get the id of the object to facilitate modification, and the page displays the value of the object. And use model to carry
    public String toUpdatePaper(int id,Model model) {
    	Books books = bookService.queryBookById(id);
    	model.addAttribute("QBook",books);
    	return "updateBook";
    }
    //Request to modify a Book
    @RequestMapping("/updateBook")
    public String UpdateBook(Books books) {
    	System.out.println("UpdateBook=>"+books);
    	bookService.updateBook(books);
    	return "redirect:/book/allBook";//redirect
    }

4.3. Modify the book page updateBook.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Revise books</title>
<link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
	<div class="row clearfix">
		<div class="col-md-12 column">
			<div class="page-header">
				<h1>
					<small>Revise books</small>
				</h1>
			</div>
		</div>
	</div>
	<%-- No, I didn't bookID There was a problem running: submit the modified SQL There was a problem with the request. It was submitted successfully, but the content was not modified --%>
	<%-- The first consideration is to commit transactions. After configuration, it is found that it still fails --%>
	<%-- to glance at SQL Statement, whether it can be executed successfully: SQL Failed to execute. The modification is not completed. It will be found ID The default submission is 0, which is inconsistent with the actual parameter, and the database does not have this parameter --%>
	<%-- Modify: add bookID Statement, you can use the preceding paragraph to pass a hidden field --%>
	<%-- <input type="hidden" name="bookID" value="${QBook.bookID}"> --%>
	<%-- I think it shows ID More reasonable,readonly Non modifiable content and dyeing --%>
    <form action="${pageContext.request.contextPath}/book/updateBook" method="post">
        ID: <input type="text" name="bookID" value="${QBook.bookID}" style="background:#FFFF00" readonly><br><br><br>
        Book Name:<input type="text" name="bookName" value="${QBook.bookName}" required><br><br><br>
        Number of books:<input type="text" name="bookCounts" value="${QBook.bookCounts}" required><br><br><br>
        Book details:<input type="text" name="detail" value="${QBook.detail}" required><br><br><br>
        <input type="submit" value="modify">
    </form>
</div>

</body>
</html>

Problems in modifying function program:

  • At the beginning of adding, because the ID cannot be modified, the bookID is not intended to be transmitted, but there is a problem at runtime: there is a problem when submitting the modified SQL request. The submission is successful, but the content is not modified

  • The first consideration is to commit transactions. After configuration, it is found that it still fails

    Crosscutting transactions:

    Transaction jar package

    <dependency>
    	<groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
    	<version>1.8.13</version>
    </dependency>
    

    Crosscutting:

    <!-- Configure transaction notifications -->
    <tx:advice id="txAdvice" transaciton-manager="transactionManager">
        <tx:attributes>
        	<tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
    
    <!-- Configure transaction entry -->
    <aop:config>
    	<aop:pointcut id="txPointCut" expression="execution(* com.kuang.dao.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
    </aop:config>
    
  • Check whether the SQL statement can be executed successfully: the SQL execution fails and the modification is not completed. It is found that the default submission ID is 0, which is inconsistent with the actual parameter, and the database does not have this parameter

  • Modify: add a bookID statement. You can use the preceding paragraph to pass the hidden field

4.4. BookController - class writing method 4: delete books

    //Delete books
    	//The submitted id will be converted to bookId, resolved to int type and passed to the following
    @RequestMapping("/deleteBook/{bookId}")
    public String deleteBook(@PathVariable("bookId") int id) {
    	bookService.deleteBookById(id);
    	return "redirect:/book/allBook";
    }

8, Project structure diagram


9, All codes

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.kuang</groupId>
  <artifactId>ssmbuild03</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  
  <dependencies>
    <!--Junit-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <!--Database driven-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>
    <!-- Database connection pool -->
    <dependency>
        <groupId>com.mchange</groupId>
        <artifactId>c3p0</artifactId>
        <version>0.9.5.2</version>
    </dependency>
 
    <!--Servlet - JSP -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.2</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
 
    <!--Mybatis-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.2</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>2.0.2</version>
    </dependency>
 
    <!--Spring-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.1.9.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.1.9.RELEASE</version>
    </dependency>
</dependencies>
<build>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>false</filtering>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>false</filtering>
        </resource>
    </resources>
</build>

</project>

src/mian/java

com.kuang.controller.BookController.java

package com.kuang.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import com.kuang.pojo.Books;
import com.kuang.service.BookService;

@Controller
@RequestMapping("/book")

public class BookController {

	 
    @Autowired
    @Qualifier("BookServiceImpl")
    private BookService bookService;
 
    @RequestMapping("/allBook")
    public String list(Model model) {
        List<Books> list = bookService.queryAllBook();
        model.addAttribute("list", list);
        return "allbook";
    }
    
    //Jump to the page where the book is added
    @RequestMapping("/toAddBook")
    public String toAddPaper() {
    	return "addBook";
    }
    
    //Request to add books
    @RequestMapping("/addBook")
    public String addPaper(Books books) {
    	System.out.println("addBook=>"+books);
    	bookService.addBook(books);
    	return "redirect:/book/allBook";//redirect
    }
    
    //Jump to the modification page
    @RequestMapping("/toUpdate")
    	//Get the id of the object to facilitate modification, and the page displays the value of the object. And use model to carry
    public String toUpdatePaper(int id,Model model) {
    	Books books = bookService.queryBookById(id);
    	model.addAttribute("QBook",books);
    	return "updateBook";
    }
    //Request to modify a Book
    @RequestMapping("/updateBook")
    public String UpdateBook(Books books) {
    	System.out.println("UpdateBook=>"+books);
    	bookService.updateBook(books);
    	return "redirect:/book/allBook";//redirect
    }
    
    //Delete books
    	//The submitted id will be converted to bookId, resolved to int type and passed to the following
    @RequestMapping("/deleteBook/{bookId}")
    public String deleteBook(@PathVariable("bookId") int id) {
    	bookService.deleteBookById(id);
    	return "redirect:/book/allBook";
    }
}

com.kuang.dao.BookMapper.java

package com.kuang.dao;

import java.util.List;

import com.kuang.pojo.Books;

public interface BookMapper {


    //Add a Book
    int addBook(Books book);
 
    //Delete a Book by id
    int deleteBookById(int id);
 
    //Update Book
    int updateBook(Books books);
 
    //According to the id query, a Book is returned
    Books queryBookById(int id);
 
    //Query all books and return the list set
    List<Books> queryAllBook();

}

com.kuang.dao.BookMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 
<mapper namespace="com.kuang.dao.BookMapper">
 
    <!--Add one Book-->
    <insert id="addBook" parameterType="Books">
        insert into ssmbuild.books(bookName,bookCounts,detail)
        values (#{bookName}, #{bookCounts}, #{detail})
    </insert>
 
    <!--according to id Delete a Book-->
    <delete id="deleteBookById" parameterType="int">
        delete from ssmbuild.books where bookID=#{bookID}
    </delete>
 
    <!--to update Book-->
    <update id="updateBook" parameterType="Books">
        update ssmbuild.books
        set bookName = #{bookName},bookCounts = #{bookCounts},detail = #{detail}
        where bookID = #{bookID}
    </update>
 
    <!--according to id query,Return a Book-->
    <select id="queryBookById" resultType="Books">
        select * from ssmbuild.books
        where bookID = #{bookID}
    </select>
 
    <!--Query all Book-->
    <select id="queryAllBook" resultType="Books">
        SELECT * from ssmbuild.books
    </select>
 
</mapper>

com.kuang.pojo.Books.java

package com.kuang.pojo;

public class Books {


    private int bookID;
    private String bookName;
    private int bookCounts;
    private String detail;
	public Books() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Books(int bookID, String bookName, int bookCounts, String detail) {
		super();
		this.bookID = bookID;
		this.bookName = bookName;
		this.bookCounts = bookCounts;
		this.detail = detail;
	}
	public int getBookID() {
		return bookID;
	}
	public void setBookID(int bookID) {
		this.bookID = bookID;
	}
	public String getBookName() {
		return bookName;
	}
	public void setBookName(String bookName) {
		this.bookName = bookName;
	}
	public int getBookCounts() {
		return bookCounts;
	}
	public void setBookCounts(int bookCounts) {
		this.bookCounts = bookCounts;
	}
	public String getDetail() {
		return detail;
	}
	public void setDetail(String detail) {
		this.detail = detail;
	}
	@Override
	public String toString() {
		return "Books [bookID=" + bookID + ", bookName=" + bookName + ", bookCounts=" + bookCounts + ", detail="
				+ detail + "]";
	}	
}

com.kuang.service.BookService.java

package com.kuang.service;

import java.util.List;

import com.kuang.pojo.Books;

public interface BookService {


    //Add a Book
    int addBook(Books book);
    //Delete a Book by id
    int deleteBookById(int id);
    //Update Book
    int updateBook(Books books);
    //According to the id query, a Book is returned
    Books queryBookById(int id);
    //Query all books and return the list set
    List<Books> queryAllBook();

}

com.kuang.service.BookServiceImpl.java

package com.kuang.service;

import java.util.List;

import com.kuang.dao.BookMapper;
import com.kuang.pojo.Books;

public class BookServiceImpl implements BookService {

	 
    //Call the operation of dao layer and set a set interface to facilitate Spring management
    private BookMapper bookMapper;
 
    public void setBookMapper(BookMapper bookMapper) {
        this.bookMapper = bookMapper;
    }
    
    public int addBook(Books book) {
        return bookMapper.addBook(book);
    }
    
    public int deleteBookById(int id) {
        return bookMapper.deleteBookById(id);
    }
    
    public int updateBook(Books books) {
        return bookMapper.updateBook(books);
    }
    
    public Books queryBookById(int id) {
        return bookMapper.queryBookById(id);
    }
    
    public List<Books> queryAllBook() {
        return bookMapper.queryAllBook();
    }
}

src/mian/resources

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">
        
        
    <import resource="spring-dao.xml"/>
    <import resource="spring-service.xml"/>
    <import resource="spring-mvc.xml"/>
        
 
</beans>

database.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssmbuild?useSSL=true&useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=123456

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<!-- Add log -->
	<settings>
		<setting name="logImpl" value="STDOUT_LOGGING"/>
	</settings>
    
    <typeAliases>
        <package name="com.kuang.pojo"/>
    </typeAliases>
    

    <mappers>
        <mapper resource="com/kuang/dao/BookMapper.xml"/>
    </mappers>
 
</configuration>

spring-dao.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
 
    <!-- Configuration integration mybatis -->
    <!-- 1.Associated database file -->
    <context:property-placeholder location="classpath:database.properties"/>
 
    <!-- 2.Database connection pool -->
    <!--Database connection pool
        dbcp  Semi automatic operation cannot be connected automatically
        c3p0  Automatic operation (automatically load the configuration file and set it into the object)
    -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!-- Configure connection pool properties -->
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <!-- c3p0 Private properties of connection pool -->
        <property name="maxPoolSize" value="30"/>
        <property name="minPoolSize" value="10"/>
        <!-- Not automatically after closing the connection commit -->
        <property name="autoCommitOnClose" value="false"/>
        <!-- Get connection timeout -->
        <property name="checkoutTimeout" value="10000"/>
        <!-- Number of retries when getting connection failed -->
        <property name="acquireRetryAttempts" value="2"/>
    </bean>
    <!-- 3.to configure SqlSessionFactory object -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- Inject database connection pool -->
        <property name="dataSource" ref="dataSource"/>
        <!-- to configure MyBaties Global profile:mybatis-config.xml -->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
    </bean>
    <!-- 4.Configure scan Dao Interface package, dynamic implementation Dao Interface injection into spring In container -->
    <!--Explanation: https://www.cnblogs.com/jpfss/p/7799806.html-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- injection sqlSessionFactory -->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <!-- Give the information that needs to be scanned Dao Interface package -->
        <property name="basePackage" value="com.kuang.dao"/>
    </bean>
</beans>

spring-mvc.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:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/mvc
    https://www.springframework.org/schema/mvc/spring-mvc.xsd">
 
    <!-- to configure SpringMVC -->
    <!-- 1.open SpringMVC Annotation driven -->
    <mvc:annotation-driven />
    <!-- 2.Static resource default servlet to configure-->
    <mvc:default-servlet-handler/>
 
    <!-- 3.to configure jsp display ViewResolver view resolver  -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>
    <!-- 4.scanning web dependent bean -->
    <context:component-scan base-package="com.kuang.controller" />
</beans>

spring-service.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
 
    <!-- scanning service dependent bean -->
    <context:component-scan base-package="com.kuang.service" />
 
    <!--BookServiceImpl Inject into IOC In container-->
    <bean id="BookServiceImpl" class="com.kuang.service.BookServiceImpl">
        <property name="bookMapper" ref="bookMapper"/>
    </bean>
    <!-- Configure transaction manager -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- Inject database connection pool -->
        <property name="dataSource" ref="dataSource" />
    </bean>
</beans>

front end

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.5" 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_2_5.xsd">
<!--DispatcherServlet-->
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <!--Be careful:What we load here is the total configuration file, which was previously damaged here!-->  
            <param-value>classpath:applicationContext.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <!--encodingFilter-->
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>
            org.springframework.web.filter.CharacterEncodingFilter
        </filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    <!--Session Expiration time-->
    <session-config>
        <session-timeout>15</session-timeout>
    </session-config>

</web-app>

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <title>home page</title>
    <style type="text/css">
        a {
            text-decoration: none;
            color: black;
            font-size: 18px;
        }
        h3 {
            width: 180px;
            height: 38px;
            margin: 100px auto;
            text-align: center;
            line-height: 38px;
            background: deepskyblue;
            border-radius: 4px;
        }
    </style>
</head>
<body>
 
<h3>
    <a href="${pageContext.request.contextPath}/book/allBook">Click to enter the list page</a>
</h3>
</body>

</html>

addBook.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Add books</title>
<link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
	<div class="row clearfix">
		<div class="col-md-12 column">
			<div class="page-header">
				<h1>
					<small>New books</small>
				</h1>
			</div>
		</div>
	</div>
	
    <form action="${pageContext.request.contextPath}/book/addBook" method="post">
        Book Name:<input type="text" name="bookName" required><br><br><br>
        Number of books:<input type="text" name="bookCounts" required><br><br><br>
        Book details:<input type="text" name="detail" required><br><br><br>
        <input type="submit" value="add to">
    </form>
</div>

</body>
</html>

allbook.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Book display</title>

<%-- BootStrap Beautify interface --%>
<link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">

</head>
<body>
<%-- container A format border --%>
<div class="container">
	<%-- Clear float --%>
	<div class="row clearfix">
		<%-- Split the screen horizontally into 12 parts,md Screen size, 12 for all 12 copies --%>
		<div class="col-md-12 column">
			<%-- head --%>
			<div class="page-header">
				<%-- small label --%>
				<h1>
					<small>Book list - displays all books</small>
				</h1>
			</div>
		</div>
	</div>
	
	<div class="row clearfix">
		<div class="col-md-4 column">
			<%-- toAddBook --%>
			<a href="${pageContext.request.contextPath}/book/toAddBook">New books</a>
		</div>
	</div>
	
	<div class="row clearfix">
		<div class="col-md-12 column">
			<table class="table table-hover table-striped">
				<thead>
					<tr>
						<th>Book number</th>
						<th>Book name</th>
						<th>Number of books</th>
						<th>Book details</th>
						<th>operation</th>
					</tr>
				</thead>
				<%-- Books are queried from the database list Traversal from: forEach(Note header references) --%>
				<tbody>
				<%-- get data --%>
					<c:forEach var="book" items="${list}">
						<tr>
							<td>${book.bookID}</td>
							<td>${book.bookName}</td>
							<td>${book.bookCounts}</td>
							<td>${book.detail}</td>
							<td>
								<%-- Send a modification message and find the of the modified object id,Let you see the object value when modifying --%>
								<a href="${pageContext.request.contextPath}/book/toUpdate?id=${book.bookID}">modify</a>
								 |
								<a href="${pageContext.request.contextPath}/book/deleteBook/${book.bookID}">delete</a>
								
							</td>
						</tr>
					</c:forEach>
				</tbody>
			</table>
		
		</div>
	</div>

</div>
</body>
</html>

updateBook.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Revise books</title>
<link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
	<div class="row clearfix">
		<div class="col-md-12 column">
			<div class="page-header">
				<h1>
					<small>Revise books</small>
				</h1>
			</div>
		</div>
	</div>
	<%-- No, I didn't bookID There was a problem running: submit the modified SQL There was a problem with the request. It was submitted successfully, but the content was not modified --%>
	<%-- The first consideration is to commit transactions. After configuration, it is found that it still fails --%>
	<%-- to glance at SQL Statement, whether it can be executed successfully: SQL Failed to execute. The modification is not completed. It will be found ID The default submission is 0, which is inconsistent with the actual parameter, and the database does not have this parameter --%>
	<%-- Modify: add bookID Statement, you can use the preceding paragraph to pass a hidden field --%>
	<%-- <input type="hidden" name="bookID" value="${QBook.bookID}"> --%>
	<%-- I think it shows ID More reasonable,readonly Non modifiable content and dyeing --%>
    <form action="${pageContext.request.contextPath}/book/updateBook" method="post">
        ID: <input type="text" name="bookID" value="${QBook.bookID}" style="background:#FFFF00" readonly><br><br><br>
        Book Name:<input type="text" name="bookName" value="${QBook.bookName}" required><br><br><br>
        Number of books:<input type="text" name="bookCounts" value="${QBook.bookCounts}" required><br><br><br>
        Book details:<input type="text" name="detail" value="${QBook.detail}" required><br><br><br>
        <input type="submit" value="modify">
    </form>
</div>

</body>
</html>

10, Summary and Prospect

This is the first SSM integration case of students. We must be familiar with it!

The importance of SSM framework is self-evident. After learning here, you can develop the basic website separately. However, this is only the basic operation of adding, deleting, modifying and querying. It can be said that after learning here, we can really step into the door of background development. That is the bottom line of finding a background related job.

Maybe many people do these things at work, but it's not enough for personal improvement!

We will learn some knowledge of spring MVC later!

  • Ajax and Json
  • File upload and download
  • Interceptor

There is a long way to go. It is most important to stick to it carefully

11, Error report or Eclipse usage problem

1. The first error message of eclipse Maven web POM

project declaration not found

Multiple annotations found at this line: schema_reference.4: Failed to read schema document 'https://maven.apache.org/xsd/maven-4.0.0.xsd', because could not find the document; the document could not be read; 3) the root element of the document is not <xsd:schema>. cvc-elt.1.a: Cannot find the declaration of element 'project'.

Error message: development environment eclipse, maven project, pom.xml, the first line < project... This error is always reported at the label: CVC ELT. 1: cannot find the declaration of element 'project'

Solution: right click maven project, maven - > update project, and remember to check force update of snapshots/release

Solution URL

2. Chinese garbled code of. properties file

The. properties file of eclipse is found to be garbled in Chinese

Step 1: windows – > properties – > General – > content types – > text (as shown below)

Solution URL

3. The class in the target of ECLIPS is hidden

Unhide method


Solution URL

  1. 4. Solve the error of starting tomcat in eclipse

Solve the error of starting tomcat in eclipse: could not load the tomcat server configuration at \ servers \ tomcat V6.0 server at localhost config. The servers project is closed

Double click Servers

Solution URL

New search function

New search function on the original code

  • The normal browsing order of a user is: front end - > controller layer - > service layer - > Dao layer - > database
  • However, programming should start from database - > Dao layer - > service layer - > controller layer - > front end
  • If there is no overall idea, you can start from the front end, but there will be many steps.

Complete the original code:

dao layer

/ssmbuild03/src/main/java/com/kuang/dao/BookMapper.java

    //Search by name
    Books queryBookName(@Param("bookName") String bookName);

/ssmbuild03/src/main/java/com/kuang/dao/BookMapper.xml

 	<!--Search by name-->
    <select id="queryBookName" resultType="Books">
        select * from ssmbuild.books
        where bookName = #{bookName}
    </select>

service layer

/ssmbuild03/src/main/java/com/kuang/service/BookService.java

    //Search by name
    Books queryBookName(String bookName);

/ssmbuild03/src/main/java/com/kuang/service/BookServiceImpl.java

	@Override
	public Books queryBookName(String bookName) {	
		return bookMapper.queryBookName(bookName);
	}

controller layer

/ssmbuild03/src/main/java/com/kuang/controller/BookController.java

    //Query books
    @RequestMapping("/queryBook")
    public String queryBook(String queryBookName,Model model) {
    	Books books = bookService.queryBookName(queryBookName);
    	//Because the allbook display page needs list type storage
    	//So store the books in the list, and then jump to the display page
    	List<Books> list = new ArrayList<Books>();
    	list.add(books);
    	//If the query is empty, you will go to the display page
    	if (books==null) {
			list=bookService.queryAllBook();
			model.addAttribute("error","Not found");
		}
    	model.addAttribute("list", list);
    	
        return "allbook";
    }
  1. Send the query results to the new display page "allbook" and present them
  2. However, due to the List collection used by the display page, the passed in value needs to be passed to the List collection
  3. At the same time, judge that if the query value is empty, all book display pages will be presented
  4. At the same time, a "not found" prompt is issued

front end

allbook.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Book display</title>

<%-- BootStrap Beautify interface --%>
<link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">

</head>
<body>
<%-- container A format border --%>
<div class="container">
	<%-- Clear float --%>
	<div class="row clearfix">
		<%-- Split the screen horizontally into 12 parts,md Screen size, 12 for all 12 copies --%>
		<div class="col-md-12 column">
			<%-- head --%>
			<div class="page-header">
				<%-- small label --%>
				<h1>
					<small>Book list - displays all books</small>
				</h1>
			</div>
		</div>
	</div>
	
	<div class="row clearfix">
	<%-- utilize class="col-md-4 column",Divide the content into three parts.
		class="btn btn-primary" Model
		style="float:right" Rightmost
		 
	 --%>
		<div class="col-md-4 column">
			<%-- toAddBook --%>
			<a class="btn btn-primary" href="${pageContext.request.contextPath}/book/toAddBook">New books</a>
			<a class="btn btn-primary" href="${pageContext.request.contextPath}/book/allBook">Show all books</a>
		</div>
		<div class="col-md-4 column"></div>
		<div class="col-md-4 column">
				
				<%-- Query data, need to use form Forms, a Tags cannot be queried, form-inline Become a row of inline forms --%>
			<form class="form-inline" action="${pageContext.request.contextPath}/book/queryBook" method="post" style="float:right">
				<span style="color:red;">${error}</span>
				<input type="text" name="queryBookName" class="form-control" placeholder="Please enter book name">
				<input type="submit" value="query" class="btn btn-primary">
			</form>
		</div>
	</div>
	
	<div class="row clearfix">
		<div class="col-md-12 column">
			<table class="table table-hover table-striped">
				<thead>
					<tr>
						<th>Book number</th>
						<th>Book name</th>
						<th>Number of books</th>
						<th>Book details</th>
						<th>operation</th>
					</tr>
				</thead>
				<%-- Books are queried from the database list Traversal from: forEach(Note header references) --%>
				<tbody>
				<%-- get data --%>
					<c:forEach var="book" items="${list}">
						<tr>
							<td>${book.bookID}</td>
							<td>${book.bookName}</td>
							<td>${book.bookCounts}</td>
							<td>${book.detail}</td>
							<td>
								<%-- Send a modification message and find the of the modified object id,Let you see the object value when modifying --%>
								<a href="${pageContext.request.contextPath}/book/toUpdate?id=${book.bookID}">modify</a>
								&nbsp; | &nbsp;
								<a href="${pageContext.request.contextPath}/book/deleteBook/${book.bookID}">delete</a>
								
							</td>
						</tr>
					</c:forEach>
				</tbody>
			</table>
		
		</div>
	</div>

</div>
</body>
</html>
  1. First, the query function is added by using the from tag
  2. Use form inline to turn the form into a row of inline forms, and ${error} "not found" prompt
  3. Add a key to display all books after query

Bootstrap visual layout https://www.bootcss.com/p/layoutit/ Help front-end design, you can get the code directly

Ajax

1, Introduction

  • AJAX = Asynchronous JavaScript and XML.

  • AJAX is a technology that can update some web pages without reloading the whole web page.

  • Ajax is not a new programming language, but a technology for creating better, faster and more interactive Web applications.

  • In 2005, Google made AJAX popular through its Google suggest. Google Suggest can automatically help you search for words.

  • Google Suggest uses AJAX to create a highly dynamic web interface: when you enter keywords in Google's search box, JavaScript will send these characters to the server, and then the server will return a list of search suggestions.

  • Just like the domestic Baidu search box!

  • Traditional web pages (that is, web pages without ajax Technology) need to reload the whole web page if they want to update the content or submit a form.

  • Web pages using ajax technology can realize asynchronous local update through a small amount of data exchange in the background server.

  • With Ajax, users can create a direct, highly available, richer and more dynamic Web user interface close to local desktop applications.

2, Fake Ajax

We can use a tag on the front end to fake an ajax look. iframe tag

  1. First design a plan pop-up page. You don't need to enter an address, just a size
  2. Design a user to enter the URL and then click the button event
  3. Render the entered URL to the pop-up page
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>iframe The test experience page is not refreshed</title>
	
	<!-- All value variables are obtained in advance -->
<script>
	function go(){
		var url = document.getElementById("url").value;
		document.getElementById("iframe1").src=url;
	}
</script>
</head>
<body>

<div>
	<p>Please enter the address:</p>
	<p>
		<input type="text" id="url" >
		<input type="button" value="Submit" onclick="go()">
	</p>

</div>


<div>
	<iframe id="iframe1" style="width:100%;height:500px"></iframe>
</div>

</body>
</html>
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>kuangshen</title>
</head>
<body>
 
<script type="text/javascript">
    window.onload = function(){
        var myDate = new Date();
        document.getElementById('currentTime').innerText = myDate.getTime();
    };
 
    function LoadPage(){
        var targetUrl =  document.getElementById('url').value;
        console.log(targetUrl);
        document.getElementById("iframePosition").src = targetUrl;
    }
 
</script>
 
<div>
    <p>Please enter the address to load:<span id="currentTime"></span></p>
    <p>
        <input id="url" type="text" value="https://www.baidu.com/"/>
        <input type="button" value="Submit" onclick="LoadPage()">
    </p>
</div>
 
<div>
    <h3>Load page location:</h3>
    <iframe id="iframePosition" style="width: 100%;height: 500px;"></iframe>
</div>
 
</body>
</html>

With AJAX, you can:

  • When registering, enter the user name to automatically detect whether the user already exists.
  • When logging in, you will be prompted that the user name and password are incorrect
  • When deleting a data row, the row ID is sent to the background, and the background deletes it in the database. After the database is deleted successfully, the data row is also deleted in the page DOM.
  • ... wait

3, jQuery.ajax

We will not explain the pure JS native implementation of Ajax here, but directly use the one provided by jquery to facilitate learning and use and avoid repeated wheel building. Interested students can learn about JS native XMLHttpRequest!

The core of Ajax is the XMLHttpRequest object (XHR). XHR provides an interface for sending requests to the server and parsing server responses. The ability to obtain new data from the server asynchronously.

jQuery provides several AJAX related methods.

Through the jQuery AJAX method, you can use HTTP Get and HTTP Post to request text, HTML, XML or JSON from a remote server - and you can load these external data directly into the selected elements of the web page.

jQuery is not a producer, but a nature porter.

jQuery is a library; js a large number of functions (Methods)

The essence of jQuery Ajax is XMLHttpRequest, which is encapsulated and easy to call!

jQuery.ajax(...)
       Some parameters:
              url: Request address
             type: Request method, GET,POST(1.9.0 Later use method)
          headers: Request header
             data: Data to send
      contentType: The content encoding type of the message to be sent to the server(default: "application/x-www-form-urlencoded; charset=UTF-8")
            async: Asynchronous
          timeout: Set request timeout (MS)
       beforeSend: Function executed before sending the request(overall situation)
         complete: Callback function executed after completion(overall situation)
          success: Callback function executed after success(overall situation)
            error: Callback function executed after failure(overall situation)
          accepts: Send the request to the server and tell the server the data type acceptable to the current client
         dataType: Converts the data returned by the server to the specified type
            "xml": Convert the content returned by the server into xml format
           "text": Convert the content returned by the server to normal text format
           "html": Convert the content returned by the server into normal text format and insert DOM If it contains JavaScript Tag, it will try to execute.
         "script": Try to treat the return value as JavaScript To execute, and then convert the content returned by the server into normal text format
           "json": Convert the content returned by the server into the corresponding JavaScript object
          "jsonp": JSONP Format use JSONP When calling a function as "myurl?callback=?" jQuery Will automatically replace ? Give the correct function name to execute the callback function

/springmvc-06/src/main/resources/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:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           https://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/mvc
           https://www.springframework.org/schema/mvc/spring-mvc.xsd">

	<!-- Automatically scan the specified package, and submit all the following annotation classes to IOC Container management -->
	<context:component-scan
		base-package="com.kuang.controller" />
		
	<!-- Static resource filtering js use -->
    <mvc:default-servlet-handler />

	<mvc:annotation-driven/>
	<!-- view resolver  -->
	<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver"
		id="internalResourceViewResolver">
		<!-- prefix -->
		<property name="prefix" value="/WEB-INF/jsp/" />
		<!-- suffix -->
		<property name="suffix" value=".jsp" />
	</bean>

</beans>

/springmvc-06/src/main/java/com/kuang/controller/AjaxController.java

package com.kuang.controller;

import java.io.IOException;

import javax.servlet.http.HttpServletResponse;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AjaxController {
	@RequestMapping("/t1")
	public String test() {
		return "hello";
	}
	//Is the test environment successful
	
	@RequestMapping("/a1")
	public void a1(String name,HttpServletResponse response) throws IOException {
		System.out.println("a1:param->"+name);
		if ("kuangshen".equals(name)) {
			response.getWriter().print("true");
		}else {
			response.getWriter().print("false");
		}
	}
	
}

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>

<script src="${pageContext.request.contextPath}/statics/js/jquery-3.6.0.js"></script>
<script>
	function a(){
		<%-- 
		url: Get request address a1
		data: Transfer data, $("#username").val() gets the input value and stores it in a1.name
		success: Callback function function(data);error:function()fail
		alert: Asynchronous
		 --%>
		$.post({
			url:"${pageContext.request.contextPath}/a1",

			data:{"name":$("#username").val()},
			success:function(data){
				alert(data);
			}
		})
	}
	
</script>

</head>
<body>

<%-- When you lose focus, make a request to the background, onblur Loss of focus event --%>
user name:<input type="text" id="username" οnblur="a()">

</body>
</html>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.5" 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_2_5.xsd">

    <!--DispatcherServlet-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <!--Be careful:What we load here is the total configuration file, which was previously damaged here!-->  
            <param-value>classpath:applicationContext.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    
    <!--encodingFilter-->
    <filter>
        <filter-name>encoding</filter-name>
        <filter-class>
            org.springframework.web.filter.CharacterEncodingFilter
        </filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

</web-app>

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.kuang</groupId>
	<artifactId>springmvc-06</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>

	<dependencies>
		<!--Junit -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
		</dependency>
		<!--Database driven -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.47</version>
		</dependency>
		<!-- Database connection pool -->
		<dependency>
			<groupId>com.mchange</groupId>
			<artifactId>c3p0</artifactId>
			<version>0.9.5.2</version>
		</dependency>

		<!--Servlet - JSP -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>jsp-api</artifactId>
			<version>2.2</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>

		<!--Mybatis -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.5.2</version>
		</dependency>
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis-spring</artifactId>
			<version>2.0.2</version>
		</dependency>

		<!--Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>5.1.9.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>5.1.9.RELEASE</version>
		</dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.4</version>
    </dependency>

	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.3.1</version>
			</plugin>
		</plugins>

		<resources>
			<resource>
				<directory>src/main/java</directory>
				<includes>
					<include>**/*.properties</include>
					<include>**/*.xml</include>
				</includes>
				<filtering>false</filtering>
			</resource>
			<resource>
				<directory>src/main/resources</directory>
				<includes>
					<include>**/*.properties</include>
					<include>**/*.xml</include>
				</includes>
				<filtering>false</filtering>
			</resource>
		</resources>
	</build>


</project>

test result

Program running steps

Minimum requirements for previous knowledge: HTML + css: slightly understand + js (super skilled)

js:

  • Functions: closure () ()
  • Dom
    • id , name , tag
    • create , remove
  • Bom
    • window
    • document

ES6: import require

Status status

success:function(data,status){
				console.log("data="+data);
				console.log("status="+status);	//200 successful, 300 redirection or forwarding, 400 client error, 500 server error
			}error(){

}

4, Ajax loads data asynchronously

Create entity class

/springmvc-06/src/main/java/com/kuang/pojo/User.java

package com.kuang.pojo;

public class User {
	private String name;
	private int age;
	private String sex;
	public User() {
		super();
		// TODO Auto-generated constructor stub
	}
	public User(String name, int age, String sex) {
		super();
		this.name = name;
		this.age = age;
		this.sex = sex;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	@Override
	public String toString() {
		return "User [name=" + name + ", age=" + age + ", sex=" + sex + "]";
	}
}

Add data

/springmvc-06/src/main/java/com/kuang/controller/AjaxController.java

package com.kuang.controller;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.kuang.pojo.User;

@RestController
//RestController does not return to the view parser
public class AjaxController {
	@RequestMapping("/t1")
	public String test() {
		return "hello";
	}
	//Is the test environment successful
	
	@RequestMapping("/a1")
	public void a1(String name,HttpServletResponse response) throws IOException {
		System.out.println("a1:param->"+name);
		if ("kuangshen".equals(name)) {
			response.getWriter().print("true");
		}else {
			response.getWriter().print("false");
		}
	}
	//Returns the object to the previous segment
	@RequestMapping("/a2")
	public List<User> a2(){
		List<User> userList = new ArrayList<User>();
		//Add data
			userList.add(new User("Madness theory java", 1, "male"));
			userList.add(new User("Crazy God said", 2, "female"));
			userList.add(new User("Crazy God said", 3, "male"));
		return userList;
	}
	
}

  • RestController does not return to the view parser
  • Use the list to return the object to the previous paragraph
  • For the front end, the back end is to add, delete, modify and query

Creating an Ajax asynchronous loader

test2.jsp

  1. Draw a page < Table >, display < tr >, data < tbody > (but the data is in the background, so you need to use ajax to request data)
  2. Load jquery, use the id selector < script > to get and click the event
  3. Directly abbreviate the request to post and obtain the return value data. Here, we can obtain resources normally.
  4. Input the returned data into the asynchronous block. Add nodes and splice the front end
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
	<title>Insert title here</title>
	<script src="${pageContext.request.contextPath}/statics/js/jquery-3.6.0.js"></script>
    <script>
        $(function(){
           $("#btn").click(function(){
            /*
            	$.post(url,param((can be omitted), success)
            */
            $.post("${pageContext.request.contextPath}/a2",function(data) {
                //console.log(data);
                var html="";  
                   
                //The new feature of JavaScript 6 can also be called outside var, and let can only be used in for
                
                for(var i = 0; i < data.length;i++){
                	html += "<tr>" +
                        "<td>" + data[i].name + "</td>"+
                        "<td>" + data[i].age + "</td>"+
                        "<td>" + data[i].sex + "</td>"+
                        "</tr>"
            	}
               $("#content").html(html);
            });
       	  })
        });	
    </script>
<body>
    
    <input type="button" value="Load data" id="btn">
    <table>
        <tr>
            <td>full name</td>
        	<td>Age</td>
        	<td>Gender</td>
        </tr>
        <tbody id="content">
        	<%-- Data: background --%>
        </tbody>
    </table>
</body>   
</head>

5, Ajax authentication user name experience

Dynamic request response, local refresh

Request page

login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script
	src="${pageContext.request.contextPath}/statics/js/jquery-3.6.0.js"></script>
<script>
	function a1(){
		$.post({
			url:"${pageContext.request.contextPath}/a3",
			data:{"name":$("#name").val()},
			<%-- success Callback function --%>
			success:function(data){
				if(data.toString()==='ok'){
					$("#userInfo").css("color","green");
				}else{
					$("#userInfo").css("color","red");
				}
				$("#userInfo").html(data);
			}
		})
	}
	function a2(){
		$.post({
			url:"${pageContext.request.contextPath}/a3",
			data:{"pwd":$("#pwd").val()},
			<%-- success Callback function --%>
			success:function(data){
				if(data.toString()==='ok'){
					$("#pwdInfo").css("color","green");
				}else{
					$("#pwdInfo").css("color","red");
				}
				$("#pwdInfo").html(data);
			}
		})
	}

</script>
</head>
<body>

<p>
    user name:<input type="text" id="name" οnblur="a1()"/>
    <span id="userInfo"></span>
</p>
<p>
    password:<input type="text" id="pwd" οnblur="a2()"/>
    <span id="pwdInfo"></span>
</p>

</body>
</html>

Controller.java

	@RequestMapping("/a3")
	public String a3(String name,String pwd){
		String msg ="";
		if(name!=null) {
			//admin should be the database information
			if ("admin".equals(name)) {
				msg="ok";
			}else {
				msg="false";
			}
		}
		if(pwd!=null) {
			
			if ("123456".equals(pwd)) {
				msg="ok";
			}else {
				msg="false";
			}
		}	
		return msg;
	}

json garbled problem

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

Problem solving

1. List returns an error

No converter found for return value of type: class java.util.ArrayList]

Solution: pom increases jackson dependency

    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.4</version>
    </dependency>

https://www.cnblogs.com/zhoujian43/p/6640804.html

And Context.xml

<mvc:annotation-driven/>

If they want to rely on multiple jackson, they may report the following errors

  <properties>
    <jackson.version>2.5.4</jackson.version>
  </properties> 

  <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>${jackson.version}</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>${jackson.version}</version>
    </dependency>

Error creating bean with name 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter': Instantiation of bean failed; nested exception is

website

Interceptor

1, Overview

The processor interceptor of spring MVC is similar to the Filter in Servlet development, which is used to preprocess and post process the processor. Developers can define some interceptors to implement specific functions.

The difference between filter and Interceptor: interceptor is the specific application of AOP idea.

filter

  • Part of the servlet specification that can be used by any java web project
  • After / * is configured in URL pattern, all resources to be accessed can be intercepted

Interceptor

  • The interceptor is the spring MVC framework's own. It can only be used by projects that use the spring MVC framework
  • The interceptor will only intercept the accessed controller methods. If the accessed is jsp/html/css/image/js, it will not intercept

2, Custom interceptor

How to implement the interceptor?

To customize the interceptor, you must implement the HandlerInterceptor interface.

1. Create a Moudule, springmvc-07-Interceptor, and add web support

2. Configure the web.xml and springmvc-servlet.xml files

/springmvc-07/src/main/java/com/kuang/controller/Textcontroller.java

package com.kuang.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class Textcontroller {
	@GetMapping("/t1")
	public String test() {
		System.out.println("Textcontroller---test");
		return "ok";
		
	}
}

applicationContext.xml

	<!-- Interceptor configuration -->
	<mvc:interceptors>
		<mvc:interceptor>
		<!-- Include all requests below this request -->
			<mvc:mapping path="/**"/>
			<!-- Who's going to intercept -->
			<bean class="com.kuang.config.MyInterceptor"/>
		</mvc:interceptor>
	</mvc:interceptors>

3. Write an interceptor

/springmvc-07/src/main/java/com/kuang/config/MyInterceptor.java

package com.kuang.config;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class MyInterceptor implements HandlerInterceptor{
	
	//return ture ; Execute the next interceptor, direction
	//return false; Do not execute the next interceptor
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("--------------Before treatment-----------");
		return true;
	}
	//It mainly uses the above. The following main function is to intercept logs
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("--------------After treatment-----------");
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("--------------Cleaning up-----------");
	}
	
}

3, Login judgment verification

Create a home page

There are login page (button) and home page (button)

/springmvc-07/src/main/webapp/index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<h1><a href="${pageContext.request.contextPath}/goLogin">Login page</a></h1>
<h1><a href="${pageContext.request.contextPath}/main">home page</a></h1>


</body>
</html>

Create a front-end control layer

  • Login page (button) - turn - login page.jsp
  • Home page (button) - turn to home page.jsp
  • Save the user name information in the login page. jsp into the session

/springmvc-07/src/main/java/com/kuang/controller/LoginController.java

package com.kuang.controller;

import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/user")
public class LoginController {
	@RequestMapping("/main")
	public String main() {
		
		return "main";
	}
	@RequestMapping("/goLogin")
	public String login() {
		
		return "login";
	}
	
	@RequestMapping("/login")
	public String login(HttpSession session,String username,String password,Model model) {
		//Store the user's information in the session to facilitate downward transmission;
        //model returns user information
		session.setAttribute("userLoginInfo", username);
		model.addAttribute("username", username);
        
		return "main";
	}
}

Create a login page

/springmvc-07/src/main/webapp/jsp/login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<!-- stay web-inf All pages or resources under can only be accessed through controller,perhaps sevlet Visit -->
<h1>Login page</h1>

<form action="${pageContext.request.contextPath}/user/login" method="post">
	user name:<input type="text" name="username"/>
	password:<input type="text" name="password"/>
	<input type="submit" value="Submit"/>	
</form>
	
</body>
</html>

home page

/springmvc-07/src/main/webapp/jsp/main.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<h1>home page</h1>
    
<!-- User information is displayed on the home page -->
<span>${username}</span>

</body>
</html>

Write a new interceptor

Block users who are not logged in and cannot view the home page

/springmvc-07/src/main/java/com/kuang/config/LoginInterceptor.java

public class LoginInterceptor implements HandlerInterceptor{
	

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {
        //Release: determine when login is required
        
        HttpSession session = request.getSession();
       //Direct release on login page
        if(request.getRequestURI().contains("goLogin")){
            return true;
        }
        //Indicates that I am submitting a login
        if(request.getRequestURI().contains("login")){
            return true;
        }
        
        //When the user session has a value
        if(session.getAttribute("userLoginInfo")!=null){
            return true;
        }
        
        //Determine when you are not logged in
        request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);
		return false;
	}
}

? Question: Login release? Can I log in even if the account number is incorrect or not entered?

applicationContext.xml configuration interceptor

Add the LoginInterceptor parent user, and only intercept all requests under the parent user directory

	<!-- Interceptor configuration -->
	<mvc:interceptors>
		<mvc:interceptor>
		<!-- Include all requests below this request -->
			<mvc:mapping path="/user/**"/>
			<!-- Who's going to intercept -->
			<bean class="com.kuang.config.LoginInterceptor"/>
		</mvc:interceptor>
	</mvc:interceptors>

Add logoff function

Log out, and add a Model in login to obtain user information

/springmvc-07/src/main/java/com/kuang/controller/LoginController.java

	@RequestMapping("/login")
	public String login(HttpSession session,String username,String password,Model model) {
		//Store the user's information in the session to facilitate downward transmission;
		session.setAttribute("userLoginInfo", username);
		model.addAttribute("username",username);
		return "main";
	}	

	@RequestMapping("/goOut")
	public String goOut(HttpSession session) {
		//Deletes the specified attr object
		session.removeAttribute("userLoginInfo");
		
		return "main";
	}

home page

/springmvc-07/src/main/webapp/jsp/main.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<h1>home page</h1>

<!-- User information is displayed on the home page -->
User information:<span>${username}</span>
    
<p>
	<a href="${pageContext.request.contextPath}/user/goOut">cancellation</a>    
</p>

</body>
</html>

? Question: after the user information is displayed on the home page, refresh the web page again, and the user information will be empty

File upload and download

File upload is one of the most common functions in project development. Spring MVC can well support file upload, but MultipartResolver is not installed in the spring MVC context by default, so it cannot handle file upload by default. If you want to use spring's file upload function, you need to configure MultipartResolver in the context.

Front end form requirements: in order to upload files, the method of the form must be set to POST and the enctype must be set to multipart / form data. Only in this case, the browser will send the file selected by the user to the server as binary data;

Give a detailed description of the enctype attribute in the form:

  • Application / x-www = form urlencoded: by default, only the value attribute value in the form field is processed. Forms with this encoding method will process the value in the form field into URL encoding.
  • Multipart / form data: this encoding method will process form data in the form of binary stream. This encoding method will also encapsulate the contents of the file specified in the file field into the request parameters, and will not encode characters.
  • text/plain: except for converting spaces into "+" signs, other characters are not encoded. This method is applicable to sending mail directly through forms.
<form action="" enctype="multipart/form-data" method="post">
    <input type="file" name="file"/>
    <input type="submit">
</form>

Once the enctype is set to multipart / form data, the browser will process the form data in the form of binary stream, and the processing of file upload involves parsing the original HTTP response on the server side. In 2003, the Apache Software Foundation released the open source Commons FileUpload component, which soon became the best choice for Servlet/JSP programmers to upload files.

  • The Servlet 3.0 specification already provides methods to handle file uploads, but such uploads need to be done in the Servlet.
  • Spring MVC provides a simpler encapsulation.
  • Spring MVC provides direct support for file upload, which is implemented with the plug and play MultipartResolver.
  • Spring MVC implements a MultipartResolver implementation class using Apache Commons FileUpload Technology:
  • CommonsMultipartResolver. Therefore, the file upload of spring MVC also depends on the component of Apache Commons FileUpload.

1, File upload

1. Import the jar package uploaded by the file, commons file upload, and Maven will automatically help us import his dependent package commons IO package;

<!--File upload-->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.3</version>
</dependency>
<!--servlet-api Import a later version of-->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
</dependency>

2. Configuration bean: multipartResolver

[note!!! The id of this bena must be: multipartResolver, otherwise an error of 400 will be reported when uploading the file! I've planted a pit here, and I'll teach you a lesson!]

<!--File upload configuration-->
<bean id="multipartResolver"  class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- The encoding format of the request must be and jSP of pageEncoding Property is consistent so that the contents of the form can be read correctly. The default is ISO-8859-1 -->
    <property name="defaultEncoding" value="utf-8"/>
    <!-- Maximum upload file size, in bytes (10485760)=10M) -->
    <property name="maxUploadSize" value="10485760"/>
    <property name="maxInMemorySize" value="40960"/>
</bean>

Common methods of CommonsMultipartFile:

String getOriginalFilename(): get the original name of the uploaded file

InputStream getInputStream(): get file stream

void transferTo(File dest): save the uploaded file to a directory file

Let's actually test it

3. Write front page

<form action="/upload" enctype="multipart/form-data" method="post">
  <input type="file" name="file"/>
  <input type="submit" value="upload">
</form>

4,Controller

package com.kuang.controller;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
 
import javax.servlet.http.HttpServletRequest;
import java.io.*;
 
@Controller
public class FileController {
    //@RequestParam("file") encapsulates the file obtained by the name=file control into a CommonsMultipartFile object
    //If you upload CommonsMultipartFile in batch, it can be an array
    @RequestMapping("/upload")
    public String fileUpload(@RequestParam("file") CommonsMultipartFile file , HttpServletRequest request) throws IOException {
 
        //Get file name: file.getOriginalFilename();
        String uploadFileName = file.getOriginalFilename();
 
        //If the file name is empty, go back to the home page directly!
        if ("".equals(uploadFileName)){
            return "redirect:/index.jsp";
        }
        System.out.println("Upload file name : "+uploadFileName);
 
        //Upload path save settings
        String path = request.getServletContext().getRealPath("/upload");
        //If the path does not exist, create one
        File realPath = new File(path);
        if (!realPath.exists()){
            realPath.mkdir();
        }
        System.out.println("Upload file storage address:"+realPath);
 
        InputStream is = file.getInputStream(); //File input stream
        OutputStream os = new FileOutputStream(new File(realPath,uploadFileName)); //File output stream
 
        //Read write
        int len=0;
        byte[] buffer = new byte[1024];
        while ((len=is.read(buffer))!=-1){
            os.write(buffer,0,len);
            os.flush();
        }
        os.close();
        is.close();
        return "redirect:/index.jsp";
    }
}

5. Test upload file, OK!

Use file.Transto to save the uploaded file

1. Write Controller

/*
 * Use file.Transto to save the uploaded file
 */
@RequestMapping("/upload2")
public String  fileUpload2(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
 
    //Upload path save settings
    String path = request.getServletContext().getRealPath("/upload");
    File realPath = new File(path);
    if (!realPath.exists()){
        realPath.mkdir();
    }
    //Upload file address
    System.out.println("Upload file storage address:"+realPath);
 
    //Write the file directly through the CommonsMultipartFile method (note this time)
    file.transferTo(new File(realPath +"/"+ file.getOriginalFilename()));
 
    return "redirect:/index.jsp";
}

2. Front end form submission address modification

3. Visit submit test, OK!

2, File download

1. Set response header

2. Read file – InputStream

3. Write out file – OutputStream

4. Perform operation

5. Close flow (first on then off)

Code implementation:

@RequestMapping(value="/download")
public String downloads(HttpServletResponse response ,HttpServletRequest request) throws Exception{
    
    //To modify, you only need to change this position
    //Address of the picture to download
    String  path = request.getServletContext().getRealPath("/upload");
    String  fileName = "Basic grammar.jpg";
 
    //1. Set response header
    response.reset(); //Set the page not to be cached, and clear the buffer
    response.setCharacterEncoding("UTF-8"); //Character encoding
    response.setContentType("multipart/form-data"); //Binary transmission data
    //Set response header
    response.setHeader("Content-Disposition",
            "attachment;fileName="+URLEncoder.encode(fileName, "UTF-8"));
 
    File file = new File(path,fileName);
    //2. Read file -- input stream
    InputStream input=new FileInputStream(file);
    //3. Write out file -- output stream
    OutputStream out = response.getOutputStream();
 
    byte[] buff =new byte[1024];
    int index=0;
    //4. Perform a write out operation
    while((index= input.read(buff))!= -1){
        out.write(buff, 0, index);
        out.flush();
    }
    out.close();
    input.close();
    return null;
}

front end

<a href="/download">Click download</a>

Test, file download OK, you can compare with the Java Web native way we learned before, and you can know that this is much more convenient!

Interceptors and file operations are very important in our development. We must learn to use them!

Easier way

If you create a statistics folder, store 1.png

<a href="${pageContext.request.contextPath}/statics/1.png">Download pictures</a>

Directly use the a tag to obtain the file, and the file will be downloaded

SSM integration review

Posted by omidh on Mon, 29 Nov 2021 11:02:43 -0800