Simple project "book management system" based on SSM framework, super detailed explanation, with source code

Table of contents

I have something to say:

1 Project Introduction

2 project display

2.1 First create the database and table information

2.2 Preparation in advance

2.3 Start configuring the project

2.4 Start the web layer

3 pictures show

4 Attach the source code file (Baidu network disk):


I have something to say:

  • First of all, there is a lot of content and the length is relatively long. If you need it, you can read it patiently.
  • This project was first written down with Mad God, with a detailed video link and detailed notes attached to Mad God:

17. ssm integration: Mybatis layer_哔哩哔哩_bilibili https://www.bilibili.com/video/BV1aE41167Tu?p=17&vd_source=b1036c3d2e010aa91f6ccb4fed6293ec Mad God SSM Tutorial-Column-KuangStudy https://www.kuangstudy.com /zl/ssm#1377532368339955713

"If you don't have the basis of the SSM framework, it is recommended to learn the basics of SSM first, which sounds much easier."

  • I didn’t encounter any errors when writing the project with Kuangshen, but after I finished writing, I felt that if it was just this, I was not satisfied, so I basically wrote all the content I would know in this project. I think this is my kind of progress.
  • Normally, a project should be done step by step from the beginning to the end. Due to time constraints, we cannot show it step by step.
  • Although the content is for the entire project, it is recommended to type it again by hand, because there will always be some unnecessary problems in copying and pasting, even if the code is correct, there may still be problems in copying and pasting.
  • The jsp page in the project can be written with vscode first and then copied to the jsp page.
  • The so-called framework is to set up a shelf, and then all operations are carried out inside the framework. There is no need to make other modifications to the framework, and some operations can be done for you by handing over to the Spring framework.
  • Some problems encountered in writing this project: garbled information in the previous paragraph, pagination query, most js operations, sometimes it may not be a code problem...etc, but fortunately stick to it and solve it one by one, this project It can still be improved in some aspects, such as multi-table query, page jump animation, paging information, some nice css styles, etc.
  • Knowledge is not learned in vain, learning is endless.

1 Project Introduction

1. Development environment:

  • JDK1.8; mysql8.0.31; mybatis3.5.2; mybatis-spring2.0.2; spring-webmvc and springjdbc are both 5.1.9.RELEASE (I personally think it is the most comfortable version to use at present)

2. Development software:

  • Visual front-end: VSCode; database: navicat; backend: IDEA2021.3.3; server: Tomcat

3. Other plug-ins: lombok PageHelper fileupload

4. The project is implemented through the SSM framework, and its functions include " basic CRUD; user login, registration and logout; interceptor; paging; file upload and file download, and some front-end operations, etc. "

2 project display

2.1 First create the database and table information

   1. book form

