├── .gitignore
├── .settings
├── org.eclipse.wst.jsdt.ui.superType.name
├── org.eclipse.wst.validation.prefs
├── org.eclipse.wst.jsdt.ui.superType.container
├── org.eclipse.m2e.core.prefs
├── org.eclipse.wst.common.project.facet.core.xml
├── .jsdtscope
├── org.eclipse.wst.common.component
└── org.eclipse.jdt.core.prefs
├── src
└── main
│ ├── webapp
│ ├── index.jsp
│ ├── WEB-INF
│ │ ├── jsp
│ │ │ ├── common
│ │ │ │ ├── tag.jsp
│ │ │ │ └── head.jsp
│ │ │ ├── appointBookList.jsp
│ │ │ ├── list.jsp
│ │ │ └── detail.jsp
│ │ └── web.xml
│ └── resources
│ │ └── script
│ │ └── bookappointment.js
│ ├── resources
│ ├── jdbc.properties
│ ├── mapper
│ │ ├── StudentDao.xml
│ │ ├── BookDao.xml
│ │ └── AppointmentDao.xml
│ ├── logback.xml
│ ├── mybatis-config.xml
│ └── spring
│ │ ├── spring-service.xml
│ │ ├── spring-web.xml
│ │ └── spring-dao.xml
│ ├── java
│ └── com
│ │ └── imooc
│ │ └── appoint
│ │ ├── exception
│ │ ├── AppointException.java
│ │ ├── NoNumberException.java
│ │ └── RepeatAppointException.java
│ │ ├── dao
│ │ ├── StudentDao.java
│ │ ├── BookDao.java
│ │ └── AppointmentDao.java
│ │ ├── entiy
│ │ ├── Student.java
│ │ ├── Book.java
│ │ └── Appointment.java
│ │ ├── enums
│ │ └── AppointStateEnum.java
│ │ ├── dto
│ │ ├── Result.java
│ │ └── AppointExecution.java
│ │ ├── service
│ │ ├── BookService.java
│ │ └── Impl
│ │ │ └── BookServiceImpl.java
│ │ └── web
│ │ └── BookController.java
│ └── sql
│ └── schema.sql
├── .project
├── .classpath
├── pom.xml
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.wst.jsdt.ui.superType.name:
--------------------------------------------------------------------------------
1 | Window
--------------------------------------------------------------------------------
/.settings/org.eclipse.wst.validation.prefs:
--------------------------------------------------------------------------------
1 | disabled=06target
2 | eclipse.preferences.version=1
3 |
--------------------------------------------------------------------------------
/src/main/webapp/index.jsp:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hello World!
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.wst.jsdt.ui.superType.container:
--------------------------------------------------------------------------------
1 | org.eclipse.wst.jsdt.launching.baseBrowserLibrary
--------------------------------------------------------------------------------
/.settings/org.eclipse.m2e.core.prefs:
--------------------------------------------------------------------------------
1 | activeProfiles=
2 | eclipse.preferences.version=1
3 | resolveWorkspaceProjects=true
4 | version=1
5 |
--------------------------------------------------------------------------------
/src/main/resources/jdbc.properties:
--------------------------------------------------------------------------------
1 | jdbc.driver=com.mysql.jdbc.Driver
2 | jdbc.url=jdbc:mysql://127.0.0.1:3306/ssmbookappoint?useUnicode=true&characterEncoding=utf8
3 | jdbc.username=
4 | jdbc.password=
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/jsp/common/tag.jsp:
--------------------------------------------------------------------------------
1 | <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
2 | <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
3 | <%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
4 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.wst.common.project.facet.core.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/main/java/com/imooc/appoint/exception/AppointException.java:
--------------------------------------------------------------------------------
1 | package com.imooc.appoint.exception;
2 | //预约义务异常
3 | public class AppointException extends RuntimeException{
4 | public AppointException(String message) {
5 | super(message);
6 | }
7 |
8 | public AppointException(String message, Throwable cause) {
9 | super(message, cause);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/imooc/appoint/dao/StudentDao.java:
--------------------------------------------------------------------------------
1 | package com.imooc.appoint.dao;
2 |
3 | import org.apache.ibatis.annotations.Param;
4 |
5 | import com.imooc.appoint.entiy.Student;
6 |
7 | public interface StudentDao {
8 | /**
9 | * 向数据库验证输入的密码是否正确
10 | */
11 | Student quaryStudent(@Param("studentId") long studentId, @Param("password") long password);
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/imooc/appoint/exception/NoNumberException.java:
--------------------------------------------------------------------------------
1 | package com.imooc.appoint.exception;
2 |
3 | //库存不足异常
4 | public class NoNumberException extends RuntimeException{
5 | public NoNumberException(String message) {
6 | super(message);
7 | }
8 |
9 | public NoNumberException(String message, Throwable cause) {
10 | super(message, cause);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/imooc/appoint/exception/RepeatAppointException.java:
--------------------------------------------------------------------------------
1 | package com.imooc.appoint.exception;
2 | //重复预约异常
3 | public class RepeatAppointException extends RuntimeException{
4 | public RepeatAppointException(String message) {
5 | super(message);
6 | }
7 |
8 | public RepeatAppointException(String message, Throwable cause) {
9 | super(message, cause);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/resources/mapper/StudentDao.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
16 |
17 |
--------------------------------------------------------------------------------
/src/main/java/com/imooc/appoint/dao/BookDao.java:
--------------------------------------------------------------------------------
1 | package com.imooc.appoint.dao;
2 |
3 | import java.util.List;
4 |
5 | import org.apache.ibatis.annotations.Param;
6 |
7 | import com.imooc.appoint.entiy.Book;
8 |
9 | public interface BookDao {
10 | /*
11 | * 根据id查询书
12 | *
13 | */
14 | Book queryById(long id);
15 | List querySome(String name);
16 | List queryAll(@Param("offset") int offset,@Param("limit") int limit);
17 |
18 | /*减少管存数量
19 | * 用返回值可判断当前库存是否还有书
20 | */
21 | int reduceNumber(long bookId);
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/main/java/com/imooc/appoint/dao/AppointmentDao.java:
--------------------------------------------------------------------------------
1 | package com.imooc.appoint.dao;
2 |
3 | import java.util.List;
4 |
5 | import org.apache.ibatis.annotations.Param;
6 |
7 | import com.imooc.appoint.entiy.Appointment;
8 |
9 | public interface AppointmentDao {
10 | //通过图书ID和学生ID预约书籍,并插入
11 | int insertAppointment(@Param("bookId") long bookId, @Param("studentId") long studentId);
12 |
13 | //通过一个学生ID查询已经预约了哪些书。
14 | List quaryAndReturn(long studentId);
15 | // //查询所有已经预约书籍,暂时不开发管理员界面
16 | // List queryAll(@Param("offset") int offset,@Param("limit") int limit);
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/resources/mybatis-config.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/.settings/.jsdtscope:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/jsp/common/head.jsp:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.wst.common.component:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/main/java/com/imooc/appoint/entiy/Student.java:
--------------------------------------------------------------------------------
1 | package com.imooc.appoint.entiy;
2 |
3 | public class Student {
4 | private Long studentId;
5 | private Long password;
6 |
7 | public Student(){
8 |
9 | }
10 | public Student(Long studentId,Long password){
11 | this.studentId=studentId;
12 | this.password=password;
13 | }
14 | public Long getStudentId() {
15 | return studentId;
16 | }
17 | public void setStudentId(Long studentId) {
18 | this.studentId = studentId;
19 | }
20 | public Long getPassword() {
21 | return password;
22 | }
23 | public void setPassword(Long password) {
24 | this.password = password;
25 | }
26 |
27 | @Override
28 | public String toString() {
29 | return "Student [studentId=" + studentId + ", password=" + password + "]";
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3 | org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
4 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
5 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
6 | org.eclipse.jdt.core.compiler.compliance=1.8
7 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate
8 | org.eclipse.jdt.core.compiler.debug.localVariable=generate
9 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate
10 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
11 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
12 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
13 | org.eclipse.jdt.core.compiler.source=1.8
14 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 | BookAppointment-dispatcher
7 | org.springframework.web.servlet.DispatcherServlet
8 |
9 | contextConfigLocation
10 | classpath:spring/spring-*.xml
11 |
12 |
13 |
14 | BookAppointment-dispatcher
15 | /
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/main/java/com/imooc/appoint/enums/AppointStateEnum.java:
--------------------------------------------------------------------------------
1 | package com.imooc.appoint.enums;
2 |
3 | //使用枚举表述常量数据字典,我们先定义几个预约图书操作返回码的数据字典,也就是我们要返回给客户端的信息。
4 | public enum AppointStateEnum {
5 | SUCCESS(1, "预约成功"), NO_NUMBER(0, "库存不足"), REPEAT_APPOINT(-1, "重复预约"), INNER_ERROR(-2, "系统异常");
6 |
7 | private int state;
8 |
9 | private String stateInfo;
10 |
11 | private AppointStateEnum(int state, String stateInfo) {
12 | this.state = state;
13 | this.stateInfo = stateInfo;
14 | }
15 |
16 | public int getState() {
17 | return state;
18 | }
19 |
20 | public String getStateInfo() {
21 | return stateInfo;
22 | }
23 |
24 | public static AppointStateEnum stateOf(int index) {
25 | for (AppointStateEnum state : values()) {
26 | if (state.getState() == index) {
27 | return state;
28 | }
29 | }
30 | return null;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/com/imooc/appoint/dto/Result.java:
--------------------------------------------------------------------------------
1 | package com.imooc.appoint.dto;
2 |
3 |
4 | /**
5 | * 封装json对象,所有返回结果都使用它
6 | */
7 | public class Result {
8 | private boolean success;// 是否成功标志
9 |
10 | private T data;// 成功时返回的数据
11 |
12 | private String error;// 错误信息
13 |
14 | public Result() {
15 | }
16 |
17 | // 成功时的构造器
18 | public Result(boolean success, T data) {
19 | this.success = success;
20 | this.data = data;
21 | }
22 |
23 | // 错误时的构造器
24 | public Result(boolean success, String error) {
25 | this.success = success;
26 | this.error = error;
27 | }
28 |
29 |
30 | public boolean isSuccess() {
31 | return success;
32 | }
33 |
34 | public void setSuccess(boolean success) {
35 | this.success = success;
36 | }
37 |
38 | public T getData() {
39 | return data;
40 | }
41 |
42 | public void setData(T data) {
43 | this.data = data;
44 | }
45 |
46 | public String getError() {
47 | return error;
48 | }
49 |
50 | public void setError(String error) {
51 | this.error = error;
52 | }
53 |
54 | }
--------------------------------------------------------------------------------
/src/main/java/com/imooc/appoint/service/BookService.java:
--------------------------------------------------------------------------------
1 | package com.imooc.appoint.service;
2 |
3 | import java.util.List;
4 |
5 | import com.imooc.appoint.dto.AppointExecution;
6 | import com.imooc.appoint.entiy.Appointment;
7 | import com.imooc.appoint.entiy.Book;
8 | import com.imooc.appoint.entiy.Student;
9 |
10 | public interface BookService {
11 | /**
12 | * 查询一本图书
13 | *
14 | * @param bookId
15 | * @return
16 | */
17 | Book getById(long bookId);
18 | /**
19 | * 查询所有图书
20 | *
21 | * @return
22 | */
23 | List getList();
24 | /**
25 | * 登陆时查询数据库是否有该学生记录。
26 | */
27 | Student validateStu(Long studentId,Long password);
28 | /**按照图书名称查询
29 | * 按条件搜索图书
30 | *
31 | */
32 | List getSomeList(String name);
33 | /*
34 | * 查看某学生预约的所有图书
35 | *
36 | */
37 | List getAppointByStu(long studentId);
38 | /**
39 | * 预约图书
40 | *
41 | * @param bookId
42 | * @param studentId
43 | * @return
44 | */
45 | AppointExecution appoint(long bookId, long studentId);//返回预约成功的实体类
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/resources/spring/spring-service.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
15 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/main/java/com/imooc/appoint/entiy/Book.java:
--------------------------------------------------------------------------------
1 | package com.imooc.appoint.entiy;
2 |
3 | public class Book {
4 |
5 | private long bookId;//图书ID
6 | private String name;//图书名称
7 | private int number;//馆藏数量
8 | private String introd;
9 | public Book() { //为什么要有个无参构造器
10 | }
11 | public Book(long bookId, String name, int number) {
12 | this.bookId = bookId;
13 | this.name = name;
14 | this.number = number;
15 | }
16 | public long getBookId() {
17 | return bookId;
18 | }
19 | public void setBookId(long bookId) {
20 | this.bookId = bookId;
21 | }
22 | public String getName() {
23 | return name;
24 | }
25 | public void setName(String name) {
26 | this.name = name;
27 | }
28 | public int getNumber() {
29 | return number;
30 | }
31 | public void setNumber(int number) {
32 | this.number = number;
33 | }
34 | public String getIntrod() {
35 | return introd;
36 | }
37 | public void setIntrod(String introd) {
38 | this.introd = introd;
39 | }
40 |
41 | @Override
42 | public String toString() {
43 | return "Book [bookId=" + bookId + ", name=" + name + ", number=" + number + ", introd=" + introd + "]";
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/com/imooc/appoint/dto/AppointExecution.java:
--------------------------------------------------------------------------------
1 | package com.imooc.appoint.dto;
2 | import com.imooc.appoint.enums.AppointStateEnum;
3 |
4 | public class AppointExecution {
5 |
6 | // 图书ID
7 | private long bookId;
8 |
9 | // 秒杀预约结果状态
10 | private int state;
11 |
12 | // 状态标识
13 | private String stateInfo;
14 |
15 | public AppointExecution() {
16 | }
17 |
18 | // 预约失败的构造器
19 | public AppointExecution(long bookId, AppointStateEnum stateEnum) {
20 | this.bookId = bookId;
21 | this.state = stateEnum.getState();
22 | this.stateInfo = stateEnum.getStateInfo();
23 | }
24 |
25 | //set get 方法!
26 | public long getBookId() {
27 | return bookId;
28 | }
29 |
30 | public void setBookId(long bookId) {
31 | this.bookId = bookId;
32 | }
33 |
34 | public int getState() {
35 | return state;
36 | }
37 |
38 | public void setState(int state) {
39 | this.state = state;
40 | }
41 |
42 | public String getStateInfo() {
43 | return stateInfo;
44 | }
45 |
46 | public void setStateInfo(String stateInfo) {
47 | this.stateInfo = stateInfo;
48 | }
49 |
50 | @Override
51 | public String toString() {
52 | return "AppointExecution [bookId=" + bookId + ", state=" + state + ", stateInfo=" + stateInfo+"]";
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/com/imooc/appoint/entiy/Appointment.java:
--------------------------------------------------------------------------------
1 | package com.imooc.appoint.entiy;
2 |
3 | import java.util.Date;
4 |
5 | public class Appointment {
6 | private long bookId;
7 | private long studentId;
8 | private Date appointTime;
9 | // 多对一的复合属性
10 | private Book book;// 图书实体
11 | public Appointment(){
12 | }
13 | public Appointment(long bookId, long studentId, Date appointTime) {
14 | this.bookId = bookId;
15 | this.studentId = studentId;
16 | this.appointTime = appointTime;
17 | }
18 | public long getBookId() {
19 | return bookId;
20 | }
21 | public void setBookId(long bookId) {
22 | this.bookId = bookId;
23 | }
24 | public long getStudentId() {
25 | return studentId;
26 | }
27 | public void setStudentId(long studentId) {
28 | this.studentId = studentId;
29 | }
30 | public Date getAppointTime() {
31 | return appointTime;
32 | }
33 | public void setAppointTime(Date appointTime) {
34 | this.appointTime = appointTime;
35 | }
36 | public Book getBook() {
37 | return book;
38 | }
39 | public void setBook(Book book) {
40 | this.book = book;
41 | }
42 | @Override
43 | public String toString() {
44 | return "Appointment [bookId=" + bookId + ", studentId=" + studentId + ", appointTime=" + appointTime + ", book="
45 | + book + "]";
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/resources/mapper/BookDao.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
18 |
19 |
27 |
28 |
40 |
41 |
42 | UPDATE book
43 | SET number = number - 1
44 | WHERE
45 | book_id = #{bookId}
46 | AND number > 0
47 |
48 |
49 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | ssm-BookAppointment
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.wst.jsdt.core.javascriptValidator
10 |
11 |
12 |
13 |
14 | org.eclipse.jdt.core.javabuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.wst.common.project.facet.core.builder
20 |
21 |
22 |
23 |
24 | org.eclipse.m2e.core.maven2Builder
25 |
26 |
27 |
28 |
29 | org.eclipse.wst.validation.validationbuilder
30 |
31 |
32 |
33 |
34 |
35 | org.eclipse.jem.workbench.JavaEMFNature
36 | org.eclipse.wst.common.modulecore.ModuleCoreNature
37 | org.eclipse.jdt.core.javanature
38 | org.eclipse.m2e.core.maven2Nature
39 | org.eclipse.wst.common.project.facet.core.nature
40 | org.eclipse.wst.jsdt.core.jsNature
41 |
42 |
43 |
--------------------------------------------------------------------------------
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/main/resources/spring/spring-web.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
18 |
19 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/main/resources/mapper/AppointmentDao.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 | INSERT ignore INTO appointment (book_id, student_id)
9 | VALUES (#{bookId}, #{studentId})
10 |
11 |
14 |
15 |
32 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/jsp/appointBookList.jsp:
--------------------------------------------------------------------------------
1 | <%@page contentType="text/html; charset=UTF-8" language="java" %>
2 | <%@include file="common/tag.jsp"%>
3 |
4 |
5 |
6 | 预约图书列表
7 | <%@include file="common/head.jsp" %>
8 |
9 |
10 |
11 |
12 |
13 |
您已预约图书列表
14 |
15 |
16 |
17 |
18 |
19 | | 预定学号 |
20 | 预约时间 |
21 | 图书ID |
22 | 图书名称 |
23 | 图书简介 |
24 | 预约数量 |
25 |
26 |
27 |
28 |
29 |
30 | | ${sk.studentId} |
31 | ${sk.appointTime} |
32 | ${sk.bookId} |
33 | ${sk.book.getName()} |
34 | ${sk.book.getIntrod()} |
35 | 1 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/src/main/sql/schema.sql:
--------------------------------------------------------------------------------
1 | -- 创建图书表
2 | CREATE TABLE `book` (
3 | `book_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '图书ID',
4 | `name` varchar(100) NOT NULL COMMENT '图书名称',
5 | `introd` varchar(1000) NOT NULL COMMENT '简介',
6 | `number` int(11) NOT NULL COMMENT '馆藏数量',
7 | PRIMARY KEY (`book_id`)
8 | ) ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8 COMMENT='图书表';
9 |
10 | -- 初始化图书数据
11 | INSERT INTO `book` (`book_id`, `name`, `introd`,`number`)
12 | VALUES
13 | (1000, 'Java程序设计', 'Java程序设计是一门balbal',10),
14 | (1001, '数据结构','数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。', 10),
15 | (1002, '设计模式','设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。',10),
16 | (1003, '编译原理','编译原理是计算机专业的一门重要专业课,旨在介绍编译程序构造的一般原理和基本方法。',10),
17 | (1004,'大学语文','基于长期的教学实践和学科思考,我们编写了这本《大学语文》教材balbal',10),
18 | (1005,'计算方法','计算方法又称“数值分析”。是为各种数学问题的数值解答研究提供最有效的算法。',10),
19 | (1006,'高等数学','广义地说,初等数学之外的数学都是高等数学,也有将中学较深入的代数、几何以及简单的集合论初步balbal',10);
20 |
21 | -- 创建预约图书表
22 | CREATE TABLE `appointment` (
23 | `book_id` bigint(20) NOT NULL COMMENT '图书ID',
24 | `student_id` bigint(20) NOT NULL COMMENT '学号',
25 | `appoint_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '预约时间' ,
26 | PRIMARY KEY (`book_id`, `student_id`),
27 | INDEX `idx_appoint_time` (`appoint_time`)
28 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='预约图书表';
29 | -- 创建学生数据表
30 | CREATE TABLE `student`(
31 | `student_id` bigint(20) NOT NULL COMMENT '学生ID',
32 | `password` bigint(20) NOT NULL COMMENT '密码',
33 | PRIMARY KEY(`student_id`)
34 | )ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='学生统计表';
35 | -- 初始化学生数据
36 | INSERT INTO `student`(`student_id`,`password`)
37 | VALUES
38 | (3211200801,346543),
39 | (3211200802,754323),
40 | (3211200803,674554),
41 | (3211200804,542344),
42 | (3211200805,298383),
43 | (3211200806,873973),
44 | (3211200807,193737),
45 | (3211200808,873092);
46 |
47 |
48 |
--------------------------------------------------------------------------------
/src/main/resources/spring/spring-dao.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/jsp/list.jsp:
--------------------------------------------------------------------------------
1 | <%@page contentType="text/html; charset=UTF-8" language="java" %>
2 | <%@include file="common/tag.jsp"%>
3 |
4 |
5 |
6 | 图书列表
7 | <%@include file="common/head.jsp" %>
8 |
9 |
10 |
11 |
12 |
13 |
图书列表
14 |
15 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | | 图书ID |
39 | 图书名称 |
40 | 馆藏数量 |
41 | 详细 |
42 |
43 |
44 |
45 |
46 |
47 | | ${sk.bookId} |
48 | ${sk.name} |
49 | ${sk.number} |
50 | 详细 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/src/main/java/com/imooc/appoint/service/Impl/BookServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.imooc.appoint.service.Impl;
2 |
3 | import java.util.List;
4 |
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.stereotype.Service;
9 | import org.springframework.transaction.annotation.Transactional;
10 |
11 | import com.imooc.appoint.dao.AppointmentDao;
12 | import com.imooc.appoint.dao.BookDao;
13 | import com.imooc.appoint.dao.StudentDao;
14 | import com.imooc.appoint.dto.AppointExecution;
15 | import com.imooc.appoint.entiy.Appointment;
16 | import com.imooc.appoint.entiy.Book;
17 | import com.imooc.appoint.entiy.Student;
18 | import com.imooc.appoint.enums.AppointStateEnum;
19 | import com.imooc.appoint.exception.AppointException;
20 | import com.imooc.appoint.exception.NoNumberException;
21 | import com.imooc.appoint.exception.RepeatAppointException;
22 | import com.imooc.appoint.service.BookService;
23 |
24 | @Service
25 | public class BookServiceImpl implements BookService{
26 | private Logger logger=LoggerFactory.getLogger(this.getClass());
27 | @Autowired
28 | private BookDao bookDao;
29 | @Autowired
30 | private AppointmentDao appointmentDao;
31 | @Autowired
32 | private StudentDao studentDao;
33 | @Override
34 | public Book getById(long bookId) {
35 | return bookDao.queryById(bookId);
36 | }
37 | @Override
38 | public List getList() {
39 | return bookDao.queryAll(0, 1000);
40 | }
41 | @Override
42 | public Student validateStu(Long studentId,Long password){
43 | return studentDao.quaryStudent(studentId, password);
44 | }
45 | @Override
46 | public List getSomeList(String name) {
47 |
48 | return bookDao.querySome(name);
49 | }
50 | @Override
51 | public List getAppointByStu(long studentId) {//DOTO
52 | return appointmentDao.quaryAndReturn(studentId);
53 |
54 | }
55 | @Override
56 | @Transactional
57 | public AppointExecution appoint(long bookId, long studentId) {//在Dao的基础上组织逻辑,形成与web成交互用的方法
58 | try{ //返回成功预约的类型。
59 | int update=bookDao.reduceNumber(bookId);//减库存
60 | if(update<=0){//已经无库存!
61 | throw new NoNumberException("no number");
62 | }else{
63 | //执行预约操作
64 | int insert=appointmentDao.insertAppointment(bookId, studentId);
65 | if(insert<=0){//重复预约
66 | throw new RepeatAppointException("repeat appoint");
67 | }else{//预约成功
68 | return new AppointExecution(bookId,AppointStateEnum.SUCCESS);
69 | }
70 |
71 | }
72 | } catch (NoNumberException e1) {
73 | throw e1;
74 | } catch (RepeatAppointException e2) {
75 | throw e2;
76 | } catch (Exception e) {
77 | logger.error(e.getMessage(), e);
78 | // 所有编译期异常转换为运行期异常
79 | throw new AppointException("appoint inner error:" + e.getMessage());
80 | }
81 | }
82 |
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/jsp/detail.jsp:
--------------------------------------------------------------------------------
1 | <%@page contentType="text/html; charset=UTF-8" language="java" %>
2 | <%@include file="common/tag.jsp" %>
3 |
4 |
5 |
6 | 预约详情页
7 | <%@include file="common/head.jsp" %>
8 |
9 |
10 |
11 |
12 |
13 |
图书详情
14 |
15 |
16 |
17 |
18 |
19 | | 图书ID |
20 | 图书名称 |
21 | 图书简介 |
22 | 剩余数量 |
23 | 预约数量 |
24 |
25 |
26 |
27 |
28 | | ${book.bookId} |
29 | ${book.name} |
30 | ${book.introd} |
31 | ${book.number } |
32 | 1 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | 查看我的已预约书籍
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
57 |
58 |
70 |
71 |
79 |
80 |
81 |
82 |
83 |
84 | <%--jQery文件,务必在bootstrap.min.js之前引入--%>
85 |
86 |
87 | <%--使用CDN 获取公共js http://www.bootcdn.cn/--%>
88 | <%--jQuery Cookie操作插件--%>
89 |
90 | <%--jQuery countDown倒计时插件--%>
91 |
92 |
93 |
94 |
95 |
104 |
105 |
--------------------------------------------------------------------------------
/src/main/webapp/resources/script/bookappointment.js:
--------------------------------------------------------------------------------
1 | var bookappointment={
2 | //封装相关ajax的url
3 | URL:{
4 | appoint:function(bookId,studentId){
5 | return '/books/'+bookId+'/appoint?studentId='+studentId;
6 | },
7 | verify:function(){
8 | return '/books'+'/verify';
9 | }
10 | },
11 |
12 | //验证学号和密码
13 | validateStudent:function(studentId,password){
14 | console.log("studentId"+studentId);
15 | if(!studentId||!password){
16 | return "nothing";
17 | }else if(studentId.length!=10 ||isNaN(studentId)||password.length!=6 ||isNaN(password)){
18 | return "typerror";
19 | }else {
20 | if(bookappointment.verifyWithDatabase(studentId, password)){
21 | console.log("验证成功!");
22 | return "success";
23 | }else{
24 | console.log("验证失败!");
25 | return "mismatch";
26 | }
27 | }
28 | },
29 | //将学号和用户名与数据库匹配
30 | verifyWithDatabase:function(studentId,password){
31 | var result=false;
32 | var params={};
33 | params.studentId=studentId;
34 | params.password=password;
35 | console.log("params.password:"+params.password);
36 | var verifyUrl=bookappointment.URL.verify();
37 | $.ajax({
38 | type:'post',
39 | url:verifyUrl,
40 | data:params,
41 | datatype:'josn',
42 | async:false, //同步调用,保证先执行result=true,后再执行return result;
43 | success:function(data){
44 | if(data.result=='SUCCESS'){
45 | window.location.reload();
46 | //弹出登录成功!
47 | alert("登陆成功!");
48 | result=true;
49 | }else{
50 | result=false;
51 | }
52 | }
53 | });
54 | console.log("我是验证结果:"+result);
55 | return result;
56 |
57 | },
58 |
59 | //预定图书逻辑
60 | detail:{
61 | //预定也初始化
62 | init:function(params){
63 | var bookId=params['bookId'];
64 | console.log("我是js文件!");
65 |
66 | var studentId=$.cookie('studentId');
67 | var password=$.cookie('password');
68 | if(!studentId||!password){
69 | //设置弹出层属性
70 | var IdAndPasswordModal=$('#varifyModal');
71 | IdAndPasswordModal.modal({
72 | show: true,//显示弹出层
73 | backdrop: 'static',//禁止位置关闭
74 | keyboard: false//关闭键盘事件
75 | });
76 | $('#studentBtn').click(function (){
77 | studentId=$('#studentIdKey').val();
78 | console.log("studentId:"+studentId);
79 | password=$('#passwordKey').val();
80 | console.log("password:"+password);
81 | //调用validateStudent函数验证用户id和密码。
82 | var temp=bookappointment.validateStudent(studentId,password);
83 | console.log(temp);
84 | if(temp=="nothing"){
85 | $('#studentMessage').hide().html('').show(300);
86 | }else if(temp=="typerror"){
87 | $('#studentMessage').hide().html('').show(300);
88 | }else if(temp=="mismatch"){
89 | console.log("已经调用验证函数!");
90 | $('#studentMessage').hide().html('').show(300);
91 | }else if(temp=="success"){
92 | //学号与密码匹配正确,将学号密码保存在cookie中。不设置cookie过期时间,这样即为session模式,关闭浏览器就不保存密码了。
93 | $.cookie('studentId', studentId, { path: '/books'});
94 | $.cookie('password', password, { path: '/books'});
95 | // 跳转到预约逻辑
96 | var appointbox=$('#appoint-box');
97 | bookappointment.appointment(bookId,studentId,appointbox);
98 | }
99 | });
100 | }else{
101 | var appointbox=$('#appoint-box');
102 | bookappointment.appointment(bookId,studentId,appointbox);
103 | }
104 | }
105 | },
106 | appointment:function(bookId,studentId, node){
107 | console.log("我执行预约的方法!" );
108 | node.html('');
109 |
110 | var appointmentUrl = bookappointment.URL.appoint(bookId,studentId);
111 | console.log("appointmentUrl:"+appointmentUrl);
112 | //绑定一次点击事件
113 | $('#appointmentBtn').one('click', function () {
114 | //执行预约请求
115 | //1、先禁用请求
116 | $(this).addClass('disabled');
117 | //2、发送预约请求执行预约
118 | $.post(appointmentUrl,{},function(result){ //Ajax强大之处,向Controller方法提出请求和返回结果在一处!
119 | if(result && result['success']){ //同时还可以连续取对象的子对象!
120 | var appointResult=result['data'];
121 | console.log("appointResult"+appointResult);
122 | var state=appointResult['state'];
123 | console.log("state"+state);
124 | var stateInfo=appointResult['stateInfo'];
125 | console.log("stateInfo"+stateInfo);
126 | //显示预约结果 把结果显示给页面,完成了jsp的工作
127 |
128 | node.html(''+stateInfo+'');
129 | } //因为公用一个node所以,用来显示“stateInfo”时就不会显示上面的“预约”
130 | console.log('result'+result);
131 | });
132 | });
133 |
134 |
135 | }
136 | }
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | cn.nize
5 | ssm-BookAppointment
6 | 1.0-SNAPSHOT
7 | ssm-BookAppointment Maven Webapp
8 | http://maven.apache.org
9 |
10 |
11 |
12 |
13 | junit
14 | junit
15 | 4.11
16 |
17 |
18 |
19 |
20 |
21 | ch.qos.logback
22 | logback-classic
23 | 1.1.1
24 |
25 |
26 |
27 |
28 | mysql
29 | mysql-connector-java
30 | 5.1.35
31 |
32 |
33 |
34 | c3p0
35 | c3p0
36 | 0.9.1.2
37 |
38 |
39 |
40 |
41 | org.mybatis
42 | mybatis
43 | 3.3.0
44 |
45 |
46 | org.mybatis
47 | mybatis-spring
48 | 1.2.3
49 |
50 |
51 |
52 |
53 | taglibs
54 | standard
55 | 1.1.2
56 |
57 |
58 | jstl
59 | jstl
60 | 1.2
61 |
62 |
63 | com.fasterxml.jackson.core
64 | jackson-databind
65 | 2.5.0
66 |
67 |
68 | com.fasterxml.jackson.core
69 | jackson-core
70 | 2.5.0
71 |
72 |
73 | com.fasterxml.jackson.core
74 | jackson-annotations
75 | 2.5.0
76 |
77 |
82 |
83 | javax.servlet
84 | javax.servlet-api
85 | 3.1.0
86 |
87 |
88 |
89 |
90 |
91 | org.springframework
92 | spring-core
93 | 4.1.7.RELEASE
94 |
95 |
96 | org.springframework
97 | spring-beans
98 | 4.1.7.RELEASE
99 |
100 |
101 | org.springframework
102 | spring-context
103 | 4.1.7.RELEASE
104 |
105 |
106 |
107 | org.springframework
108 | spring-jdbc
109 | 4.1.7.RELEASE
110 |
111 |
112 | org.springframework
113 | spring-tx
114 | 4.1.7.RELEASE
115 |
116 |
117 |
118 | org.springframework
119 | spring-web
120 | 4.1.7.RELEASE
121 |
122 |
123 | org.springframework
124 | spring-webmvc
125 | 4.1.7.RELEASE
126 |
127 |
128 |
129 | org.springframework
130 | spring-test
131 | 4.1.7.RELEASE
132 |
133 |
134 |
135 |
136 | redis.clients
137 | jedis
138 | 2.7.3
139 |
140 |
141 | com.dyuproject.protostuff
142 | protostuff-core
143 | 1.0.8
144 |
145 |
146 | com.dyuproject.protostuff
147 | protostuff-runtime
148 | 1.0.8
149 |
150 |
151 |
152 |
153 | commons-collections
154 | commons-collections
155 | 3.2
156 |
157 |
158 |
159 |
160 | ssm-BookAppointment
161 |
162 |
163 |
--------------------------------------------------------------------------------
/src/main/java/com/imooc/appoint/web/BookController.java:
--------------------------------------------------------------------------------
1 | package com.imooc.appoint.web;
2 |
3 | import java.io.IOException;
4 | import java.util.ArrayList;
5 | import java.util.HashMap;
6 | import java.util.List;
7 | import java.util.Map;
8 |
9 | import javax.servlet.ServletException;
10 | import javax.servlet.http.HttpServletRequest;
11 | import javax.servlet.http.HttpServletResponse;
12 |
13 | import org.apache.ibatis.annotations.Param;
14 | import org.slf4j.Logger;
15 | import org.slf4j.LoggerFactory;
16 | import org.springframework.beans.factory.annotation.Autowired;
17 | import org.springframework.stereotype.Controller;
18 | import org.springframework.ui.Model;
19 | import org.springframework.web.bind.annotation.PathVariable;
20 | import org.springframework.web.bind.annotation.RequestMapping;
21 | import org.springframework.web.bind.annotation.RequestMethod;
22 | import org.springframework.web.bind.annotation.RequestParam;
23 | import org.springframework.web.bind.annotation.ResponseBody;
24 |
25 | import com.imooc.appoint.dto.AppointExecution;
26 | import com.imooc.appoint.dto.Result;
27 | import com.imooc.appoint.entiy.Appointment;
28 | import com.imooc.appoint.entiy.Book;
29 | import com.imooc.appoint.entiy.Student;
30 | import com.imooc.appoint.enums.AppointStateEnum;
31 | import com.imooc.appoint.service.BookService;
32 | import com.imooc.appoint.exception.RepeatAppointException;
33 | import com.imooc.appoint.exception.NoNumberException;
34 |
35 |
36 | @Controller
37 | @RequestMapping("/books")
38 | public class BookController {
39 | private Logger logger=LoggerFactory.getLogger(this.getClass());
40 | @Autowired
41 | private BookService bookService;
42 | //获取图书列表
43 | @RequestMapping(value="/list",method = RequestMethod.GET)
44 | private String List(Model model){
45 | List list = bookService.getList();
46 | model.addAttribute("list", list);
47 |
48 | return "list";
49 | }
50 | //搜索是否有某图书
51 | @RequestMapping(value="/search",method = RequestMethod.POST)
52 | private void search(HttpServletRequest req,HttpServletResponse resp)
53 | throws ServletException, IOException{
54 | //接收页面的值
55 | String name=req.getParameter("name");
56 | name=name.trim();
57 | //向页面传值
58 | req.setAttribute("name", name);
59 | req.setAttribute("list", bookService.getSomeList(name));
60 | req.getRequestDispatcher("/WEB-INF/jsp/list.jsp").forward(req, resp);
61 | }
62 | //查看某图书的详细情况
63 | @RequestMapping(value = "/{bookId}/detail", method = RequestMethod.GET)
64 | private String detail(@PathVariable("bookId") Long bookId, Model model){
65 | if(bookId==null){
66 | return "redict:/book/list";
67 | }
68 | Book book=bookService.getById(bookId);
69 | if(book==null){
70 | return "forward:/book/list";
71 | }
72 | model.addAttribute("book",book);
73 | System.out.println(book);
74 | return "detail";
75 | }
76 | //验证输入的用户名、密码是否正确
77 | @RequestMapping(value="/verify", method = RequestMethod.POST, produces = {
78 | "application/json; charset=utf-8" })
79 | @ResponseBody
80 | private Map validate(Long studentId,Long password){ //(HttpServletRequest req,HttpServletResponse resp){
81 | Map resultMap=new HashMap();
82 | Student student =null;
83 | System.out.println("验证函数");
84 | student =bookService.validateStu(studentId,password);
85 |
86 | System.out.println("输入的学号、密码:"+studentId+":"+password);
87 | System.out.println("查询到的:"+student.getStudentId()+":"+student.getPassword());
88 |
89 | if(student!=null){
90 | System.out.println("SUCCESS");
91 | resultMap.put("result", "SUCCESS");
92 | return resultMap;
93 | }else{
94 | resultMap.put("result", "FAILED");
95 | return resultMap;
96 | }
97 |
98 | }
99 | //执行预约的逻辑
100 | @RequestMapping(value = "/{bookId}/appoint", method = RequestMethod.POST, produces = {
101 | "application/json; charset=utf-8" })
102 | @ResponseBody
103 | private Result execute(@PathVariable("bookId") Long bookId,@RequestParam("studentId") Long studentId){
104 | Result result;
105 | AppointExecution execution=null;
106 |
107 | try{//手动try catch,在调用appoint方法时可能报错
108 | execution=bookService.appoint(bookId, studentId);
109 | result=new Result(true,execution);
110 | return result;
111 |
112 | } catch(NoNumberException e1) {
113 | execution=new AppointExecution(bookId,AppointStateEnum.NO_NUMBER);
114 | result=new Result(true,execution);
115 | return result;
116 | }catch(RepeatAppointException e2){
117 | execution=new AppointExecution(bookId,AppointStateEnum.REPEAT_APPOINT);
118 | result=new Result(true,execution);
119 | return result;
120 | }catch (Exception e){
121 | execution=new AppointExecution(bookId,AppointStateEnum.INNER_ERROR);
122 | result=new Result(true,execution);
123 | return result;
124 | }
125 | }
126 | @RequestMapping(value ="/appoint")
127 | private String appointBooks(@RequestParam("studentId") long studentId,Model model){
128 |
129 | List appointList=new ArrayList();
130 | appointList=bookService.getAppointByStu(studentId);
131 | model.addAttribute("appointList", appointList);
132 |
133 | return "appointBookList";
134 | }
135 |
136 | }
137 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ssm-BookAppointment
2 | 优雅整合SSM框架:SpringMVC + Spring + MyBatis(图书预约系统)
3 | 话不多说先让我们看看此项目运行起来的效果,方便大家有个直观了解,好在事先估计要用到那些技术,方便大家有针对性的学习。
4 | 看图!
5 | 这是图书管理系统的首页,不用登陆即可查看、搜索系统有已有图书。
6 | 
7 | 搜索想要预定的书:
8 | 
9 | 点击详情,进入预定页面,如果没有登陆的话会弹出登陆层,提示输入学号密码,如果用户已经在之前查看某本书的详细时已经登陆,则不会要求再登陆,这里的用户名密码与数据库验证成功后保存在cookie中,且生命周期默认与session相同,即关闭路径窗口后就失效。
10 | 
11 | 这是什么都不输入和输入格式不对时,点击submit的提示:
12 | 
13 | 
14 | 
15 | 登陆后进入预约界面,点击预约后的界面:
16 | 
17 | 如果已经对当前书预约过,点击预约会提示重复预约,如果没有库存,点击预约会提示没有库存。
18 | 
19 | 预约后点击:查看我的已预约书籍,会显示之前所有预约的信息:
20 | 
21 | ## 1、利用maven创建文件路径:
22 | 利用命令行工具输入:mvn archetype:generate -DgroupId=cn.nize -DarchetypeArtifactId=
23 | maven-archetype-webapp -DarchetypeCatalog=internal
24 | ## 2、创建项目包:
25 | 
26 | ## 3、再然后就是在pom.xml里面注入依赖,maven会自动在网站上下载。关于maven大家可以看看慕课网上的教学视频。
27 | pom.xml
28 | ```java
29 |
31 | 4.0.0
32 | cn.nize
33 | ssm-BookAppointment
34 | 1.0-SNAPSHOT
35 | ssm-BookAppointment Maven Webapp
36 | http://maven.apache.org
37 |
38 |
39 |
40 |
41 | junit
42 | junit
43 | 4.11
44 |
45 |
46 |
47 |
48 |
49 | ch.qos.logback
50 | logback-classic
51 | 1.1.1
52 |
53 |
54 |
55 |
56 | mysql
57 | mysql-connector-java
58 | 5.1.35
59 |
60 |
61 |
62 | c3p0
63 | c3p0
64 | 0.9.1.2
65 |
66 |
67 |
68 |
69 | org.mybatis
70 | mybatis
71 | 3.3.0
72 |
73 |
74 | org.mybatis
75 | mybatis-spring
76 | 1.2.3
77 |
78 |
79 |
80 |
81 | taglibs
82 | standard
83 | 1.1.2
84 |
85 |
86 | jstl
87 | jstl
88 | 1.2
89 |
90 |
91 | com.fasterxml.jackson.core
92 | jackson-databind
93 | 2.5.0
94 |
95 |
96 | com.fasterxml.jackson.core
97 | jackson-core
98 | 2.5.0
99 |
100 |
101 | com.fasterxml.jackson.core
102 | jackson-annotations
103 | 2.5.0
104 |
105 |
110 |
111 | javax.servlet
112 | javax.servlet-api
113 | 3.1.0
114 |
115 |
116 |
117 |
118 |
119 | org.springframework
120 | spring-core
121 | 4.1.7.RELEASE
122 |
123 |
124 | org.springframework
125 | spring-beans
126 | 4.1.7.RELEASE
127 |
128 |
129 | org.springframework
130 | spring-context
131 | 4.1.7.RELEASE
132 |
133 |
134 |
135 | org.springframework
136 | spring-jdbc
137 | 4.1.7.RELEASE
138 |
139 |
140 | org.springframework
141 | spring-tx
142 | 4.1.7.RELEASE
143 |
144 |
145 |
146 | org.springframework
147 | spring-web
148 | 4.1.7.RELEASE
149 |
150 |
151 | org.springframework
152 | spring-webmvc
153 | 4.1.7.RELEASE
154 |
155 |
156 |
157 | org.springframework
158 | spring-test
159 | 4.1.7.RELEASE
160 |
161 |
162 |
163 |
164 | redis.clients
165 | jedis
166 | 2.7.3
167 |
168 |
169 | com.dyuproject.protostuff
170 | protostuff-core
171 | 1.0.8
172 |
173 |
174 | com.dyuproject.protostuff
175 | protostuff-runtime
176 | 1.0.8
177 |
178 |
179 |
180 |
181 | commons-collections
182 | commons-collections
183 | 3.2
184 |
185 |
186 |
187 |
188 | ssm-BookAppointment
189 |
190 |
191 | ```
192 | ## 4、做好之前的准备工作后,逻辑理顺,现在就要开始编码啦,首先我们创建数据库!
193 | 根据我们的实际情况,在数据库中创建表:
194 | schema.sql
195 | ```java
196 | -- 创建图书表
197 | CREATE TABLE `book` (
198 | `book_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '图书ID',
199 | `name` varchar(100) NOT NULL COMMENT '图书名称',
200 | `introd` varchar(1000) NOT NULL COMMENT '简介',
201 | `number` int(11) NOT NULL COMMENT '馆藏数量',
202 | PRIMARY KEY (`book_id`)
203 | ) ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8 COMMENT='图书表';
204 |
205 | -- 初始化图书数据
206 | INSERT INTO `book` (`book_id`, `name`, `introd`,`number`)
207 | VALUES
208 | (1000, 'Java程序设计', 'Java程序设计是一门balbal',10),
209 | (1001, '数据结构','数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。', 10),
210 | (1002, '设计模式','设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。',10),
211 | (1003, '编译原理','编译原理是计算机专业的一门重要专业课,旨在介绍编译程序构造的一般原理和基本方法。',10),
212 | (1004,'大学语文','基于长期的教学实践和学科思考,我们编写了这本《大学语文》教材balbal',10),
213 | (1005,'计算方法','计算方法又称“数值分析”。是为各种数学问题的数值解答研究提供最有效的算法。',10),
214 | (1006,'高等数学','广义地说,初等数学之外的数学都是高等数学,也有将中学较深入的代数、几何以及简单的集合论初步balbal',10);
215 |
216 | -- 创建预约图书表
217 | CREATE TABLE `appointment` (
218 | `book_id` bigint(20) NOT NULL COMMENT '图书ID',
219 | `student_id` bigint(20) NOT NULL COMMENT '学号',
220 | `appoint_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '预约时间' ,
221 | PRIMARY KEY (`book_id`, `student_id`),
222 | INDEX `idx_appoint_time` (`appoint_time`)
223 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='预约图书表';
224 | -- 创建学生数据表
225 | CREATE TABLE `student`(
226 | `student_id` bigint(20) NOT NULL COMMENT '学生ID',
227 | `password` bigint(20) NOT NULL COMMENT '密码',
228 | PRIMARY KEY(`student_id`)
229 | )ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='学生统计表';
230 | -- 初始化学生数据
231 | INSERT INTO `student`(`student_id`,`password`)
232 | VALUES
233 | (3211200801,346543),
234 | (3211200802,754323),
235 | (3211200803,674554),
236 | (3211200804,542344),
237 | (3211200805,298383),
238 | (3211200806,873973),
239 | (3211200807,193737),
240 | (3211200808,873092);
241 |
242 | ```
243 | ## 5 根据数据库对象创建实体类。
244 | 第一个开始填充的类当然是entiy包,他是承接我们从数据库里去除数据的类,或者把该类存入数据库,在这里我们创建两个类,一个是Book包(从数据库取出书后放入该包),一个是Appointment(存放从数据库取出的预约书籍信息)。
245 | Book.java
246 | ```java
247 | package com.imooc.appoint.entiy;
248 |
249 | public class Book {
250 |
251 | private long bookId;//图书ID
252 | private String name;//图书名称
253 | private int number;//馆藏数量
254 | private String introd;
255 | public Book() { //为什么要有个无参构造器
256 | }
257 | public Book(long bookId, String name, int number) {
258 | this.bookId = bookId;
259 | this.name = name;
260 | this.number = number;
261 | }
262 | public long getBookId() {
263 | return bookId;
264 | }
265 | public void setBookId(long bookId) {
266 | this.bookId = bookId;
267 | }
268 | public String getName() {
269 | return name;
270 | }
271 | public void setName(String name) {
272 | this.name = name;
273 | }
274 | public int getNumber() {
275 | return number;
276 | }
277 | public void setNumber(int number) {
278 | this.number = number;
279 | }
280 | public String getIntrod() {
281 | return introd;
282 | }
283 | public void setIntrod(String introd) {
284 | this.introd = introd;
285 | }
286 |
287 | @Override
288 | public String toString() {
289 | return "Book [bookId=" + bookId + ", name=" + name + ", number=" + number + ", introd=" + introd + "]";
290 | }
291 | }
292 | ```
293 | Appointment.java
294 | ```java
295 | package com.imooc.appoint.entiy;
296 |
297 | import java.util.Date;
298 |
299 | public class Appointment {
300 | private long bookId;
301 | private long studentId;
302 | private Date appointTime;
303 | // 多对一的复合属性
304 | private Book book;// 图书实体
305 | public Appointment(){
306 | }
307 | public Appointment(long bookId, long studentId, Date appointTime) {
308 | this.bookId = bookId;
309 | this.studentId = studentId;
310 | this.appointTime = appointTime;
311 | }
312 | public long getBookId() {
313 | return bookId;
314 | }
315 | public void setBookId(long bookId) {
316 | this.bookId = bookId;
317 | }
318 | public long getStudentId() {
319 | return studentId;
320 | }
321 | public void setStudentId(long studentId) {
322 | this.studentId = studentId;
323 | }
324 | public Date getAppointTime() {
325 | return appointTime;
326 | }
327 | public void setAppointTime(Date appointTime) {
328 | this.appointTime = appointTime;
329 | }
330 | public Book getBook() {
331 | return book;
332 | }
333 | public void setBook(Book book) {
334 | this.book = book;
335 | }
336 | @Override
337 | public String toString() {
338 | return "Appointment [bookId=" + bookId + ", studentId=" + studentId + ", appointTime=" + appointTime + ", book="
339 | + book + "]";
340 | }
341 | }
342 | ```
343 | 因为我们还打算做一个学生ID、密码验证,所以也得有学生类.
344 | Student.java
345 | ```java
346 | package com.imooc.appoint.entiy;
347 |
348 | public class Student {
349 | private Long studentId;
350 | private Long password;
351 |
352 | public Student(){
353 |
354 | }
355 | public Student(Long studentId,Long password){
356 | this.studentId=studentId;
357 | this.password=password;
358 | }
359 | public Long getStudentId() {
360 | return studentId;
361 | }
362 | public void setStudentId(Long studentId) {
363 | this.studentId = studentId;
364 | }
365 | public Long getPassword() {
366 | return password;
367 | }
368 | public void setPassword(Long password) {
369 | this.password = password;
370 | }
371 |
372 | @Override
373 | public String toString() {
374 | return "Student [studentId=" + studentId + ", password=" + password + "]";
375 | }
376 | }
377 |
378 | ```
379 | ## 6创建DAO中的类
380 | DAO包中的类主要功能是实现与数据库交互,所以我们需要大的逻辑是:1、学生类与数据库交互;2、预约是与数据库交互;3、查询书时与时与数据库交互。这里大致分为几类,等具体写接口时再去细写。还有就是注意,DAO只是与数据库交互,不能写交互组成的逻辑,这个放在service里面。我们应该站在用户的角度设计DAO接口,至于具体怎么用,后面再写。
381 | BookDao.java
382 | ```java
383 | package com.imooc.appoint.dao;
384 |
385 | import java.util.List;
386 |
387 | import org.apache.ibatis.annotations.Param;
388 |
389 | import com.imooc.appoint.entiy.Book;
390 |
391 | public interface BookDao {
392 | /*
393 | * 根据id查询书
394 | *
395 | */
396 | Book queryById(long id);
397 | List querySome(String name);
398 | List queryAll(@Param("offset") int offset,@Param("limit") int limit);
399 |
400 | /*减少管存数量
401 | * 用返回值可判断当前库存是否还有书
402 | */
403 | int reduceNumber(long bookId);
404 | }
405 |
406 |
407 | ```
408 | AppointmentDao.java
409 | ```java
410 | package com.imooc.appoint.dao;
411 |
412 | import java.util.List;
413 |
414 | import org.apache.ibatis.annotations.Param;
415 |
416 | import com.imooc.appoint.entiy.Appointment;
417 |
418 | public interface AppointmentDao {
419 | //通过图书ID和学生ID预约书籍,并插入
420 | int insertAppointment(@Param("bookId") long bookId, @Param("studentId") long studentId);
421 |
422 | //通过一个学生ID查询已经预约了哪些书。
423 | List quaryAndReturn(long studentId);
424 |
425 | }
426 |
427 | ```
428 | StudentDao.java
429 | ```java
430 | package com.imooc.appoint.dao;
431 |
432 | import org.apache.ibatis.annotations.Param;
433 |
434 | import com.imooc.appoint.entiy.Student;
435 |
436 | public interface StudentDao {
437 | /**
438 | * 向数据库验证输入的密码是否正确
439 | */
440 | Student quaryStudent(@Param("studentId") long studentId, @Param("password") long password);
441 | }
442 |
443 | ```
444 | ## 7我们暂时先不管以上接口实现,先为DAO配置入框架,实现spring与mybatis的整合。
445 | 因为spring的配置太多,我们这里分三层,分别是dao service web。我们这里先写spring-dao.xml,其他的等我们实现相应包后再去配置。
446 | 配置时,主要注意一下几个方面:
447 | 1、读入数据库连接相关参数(可选)
448 | 2、配置数据连接池
449 | 3、配置连接属性,可以不读配置项文件直接在这里写死
450 | 4、配置c3p0,只配了几个常用的
451 | 5、配置SqlSessionFactory对象(mybatis)
452 | 6、扫描dao层接口,动态实现dao接口,也就是说不需要daoImpl,sql和参数都写在xml文件上
453 | spring-dao.xml
454 | ```java
455 |
456 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 | ```
506 | ### 配置jdbc.properties文件
507 | ```java
508 | jdbc.driver=com.mysql.jdbc.Driver
509 | jdbc.url=jdbc:mysql://127.0.0.1:3306/ssmbookappoint?useUnicode=true&characterEncoding=utf8
510 | jdbc.username=
511 | jdbc.password=
512 | ```
513 | 第一次上传忘记去掉用户名密码了,好险!大家用的时候填上自己的用户名、密码。
514 | ### 配置mybatis。
515 | 所以需要配置mybatis核心文件,在recources文件夹里新建mybatis-config.xml文件。
516 |
517 | 1、使用自增主键
518 | 2、使用列别名
519 | 3、开启驼峰命名转换 create_time -> createTime
520 | mybatis-config.xml
521 | ```java
522 |
523 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 | ```
540 |
541 | ## 8配置实现接口的xml
542 | 我们要开始写DAO接口的实现类,因为我们配置扫描sql配置文件路径是:mapper下的xml,所有我们应该在resourse下新建mapper文件夹,在这里存放实现DAO接口的各种xml
543 | BookDao.xml
544 | ```java
545 |
546 |
549 |
550 |
562 |
563 |
571 |
572 |
584 |
585 |
586 | UPDATE book
587 | SET number = number - 1
588 | WHERE
589 | book_id = #{bookId}
590 | AND number > 0
591 |
592 |
593 |
594 | ```
595 | AppointmentDao.xml
596 | ```java
597 |
598 |
601 |
602 |
603 |
604 | INSERT ignore INTO appointment (book_id, student_id)
605 | VALUES (#{bookId}, #{studentId})
606 |
607 |
610 |
611 |
628 |
645 |
646 |
647 | ```
648 | StudentDao.java
649 | ```java
650 |
651 |
654 |
655 |
665 |
666 |
667 | ```
668 | 到此为止,我们dao层的开发就算结束了,大家可以写个测试类,测试一下。(我没写,哈哈),要实现预约功能还得有更多详细的逻辑组织,这个功能将他放在service中,他把DAO中与数据库交互的功能组织成可以用的详细逻辑。提供给上层web调用。
669 | ## 8 service层
670 | ### 首先写service接口类
671 | BookService.java
672 | ```java
673 | package com.imooc.appoint.service;
674 |
675 | import java.util.List;
676 |
677 | import com.imooc.appoint.dto.AppointExecution;
678 | import com.imooc.appoint.entiy.Appointment;
679 | import com.imooc.appoint.entiy.Book;
680 | import com.imooc.appoint.entiy.Student;
681 |
682 | public interface BookService {
683 | /**
684 | * 查询一本图书
685 | *
686 | * @param bookId
687 | * @return
688 | */
689 | Book getById(long bookId);
690 | /**
691 | * 查询所有图书
692 | *
693 | * @return
694 | */
695 | List getList();
696 | /**
697 | * 登陆时查询数据库是否有该学生记录。
698 | */
699 | Student validateStu(Long studentId,Long password);
700 | /**按照图书名称查询
701 | * 按条件搜索图书
702 | *
703 | */
704 | List getSomeList(String name);
705 | /*
706 | * 查看某学生预约的所有图书
707 | *
708 | */
709 | List getAppointByStu(long studentId);
710 | /**
711 | * 预约图书
712 | *
713 | * @param bookId
714 | * @param studentId
715 | * @return
716 | */
717 | AppointExecution appoint(long bookId, long studentId);//返回预约成功的实体类
718 | }
719 | ```
720 | 大家可以看到,这个借口类中基本和DAO中的没啥区别,有区别的是某些类他是在dao上更进一步,需要多个dao类一起组织,或者在加入其它逻辑才能实现
721 | 为了实现BookService的借口,我们得写BookServiceImpl类。但是想让我们想想,为了写BookServiceImpl,我们需要什么,上面我们已经写出预约成功的实体类是AppointExecution,所以当然我们得写出该类,因为该类交互service和web,对这类有点像entiy包我们管叫bto包(bto包和其他包一起存放在appoint下)。对于AppointExecution来说,作用就是预约成功后给web层提供返回的信息。(就是返回预约成功、预约失败、无库存、之类的信息)
722 | ```java
723 | package com.imooc.appoint.dto;
724 | import com.imooc.appoint.enums.AppointStateEnum;
725 |
726 | public class AppointExecution {
727 |
728 | // 图书ID
729 | private long bookId;
730 |
731 | // 预约结果状态
732 | private int state;
733 |
734 | // 状态标识
735 | private String stateInfo;
736 |
737 | public AppointExecution() {
738 | }
739 |
740 | // 预约失败的构造器
741 | public AppointExecution(long bookId, AppointStateEnum stateEnum) {
742 | this.bookId = bookId;
743 | this.state = stateEnum.getState();
744 | this.stateInfo = stateEnum.getStateInfo();
745 | }
746 |
747 | //set get 方法!
748 | public long getBookId() {
749 | return bookId;
750 | }
751 |
752 | public void setBookId(long bookId) {
753 | this.bookId = bookId;
754 | }
755 |
756 | public int getState() {
757 | return state;
758 | }
759 |
760 | public void setState(int state) {
761 | this.state = state;
762 | }
763 |
764 | public String getStateInfo() {
765 | return stateInfo;
766 | }
767 |
768 | public void setStateInfo(String stateInfo) {
769 | this.stateInfo = stateInfo;
770 | }
771 |
772 | @Override
773 | public String toString() {
774 | return "AppointExecution [bookId=" + bookId + ", state=" + state + ", stateInfo=" + stateInfo+"]";
775 | }
776 | }
777 | ```
778 | 除此之外,我们在预约图书时可能出现异常,例如重复预约、无库存、和其他异常,我们需要事先设计好异常类,来接收这类异常,方便处理,而不是直接报错。因此在appoint包下新建excption包,报下新建三个类:AppoinException.java;NoNumberException.java;RepeatAppoint.java
779 | AppoinException.java
780 | ```java
781 | package com.imooc.appoint.exception;
782 | //预约义务异常
783 | public class AppointException extends RuntimeException{
784 | public AppointException(String message) {
785 | super(message);
786 | }
787 |
788 | public AppointException(String message, Throwable cause) {
789 | super(message, cause);
790 | }
791 | }
792 |
793 | ```
794 | NoNumberException.java
795 | ```java
796 | package com.imooc.appoint.exception;
797 |
798 | //库存不足异常
799 | public class NoNumberException extends RuntimeException{
800 | public NoNumberException(String message) {
801 | super(message);
802 | }
803 |
804 | public NoNumberException(String message, Throwable cause) {
805 | super(message, cause);
806 | }
807 |
808 | }
809 |
810 | ```
811 | RepeatAppoint.java
812 | ```java
813 | package com.imooc.appoint.exception;
814 | //重复预约异常
815 | public class RepeatAppointException extends RuntimeException{
816 | public RepeatAppointException(String message) {
817 | super(message);
818 | }
819 |
820 | public RepeatAppointException(String message, Throwable cause) {
821 | super(message, cause);
822 | }
823 | }
824 | ```
825 | 现在可以写接口的实现类啦:BookServiceImpl.java
826 | ```java
827 | package com.imooc.appoint.service.Impl;
828 |
829 | import java.util.List;
830 |
831 | import org.slf4j.Logger;
832 | import org.slf4j.LoggerFactory;
833 | import org.springframework.beans.factory.annotation.Autowired;
834 | import org.springframework.stereotype.Service;
835 | import org.springframework.transaction.annotation.Transactional;
836 |
837 | import com.imooc.appoint.dao.AppointmentDao;
838 | import com.imooc.appoint.dao.BookDao;
839 | import com.imooc.appoint.dao.StudentDao;
840 | import com.imooc.appoint.dto.AppointExecution;
841 | import com.imooc.appoint.entiy.Appointment;
842 | import com.imooc.appoint.entiy.Book;
843 | import com.imooc.appoint.entiy.Student;
844 | import com.imooc.appoint.enums.AppointStateEnum;
845 | import com.imooc.appoint.exception.AppointException;
846 | import com.imooc.appoint.exception.NoNumberException;
847 | import com.imooc.appoint.exception.RepeatAppointException;
848 | import com.imooc.appoint.service.BookService;
849 |
850 | @Service
851 | public class BookServiceImpl implements BookService{
852 | private Logger logger=LoggerFactory.getLogger(this.getClass());
853 | @Autowired
854 | private BookDao bookDao;
855 | @Autowired
856 | private AppointmentDao appointmentDao;
857 | @Autowired
858 | private StudentDao studentDao;
859 | @Override
860 | public Book getById(long bookId) {
861 | return bookDao.queryById(bookId);
862 | }
863 | @Override
864 | public List getList() {
865 | return bookDao.queryAll(0, 1000);
866 | }
867 | @Override
868 | public Student validateStu(Long studentId,Long password){
869 | return studentDao.quaryStudent(studentId, password);
870 | }
871 | @Override
872 | public List getSomeList(String name) {
873 |
874 | return bookDao.querySome(name);
875 | }
876 | @Override
877 | public List getAppointByStu(long studentId) {//DOTO
878 | return appointmentDao.quaryAndReturn(studentId);
879 |
880 | }
881 | @Override
882 | @Transactional
883 | public AppointExecution appoint(long bookId, long studentId) {//在Dao的基础上组织逻辑,形成与web成交互用的方法
884 | try{ //返回成功预约的类型。
885 | int update=bookDao.reduceNumber(bookId);//减库存
886 | if(update<=0){//已经无库存!
887 | throw new NoNumberException("no number");
888 | }else{
889 | //执行预约操作
890 | int insert=appointmentDao.insertAppointment(bookId, studentId);
891 | if(insert<=0){//重复预约
892 | throw new RepeatAppointException("repeat appoint");
893 | }else{//预约成功
894 | return new AppointExecution(bookId,AppointStateEnum.SUCCESS);
895 | }
896 |
897 | }
898 | } catch (NoNumberException e1) {
899 | throw e1;
900 | } catch (RepeatAppointException e2) {
901 | throw e2;
902 | } catch (Exception e) {
903 | logger.error(e.getMessage(), e);
904 | // 所有编译期异常转换为运行期异常
905 | throw new AppointException("appoint inner error:" + e.getMessage());
906 | }
907 | }
908 | }
909 |
910 | ```
911 | ### 又到了我们写service层配置的时候!
912 | 该xml依然位于resourse下的spring包下
913 | spring-service.xml
914 | ```java
915 |
916 |
926 |
927 |
928 |
929 |
931 |
932 |
933 |
934 |
935 |
936 |
937 | ```
938 | ## 9web层
939 | 现在我们一起看看web层该如何组织。
940 | 在写具体的代码之前,先配置web层,在这里主要实现的作用是:
941 | 1、开启SpringMVC注解模式,可以使用@RequestMapping,@PathVariable,@ResponseBody等
942 | 2、对静态资源处理,如js,css,jpg等
943 | 3、配置jsp 显示ViewResolver,例如在controller中某个方法返回一个string类型的"login",实际上会返回"/WEB-INF/login.jsp"
944 | 4、扫描web层 @Controller
945 | 详细见xml中每一步的注释
946 | spring-web.xml
947 | ```java
948 |
949 |
959 |
960 |
961 |
965 |
966 |
970 |
971 |
972 |
973 |
974 |
975 |
976 |
977 |
978 |
979 |
980 |
981 | ```
982 | 当然我们必须修改web.xml文件,它在webapp的WEB-INF下,这个文件配置servlet,并初始化,指定扫描spring相关的配置,最后我们将所有的url都拦截下来。
983 | web.xml
984 | ```java
985 |
989 |
990 | BookAppointment-dispatcher
991 | org.springframework.web.servlet.DispatcherServlet
992 |
993 | contextConfigLocation
994 | classpath:spring/spring-*.xml
995 |
996 |
997 |
998 | BookAppointment-dispatcher
999 | /
1000 |
1001 |
1002 |
1003 |
1004 | ```
1005 | 因为在运行时,我们经常会查看日志什么的,所以我们把这个配置进去
1006 | logback.xml
1007 | ```java
1008 |
1009 |
1010 |
1011 |
1012 |
1013 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
1014 |
1015 |
1016 |
1017 |
1018 |
1019 |
1020 |
1021 | ```
1022 | 最后我们开始组织我们web的逻辑,也就是具体的controller层代码的编写。
1023 | 这一层中与我们的前段联系的较为紧密,大家可以边写边看效果,再调试。
1024 | ```java
1025 | package com.imooc.appoint.web;
1026 |
1027 | import java.io.IOException;
1028 | import java.util.ArrayList;
1029 | import java.util.HashMap;
1030 | import java.util.List;
1031 | import java.util.Map;
1032 |
1033 | import javax.servlet.ServletException;
1034 | import javax.servlet.http.HttpServletRequest;
1035 | import javax.servlet.http.HttpServletResponse;
1036 |
1037 | import org.apache.ibatis.annotations.Param;
1038 | import org.slf4j.Logger;
1039 | import org.slf4j.LoggerFactory;
1040 | import org.springframework.beans.factory.annotation.Autowired;
1041 | import org.springframework.stereotype.Controller;
1042 | import org.springframework.ui.Model;
1043 | import org.springframework.web.bind.annotation.PathVariable;
1044 | import org.springframework.web.bind.annotation.RequestMapping;
1045 | import org.springframework.web.bind.annotation.RequestMethod;
1046 | import org.springframework.web.bind.annotation.RequestParam;
1047 | import org.springframework.web.bind.annotation.ResponseBody;
1048 |
1049 | import com.imooc.appoint.dto.AppointExecution;
1050 | import com.imooc.appoint.dto.Result;
1051 | import com.imooc.appoint.entiy.Appointment;
1052 | import com.imooc.appoint.entiy.Book;
1053 | import com.imooc.appoint.entiy.Student;
1054 | import com.imooc.appoint.enums.AppointStateEnum;
1055 | import com.imooc.appoint.service.BookService;
1056 | import com.imooc.appoint.exception.RepeatAppointException;
1057 | import com.imooc.appoint.exception.NoNumberException;
1058 |
1059 |
1060 | @Controller
1061 | @RequestMapping("/books")
1062 | public class BookController {
1063 | private Logger logger=LoggerFactory.getLogger(this.getClass());
1064 | @Autowired
1065 | private BookService bookService;
1066 | //获取图书列表
1067 | @RequestMapping(value="/list",method = RequestMethod.GET)
1068 | private String List(Model model){
1069 | List list = bookService.getList();
1070 | model.addAttribute("list", list);
1071 |
1072 | return "list";
1073 | }
1074 | //搜索是否有某图书
1075 | @RequestMapping(value="/search",method = RequestMethod.POST)
1076 | private void search(HttpServletRequest req,HttpServletResponse resp)
1077 | throws ServletException, IOException{
1078 | //接收页面的值
1079 | String name=req.getParameter("name");
1080 | name=name.trim();
1081 | //向页面传值
1082 | req.setAttribute("name", name);
1083 | req.setAttribute("list", bookService.getSomeList(name));
1084 | req.getRequestDispatcher("/WEB-INF/jsp/list.jsp").forward(req, resp);
1085 | }
1086 | //查看某图书的详细情况
1087 | @RequestMapping(value = "/{bookId}/detail", method = RequestMethod.GET)
1088 | private String detail(@PathVariable("bookId") Long bookId, Model model){
1089 | if(bookId==null){
1090 | return "redict:/book/list";
1091 | }
1092 | Book book=bookService.getById(bookId);
1093 | if(book==null){
1094 | return "forward:/book/list";
1095 | }
1096 | model.addAttribute("book",book);
1097 | System.out.println(book);
1098 | return "detail";
1099 | }
1100 | //验证输入的用户名、密码是否正确
1101 | @RequestMapping(value="/verify", method = RequestMethod.POST, produces = {
1102 | "application/json; charset=utf-8" })
1103 | @ResponseBody
1104 | private Map validate(Long studentId,Long password){ //(HttpServletRequest req,HttpServletResponse resp){
1105 | Map resultMap=new HashMap();
1106 | Student student =null;
1107 | System.out.println("验证函数");
1108 | student =bookService.validateStu(studentId,password);
1109 |
1110 | System.out.println("输入的学号、密码:"+studentId+":"+password);
1111 | System.out.println("查询到的:"+student.getStudentId()+":"+student.getPassword());
1112 |
1113 | if(student!=null){
1114 | System.out.println("SUCCESS");
1115 | resultMap.put("result", "SUCCESS");
1116 | return resultMap;
1117 | }else{
1118 | resultMap.put("result", "FAILED");
1119 | return resultMap;
1120 | }
1121 |
1122 | }
1123 | //执行预约的逻辑
1124 | @RequestMapping(value = "/{bookId}/appoint", method = RequestMethod.POST, produces = {
1125 | "application/json; charset=utf-8" })
1126 | @ResponseBody
1127 | private Result execute(@PathVariable("bookId") Long bookId,@RequestParam("studentId") Long studentId){
1128 | Result result;
1129 | AppointExecution execution=null;
1130 |
1131 | try{//手动try catch,在调用appoint方法时可能报错
1132 | execution=bookService.appoint(bookId, studentId);
1133 | result=new Result(true,execution);
1134 | return result;
1135 |
1136 | } catch(NoNumberException e1) {
1137 | execution=new AppointExecution(bookId,AppointStateEnum.NO_NUMBER);
1138 | result=new Result(true,execution);
1139 | return result;
1140 | }catch(RepeatAppointException e2){
1141 | execution=new AppointExecution(bookId,AppointStateEnum.REPEAT_APPOINT);
1142 | result=new Result(true,execution);
1143 | return result;
1144 | }catch (Exception e){
1145 | execution=new AppointExecution(bookId,AppointStateEnum.INNER_ERROR);
1146 | result=new Result(true,execution);
1147 | return result;
1148 | }
1149 | }
1150 | @RequestMapping(value ="/appoint")
1151 | private String appointBooks(@RequestParam("studentId") long studentId,Model model){
1152 |
1153 | List appointList=new ArrayList();
1154 | appointList=bookService.getAppointByStu(studentId);
1155 | model.addAttribute("appointList", appointList);
1156 |
1157 | return "appointBookList";
1158 | }
1159 |
1160 | }
1161 |
1162 | ```
1163 | 为了把执行预约逻辑是否返回的不同信息封装起来,我们创建一个Result类,它是类型T的集合。
1164 | Result.java
1165 | ```java
1166 | package com.imooc.appoint.dto;
1167 | /**
1168 | * 封装json对象,所有返回结果都使用它
1169 | */
1170 | public class Result {
1171 | private boolean success;// 是否成功标志
1172 |
1173 | private T data;// 成功时返回的数据
1174 |
1175 | private String error;// 错误信息
1176 |
1177 | public Result() {
1178 | }
1179 |
1180 | // 成功时的构造器
1181 | public Result(boolean success, T data) {
1182 | this.success = success;
1183 | this.data = data;
1184 | }
1185 |
1186 | // 错误时的构造器
1187 | public Result(boolean success, String error) {
1188 | this.success = success;
1189 | this.error = error;
1190 | }
1191 |
1192 |
1193 | public boolean isSuccess() {
1194 | return success;
1195 | }
1196 |
1197 | public void setSuccess(boolean success) {
1198 | this.success = success;
1199 | }
1200 |
1201 | public T getData() {
1202 | return data;
1203 | }
1204 |
1205 | public void setData(T data) {
1206 | this.data = data;
1207 | }
1208 |
1209 | public String getError() {
1210 | return error;
1211 | }
1212 |
1213 | public void setError(String error) {
1214 | this.error = error;
1215 | }
1216 |
1217 | }
1218 | ```
1219 | 为了给web显示预约后的反馈信息,我们建立一个常量数据字典类存放这些要反馈给客户的信息
1220 | AppointStateEnum.java
1221 | ```java
1222 | package com.imooc.appoint.enums;
1223 |
1224 | //使用枚举表述常量数据字典,我们先定义几个预约图书操作返回码的数据字典,也就是我们要返回给客户端的信息。
1225 | public enum AppointStateEnum {
1226 | SUCCESS(1, "预约成功"), NO_NUMBER(0, "库存不足"), REPEAT_APPOINT(-1, "重复预约"), INNER_ERROR(-2, "系统异常");
1227 |
1228 | private int state;
1229 |
1230 | private String stateInfo;
1231 |
1232 | private AppointStateEnum(int state, String stateInfo) {
1233 | this.state = state;
1234 | this.stateInfo = stateInfo;
1235 | }
1236 |
1237 | public int getState() {
1238 | return state;
1239 | }
1240 |
1241 | public String getStateInfo() {
1242 | return stateInfo;
1243 | }
1244 |
1245 | public static AppointStateEnum stateOf(int index) {
1246 | for (AppointStateEnum state : values()) {
1247 | if (state.getState() == index) {
1248 | return state;
1249 | }
1250 | }
1251 | return null;
1252 | }
1253 | }
1254 | ```
1255 | 到此为止,我们后端写的差不多了,下面是前段页面的开发,其实前段和controller中的方法开发是相互嵌套的,在写方法的同时,写js或者jsp文件。这样逻辑才能连贯。再此用bootstrap这种轻量一站式框架开发前段,能死前端技术不怎么好的童鞋也能开发出还看得过去的页面。
1256 | 话不多少,我们上代码:
1257 | list.jsp
1258 | ```java
1259 | <%@page contentType="text/html; charset=UTF-8" language="java" %>
1260 | <%@include file="common/tag.jsp"%>
1261 |
1262 |
1263 |
1264 | 图书列表
1265 | <%@include file="common/head.jsp" %>
1266 |
1267 |
1268 |
1269 |
1270 |
1271 |
图书列表
1272 |
1273 |
1290 |
1291 |
1292 |
1293 |
1294 |
1295 |
1296 | | 图书ID |
1297 | 图书名称 |
1298 | 馆藏数量 |
1299 | 详细 |
1300 |
1301 |
1302 |
1303 |
1304 |
1305 | | ${sk.bookId} |
1306 | ${sk.name} |
1307 | ${sk.number} |
1308 | 详细 |
1309 |
1310 |
1311 |
1312 |
1313 |
1314 |
1315 |
1316 |
1317 |
1318 |
1319 |
1320 |
1321 |
1322 |
1323 |
1324 |
1325 | ```
1326 | detail.jsp
1327 | ```java
1328 | <%@page contentType="text/html; charset=UTF-8" language="java" %>
1329 | <%@include file="common/tag.jsp" %>
1330 |
1331 |
1332 |
1333 | 预约详情页
1334 | <%@include file="common/head.jsp" %>
1335 |
1336 |
1337 |
1338 |
1339 |
1340 |
图书详情
1341 |
1342 |
1343 |
1344 |
1345 |
1346 | | 图书ID |
1347 | 图书名称 |
1348 | 图书简介 |
1349 | 剩余数量 |
1350 | 预约数量 |
1351 |
1352 |
1353 |
1354 |
1355 | | ${book.bookId} |
1356 | ${book.name} |
1357 | ${book.introd} |
1358 | ${book.number } |
1359 | 1 |
1360 |
1361 |
1362 |
1363 |
1364 |
1365 |
1366 |
1367 |
1368 |
1369 | 查看我的已预约书籍
1370 |
1371 |
1372 |
1373 |
1374 |
1375 |
1376 |
1377 |
1378 |
1379 |
1384 |
1385 |
1397 |
1398 |
1406 |
1407 |
1408 |
1409 |
1410 |
1411 | <%--jQery文件,务必在bootstrap.min.js之前引入--%>
1412 |
1413 |
1414 | <%--使用CDN 获取公共js http://www.bootcdn.cn/--%>
1415 | <%--jQuery Cookie操作插件--%>
1416 |
1417 | <%--jQuery countDown倒计时插件--%>
1418 |
1419 |
1420 |
1421 |
1422 |
1431 |
1432 | ```
1433 | bookappointment.js
1434 | ```javascript
1435 | var bookappointment={
1436 | //封装相关ajax的url
1437 | URL:{
1438 | appoint:function(bookId,studentId){
1439 | return '/books/'+bookId+'/appoint?studentId='+studentId;
1440 | },
1441 | verify:function(){
1442 | return '/books'+'/verify';
1443 | }
1444 | },
1445 |
1446 | //验证学号和密码
1447 | validateStudent:function(studentId,password){
1448 | console.log("studentId"+studentId);
1449 | if(!studentId||!password){
1450 | return "nothing";
1451 | }else if(studentId.length!=10 ||isNaN(studentId)||password.length!=6 ||isNaN(password)){
1452 | return "typerror";
1453 | }else {
1454 | if(bookappointment.verifyWithDatabase(studentId, password)){
1455 | console.log("验证成功!");
1456 | return "success";
1457 | }else{
1458 | console.log("验证失败!");
1459 | return "mismatch";
1460 | }
1461 | }
1462 | },
1463 | //将学号和用户名与数据库匹配
1464 | verifyWithDatabase:function(studentId,password){
1465 | var result=false;
1466 | var params={};
1467 | params.studentId=studentId;
1468 | params.password=password;
1469 | console.log("params.password:"+params.password);
1470 | var verifyUrl=bookappointment.URL.verify();
1471 | $.ajax({
1472 | type:'post',
1473 | url:verifyUrl,
1474 | data:params,
1475 | datatype:'josn',
1476 | async:false, //同步调用,保证先执行result=true,后再执行return result;
1477 | success:function(data){
1478 | if(data.result=='SUCCESS'){
1479 | window.location.reload();
1480 | //弹出登录成功!
1481 | alert("登陆成功!");
1482 | result=true;
1483 | }else{
1484 | result=false;
1485 | }
1486 | }
1487 | });
1488 | console.log("我是验证结果:"+result);
1489 | return result;
1490 |
1491 | },
1492 |
1493 | //预定图书逻辑
1494 | detail:{
1495 | //预定也初始化
1496 | init:function(params){
1497 | var bookId=params['bookId'];
1498 | console.log("我是js文件!");
1499 |
1500 | var studentId=$.cookie('studentId');
1501 | var password=$.cookie('password');
1502 | if(!studentId||!password){
1503 | //设置弹出层属性
1504 | var IdAndPasswordModal=$('#varifyModal');
1505 | IdAndPasswordModal.modal({
1506 | show: true,//显示弹出层
1507 | backdrop: 'static',//禁止位置关闭
1508 | keyboard: false//关闭键盘事件
1509 | });
1510 | $('#studentBtn').click(function (){
1511 | studentId=$('#studentIdKey').val();
1512 | console.log("studentId:"+studentId);
1513 | password=$('#passwordKey').val();
1514 | console.log("password:"+password);
1515 | //调用validateStudent函数验证用户id和密码。
1516 | var temp=bookappointment.validateStudent(studentId,password);
1517 | console.log(temp);
1518 | if(temp=="nothing"){
1519 | $('#studentMessage').hide().html('').show(300);
1520 | }else if(temp=="typerror"){
1521 | $('#studentMessage').hide().html('').show(300);
1522 | }else if(temp=="mismatch"){
1523 | console.log("已经调用验证函数!");
1524 | $('#studentMessage').hide().html('').show(300);
1525 | }else if(temp=="success"){
1526 | //学号与密码匹配正确,将学号密码保存在cookie中。不设置cookie过期时间,这样即为session模式,关闭浏览器就不保存密码了。
1527 | $.cookie('studentId', studentId, { path: '/books'});
1528 | $.cookie('password', password, { path: '/books'});
1529 | // 跳转到预约逻辑
1530 | var appointbox=$('#appoint-box');
1531 | bookappointment.appointment(bookId,studentId,appointbox);
1532 | }
1533 | });
1534 | }else{
1535 | var appointbox=$('#appoint-box');
1536 | bookappointment.appointment(bookId,studentId,appointbox);
1537 | }
1538 | }
1539 | },
1540 | appointment:function(bookId,studentId, node){
1541 | console.log("我执行预约的方法!" );
1542 | node.html('');
1543 |
1544 | var appointmentUrl = bookappointment.URL.appoint(bookId,studentId);
1545 | console.log("appointmentUrl:"+appointmentUrl);
1546 | //绑定一次点击事件
1547 | $('#appointmentBtn').one('click', function () {
1548 | //执行预约请求
1549 | //1、先禁用请求
1550 | $(this).addClass('disabled');
1551 | //2、发送预约请求执行预约
1552 | $.post(appointmentUrl,{},function(result){ //Ajax强大之处,向Controller方法提出请求和返回结果在一处!
1553 | if(result && result['success']){ //同时还可以连续取对象的子对象!
1554 | var appointResult=result['data'];
1555 | console.log("appointResult"+appointResult);
1556 | var state=appointResult['state'];
1557 | console.log("state"+state);
1558 | var stateInfo=appointResult['stateInfo'];
1559 | console.log("stateInfo"+stateInfo);
1560 | //显示预约结果 把结果显示给页面,完成了jsp的工作
1561 | node.html(''+stateInfo+'');
1562 | } //因为公用一个node所以,用来显示“stateInfo”时就不会显示上面的“预约”
1563 | console.log('result'+result);
1564 | });
1565 | });
1566 |
1567 |
1568 | }
1569 | }
1570 | ```
1571 | appointBookList.jsp
1572 | ```java
1573 | <%@page contentType="text/html; charset=UTF-8" language="java" %>
1574 | <%@include file="common/tag.jsp"%>
1575 |
1576 |
1577 |
1578 | 预约图书列表
1579 | <%@include file="common/head.jsp" %>
1580 |
1581 |
1582 |
1583 |
1584 |
1585 |
您已预约图书列表
1586 |
1587 |
1588 |
1589 |
1590 |
1591 | | 预定学号 |
1592 | 预约时间 |
1593 | 图书ID |
1594 | 图书名称 |
1595 | 图书简介 |
1596 | 预约数量 |
1597 |
1598 |
1599 |
1600 |
1601 |
1602 | | ${sk.studentId} |
1603 | ${sk.appointTime} |
1604 | ${sk.bookId} |
1605 | ${sk.book.getName()} |
1606 | ${sk.book.getIntrod()} |
1607 | 1 |
1608 |
1609 |
1610 |
1611 |
1612 |
1613 |
1614 |
1615 |
1616 |
1617 |
1618 |
1619 |
1620 |
1621 |
1622 | ```
1623 | 到此为止,所有的开发就已经结束,已经把所有源代码上传至github,需要的可以去下载,喜欢就给个star吧。
1624 |
1625 |
1626 |
1627 |
1628 |
--------------------------------------------------------------------------------