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:
-
Check whether the bean injection is successful
-
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.
-
There must be something wrong with Spring
-
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
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)
3. The class in the target of ECLIPS is hidden
Unhide method
- 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
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"; }
- Send the query results to the new display page "allbook" and present them
- However, due to the List collection used by the display page, the passed in value needs to be passed to the List collection
- At the same time, judge that if the query value is empty, all book display pages will be presented
- 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> | <a href="${pageContext.request.contextPath}/book/deleteBook/${book.bookID}">delete</a> </td> </tr> </c:forEach> </tbody> </table> </div> </div> </div> </body> </html>
- First, the query function is added by using the from tag
- Use form inline to turn the form into a row of inline forms, and ${error} "not found" prompt
- 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
- First design a plan pop-up page. You don't need to enter an address, just a size
- Design a user to enter the URL and then click the button event
- 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
- Draw a page < Table >, display < tr >, data < tbody > (but the data is in the background, so you need to use ajax to request data)
- Load jquery, use the id selector < script > to get and click the event
- Directly abbreviate the request to post and obtain the return value data. Here, we can obtain resources normally.
- 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
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