CREATE DATABASE javawork;
USE javawork;
DROP TABLE IF EXISTS `book`;
CREATE TABLE `book`  (
  `bookid` int(0) NOT NULL AUTO_INCREMENT COMMENT 'uuid',
  `bookname` varchar(20) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '图书名称',
  `author` varchar(30) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '作者',
  `publish` varchar(30) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '出版社',
  `introduction` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '简介',
  `price` double NOT NULL COMMENT '价格',
  `booktype` varchar(10) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '书籍类型',
  PRIMARY KEY (`bookid`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 19 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci COMMENT = '图书信息' ROW_FORMAT = Dynamic;


INSERT INTO `book` VALUES (1, '西游记', '吴承恩', '人民文学出版社', '师徒四人去西天取真经', 42, '奇幻类');
INSERT INTO `book` VALUES (2, '三国演义', '罗贯中', '清华大学出版社', '东汉末年分三国。。。', 48, '历史类');
INSERT INTO `book` VALUES (3, '红楼梦', '曹雪芹', '机械工业出版社', '宝玉与众多男女之间故事', 39, '历史类');
INSERT INTO `book` VALUES (4, '资本论', '马克思', '原子能出版社', '马克思的剩余价值理论', 42, '经济类');
INSERT INTO `book` VALUES (5, '经济学原理', '马歇尔', '机械工业出版社', '西方经济学界公认为划时代的著作', 66, '经济类');
INSERT INTO `book` VALUES (6, '大变局下的中国法治', '李卫东', '北京大学出版社', '十大经典法学著作', 42, '政治类');
INSERT INTO `book` VALUES (7, '从你的全世界路过', '张嘉佳', '湖南文艺出版社', '38个爱情故事的小说集', 36, '爱情类');
INSERT INTO `book` VALUES (8, '天才在左,疯子在右', '高铭', '武汉大学出版社', '国内第一本精神病人访谈手记', 30, '教育类');
INSERT INTO `book` VALUES (9, '追风筝的人', '卡勒德·胡赛尼', '上海人民出版社', '人性的背叛与救赎', 36, '情感类');
INSERT INTO `book` VALUES (10, '水浒传', '施耐庵', '人民文学出版社', '108位梁山好汉', 52, '武侠类');
INSERT INTO `book` VALUES (11, '羊脂球', '莫泊桑', '北京联合出版公司', '法国社会各阶层的丑恶嘴脸', 41, '社会类');
INSERT INTO `book` VALUES (12, '百年孤独', '加西亚·马尔克斯', '上海译文出版社', '布恩迪亚家族七代人的百年兴衰', 55, '文学类');
INSERT INTO `book` VALUES (13, '平凡的世界', '路遥', '北京十月文艺出版社', '中国西北农村的历史变革', 58, '文学类');
INSERT INTO `book` VALUES (14, '三体', '刘慈欣', '科幻世界出版社', '征服世界的中国科幻神作', 62, '科幻类');
INSERT INTO `book` VALUES (15, '解忧杂货店', '东野圭谷', '南海出版公司', '收集烦恼和困扰的杂货店', 54, '文学类');
INSERT INTO `book` VALUES (16, '白鹿原', '陈忠实', '人民文学出版社', '中国农村的50年变革', 40, '文学类');
INSERT INTO `book` VALUES (17, '茶馆', '舒庆春(老舍)', '社会科学文献出版社', '一个茶馆的近50年经历', 35, '文学类');
INSERT INTO `book` VALUES (18, '围城', '钱锺书', '上海晨光出版社', '外边的人想进去,里面的人想出来', 30, '文学类');
INSERT INTO `book` VALUES (19, '海边的卡夫卡', '村上春树', '上海译文出版社', '田村卡夫卡的精神救赎', 40, '文学类');
INSERT INTO `book` VALUES (20, '我这一辈子', '舒庆春(老舍)', '中国华侨出版社', '舒庆春的一生', 36, '其他类');
INSERT INTO `book` VALUES (21, '世上另一个我', '萨拉·帕坎南', '湖南文艺出版社', '我在别人设定的角色里拼命挣扎,以为那是我想要的人生', 28, '亲情类');
INSERT INTO `book` VALUES (22, '看见', '柴静', '广西师范大学出版社', '中国社会十年变迁的备忘录', 40, '社会文学类');

2. user table

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int(0) NOT NULL AUTO_INCREMENT COMMENT '用户id',
  `username` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '用户名',
  `password` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '用户密码\r\n',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 16 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = Dynamic;


INSERT INTO `user` VALUES (1, 'admin', '123456');

2.2 Preparation in advance

Create a new Maven project "Book" 

1. Right-click the Book module, select framework support, and select web application (version 4.0); you can also use the web-app template when selecting a Maven project, but it is not recommended.

Then there will be an extra web folder in the project. Note: the small dot of the folder icon must be on, otherwise go to Facet to adjust the selection to the current project. 

 2. Introduce dependencies

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.gcx</groupId>
    <artifactId>Book</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <!--    导入依赖-->
    <dependencies>
        <!--Junit单元测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <!--数据库驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.31</version>
        </dependency>
        <!-- 数据库连接池 -->
        <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/SpringMVC-->
        <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>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.7</version>
        </dependency>
<!--        文件上传-->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
        </dependency>
<!--        myBatis分页插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.3.2</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>

3. In order to avoid 404, create a lib file (you must ensure that all dependencies have been added to maven)

After clicking the plus sign, select the library file, select all, add, and apply

4. Configure the Tomcat server

 Then apply and confirm

5. Test whether the Tomcat server can run normally

 After starting Tomcat, the browser enters the index.jsp page named $Title$, and displays $END information, indicating that the Tomcat configuration is ok

 2.3 Start configuring the project

1. Create the project structure

The java folder belongs to source code files, the resources folder belongs to resource files, and the web folder contains some front-end configuration files and pages.

 2. Start writing entity classes

The entity class name needs to be consistent with the database table name

Book

package com.gcx.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@SuppressWarnings("all")
public class Book {
    private int bookid;
    private String bookname;
    private String author;
    private String publish;
    private String introduction;
    private Double price;
    private String booktype;
}

User

package com.gcx.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String username;
    private String password;
}

 3. Write the persistence layer (dao layer)

BookMapper interface

package com.gcx.dao;

import com.gcx.pojo.Book;
import com.gcx.pojo.User;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface BookMapper {
    //    增加一本书
    int addBook(Book book);
    //    删除一本书
    int deleteBookById(@Param("bookid") int id);
    //    更新一本书
    int updateBook(Book book);
    //    查询一本书
    Book queryBookById(@Param("bookid") int id);
    //    通过书名查询书籍,因为可能是一个集合,所以用List
    List<Book> queryBookByName(@Param("bookname") String bookname);
    //    获取登录信息
    User findUserByNameAndPassword(User user);
    //    分页
    List<Book> findList();
    //    注册
    int adduser(User user);


}

Because you want to link the database through mybatis, you need to configure its core configuration file: 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>
    <typeAliases>
        <package name="com.gcx.pojo"/>
    </typeAliases>
    <mappers>
        <mapper class="com.gcx.dao.BookMapper"/>
    </mappers>
</configuration>

 database.properties

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/javawork?useSSL=true&useUnicode=true&characterEncoding=utf8&ServerTimezone=Asia/Shanghai
jdbc.username=root
jdbc.password=123456

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">
    <Context:property-placeholder location="classpath:database.properties"/>
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="password" value="${jdbc.password}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="driverClass" value="${jdbc.driver}"/>
        <!--    配置数据库连接池属性-->
        <property name="maxPoolSize" value="30"/>
        <property name="minPoolSize" value="10"/>
        <!-- 关闭连接后不自动commit -->
        <property name="autoCommitOnClose" value="false"/>
        <!-- 获取连接超时时间 -->
        <property name="checkoutTimeout" value="10000"/>
        <!-- 当获取连接失败重试次数 -->
        <property name="acquireRetryAttempts" value="2"/>
    </bean>
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <!--        配置分页插件-->
        <property name="plugins">
            <array>
                <bean class="com.github.pagehelper.PageInterceptor">
                    <property name="properties">
                        <value>
                            helperDialect = mysql
                            reasonable = true
                        </value>
                    </property>
                </bean>
            </array>
        </property>
    </bean>

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <property name="basePackage" value="com.gcx.dao"/>
    </bean>

</beans>

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

If there is an error report, don’t worry about it, because the corresponding XML file has not been configured yet.

Note that there will be a prompt to configure the context of the application

 Click Configure Application Context to create a new application context

Click OK, enter the project settings, click the module, check whether the configuration is successful

 To complete the database link, configure BookMapper.xml

<?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.gcx.dao.BookMapper">
    <insert id="addBook" parameterType="book">
        insert into book(bookname,author,publish,introduction,price,booktype)
        values(#{bookname},#{author},#{publish},#{introduction},#{price},#{booktype});
    </insert>
    <delete id="deleteBookById" parameterType="int">
        delete from book where bookid =#{bookid};
    </delete>
    <update id="updateBook" parameterType="book">
        update book set bookname=#{bookname},author=#{author},publish=#{publish},introduction=#{introduction},price=#{price},booktype=#{booktype}
        where bookid=#{bookid};
    </update>
    <select id="queryBookById" resultType="book">
        select *from book where bookid = #{bookid};
    </select>
    <select id="queryBookByName" resultType="book">
        select *from book where bookname = #{bookname};
    </select>
    <select id="findUserByNameAndPassword" resultType="User">
        select *
        from user
        where username = #{username} and password = #{password};
    </select>
    <select id="findList" resultMap="booksresultmap">
        select *
        from book
    </select>
    <resultMap id="booksresultmap" type="com.gcx.pojo.Book">
        <id property="bookid" column="bookid" jdbcType="INTEGER"/>
        <result property="bookname" column="bookname" jdbcType="VARCHAR"/>
        <result property="author" column="author" jdbcType="VARCHAR"/>
        <result property="publish" column="publish" jdbcType="VARCHAR"/>
        <result property="introduction" column="introduction" jdbcType="VARCHAR"/>
        <result property="price" column="price" jdbcType="DOUBLE"/>
        <result property="booktype" column="booktype" jdbcType="INTEGER"/>
    </resultMap>
    <insert id="adduser" parameterType="user">
        insert into user(username,password)
        values (#{username},#{password});
    </insert>
</mapper>

4. Write business layer code (service interface and implementation class)

BookService

package com.gcx.service;

import com.gcx.pojo.Book;
import com.gcx.pojo.User;
import com.github.pagehelper.PageInfo;

public interface BookService {
    //    增加一本书
    int addBook(Book book);
    //    删除一本书
    int deleteBookById(int id);
    //    更新一本书
    int updateBook(Book book);
    //    查询一本书
    Book queryBookById(int id);
    //    通过书名查询书籍
    PageInfo<Book> queryBookByName(String bookname);
    //    获取登录信息
    User findUserByNameAndPassword(User user);
    //    分页查询
    PageInfo<Book> findList(Integer pageNum, Integer pageSize);
    //    注册
    int adduser(User user);
}

BookServiceImpl

package com.gcx.service;

import com.gcx.dao.BookMapper;
import com.gcx.pojo.Book;
import com.gcx.pojo.User;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;

public class BookServiceImpl implements BookService {
    private BookMapper bookMapper;

    public void setBookMapper(BookMapper bookMapper) {
        this.bookMapper = bookMapper;
    }

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

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

    @Override
    public int updateBook(Book book) {
        return bookMapper.updateBook(book);
    }

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

    @Override
    public PageInfo<Book> queryBookByName(String bookname) {
        List<Book> list = bookMapper.queryBookByName(bookname);
        return new PageInfo<>(list);
    }

    @Override
    public User findUserByNameAndPassword(User user) {
        return bookMapper.findUserByNameAndPassword(user);
    }

    @Override
    public PageInfo<Book> findList(@RequestParam Integer pageNum,
                                   @RequestParam Integer pageSize) {
        //        每页显示多少数据
        if (pageSize== null){
            pageSize=5;
        }
        PageHelper.startPage(pageNum,pageSize);
        List<Book> list = bookMapper.findList();
//        for (Books books : list) {
//            System.out.println("书籍信息:"+books);
//        }
        PageInfo PageInfo = new PageInfo(list);
        System.out.println("总页数:"+PageInfo.getPages());
        System.out.println("总记录数:"+PageInfo.getTotal());
        System.out.println("当前页数:"+PageInfo.getPageNum());
        System.out.println("当前页面记录数:"+PageInfo.getPageSize());
        return new PageInfo<>(list);
    }

    @Override
    public int adduser(User user) {
        return bookMapper.adduser(user);
    }
}

 Configure 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"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/cache"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
    <Context:component-scan base-package="com.gcx.service"/>
    <bean id="BookServiceImpl" class="com.gcx.service.BookServiceImpl">
        <property name="bookMapper" ref="bookMapper"/>
    </bean>
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

</beans>

The configuration context is applicationContext.xml.

5. Configure 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 https://www.springframework.org/schema/context/spring-context.xsd">
<!--    开启注解-->
    <mvc:annotation-driven/>
<!--    过滤静态资源-->
    <mvc:default-servlet-handler/>
<!--    扫描包下注解-->
    <Context:component-scan base-package="com.gcx.controller"/>
<!--    视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
<!--    配置拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/book/**"/>
            <bean class="com.gcx.interceptor.LoginInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
    <!--文件上传配置-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 请求的编码格式,必须和jSP的pageEncoding属性一致,以便正确读取表单的内容,默认为ISO-8859-1 -->
        <property name="defaultEncoding" value="utf-8"/>
        <!-- 上传文件大小上限,单位为字节(10485760=10M) -->
        <property name="maxUploadSize" value="10485760"/>
        <property name="maxInMemorySize" value="40960"/>
    </bean>
</beans>

If an error is reported where the interceptor is configured, it is because there are no interceptor classes, you can create one without writing content first.

The configuration context is applicationContext.xml

At this time, it is displayed in the Spring module as follows:

At this point, the underlying code is basically completed. Then there are links between the front and back ends:

In MVC, it is realized through the HttpServlet of the Servlet layer, and in SpringMVC, it is realized by adding annotations in the Controller layer or inheriting the Controller interface.

6. BookController

package com.gcx.controller;

import com.gcx.pojo.Book;
import com.gcx.pojo.User;
import com.gcx.service.BookService;
import com.github.pagehelper.PageInfo;
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.*;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.net.URLEncoder;
/**
 * author: labixiaoxin@
 * advice: Controller层可以写的更分工明确;
 * 新建LoginController来写登录.注册.注销的实现;
 * 新建PageController用来写分页的实现;
 * ...其他类似
 */

@Controller
@RequestMapping("/book")
@SuppressWarnings("all")
public class BookController {
    @Autowired
    @Qualifier("BookServiceImpl")
    private BookService bookService;

    //    跳转到登录页
    @RequestMapping("toLogin")
    public String Login() {
        return "Login";
    }
    
//    进入登录页
    /**
     *
     * @param session 将数据保存在session中
     * @param user    数据库内的用户登录信息
     * @param model   将数据通过el表达式显示在页面
     * @return 跳转页面
     */
    @RequestMapping("Login")
    public String Login(HttpSession session, User user, Model model) {
//        用来获取user内的信息
        User userByNP = bookService.findUserByNameAndPassword(user);
        /**
         *
         * 调用业务层接口内方法
         * 判断用户信息是否正确,且用户信息不为空.
         * 将user信息保存在session中,并进入首页
         * 否则返回error1信息
         */
        if (userByNP != null) {
            session.setAttribute("userLoginInfo", user);
            System.out.println(user);
            return "redirect:/book/allbook/1";
        } else {
            model.addAttribute("error1", "账号或密码错误,请重新输入");
            return "Login";
        }
    }

    //   跳转注册
    @RequestMapping("toregisterPage")
    public String toregisterPage() {
        return "register";
    }

    //    注册sql
    /**
     *
     * @param username
     * @param password 用@RequestParam获取前段传递的信息获取用户名和密码
     * @param session
     * @return
     */
    @GetMapping("register")
    public String register(
            @RequestParam("username") String username,
            @RequestParam("password") String password, HttpSession session) {
        User user = new User();
        user.setUsername(username);
        user.setPassword(password);
        bookService.adduser(user);
        session.setAttribute("userLoginInfo", user);
        System.out.println(user);
        return "Login";
    }

    /**
     *
     * 两种方法:
     *      1.removeAttribute 移除指定的信息
     *      2.invalidate 移除session中所有信息
     * @param
     * @return
     */
    @RequestMapping("destory")
    public String destory(HttpSession session) {
        session.removeAttribute("userLoginInfo");
//        session.invalidate();
//        User user = new User();
//         验证是否注销成功
//        System.out.println(user.toString());
        return "Login";
    }

    //    登录页面进入首页
    @RequestMapping("toallbook")
    public String toallbook() {
        return "allbook";
    }
    
    //    查询全部书籍(首页)
    /**
     *
     *对展示页面进行分页
     * @param pageIndex 当前页码
     * @param model     给前端传信息
     *                  if:如果当前页码<=1,则设置为第一页
     *                  pageSize=null=5
     * 在Service接口中返回PageInfo类型,保存到"PageInfo"中,方便前段调用PageInfo属性
     * @return
     */
    @GetMapping("allbook/{num}")
    public String list(@PathVariable("num") Integer pageIndex, Model model) {
        if (pageIndex <= 1) {
            pageIndex = 1;
        }
        PageInfo<Book> list = bookService.findList(pageIndex, null);
        model.addAttribute("PageInfo", list);
        return "allbook";
    }
    
    //跳转到新增书籍页面
    @RequestMapping("toAddBook")
    public String toAddPaper() {
        return "addBook";
    }

    //执行sql新增书籍
    @RequestMapping("addBook")
    public String addBook(Book book) {
        bookService.addBook(book);
        return "redirect:/book/allbook/1";
    }

    //    跳转到更改书籍页面
    @RequestMapping("toupdateBook")
    public String toupdatePaper(int id, Model model) {
        Book book = bookService.queryBookById(id);
        model.addAttribute("Book", book);
        return "updatebook";
    }

    //    执行sql更改书籍
    @RequestMapping("updateBook")
    public String updateBook(Book book) {
        bookService.updateBook(book);
        return "redirect:/book/allbook/1";
    }
    
//    执行sql删除书籍
    /**
     *
     * @param id restful风格
     * @return
     */
    @RequestMapping("deletebook/{bookid}")
    public String deleteBook(@PathVariable("bookid") int id) {
        bookService.deleteBookById(id);
        return "redirect:/book/allbook/1";
    }
    
//    执行SQL(根据书籍名称)查询书籍
    /**
     *
     * @param queryBookname 查询书籍的名字
     * @param model
     * @return
     */
    @GetMapping("querybook")
    public String queryBook(@RequestParam("queryBookname") String queryBookname,
                            Model model) {
        PageInfo<Book> list = bookService.queryBookByName(queryBookname);
//        如果输入为空或输入的信息不存在,返回error信息
//        if (queryBookname == null) {
//            list = bookService.queryAllBook();
//            model.addAttribute("error1", "没有该书籍,请重新查询");
//        }
            System.out.println(list);
            model.addAttribute("PageInfo", list);
            return "allbook";
    }
    
    /**
     * 文件上传
     * @param file
     * @param request
     * @return
     * @throws IOException
     *
     * @RequestParam("file") 将name=file控件得到的文件封装成CommonsMultipartFile 对象
     * 批量上传CommonsMultipartFile则为数组即可
     */
    @RequestMapping("/upload")
    public String fileUpload(@RequestParam("file") CommonsMultipartFile file , HttpServletRequest request) throws IOException {
//      file.getOriginalFilename() :获取文件名;
        String uploadFileName = file.getOriginalFilename();
//      如果文件名为空,直接回到首页!
            if ("".equals(uploadFileName)){
                return "redirect:/book/allbook/1";
            }
        System.out.println("上传文件名 : "+uploadFileName);
//      上传路径保存设置(绝对路径)
        String path = "C:\\Users\\Gu_cx\\Desktop\\Book\\web\\upload";
//      如果路径不存在,创建一个
        File realPath = new File(path);
            if (!realPath.exists()){
                realPath.mkdir();
            }
        System.out.println("上传文件保存地址:"+realPath);
        InputStream is = file.getInputStream(); //文件输入流
        OutputStream os = new FileOutputStream(new File(realPath,uploadFileName)); //文件输出流
//      读取写出
        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:/book/allbook/1";
    }
    
//    下载图片
    @RequestMapping(value="/download")
    public String downloads(HttpServletResponse response , HttpServletRequest request) throws Exception{
//      要下载的图片地址(绝对路径)
        String path = "C:\\Users\\Gu_cx\\Desktop\\Book\\web\\img\\idea.png";
        String fileName = path.substring(path.lastIndexOf("\\")+1);
//      1、设置response 响应头
            response.reset(); //设置页面不缓存,清空buffer
            response.setCharacterEncoding("UTF-8"); //字符编码
            response.setContentType("multipart/form-data"); //二进制传输数据
//      设置响应头(百度web下载文件的头信息)
            response.setHeader("Content-Disposition",
                "attachment;fileName="+ URLEncoder.encode(fileName, "UTF-8"));
//      2、 读取文件--输入流
        InputStream input=new FileInputStream(path);
//      3、 写出文件--输出流
        OutputStream out = response.getOutputStream();
        byte[] buff =new byte[1024];
        int index=0;
//      4、执行 写出操作
        while((index= input.read(buff))!= -1){
            out.write(buff, 0, index);
            out.flush();
        }
        out.close();
        input.close();
        return null;
    }
}

7. LoginInterceptor interceptor

package com.gcx.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;

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

public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
/**
*
*因为是boolean 的返回类型,true代表可以通过拦截器,false代表被拦截器拦截,不能够通过
*/
//      设置编码格式
        request.setCharacterEncoding("UTF-8");
        HttpSession session = request.getSession();
//     通过Controller中的setAttribute保存的信息,在这里通过get获取到,如果userLoginInfo内不为空时可以通过
        if ( session.getAttribute("userLoginInfo")!=null){
            System.out.println("执行了登录拦截器=>111");
            return true;
        }
//     getRequestURI().contains属于获取URL的地址,让URL进入到toLogin;Login;toregisterPage;register时可以通过
        if (request.getRequestURI().contains("toLogin")){
            System.out.println("执行了登录拦截器=>222");
            return true;
        }
        if (request.getRequestURI().contains("Login")){
            System.out.println("执行了登录拦截器=>333");
            return true;
        }
        if (request.getRequestURI().contains("toregisterPage")){
            System.out.println("执行了登录拦截器=>444");
            return true;
        }
        if (request.getRequestURI().contains("register")){
            System.out.println("执行了登录拦截器=>555");
            return true;
        }
//        判断当不满足以上条件使,都要被拦截器拦截,不能通过并重定向到Login.jsp页面
        request.getRequestDispatcher("/WEB-INF/jsp/Login.jsp").forward(request,response);
        return false;
    }
}

 At this point, the source code and configuration file layers have been completed

2.4 Start the web layer

First, because the prefix in the view parser is the jsp folder under WEB-INF, create a new jsp file under WEB-INF

 1. First index.jsp (jump to the page)

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
  Created by IntelliJ IDEA.
  User: 蜡笔小鑫
  Date: 2022/12/29
  Time: 15:11
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
  <meta charset="utf-8">
  <title>首页</title>
<%--    使用纯jquery实现轮播图;
优点:适合新手;
缺点:浪费资源,每次加载页面都要更新请求,占用内存和网络--%>
  <script src="https://cdn.bootcss.com/jquery/1.10.2/jquery.min.js"></script>
  <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
  <link rel="stylesheet" href="${pageContext.request.contextPath}/css/index.css">
  <script src="js/index.js">
  </script>
</head>
<body>
<table>
    <tr>
        <td>
            <header>

                <div class="bigBox" id="oImg">
                    <!-- 轮流播放图片 -->
                    <img id="insert" src="indexImg/1.jpg"/>
                </div>
                <p class="left" onclick="goBack()"></p>
                <p class="right" onclick="goForward()"></p>
                <ul id="nav">
                    <!-- 指定某张图片 -->
                    <li id="1" onclick="move(this)">1</li>
                    <li id="2" onclick="move(this)">2</li>
                    <li id="3" onclick="move(this)">3</li>
                    <li id="4" onclick="move(this)">4</li>
                    <li id="5" onclick="move(this)">5</li>
                    <li id="6" onclick="move(this)">6</li>
                </ul>
            </header>
        </td>
        <td>
            <h1 class="threesolid">欢迎进入书籍管理系统</h1>
            <div class="texts">
               <!-- 所有的转发地址都要养成写${pageContext.request.contextPath}的习惯 -->
                <a class="btn btn--stripe" href="${pageContext.request.contextPath}/book/toLogin">登录</a><br>
                <a class="btn btn--stripe" href="${pageContext.request.contextPath}/book/allbook">进入书籍页面</a>
            </div>
        </td>
    </tr>

</table>
</body>
</html>

 2. Home page allbook

<%--
  Created by IntelliJ IDEA.
  User: 蜡笔小鑫
  Date: 2022/12/25
  Time: 14:38
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>书籍展示</title>
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <style>
        .title{
            font-family:"华文彩云";/*设置字体*/
            font-size:64px; /*设置字体大小*/
            font-weight:normal; /*设置字体粗细*/
            -webkit-text-stroke:1px #0000FF;        /*文字描边*/
            -webkit-text-fill-color:transparent;    /*设置文字的填充颜色*/
        }
    </style>
    <script>
    /*页面弹窗*/
    function ok(){
            alert("删除成功");
        }
    </script>
</head>
<body>
<div class="title">书籍展示</div>
<div class="container">
    <div class="row clearfix">
        <div class="col-md-12 column">
            <div class="page-header">
                <h1>
                    <small>书籍列表----显示所有书籍</small>
                </h1>
                <div style="text-align: right">
                    <a href="${pageContext.request.contextPath}/book/allbook/1" title="返回显示全部书籍">首页</a>
                    <a href="${pageContext.request.contextPath}/book/toLogin" title="返回登录页面">登录</a>
                    <a href="${pageContext.request.contextPath}/book/destory" title="注销当前用户信息">注销</a>
                </div>
            </div>
        </div>
        <div class="row">
            <div class="col-md-4 column">
                <a class="btn btn-primary" href="${pageContext.request.contextPath}/book/toAddBook">新增书籍</a>
            </div>
            <div class="col-md-4 column">
            </div>
            <div class="col-md-4 column">
                <form action="${pageContext.request.contextPath}/book/querybook" method="get" style="float: right">
                    <table>
                        <tr>
                            <%--                            <td style="width: 170px">--%>
                            <%--                                <span style="color: red;font-weight: bold;text-align: right">${error1}</span>--%>
                            <%--                            </td>--%>
                            <td>
                                <input type="text" name="queryBookname" class="form-control" placeholder="请输入要查询的书籍名称">
                            </td>
                            <td>&nbsp;</td>
                            <td>
                                <input type="submit" value="查询" class="btn btn-primary">
                            </td>
                        </tr>
                    </table>
                </form>
            </div>
        </div>
    </div>
    <div class="row clearfix ">
        <div col-md-12 column class=" table-responsive" >
            <table class="table table-hover table-striped">
                <thead>
                <tr>
                    <th>书籍名称</th>
                    <th>作者</th>
                    <th>出版社</th>
                    <th>书籍编号</th>
                    <th>详情</th>
                    <th>价格</th>
                    <th>书籍类别</th>
                    <th>操作</th>
                </tr>
                </thead>
                <tbody>
                    /*调用PageInfo里的list属性*/
                <c:forEach items="${PageInfo.list}" var="book" >
                    <tr>
                        <td>${book.bookname}</td>
                        <td>${book.author}</td>
                        <td>${book.publish}</td>
                        <td>${book.bookid}</td>
                        <td>${book.introduction}</td>
                        <td>${book.price}</td>
                        <td>${book.booktype}</td>
                        <td>
                            <a href="${pageContext.request.contextPath}/book/toupdateBook?id=${book.bookid}">修改</a>
                            &nbsp;|&nbsp;
                            <a href="${pageContext.request.contextPath}/book/deletebook/${book.bookid}" onclick="ok()">删除</a>
                            <span>

                            </span>
                        </td>
                    </tr>
                </c:forEach>
                </tbody>
            </table>

            <ul class="pagination">
                <%--    如果当前页码-1>=0,则显示首页,即在第一页时不显示首页--%>
                <c:if test="${PageInfo.prePage-1>=0}">
                    <li><a href="${PageInfo.navigateFirstPage}">首页</a></li>
                </c:if>
                <%--            当有上一页"且"总页数>2时 显示上一页--%>
                <c:if test="${(PageInfo.hasPreviousPage)&&(PageInfo.pages)>2}">
                    <li><a href="${pageContext.request.contextPath}/book/allbook/${num-1}">&lt; 上一页</a></li>
                </c:if>
                <%--                循环显示页数--%>
                <c:forEach items="${PageInfo.navigatepageNums}" var="num">
                    <%--            只需要一个get请求去获得到pageIndex--%>
                    <li><a href="${pageContext.request.contextPath}/book/allbook/${num}">${num}</a></li>
                </c:forEach>
                <%--            当有下一页"且"总页数>2"且"当前页不是最后一页时 显示下一页--%>
                <c:if test="${(PageInfo.hasPreviousPage)&&(PageInfo.pages)>2&&(PageInfo.pageNum!=PageInfo.navigateLastPage)}">
                    <li><a href="${pageContext.request.contextPath}/book/allbook/${num+1}">下一页 &gt;</a></li>
                </c:if>
                <%--            当前页码+1<=总页数,则显尾页,即在最后一页时不显示尾页--%>
                <c:if test="${PageInfo.pageNum+1<=PageInfo.pages}">
                    <li><a href="${PageInfo.navigateLastPage}">尾页</a></li>
                </c:if>
                <span style="font-size: 20px;margin-left: 20px;color: #6363ee">共${PageInfo.pages}页</span>
<%--                <span style="font-size: 20px;margin-left: 20px;color: #6363ee">每页显示--%>
<%--                    <select>--%>
<%--                        <option value="${PageInfo.pageSize==5}">5</option>--%>
<%--                        <option value="${PageInfo.pageSize==10}">10</option>--%>
<%--                    </select>--%>
<%--                    条数据</span>--%>
                <span style="font-size: 20px;margin-left: 20px;color: #6363ee">每页显示${PageInfo.pageSize}条信息</span>
                <span style="font-size: 20px;margin-left: 20px;color: #6363ee">共${PageInfo.total}条信息</span>
            </ul>
            <form style="" action="${pageContext.request.contextPath}/book/upload" enctype="multipart/form-data" method="post">
                <table>
                    <td>
                        <input style="width: 190px" type="file" name="file">
                    </td>
                    <td style="width: 100px">
                        <input type="submit" value="点击上传">
                    </td>
                    <td>
                        <a href="${pageContext.request.contextPath}/img/idea.png">展示图片</a>
                        &nbsp;|&nbsp;
                        <a href="${pageContext.request.contextPath}/book/download">点击下载</a>
                    </td>

                </table>

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

3. Add book page addBook.jsp

<%--
  Created by IntelliJ IDEA.
  User: 蜡笔小鑫
  Date: 2022/12/25
  Time: 17:24
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>添加书籍</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>书籍列表----新增书籍</small>
                </h1>
            </div>
        </div>
    </div>
    <form action="${pageContext.request.contextPath}/book/addBook" method="post">
        <div class="form-group">
            <label for="bkname">书籍名称</label>
            <input type="text" class="form-control" id="bkname" name="bookname" placeholder="书籍名称" required>
        </div>
        <div class="form-group">
            <label for="author">作者</label>
            <input type="text" class="form-control" id="author" name="author" placeholder="作者" required>
        </div>
        <div class="form-group">
            <label for="publish">出版社</label>
            <input type="text" class="form-control" id="publish" name="publish" placeholder="出版社" required>
        </div>
        <div class="form-group">
            <label for="introduction">详情</label>
            <input type="text" class="form-control" id="introduction" name="introduction" placeholder="书籍详情" required>
        </div>
        <div class="form-group">
            <label for="price">价格</label>
            <input type="text" class="form-control" id="price" name="price" placeholder="价格" required>
        </div>
        <div class="select">
            <label for="booktype">书籍类别</label>
            <input type="text" class="form-control" list="optionList" id="booktype" name="booktype" placeholder="书籍类别" required>
            <datalist id="optionList">
                <option value="文学类">文学类</option>
                <option value="历史类">历史类</option>
                <option value="社会类">社会类</option>
                <option value="爱情类">爱情类</option>
                <option value="科幻类">科幻类</option>
                <option value="社会文学类">社会文学类</option>
                <option value="武侠类">武侠类</option>
                <option value="亲情类">亲情类</option>
                <option value="奇幻类">奇幻类</option>
                <option value="政治类">政治类</option>
                <option value="经济类">经济类</option>
                <option value="其他类">其他类</option>
            </datalist>
        </div>
        <button type="submit" class="btn btn-default btn-lg active" style="margin-left:1050px;margin-top: 30px">添加</button>
    </form>
</div>
</body>
</html>

4. Modify the book page updatebook.jsp

<%--
  Created by IntelliJ IDEA.
  User: 蜡笔小鑫
  Date: 2022/12/25
  Time: 17:49
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>修改书籍</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>书籍列表----修改书籍</small>
                </h1>
            </div>
        </div>
    </div>
    <form action="${pageContext.request.contextPath}/book/updateBook" method="get">
        <input type="hidden" name="bookid" value="${Book.bookid}">
    <div class="form-group">
        <label for="bookname">书籍名称</label>
        <input type="text" class="form-control" id="bookname" name="bookname" value="${Book.bookname}" placeholder="书籍名称" required>
    </div>
    <div class="form-group">
        <label for="author">作者</label>
        <input type="text" class="form-control" id="author" name="author" value="${Book.author}" placeholder="作者" required>
    </div>
    <div class="form-group">
        <label for="publish">出版社</label>
        <input type="text" class="form-control" id="publish" name="publish" value="${Book.publish}" placeholder="出版社" required>
    </div>
    <div class="form-group">
        <label for="introduction">详情</label>
        <input type="text" class="form-control" id="introduction" name="introduction" value="${Book.introduction}" placeholder="书籍详情" required>
    </div>
    <div class="form-group">
        <label for="price">价格</label>
        <input type="text" class="form-control" id="price" name="price" value="${Book.price}" placeholder="价格" required>
    </div>
    <div class="form-group">
        <label for="booktype">书籍类别</label>
        <input type="text" class="form-control" list="optionList" id="booktype" name="booktype" value="${Book.booktype}" placeholder="书籍类别" required>
        <datalist id="optionList">
            <option value="文学类">文学类</option>
            <option value="历史类">历史类</option>
            <option value="社会类">社会类</option>
            <option value="爱情类">爱情类</option>
            <option value="科幻类">科幻类</option>
            <option value="社会文学类">社会文学类</option>
            <option value="武侠类">武侠类</option>
            <option value="亲情类">亲情类</option>
            <option value="奇幻类">奇幻类</option>
            <option value="政治类">政治类</option>
            <option value="经济类">经济类</option>
            <option value="其他类">其他类</option>
        </datalist>
    </div>
        <button type="submit" class="btn btn-default btn-lg active " style="margin-left:1050px;margin-top: 20px">修改</button>
    </form>
</div>
</body>
</html>

 5. Login page Login.jsp

<%--
  Created by IntelliJ IDEA.
  User: 蜡笔小鑫
  Date: 2022/12/30
  Time: 14:20
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>登录</title>
    <link rel="stylesheet" href="${pageContext.request.contextPath}/css/style.css">
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>

<body>
<form action="${pageContext.request.contextPath}/book/Login" method="get">
    <div class="box">
        <div class="content">
            <div class="login-wrapper">
                <h1 style="font-family: 华文楷体;font-weight: bolder;font-size: 50px">登录</h1>
                <div class="login-form">
                    <div class="username form-item">
                        <span style="font-weight: bolder;font-family: 华文宋体;font-size: 15px">用户名</span>
                        <input type="text" class="input-item" name="username" placeholder="请输入用户名">
                    </div>
                    <div class="password form-item">
                        <span style="font-weight: bolder;font-family: 华文宋体;font-size: 15px">密码</span>
                        <input type="password" class="input-item" name="password" placeholder="请输入密码">
                    </div>
                    <span style="color: red;font-weight: bolder">${error1}</span>
                    <input type="submit" style="margin-bottom: 20px" class="login-btn" value="登录">
                    <a class="astyle" href="${pageContext.request.contextPath}/book/toregisterPage" title="注册账号">没有账号?点击注册</a>
                </div>
                <div class="divider">
                    <span class="line"></span>
                    <span class="divider-text">其他方式登录</span>
                    <span class="line"></span>
                </div>
                <div class="other-login-wrapper">
                    <div class="other-login-item">
                        <img src="../img/QQ.png" alt="啊!图片去月球度假了" title="使用QQ登录">
                    </div>
                    <div class="other-login-item">
                        <img src="../img/WeChat.png" alt="啊!图片去月球度假了" title="使用微信登录">
                    </div>
                </div>
            </div>
        </div>
    </div>
</form>
</body>

</html>

6. Registration page register.jsp

<%--
  Created by IntelliJ IDEA.
  User: 蜡笔小鑫
  Date: 2022/12/30
  Time: 15:49
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <link rel="stylesheet" href="${pageContext.request.contextPath}/css/register.css">
    <title>注册</title>
</head>

<body>
<form action="${pageContext.request.contextPath}/book/register"  method="get" >
    <div class="headbox">
        <p style="font-family: 华文新魏,serif;font-size: 40px">
        &nbsp;&nbsp;新用户注册
        </p>
        <h1 style="font-size: 40px">
            USER REGISTER
        </h1>
        <div class="hd_center">
            <div class="hd_form">
                <form action="${pageContext.request.contextPath}/book/register" method="get">
                    <table style="margin-top: 40px">
                        <tr>
                            <td class="td_left">用户名:</td>
                            <td class="td_right">
                                <input type="text" name="username" placeholder="请输入注册用户名">
                            </td>
                        </tr>
                    <tr></tr>
                    <tr></tr>
                        <tr>
                            <td class="td_left">密码:</td>
                            <td class="td_right">
                                <input type="text" name="password" placeholder="请输入注册密码">
                            </td>
                        </tr>
                        <tr></tr>
                        <tr></tr>
                        <tr>
                            <td></td>
                            <td colspan="2">
                                <input type="submit"value="注册" target="_blank">
                            </td>
                        </tr>
                        <tr>
                            <td></td>
                            <td>
                                <p style="text-align: right;">已有账号?<a href="${pageContext.request.contextPath}/book/toLogin" target="_blank">立即登录</a></p>
                            </td>
                        </tr>
                    </table>
                </form>
            </div>
        </div>
    </div>
</form>
</body>

</html>

7. css layer 

 index.css

header {
    width: 1000px;
    height: 600px;
    position: relative;
    margin: 70px 60px auto;
}
.bigBox{
    width:1000px;
    height:600px;
    overflow:hidden;
    overflow-x: auto;
    white-space: nowrap;
}
.bigBox img{
    width: 100%;
    height: 100%;
}
.left{
    width: 70px;
    height: 70px;
    cursor: pointer;
    float: left;
    left: 0;
    top: 50%;
    background: url("../indexImg/left.png") ;
}
.right{
    width: 70px;
    height: 70px;
    cursor: pointer;
    float: right;
    right: 0;
    top: 50%;
    background: url("../indexImg/right.png") ;
}
#nav {
    bottom: 5px;
    left: 30%;
    margin: 10px 10px 150px 150px;
}

#nav li {
    width: 30px;
    height: 30px;
    line-height: 30px;
    text-align: center;
    background: #ccc;
    font-size: 24px;
    border-radius: 9px;
    color: darkslategrey;
    font-family: 'Times New Roman', Times, serif;
    margin: 0 25px;
    float: left;
    cursor: pointer;
    list-style: none;
}

#nav li:hover {
    background: peru;
}

a{
    /*display: inline-block;*/
    /*padding-left: 10px;*/
    /*text-decoration: none;*/
    /*color: black;*/
    /*font-size: 30px;*/
    width: 250px;
    height: 70px;
    /*margin: 100px auto;*/
    /*text-align: center;*/
    /*line-height: 40px;*/
    /*background: green;*/
    /*border-radius: 5px 0px 0px 5px;*/
}

.texts{
    width: 250px;
    height: 70px;
    text-align: center;
    line-height: 40px;
}
h1{
    font-family: 黑体, serif;
    font-size: xx-large;
    font-weight: bold;
    margin: 30px 50px 120px 40px;
}
.threesolid{
     font-size: 30px;
     color:#fefefe;
     text-shadow:0px 1px 0px #c0c0c0,
     0px 2px 0px #b0b0b0,
     0px 3px 0px #a0a0a0,
     0px 4px 0px #909090,
     0px 5px 10px rgba(0, 0, 0, .9);
 }

@-webkit-keyframes stripe-slide {
    0% {
        background-position: 0% 0;
    }
    100% {
        background-position: 100% 0;
    }
}
@keyframes stripe-slide {
    0% {
        background-position: 0% 0;
    }
    100% {
        background-position: 100% 0;
    }
}
body {
    width: 100%;
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    font-family: sans-serif;
}
.btn {
    overflow: visible;
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    font: inherit;
    line-height: normal;
    cursor: pointer;
    -moz-user-select: text;
    display: block;
    text-decoration: none;
    text-transform: uppercase;
    padding: 16px 36px 22px;
    background-color: #fff;
    color: #666;
    border: 2px solid #666;
    border-radius: 6px;
    margin-bottom: 16px;
    transition: all 0.5s ease;
}
.btn::-moz-focus-inner {
    padding: 0;
    border: 0;
}
.btn--stripe {
    overflow: hidden;
    position: relative;
}
.btn--stripe:after {
    content: "";
    display: block;
    height: 7px;
    width: 100%;
    background-image: repeating-linear-gradient(45deg, #666, #666 1px, transparent 2px, transparent 5px);
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;
    border-top: 1px solid #666;
    position: absolute;
    left: 0;
    bottom: 0;
    background-size: 7px 7px;
}
.btn--stripe:hover {
    background-color: #666;
    color: #fff;
    border-color: #000;
}
.btn--stripe:hover:after {
    background-image: repeating-linear-gradient(45deg, #fff, #fff 1px, transparent 2px, transparent 5px);
    border-top: 1px solid #000;
    -webkit-animation: stripe-slide 12s infinite linear forwards;
    animation: stripe-slide 12s infinite linear forwards;
}
.btn--large {
    width: 50%;
}
.btn--radius {
    border-radius: 36px;
}

register.css

header {
    width: 1000px;
    height: 600px;
    position: relative;
    margin: 70px 60px auto;
}
.bigBox{
    width:1000px;
    height:600px;
    overflow:hidden;
    overflow-x: auto;
    white-space: nowrap;
}
.bigBox img{
    width: 100%;
    height: 100%;
}
.left{
    width: 70px;
    height: 70px;
    cursor: pointer;
    float: left;
    left: 0;
    top: 50%;
    background: url("../indexImg/left.png") ;
}
.right{
    width: 70px;
    height: 70px;
    cursor: pointer;
    float: right;
    right: 0;
    top: 50%;
    background: url("../indexImg/right.png") ;
}
#nav {
    bottom: 5px;
    left: 30%;
    margin: 10px 10px 150px 150px;
}

#nav li {
    width: 30px;
    height: 30px;
    line-height: 30px;
    text-align: center;
    background: #ccc;
    font-size: 24px;
    border-radius: 9px;
    color: darkslategrey;
    font-family: 'Times New Roman', Times, serif;
    margin: 0 25px;
    float: left;
    cursor: pointer;
    list-style: none;
}

#nav li:hover {
    background: peru;
}

a{
    /*display: inline-block;*/
    /*padding-left: 10px;*/
    /*text-decoration: none;*/
    /*color: black;*/
    /*font-size: 30px;*/
    width: 250px;
    height: 70px;
    /*margin: 100px auto;*/
    /*text-align: center;*/
    /*line-height: 40px;*/
    /*background: green;*/
    /*border-radius: 5px 0px 0px 5px;*/
}

.texts{
    width: 250px;
    height: 70px;
    text-align: center;
    line-height: 40px;
}
h1{
    font-family: 黑体, serif;
    font-size: xx-large;
    font-weight: bold;
    margin: 30px 50px 120px 40px;
}
.threesolid{
     font-size: 30px;
     color:#fefefe;
     text-shadow:0px 1px 0px #c0c0c0,
     0px 2px 0px #b0b0b0,
     0px 3px 0px #a0a0a0,
     0px 4px 0px #909090,
     0px 5px 10px rgba(0, 0, 0, .9);
 }

@-webkit-keyframes stripe-slide {
    0% {
        background-position: 0% 0;
    }
    100% {
        background-position: 100% 0;
    }
}
@keyframes stripe-slide {
    0% {
        background-position: 0% 0;
    }
    100% {
        background-position: 100% 0;
    }
}
body {
    width: 100%;
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    font-family: sans-serif;
}
.btn {
    overflow: visible;
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    font: inherit;
    line-height: normal;
    cursor: pointer;
    -moz-user-select: text;
    display: block;
    text-decoration: none;
    text-transform: uppercase;
    padding: 16px 36px 22px;
    background-color: #fff;
    color: #666;
    border: 2px solid #666;
    border-radius: 6px;
    margin-bottom: 16px;
    transition: all 0.5s ease;
}
.btn::-moz-focus-inner {
    padding: 0;
    border: 0;
}
.btn--stripe {
    overflow: hidden;
    position: relative;
}
.btn--stripe:after {
    content: "";
    display: block;
    height: 7px;
    width: 100%;
    background-image: repeating-linear-gradient(45deg, #666, #666 1px, transparent 2px, transparent 5px);
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;
    border-top: 1px solid #666;
    position: absolute;
    left: 0;
    bottom: 0;
    background-size: 7px 7px;
}
.btn--stripe:hover {
    background-color: #666;
    color: #fff;
    border-color: #000;
}
.btn--stripe:hover:after {
    background-image: repeating-linear-gradient(45deg, #fff, #fff 1px, transparent 2px, transparent 5px);
    border-top: 1px solid #000;
    -webkit-animation: stripe-slide 12s infinite linear forwards;
    animation: stripe-slide 12s infinite linear forwards;
}
.btn--large {
    width: 50%;
}
.btn--radius {
    border-radius: 36px;
}

style.css (login page style)

@charset "UTF-8";
* {
  margin: 0;
  padding: 0;
}

/*公共CSS*/
.box {
  width: 100vw;
  height: 100vh;
  background-color: rgb(29, 67, 89);
}
.box .content .login-wrapper .login-form .astyle{
  color: black;
  margin-left: 200px;
  text-decoration: none;
}
.box .content .login-wrapper .login-form .astyle:hover{
  color: #6363ee;
  font-weight: bolder;
}
.box .content .login-wrapper h1 {
  text-align: center;
}
.box .content .login-wrapper .login-form .form-item {
  margin: 20px 0;
}
.box .content .login-wrapper .login-form .form-item span {
  display: block;
  margin: 5px 20px;
  font-weight: 100;
}
.box .content .login-wrapper .login-form .form-item .input-item {
  width: 100%;
  border-radius: 40px;
  padding: 20px;
  box-sizing: border-box;
  font-size: 20px;
  font-weight: 200;
}
.box .content .login-wrapper .login-form .form-item .input-item:focus {
  outline: none;
}
.box .content .login-wrapper .login-form .login-btn {
  width: 100%;
  border-radius: 40px;
  color: #fff;
  border: 0;
  font-weight: 100;
  margin-top: 10px;
  cursor: pointer;
}
.box .content .login-wrapper .divider {
  width: 100%;
  margin: 20px 0;
  text-align: center;
  display: flex;
  align-items: center;
  justify-content: center;
}
.box .content .login-wrapper .divider span:nth-child(1) {
  flex: 1;
}
.box .content .login-wrapper .divider span:nth-child(3) {
  flex: 1;
}
.box .content .login-wrapper .divider .line {
  display: inline-block;
  max-width: 30%;
  width: 30%;
}
.box .content .login-wrapper .divider .divider-text {
  vertical-align: middle;
  margin: 0px 20px;
  line-height: 0px;
  display: inline-block;
  width: 100px;
}
.box .content .login-wrapper .other-login-wrapper {
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}
.box .content .login-wrapper .other-login-item {
  border: 1px solid rgb(214, 222, 228);
  padding: 10px;
  margin: 10px;
  cursor: pointer;
}

/*一般大于手机的尺寸CSS*/
@media (min-width: 767px) {
  .box {
    background-color: rgb(29, 67, 89);
  }
  .box .content {
    width: 85vw;
    height: 90vh;
    background: url('../img/login_two.jpg') no-repeat;
    background-size: 90% 100%;
    position: absolute;
    right: 15%;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    border-radius: 20px;
    background-color: #fff;
  }
  .box .content .login-wrapper {
    width: 25vw;
    position: absolute;
    right: 15%;
    top: 50%;
    transform: translateY(-50%);
  }
  .box .content .login-wrapper h1 {
    text-align: center;
    font-size: 45px;
    color: rgb(81, 100, 115);
    margin-bottom: 40px;
  }
  .box .content .login-wrapper .login-form {
    margin: 10px 0;
  }
  .box .content .login-wrapper .login-form .form-item span {
    color: rgb(81, 100, 115);
  }
  .box .content .login-wrapper .login-form .form-item .input-item {
    height: 60px;
    border: 1px solid rgb(214, 222, 228);
  }
  .box .content .login-wrapper .login-form .login-btn {
    height: 50px;
    background-color: rgb(59, 72, 89);
    font-size: 20px;
  }
  .box .content .login-wrapper .divider .line {
    border-bottom: 1px solid rgb(214, 222, 228);
  }
  .box .content .login-wrapper .other-login-item {
    border-radius: 20px;
  }
  .box .content .login-wrapper .other-login-item img {
    width: 40px;
    height: 40px;
  }
}
/*手机端CSS*/
@media (max-width: 768px) {
  .box .content {
    width: 100vw;
    height: 100vh;
    background: url("../img/login_bg_phone.png") no-repeat;
    background-size: 100% 100%;
    display: flex;
    align-items: flex-start;
    justify-content: center;
  }
  .box .content .login-wrapper {
    width: 70%;
    height: 60%;
    padding-top: 15%;
  }
  .box .content .login-wrapper h1 {
    font-size: 30px;
    color: #fff;
  }
  .box .content .login-wrapper .login-form .form-item {
    margin: 10px 0;
  }
  .box .content .login-wrapper .login-form .form-item span {
    color: rgb(113, 129, 141);
  }
  .box .content .login-wrapper .login-form .form-item .input-item {
    height: 30px;
    border: 1px solid rgb(113, 129, 141);
    background-color: transparent;
    color: #fff;
  }
  .box .content .login-wrapper .login-form .login-btn {
    height: 40px;
    background-color: rgb(235, 95, 93);
    font-size: 16px;
  }
  .box .content .login-wrapper .divider .line {
    border-bottom: 1px solid #fff;
  }
  .box .content .login-wrapper .divider .divider-text {
    color: #fff;
  }
  .box .content .login-wrapper .other-login-item {
    border-radius: 15px;
  }
  .box .content .login-wrapper .other-login-item img {
    width: 35px;
    height: 35px;
  }
}/*# sourceMappingURL=style.css.map */

8. js

 index.js

// 五张图片的url
var oImg1 = "indexImg/1.jpg";
var oImg2 = "indexImg/2.jpg";
var oImg3 = "indexImg/3.jpg";
var oImg4 = "indexImg/4.jpg";
var oImg5 = "indexImg/5.jpg";
var oImg6 = "indexImg/6.jpg";
// 把5张图片存入一个数组
var arr = [oImg1, oImg2, oImg3, oImg4, oImg5 ,oImg6];

window.onload = function() {
    //刚加载时第一张图片1号背景颜色
    document.getElementById("1").style.background = "peru";
    run()


}

//轮播
function run() {
    timer = setInterval(function() {
        //随机点数字时能接着变化
        var pic = document.getElementById("insert").name;

        //如果为最后一张图片则重新循环
        if (pic == 5) {
            pic = -1;
        }

        //点一个数字该数字背景颜色变化其余的不变
        var aLi = document.getElementsByTagName("li");
        for (var j = 0; j < aLi.length; j++) {
            aLi[j].style.backgroundColor = "#CCCCCC";
        }

        var i = parseInt(pic);
        //  图片地址
        document.getElementById("insert").src = arr[i + 1];

        document.getElementById("insert").name = i + 1;

        //数字随图片变化
        switch (i) {
            case 0:
                var temp = '2';
                break;
            case 1:
                var temp = '3';
                break;
            case 2:
                var temp = '4';
                break;
            case 3:
                var temp = '5';
                break;
            case 4:
                var temp = '6';
                break;
            case -1:
                var temp = '1';
                break;
        }
        document.getElementById(temp).style.background = "peru"

    }, 5000)
}

//右箭头
function goForward() {
    var temp = document.getElementById("insert").name;
    var oBox = document.getElementById("insert");
    var aLi = document.getElementsByTagName("li");
    // 数字跟着图片一起变
    for (var i = 0; i < aLi.length; i++) {
        aLi[i].style.backgroundColor = "#CCCCCC";
    }

    switch (temp) {
        case "0":
            var n = '2';
            break;
        case "1":
            var n = '3';
            break;
        case "2":
            var n = '4';
            break;
        case "3":
            var n = '5';
            break;
        case "4":
            var n = '6';
            break;
        case "5":
            var n = '1';
            break;
    }

    document.getElementById(n).style.background = "peru"
    // 向右移动图片
    for (var j = 0; j < arr.length; j++) {
        if (j < 5) {
            if (temp == j) {
                oBox.src = arr[j + 1];
            }
        } else {
            if (temp == 5) {
                oBox.src = arr[0];
            }
        }
    }
    // 轮到最后一张图片时返回第一张
    if (temp < 5) {
        oBox.name = parseInt(temp) + 1;
    } else {
        oBox.name = 0;
    }
}

//左箭头
function goBack() {
    var temp = document.getElementById("insert").name;
    var oBox = document.getElementById("insert")
    var aLi = document.getElementsByTagName("li");
    // 图片移动时数字也跟着变
    for (var i = 0; i < aLi.length; i++) {
        aLi[i].style.backgroundColor = "#CCCCCC";
    }

    switch (temp) {
        case "0":
            var n = '6';
            break;
        case "1":
            var n = '1';
            break;
        case "2":
            var n = '2';
            break;
        case "3":
            var n = '3';
            break;
        case "4":
            var n = '4';
            break;
        case "5":
            var n = '5';
            break;
    }

    document.getElementById(n).style.background = "peru"
    // 向左移动图片

    for (var j = 0; j < arr.length; j++) {
        if (j > 0) {
            if (temp == j) {
                oBox.src = arr[j - 1];
            }
        } else {
            if (temp == 0) {
                oBox.src = arr[5];
            }
        }
    }
    // 轮到第一张图片时返回最后一张
    if (temp > 0) {
        oBox.name = parseInt(temp) - 1;
    } else {
        oBox.name = 5;
    }
}

//指定图片
function move(num) {
    var oBox = document.getElementById("insert");
    var temp = document.getElementById("insert").name;
    var aLi = document.getElementsByTagName("li");
    for (var i = 0; i < aLi.length; i++) {
        aLi[i].style.backgroundColor = "#CCCCCC";
    }

    document.getElementById(num.innerHTML).style.background = "peru"

    switch (num.innerHTML) {
        case "1":
            oBox.src = arr[0];
            oBox.name = 0;
            break;
        case "2":
            oBox.src = arr[1];
            oBox.name = 1;
            break;
        case "3":
            oBox.src = arr[2];
            oBox.name = 2;
            break;
        case "4":
            oBox.src = arr[3];
            oBox.name = 3;
            break;
        case "5":
            oBox.src = arr[4];
            oBox.name = 4;
            break;
        case "6":
            oBox.src = arr[5];
            oBox.name = 5;
            break;
    }
}

Both img and indexImg are images, which can be added by yourself.

uplode is the location of the file upload

3 pictures show

1. index.jsp

2. Because of the interceptor, whether you click to log in or enter the book page will be intercepted to the login page Login.jsp

3. To register, enter the registration page register.jsp

Clicking to register or log in immediately will redirect you to the login page Login, jsp 

4. To log in, use the user information in the user table

5. Click Login to enter the allbook homepage (the first page)

It includes most of the operations in the Controller layer: adding, modifying, deleting, querying books, returning to the login page, logging out users, displaying pages, uploading and downloading files

6. Add book page addbook.jsp

 7. Modify the book page updatebook.jsp

 

 8. Book inquiry

9. Pagination operation 

 10. File upload

11. Download

 ok, this is the end of the project display

4 Attach the source code file (Baidu network disk):

Link: https://pan.baidu.com/s/1IrCCDYkcxbszNR7dmceEew?pwd=gbz8 
Extraction code: gbz8

Guess you like

Origin blog.csdn.net/m0_74135466/article/details/128593695