图书管理
简介
第一次写博客,图个稀罕。
- 此项目为B站上面楠哥说java教程里面的web教学实战项目
- 视频地址:https://www.bilibili.com/video/BV1BJ411L7NR?p=31
- 笔记、源码链接: https://pan.baidu.com/s/1MDbbNKqC5mgUGg2yUiM9cg 提取码: zmpi
- 写此文章实属佩服楠哥,顺便记录下看看自己学了多少
- 仅此。
- 我发现我写作的文笔的真是菜哦,然后写到一半我自己都有点懵了,让我想起了我大学复制粘贴的毕业设计了,打算这个写完,有机会的话写下那个,那是一个黑马旅游网站,锻炼下WEB以及不及小学生的写作的手法
- 2020年8月5日12:03:55写着写着感觉自己写的好乱啊,我觉得是因为我能力不够,还学人家写博客,不写了,妈的
项目展览
- 登录页面(因为只注重业务,所以前端页面不怎么展活)
就这吧,不展示了功能太多了,嫌烦了
项目分析
- 创建一个Web项目,名字尽量和项目相关比如“TuShuGuanLi_Dog”
- 此项目纯属锻炼Java Web所以只写业务,导入前端静态页面即可
- 创建数据库,来存放图书信息
- 一步一验证,不给自己的弱智大脑找麻烦,运行下项目
- 实现读者的登录功能
- 实现管理员的登录功能
搭建项目
我们按照分析一步一步来创建自己项目实现功能
1. 创建一个Web项目
2. 导入静态页面至项目的Web文件夹下
先导入login.jsp、css、images方便后面验证由于不是maven项目,此处WEB-INF下应该创建lib目录导入jar包,后期用到什么jar包,现导什么jar包
3. 创建数据库
目资源里有个xxx.sql文件导入即可
4. IDEA连接数据库
选择刚才创建的数据库
项目验证
成功!
三层架构创建
这个“login”跟servlet映射起来,所以要在src下开始创建LoginServlet.java,获取前端传过来的username和password来写登录业务
@WebServlet("/login")
public class LoginSrevlet extends HttpServlet {
/**
* 处理登录的业务逻辑
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
}
}
getParameter与getAttribute两者的区别
request.setAttribute(“xiaoxi”, “欢迎用户”+name);//向request域中放置信息 ( 键值对的形式) 名字为xiaoxi 内容为"欢迎用户"+name
request.getAttribute(“xiaoxi”);//得到request域中放置名字为xiaoxi的信息
request.getParameter(“name”);//得到request域的参数信息(得到jsp页面传过来的参数)
getAttribute表示从request范围取得设置的属性,必须要先setAttribute设置属性,才能通过getAttribute来取得,设置与取得的为Object对象类型 。
getParameter表示接收参数,参数为页面提交的参数,包括:表单提交的参数、URL重写(就是xxx?id=1中的id)传的参数等,因此这个并没有设置参数的方法(没有setParameter),而且接收参数返回的不是Object,而是String类型
拿到数据以后,去验证,去数据库“reader”表验证
说到数据库,第一时间想的就是用代码去连接数据库。三层架构的原因,我们要一步一步的来,“LoginServlet.java"代表controller(控制层),那么接下来就是业务层"service”,面向接口编程,所以先写接口,在写实现类,实现登录的业务,用它去调用repository层来查询数据库,在返回给控制层,然后显示到页面
返回结果为Boolean明显不行,应该返回为读者“reader”的实体类封装对象,所以创建entity(实体类包)下名和数据库对照的实体类“Reader"set,get,toString,有参无参直接怼就完事,然后回到service层下的LoginService接口续写登录方法,返回类型为实体类“Reader"
public interface LoginService {
public Reader login(String username,String password);
}
接着写实现类,在service下创建impl包,包下创建实体类“LoginServiceImpl"
public class LoginServiceImpl implements com.bin.service.LoginService {
@Override
public Reader login(String username, String password) {
return null;
}
}
然后写数据库连接层(repository层),老规矩一个接口一个实现类,基本上一个表一个类
public interface ReaderRepository {
public Reader login(String username,String password);
}
实现类“ReaderRepositoryImpl ”
public class ReaderRepositoryImpl implements ReaderRepository {
@Override
public Reader login(String username, String password) {
return null;
}
}
至此三层架构基本完工,目录结构
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200802172901925.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NTU5MjUwMg==,size_16,color_FFFFFF,t_70
开始调用各个层
实现业务(注入灵魂)
登录功能
三层架构已有,开始互相调用
如:
@WebServlet("/login")
public class LoginSrevlet extends HttpServlet {
private LoginService loginService = new LoginServiceImpl();//调用service层
/**
* 处理登录的业务逻辑
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
Reader reader = loginService.login(username, password);//调用service层的login方法,传入获取的参数,返回一个实体类,判断实体类是否为空
}
}
然后service调用Repository
public class LoginServiceImpl implements com.bin.service.LoginService {
private ReaderRepository readerRepository = new ReaderRepositoryImpl();
@Override
public Reader login(String username, String password) {
return readerRepository.login(username, password);
}
}
Repository是最底层的东西了,它去调用数据库,由于是Web项目没有框架的支持,所以整个数据库工具类说到数据库,那就要开始在web目录下的WEB-INF创建lib目录放jar包(mysql-connector-java-5.1.18.jar和c3p0-0.9.1.2.jar),然后把jar包导入到项目中,把数据库配置文件(c3p0-config.xml)复制到src目录下
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<named-config name="testc3p0">
<!-- 指定连接数据源的基本属性 -->
<property name="user">root</property>
<property name="password">123456</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/library?useUnicode=true&characterEncoding=UTF-8</property>
<!-- 若数据库中连接数不足时, 一次向数据库服务器申请多少个连接 -->
<property name="acquireIncrement">5</property>
<!-- 初始化数据库连接池时连接的数量 -->
<property name="initialPoolSize">5</property>
<!-- 数据库连接池中的最小的数据库连接数 -->
<property name="minPoolSize">5</property>
<!-- 数据库连接池中的最大的数据库连接数 -->
<property name="maxPoolSize">10</property>
</named-config>
</c3p0-config>
然后写数据库工具类JDBCTools.java
public class JDBCTools {
private static DataSource dataSource;//DataSource是一个接口,c3p0是对接口的实现
static {
dataSource = new ComboPooledDataSource("testc3p0");//加载数据源
}
public static Connection getConnection(){
Connection connection = null;
try {
connection = dataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
public static void release(Connection connection, Statement statement, ResultSet resultSet){
try {
if (connection != null){
connection.close();
}
if (statement != null){
statement.close();
}
if (resultSet != null){
resultSet.close();
}
} catch (SQLException e){
e.printStackTrace();
}
}
public static void main(String[] args) {
System.out.println(JDBCTools.getConnection());
}
}
main方法为测试是否成功,如果输出类似“com.mchange.v2.c3p0.impl.NewProxyConnection@2437c6dc”即为成功,可以删除main方法了
工具类没问题,那就开始写ReaderRepositoryImpl.java类
public class ReaderRepositoryImpl implements ReaderRepository {
@Override
public Reader login(String username, String password) {
Connection connection = JDBCTools.getConnection();
String sql = "select * from reader where username = ? and password = ?";
PreparedStatement statement = null;
ResultSet resultSet = null;
Reader reader = null;
try {
statement = connection.prepareStatement(sql);
statement.setString(1,username);
statement.setString(2,password);
resultSet = statement.executeQuery();
if (resultSet.next()){
reader = new Reader(resultSet.getInt(1),resultSet.getString(2),
resultSet.getString(3),resultSet.getString(4),
resultSet.getString(5),resultSet.getString(6),
resultSet.getString(7));
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCTools.release(connection,statement,resultSet);
}
return reader;
}
}
然后直接回到servlet层,DeBug下看能不能取到值,这里service层方法调用Repository,所以直接回到了serlet层,调用service层
进到首页验证
成功
登录有两种类型,一种为读者,一种为管理员,现在验证读者
只需要拿到它的type看它的值为reader(读者)还是admin(管理员)即可,所以说出拿到用户名和密码以外,还要拿到type
@WebServlet("/login")
public class LoginSrevlet extends HttpServlet {
private LoginService loginService = new LoginServiceImpl();
/**
* 处理登录的业务逻辑
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//用户名和密码
String username = req.getParameter("username");
String password = req.getParameter("password");
//获取登录的类型
String type = req.getParameter("type");
Reader reader = loginService.login(username, password);
if (reader != null){
HttpSession session = req.getSession();
session.setAttribute("reader",reader);
req.getRequestDispatcher("");
}else {
resp.sendRedirect("login.jsp");
}
}
}
可以用swich来控制程序流程
switch (type){
case "reader":
break;
case "admin":
break;
}
所以交给Service做,从接口写到实现类
public interface LoginService {
public Reader login(String username,String password,String type);
}
实现类,当type是reader(读者)就返回一个reader(读者),是admin(管理员)就返回一个admin(管理员),写到这时,发现没有管理员的实体类,所以在entity下写个管理员实体类
public class LoginServiceImpl implements com.bin.service.LoginService {
private ReaderRepository readerRepository = new ReaderRepositoryImpl();
@Override
public Reader login(String username, String password,String type) {
switch (type){
case "reader":
break;
case "admin":
break;
}
return readerRepository.login(username, password);
}
}
Admin实体类,按照数据库字段,然后get,set有参无参toString一段狂敲,然后再次回到loginServiceImpl.java
铛铛铛,多态要出现了,方法返回类型为Reader(读者),所以当type返回一个Admin(管理员)肯定不行,所以返回一个Object类型,这样又能是admin又能是reader
更改为,然后发现==readerRepository.login(username, password);==调用的是读者的表,所以要在写一个调用管理员的表
public class LoginServiceImpl implements com.bin.service.LoginService {
private ReaderRepository readerRepository = new ReaderRepositoryImpl();
@Override
public Object login(String username, String password,String type) {
Object object = null;
switch (type){
case "reader":
object = readerRepository.login(username, password);
break;
case "admin":
object = new Admin();
break;
}
return object;
}
}
写调用的Admin表的代码,在repository包下写接口Admin接口及实现类
public interface AdminRepository {
public Admin login(String username,String password);
}
AdminRepositoryImpl.java和ReaderRepositoryImpl.java大差不差,改sql语句里面的表名,和传的类型、获取的字段以及返回的类型
public class AdminRepositoryImpl implements AdminRepository {
@Override
public Admin login(String username, String password) {
Connection connection = JDBCTools.getConnection();
String sql = "select * from bookadmin where username = ? and password = ?";
PreparedStatement statement = null;
ResultSet resultSet = null;
Admin admin = null;
try {
statement = connection.prepareStatement(sql);
statement.setString(1,username);
statement.setString(2,password);
resultSet = statement.executeQuery();
if (resultSet.next()){
admin = new Admin(resultSet.getInt(1),resultSet.getString(2),
resultSet.getString(3));
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCTools.release(connection,statement,resultSet);
}
return admin;
}
}
然后继续回到LoginServiceImpl.java类,调用AdminRepositoyr
public class LoginServiceImpl implements com.bin.service.LoginService {
private ReaderRepository readerRepository = new ReaderRepositoryImpl();
private AdminRepository adminRepository = new AdminRepositoryImpl();
@Override
public Object login(String username, String password,String type) {
Object object = null;
switch (type){
case "reader":
object = readerRepository.login(username, password);
break;
case "admin":
object = adminRepository.login(username,password);
break;
}
return object;
}
}
区分读者还是管理员的就此完成,然后回到上一层LoginServlet.java,续写代码如下,大概意思为,拿到Controller后只有用户名和密码type,然后把这三个值传给service,service会返回一个对象,这个对象使用多态的特性,既可以返一个reader读者又可以反一个admin管理员,这个就是根据type决定的,到LoginServiceImpl后,分别调用readerRepository.login和adminRepository.login获取到对应的对象,再把对象返回到LoginServlet,再去解析出来,把它从父类转到子类,然后存到session。
public class LoginSrevlet extends HttpServlet {
private LoginService loginService = new LoginServiceImpl();
/**
* 处理登录的业务逻辑
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取用户名和密码
String username = req.getParameter("username");
String password = req.getParameter("password");
//获取登录的类型
String type = req.getParameter("type");
Object object = loginService.login(username, password,type);
if (object != null){
HttpSession session = req.getSession();
switch (type){
case "reader":
Reader reader = (Reader) object;
session.setAttribute("reader",reader);
break;
case "admin":
Admin admin = (Admin) object;
session.setAttribute("admin",admin);
break;
}
}else {
resp.sendRedirect("login.jsp");
}
}
}
然后DeBug验证下
成功
展示数据
成功以后肯定需要跳转到相关的页面,所以引入资源index.jsp文件到web目录下,这涉及到一个知识“分页”,看下index.jsp文件,发现又引入头文件,有头就又脚,所以继续引入
这里用到了js文件,所以需要导入jar包jstl.jar和standard.jar,打开Index.jsp报错
然后百度到解决方法:https://blog.csdn.net/qq_41582255/article/details/106470696
在重新打包下项目,成功
中间展示就是具体的数据,从数据库里读,是展示book里面的数据, 所以现在要做的就是把这些数据查出来
查完之后展示到Index.jsp页面就可以了
当读者登录后肯定要跳转到图书页面,展示图书数据,现在缺的就是一个装满图书对象的list,所以说我们可以继续往下走了,写一个service
service干的就是把book表里的数据拿出来,给返回,所以就需要把它封装成一个集合对象,所以创建book表的实体类
黄色代表主键,蓝色是外键,跟其他表进行关联了,通过外键约束,这个外键是关联表的主键,book表是一对多的关系book和bookcase进行关联了,所以说写book实体类怎么去映射这个关系,答案就是再写个bookcase实体类,哈哈哈哈哈哈哈哈哈
实体类老规矩一顿快捷键乱造
public class BookCase {
private Integer id;
private String name;
public BookCase(Integer id, String name) {
this.id = id;
this.name = name;
}
public BookCase() {
}
@Override
public String toString() {
return "Bookcaseid{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
继续Book.java
public class Book {
private Integer id;
private String name;
private String author; //作者
private String publish; //出版社
private Integer pages; //页数
private Double price; //价钱
private BookCase bookCase; //图书分类
public Book(Integer id, String name, String author, String publish, Integer pages, Double price, BookCase bookCase) {
this.id = id;
this.name = name;
this.author = author;
this.publish = publish;
this.pages = pages;
this.price = price;
this.bookCase = bookCase;
}
public Book() {
}
@Override
public String toString() {
return "Book{" +
"id=" + id +
", name='" + name + '\'' +
", author='" + author + '\'' +
", publish='" + publish + '\'' +
", pages=" + pages +
", price=" + price +
", bookCase=" + bookCase +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getPublish() {
return publish;
}
public void setPublish(String publish) {
this.publish = publish;
}
public Integer getPages() {
return pages;
}
public void setPages(Integer pages) {
this.pages = pages;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public BookCase getBookCase() {
return bookCase;
}
public void setBookCase(BookCase bookCase) {
this.bookCase = bookCase;
}
}
继续往后走,到service里面
接口
public interface Boo
//把所有图书查询出来kService {
public List<Book> findAll();
}
实现类写到一半发现sql语句不能写成“select * from book”
所以sql语句改成“select * from book,bookcase where book.bookcaseid=bookcase.id”
续写实现类
public class BookRepositoryImpl implements BookRepository {
@Override
public List<Book> findAll() {
Connection connection = JDBCTools.getConnection();
String sql = "select * from book,bookcase where book.bookcaseid=bookcase.id";
PreparedStatement statement = null;
ResultSet resultSet = null;
List<Book> list = new ArrayList<>();
try {
statement = connection.prepareStatement(sql);
resultSet = statement.executeQuery();
while (resultSet.next()){
list.add(new Book(resultSet.getInt(1),resultSet.getString(2),
resultSet.getString(3), resultSet.getString(4),resultSet.getInt(5),
resultSet.getDouble(6),new BookCase(resultSet.getInt(9),resultSet.getString(10))));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCTools.release(connection,statement,resultSet);
}
return list;
}
}
回到上一层,让service调用它,因为业务简单所以直接调用,
public class BookServiceImpl implements BookService {
private BookRepository bookRepository = new BookRepositoryImpl();
@Override
public List<Book> findAll() {
return bookRepository.findAll();
}
}
再上一层servlet,写数据让它返回到前端,当然servlet要调上面写的Book的Service,然后传到
请求作用域里,是这么说的吧,我也记不清楚了,回头补一下
@WebServlet("/login")
public class LoginSrevlet extends HttpServlet {
private LoginService loginService = new LoginServiceImpl();
private BookService bookService = new BookServiceImpl();
/**
* 处理登录的业务逻辑
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取用户名和密码
String username = req.getParameter("username");
String password = req.getParameter("password");
//获取登录的类型
String type = req.getParameter("type");
Object object = loginService.login(username, password,type);
if (object != null){
HttpSession session = req.getSession();
switch (type){
case "reader":
Reader reader = (Reader) object;
session.setAttribute("reader",reader);
List<Book> list = bookService.findAll();
req.setAttribute("list",list);
//跳转到读者页面
req.getRequestDispatcher("index.jsp").forward(req,resp);
break;
case "admin":
Admin admin = (Admin) object;
session.setAttribute("admin",admin);
//跳转到管理员页面
break;
}
}else {
resp.sendRedirect("login.jsp");
}
}
}
紧接着去index.jsp解析list,展示到页面
运行项目,成功,书架那的应该是我BookCase.java里面toString的问题
所以我们上面展示书架的代码应该改成${book.bookCase.name},不让他调用toString方法
当然问题还是很明显,数据超出页面了,所以分页来了
分页
分页怎么处理呢,还是要看数据库,语句查询的时候给她来个甲鱼的臀部-规定下
比如一次取10条,第一次取出前10条
改SQL语句
select * from book,bookcase where book.bookcaseid=bookcase.id limit 0,10
那取后面的就是
select * from book,bookcase where book.bookcaseid=bookcase.id limit 10,10
一直改数值不是个方法,所以发现个规律
# 每页3条
#1 0,3
#2 3,3
#3 6,3
#....
#n (n-1)*3,3
这是数据库,然后回到index.jsp页面
这是第一页,当点击第二页的时候应该返回2给我,然后通过2的参数对应第2页的记录,所以我们就要page和n (n-1)*3,3 关联起来,实际上这个n就是page,这就是我们公式,现在来分页实一下
在index.jsp实现下一页
我们单独写一个servlet拿这个数据
然后发现上面代码要改一下,BookRepositoryImpl.java里面的sql语句一次把数据拿完了,所以要改一下,一次拿10条
sql语句改为
String sql = "select * from book,bookcase where book.bookcaseid=bookcase.id limit ?,?";
BookRepository.java类里面的方法要带过来两个int类型的参数,然后改接口
public List<Book> findAll(int index,int limit) {
}
回到刚才单独写的servlet类(BookServlet.java),要查询图书的话,把页码信息给我,所以首先拿到一个page,在转成一个int类型
@WebServlet("/book")
public class BookServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String pageStr = req.getParameter("page");
int page = Integer.parseInt(pageStr);
}
}
在Bookservice里面把页数给传进去,就是说当前要查询第几页
public interface BookService {
public List<Book> findAll(int page);
}
传到这以后,需要把page转换成两个参数
比如把1转换成0,3
2转成 3,3以此类推,要做这么一个处理,因为最后落实到SQL语句是两个参数,但是传的是一个参数,因为要用公式转
BookService.java这样写,page就是n,3就是LIMIT,然后把计算结果和LIMIT传到下一层
public class BookServiceImpl implements BookService {
private final int LIMIT = 6;
private BookRepository bookRepository = new BookRepositoryImpl();
@Override
public List<Book> findAll(int page) {
int index = (page-1)*LIMIT;
return bookRepository.findAll(index,LIMIT);
}
}
由于是从下往上写的,所以咱们可以回到BookServlet了,打个断点,Debug登录下,看能取到前6条不能
发现了前面的遗留的坑,随便传个1吧
是前6个,成功了,因为传的是1所以把前6条传出来了,接下来点击下一页让数据更新
显示页数
所以回到index.jsp
服务器还要把这个三个参数给带过去,所以Servlet继续获取,当获取到总页数的时候,问题出现了
这个需要 数据总数/每页数据=总页数现在就要写个方法了,调用它了,这就是业务层的东西了,去写接口,实现类,实现类写具体内容发现,需要往下一层在写一个方法(Repository)获取总记录条数
public class BookRepositoryImpl implements BookRepository {
@Override
public List<Book> findAll(int index,int limit) {
Connection connection = JDBCTools.getConnection();
String sql = "select * from book,bookcase where book.bookcaseid=bookcase.id limit ?,?";
PreparedStatement statement = null;
ResultSet resultSet = null;
List<Book> list = new ArrayList<>();
try {
statement = connection.prepareStatement(sql);
statement.setInt(1,index);
statement.setInt(2,limit);
resultSet = statement.executeQuery();
while (resultSet.next()){
list.add(new Book(resultSet.getInt(1),resultSet.getString(2),
resultSet.getString(3), resultSet.getString(4),resultSet.getInt(5),
resultSet.getDouble(6),new BookCase(resultSet.getInt(9),resultSet.getString(10))));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCTools.release(connection,statement,resultSet);
}
return list;
}
@Override
public int count() {
Connection connection = JDBCTools.getConnection();
String sql = "select count(*) from book,bookcase where book.bookcaseid=bookcase.id";
ResultSet resultSet = null;
PreparedStatement statement = null;
int count = 0;
try {
statement = connection.prepareStatement(sql);
resultSet = statement.executeQuery();
while (resultSet.next()){
count=resultSet.getInt(1);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCTools.release(connection,statement,resultSet);
}
return count;
}
}
我想着这个换成count++,竟然还不行,那就这样吧,这个方法简单,就不多介绍了,业务层完毕,现在再去上一层,Servlet
while (resultSet.next()){
count=resultSet.getInt(1);
}
现在往上一层,回到service
public class BookServiceImpl implements BookService {
private final int LIMIT = 6;
private BookRepository bookRepository = new BookRepositoryImpl();
@Override
public List<Book> findAll(int page) {
int index = (page-1)*LIMIT;
return bookRepository.findAll(index,LIMIT);
}
@Override
public int getPages() {
int count = bookRepository.count();
int page = 0;
if (count%LIMIT ==0){
page = count/LIMIT;
}else {
page = count/LIMIT+1;
}
return page;
}
}
这个无需多言了,我不知道该怎么说了,大脑有点混乱了,第一次做项目,我应该要重新捋一遍了
@WebServlet("/login")
public class LoginSrevlet extends HttpServlet {
private LoginService loginService = new LoginServiceImpl();
private BookService bookService = new BookServiceImpl();
/**
* 处理登录的业务逻辑
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取用户名和密码
String username = req.getParameter("username");
String password = req.getParameter("password");
//获取登录的类型
String type = req.getParameter("type");
Object object = loginService.login(username, password,type);
if (object != null){
HttpSession session = req.getSession();
switch (type){
case "reader":
Reader reader = (Reader) object;
session.setAttribute("reader",reader);
List<Book> list = bookService.findAll(2);
req.setAttribute("list",list);
req.setAttribute("dataPrePage",6);//每页展示记录数
req.setAttribute("currentPage",1);//当前页数
req.setAttribute("pages",bookService.getPages());//总页数,不能写死,需要动态获取
//跳转到读者页面
req.getRequestDispatcher("index.jsp").forward(req,resp);
break;
case "admin":
Admin admin = (Admin) object;
session.setAttribute("admin",admin);
//跳转到管理员页面
break;
}
}else {
resp.sendRedirect("login.jsp");
}
}
}
运行项目成功
开始实现下一页功能,点击下一页,当前页数应该+1,把2传过去,把第2页的信息都拿出来,在返回出来,通过js来实现
下一页及首页尾页
给下一页(nex)写个单击事件,然后在拿到当前页数(currentPage)的内容xxx.html()(就是1)转成int类型再+1,就变成了2
<script type="text/javascript">
$(function () {
$("#next").click(function () {
var page = parseInt($("#currentPage").html())+1;
location.href = "/book?page="+page;//通过js访问后台的一个方法,访问的是BookServletImpl的doget方法,
// 传的是当前拿到的2
})
})
</script>
然后回到BookServletImpl.java
@WebServlet("/book")
public class BookServlet extends HttpServlet {
private BookService bookService = new BookServiceImpl();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String pageStr = req.getParameter("page");//拿到了2,3,4...
int page = Integer.parseInt(pageStr);
List<Book> list = bookService.findAll(page);
req.setAttribute("list",list);
req.setAttribute("dataPrePage",6);//每页展示记录数
req.setAttribute("currentPage",page);//当前页数
req.setAttribute("pages",bookService.getPages());
req.getRequestDispatcher("index.jsp").forward(req,resp);
}
}
紧接着发现了新的问题,需要设置一个上线,前端就能设置,当前页面肯定不能大于总页面
成了
<script type="text/javascript">
$(function () {
$("#next").click(function () {
var pages = parseInt($("#pages").html());
var page = parseInt($("#currentPage").html());
if (page == pages){//说明是最后一页,直接跳出方法
return;
}
page++;
location.href = "/book?page="+page;//通过js访问后台的一个方法,访问的是BookServletImpl的doget方法,
// 传的是当前拿到的2
})
})
这样一说上一页岂不是减减就行了吗
$("#previous").click(function () {
var page = parseInt($("#currentPage").html());
if (page == 1){//说明是第一页,直接跳出方法
return;
}
page--;
location.href = "/book?page="+page;
})
那首页和最后一也起步更简单了
//首页
$("#first").click(function () {
location.href = "/book?page=1";//第一页不需要判断,只需要等于1就行了
})
//最后一页
$("#last").click(function () {
var pages = parseInt($("#pages").html());//总页数
location.href = "/book?page="+pages;
})
优化代码
发现这俩个代码有重复的,这就需要优化了,LoginServlet代码里一个逻辑块写了两个业务信息
1.验证用户和密码
2.加载图书信息
这就是高耦合,现在开始解耦
LoginServlet修改为,通过代码resp.sendRedirect("/book?page=1"); 直接调到BookServlet还带了一个初始页面
@WebServlet("/login")
public class LoginSrevlet extends HttpServlet {
private LoginService loginService = new LoginServiceImpl();
private BookService bookService = new BookServiceImpl();
/**
* 处理登录的业务逻辑
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取用户名和密码
String username = req.getParameter("username");
String password = req.getParameter("password");
//获取登录的类型
String type = req.getParameter("type");
Object object = loginService.login(username, password,type);
if (object != null){
HttpSession session = req.getSession();
switch (type){
case "reader":
Reader reader = (Reader) object;
session.setAttribute("reader",reader);
resp.sendRedirect("/book?page=1");
break;
case "admin":
Admin admin = (Admin) object;
session.setAttribute("admin",admin);
//跳转到管理员页面
break;
}
}else {
resp.sendRedirect("login.jsp");
}
}
}
借阅
下面开始实现借阅功能,比如借一本书,管理员如果同意,就能把书拿走,反之不能,我们来实现借阅功能,首先要把借阅请求发出去,操作入口就在view这一层就是jsp,点击借阅按钮表示用户做了这么一个操作,然后把这个操作转换成程序,落实到数据库里,我们需要这样一张表,这张表关联了三个表,图书表,读者表,管理员表,因为借书这个事,需要三个参与对象,哪本书被哪个人借走,又被哪个管理员审核
state 0表示未审核,1表是通过,2表示不通过,还回来3
借阅就是向数据库添加一条新记录
来到入口index.jsp,这个进到BookServlet,所以图书相关的都放这
这就要逻辑分层了,因为只有一个doGet方法,这个方法里面处理的是加载图书信息的,现在要添加一个借阅审核的逻辑,一个方法怎么用两个逻辑,让他传过来一个method,我就知道它要干啥了,这就能分开了
根据传来的method来控制程序流程
@WebServlet("/book")
public class BookServlet extends HttpServlet {
private BookService bookService = new BookServiceImpl();
/**
* 加载图书数据
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getParameter("method");//区分逻辑,是否是借阅
if (method == null){
method = "findAll";//默认就是图书查询
}
//流程控制
switch (method){
case "findAll":
String pageStr = req.getParameter("page");
int page = Integer.parseInt(pageStr);
List<Book> list = bookService.findAll(page);
req.setAttribute("list",list);
req.setAttribute("dataPrePage",6);//每页展示记录数
req.setAttribute("currentPage",page);//当前页数
req.setAttribute("pages",bookService.getPages());
req.getRequestDispatcher("index.jsp").forward(req,resp);
break;
case "addBorrow":
break;
}
}
}
接下来考虑传什么参数,就看数据库需要哪些字段,id是自增的,不需要,bookid需要判断是哪本书readerid不需要传,因为reader在session里面存的,直接拿session就行 ,登录的时候回已经把reader存进去了
总结下来只需要传bookid就好了
然后写servlet
@WebServlet("/book")
public class BookServlet extends HttpServlet {
private BookService bookService = new BookServiceImpl();
/**
* 加载图书数据
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getParameter("method");//区分逻辑,是否是借阅
if (method == null){
method = "findAll";//默认就是图书查询
}
//流程控制
switch (method){
case "findAll":
String pageStr = req.getParameter("page");
int page = Integer.parseInt(pageStr);
List<Book> list = bookService.findAll(page);
req.setAttribute("list",list);
req.setAttribute("dataPrePage",6);//每页展示记录数
req.setAttribute("currentPage",page);//当前页数
req.setAttribute("pages",bookService.getPages());
req.getRequestDispatcher("index.jsp").forward(req,resp);
break;
case "addBorrow":
//拿到jsp页面传来的bookid,再转成int
String bookidStr = req.getParameter("bookid");
int bookid = Integer.parseInt(bookidStr);
//拿到LoginServlet登录成功的reader session
HttpSession session = req.getSession();
Reader reader = (Reader) session.getAttribute("reader");
break;
}
}
}
接下来就是业务层的事了,service里写一个方法,传递两个参数,service层拿不到的东西,需要Controller传过来
public interface BookService {
public List<Book> findAll(int page);
public int getPages();
public void addBorrow(Integer bookid,Integer readerid);
}
这层写完,继续下一层
public class BookServiceImpl implements BookService {
private final int LIMIT = 6;
private BookRepository bookRepository = new BookRepositoryImpl();
@Override
public List<Book> findAll(int page) {
int index = (page-1)*LIMIT;
return bookRepository.findAll(index,LIMIT);
}
@Override
public int getPages() {
int count = bookRepository.count();
int page = 0;
if (count%LIMIT ==0){
page = count/LIMIT;
}else {
page = count/LIMIT+1;
}
return page;
}
@Override
public void addBorrow(Integer bookid, Integer readerid) {
//借书时间
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
String borrowTime = simpleDateFormat.format(date);
//还书时间,借书时间+14天
Calendar calendar = Calendar.getInstance();
int dates = calendar.get(Calendar.DAY_OF_YEAR) + 14;
calendar.set(Calendar.DAY_OF_YEAR, dates);
Date date2 = calendar.getTime();
String returnTime = simpleDateFormat.format(date2);
}
}
下一层,一个表对应一个Repository,创建一个borroRepository接口实现类
public class BorroRepositoryImpl implements BorrowRepository {
@Override
public void insert(Integer bookid, Integer readerid, String borrowtime, String returntime, Integer adminid, Integer state) {
}
}
实现类
public class BorroRepositoryImpl implements BorrowRepository {
@Override
public void insert(Integer bookid, Integer readerid, String borrowtime, String returntime, Integer adminid, Integer state) {
Connection connection = JDBCTools.getConnection();
String sql = "insert into borrow(bookid,readerid,borrowtime,returntime,state) values(?,?,?,?,0)";
PreparedStatement statement = null;
try {
statement = connection.prepareStatement(sql);
statement.setInt(1,bookid);
statement.setInt(2,readerid);
statement.setString(3,borrowtime);
statement.setString(4,returntime);
statement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCTools.release(connection,statement,null);
}
}
}
上一层(service)让它调用Repsotory
public class BookServiceImpl implements BookService {
private final int LIMIT = 6;
private BookRepository bookRepository = new BookRepositoryImpl();
private BorrowRepository borrowRepository = new BorroRepositoryImpl();
@Override
public List<Book> findAll(int page) {
int index = (page-1)*LIMIT;
return bookRepository.findAll(index,LIMIT);
}
@Override
public int getPages() {
int count = bookRepository.count();
int page = 0;
if (count%LIMIT ==0){
page = count/LIMIT;
}else {
page = count/LIMIT+1;
}
return page;
}
@Override
public void addBorrow(Integer bookid, Integer readerid) {
//借书时间
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
String borrowTime = simpleDateFormat.format(date);
//还书时间,借书时间+14天
Calendar calendar = Calendar.getInstance();
int dates = calendar.get(Calendar.DAY_OF_YEAR) + 14;
calendar.set(Calendar.DAY_OF_YEAR, dates);
Date date2 = calendar.getTime();
String returnTime = simpleDateFormat.format(date2);
borrowRepository.insert(bookid,readerid,borrowTime,returnTime,null,0);
}
}
再往上一层(Bookservlet),调用
@WebServlet("/book")
public class BookServlet extends HttpServlet {
private BookService bookService = new BookServiceImpl();
/**
* 加载图书数据
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getParameter("method");//区分逻辑,是否是借阅
if (method == null){
method = "findAll";//默认就是图书查询
}
//流程控制
switch (method){
case "findAll":
String pageStr = req.getParameter("page");
int page = Integer.parseInt(pageStr);
List<Book> list = bookService.findAll(page);
req.setAttribute("list",list);
req.setAttribute("dataPrePage",6);//每页展示记录数
req.setAttribute("currentPage",page);//当前页数
req.setAttribute("pages",bookService.getPages());
req.getRequestDispatcher("index.jsp").forward(req,resp);
break;
case "addBorrow":
//拿到jsp页面传来的bookid,再转成int
String bookidStr = req.getParameter("bookid");
int bookid = Integer.parseInt(bookidStr);
//拿到LoginServlet登录成功的reader session
HttpSession session = req.getSession();
Reader reader = (Reader) session.getAttribute("reader");
bookService.addBorrow(bookid,reader.getId());
break;
}
}
}
大致就是从index.jsp那个借阅一点把method和id传过去
进到servlet里面,通过method来判断执行借阅的代码操作,把id拿过来,在把reader拿过来,把id和reader的id在传给service
在service中,把系统时间拿出来,在把还书时间整出来,在把这些参数传给repository
repository直接往里面就行了,分工相当明确
servlet只需要拿到参数就行了
service只需要进行业务处理,业务处理好交给repository
repository只负责存
好了,运行项目点击借阅,然后一片空白
发现数据库多了条记录,成功了
然后给响应下,不能一片空白,就是吧这个用户的所有借书信息给响应出来,就是展示数据表(borrow)里面一个读者(readerid)的全部借书信息,从下往上,所有要在BorrowkRepository写一个方法,写到返回类型的时候,发现要有一个实体类,对应borrow表,表关系复杂,所有直接弄其他实体类,然后一套组合拳set,get…等一系列操作
public class Borrow {
private Integer id;
private Book book;
private Reader reader;
private String borromTime;
private String returnTime;
}
然后根据自己要返回的的子段,补充下有参,这里我们需要这些信息
select br.id,b.name,b.author,b.publish,br.borrowtime,br.returntime,r.name,r.tel,r.cardid from borrow br,book b ,reader r where readerid = 3 and b.id = br.bookid and r.id=br.readerid
实体类里在写一些有参
回到Repository方法就有返回对象了,这里需要个id,根据id才能查出信息,再次回到实现类
public interface BorrowRepository {
//插入一条借书信息
public void insert(Integer bookid,Integer readerid,String borrowtime,String returntime,Integer adminid,Integer state);
public List<Borrow> findAllByReaderId(Integer id);
}
实现类,有点安耐不住了,烦了
public class BorroRepositoryImpl implements BorrowRepository {
@Override
public void insert(Integer bookid, Integer readerid, String borrowtime, String returntime, Integer adminid, Integer state) {
Connection connection = JDBCTools.getConnection();
String sql = "insert into borrow(bookid,readerid,borrowtime,returntime,state) values(?,?,?,?,0)";
PreparedStatement statement = null;
try {
statement = connection.prepareStatement(sql);
statement.setInt(1,bookid);
statement.setInt(2,readerid);
statement.setString(3,borrowtime);
statement.setString(4,returntime);
statement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCTools.release(connection,statement,null);
}
}
@Override
public List<Borrow> findAllByReaderId(Integer id) {
Connection connection = JDBCTools.getConnection();
String sql = "select br.id,b.name,b.author,b.publish,br.borrowtime,br.returntime,r.name,r.tel,r.cardid from borrow br,book b ,reader r where readerid = ? and b.id = br.bookid and r.id=br.readerid";
PreparedStatement statement = null;
ResultSet resultSet = null;
List<Borrow> list = new ArrayList<>();
try {
statement=connection.prepareStatement(sql);
statement.setInt(1,id);
resultSet = statement.executeQuery();
while (resultSet.next()){
list.add(new Borrow(resultSet.getInt(1),
new Book(resultSet.getString(2),resultSet.getString(3),resultSet.getString(4)),
new Reader(resultSet.getString(7),resultSet.getString(8),resultSet.getString(9)),
resultSet.getString(5),
resultSet.getString(6)));
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCTools.release(connection,statement,resultSet);
}
return list;
}
}
再往上走
public interface BookService {
public List<Book> findAll(int page);
public int getPages();
public void addBorrow(Integer bookid,Integer readerid);
//返回他所有借书记录
public List<Borrow> findAllBorrowByReaderId(Integer id);
}
service实现类
public class BookServiceImpl implements BookService {
private final int LIMIT = 6;
private BookRepository bookRepository = new BookRepositoryImpl();
private BorrowRepository borrowRepository = new BorroRepositoryImpl();
@Override
public List<Book> findAll(int page) {
int index = (page-1)*LIMIT;
return bookRepository.findAll(index,LIMIT);
}
@Override
public int getPages() {
int count = bookRepository.count();
int page = 0;
if (count%LIMIT ==0){
page = count/LIMIT;
}else {
page = count/LIMIT+1;
}
return page;
}
@Override
public void addBorrow(Integer bookid, Integer readerid) {
//借书时间
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
String borrowTime = simpleDateFormat.format(date);
//还书时间,借书时间+14天
Calendar calendar = Calendar.getInstance();
int dates = calendar.get(Calendar.DAY_OF_YEAR) + 14;
calendar.set(Calendar.DAY_OF_YEAR, dates);
Date date2 = calendar.getTime();
String returnTime = simpleDateFormat.format(date2);
borrowRepository.insert(bookid,readerid,borrowTime,returnTime,null,0);
}
@Override
public List<Borrow> findAllBorrowByReaderId(Integer id) {
return borrowRepository.findAllByReaderId(id);
}
}
在往上走回到servlet,打个点断验证下
点击借阅
成功
现在,在Repository的sql语句追加一个审核状态state
public class BorroRepositoryImpl implements BorrowRepository {
@Override
public void insert(Integer bookid, Integer readerid, String borrowtime, String returntime, Integer adminid, Integer state) {
Connection connection = JDBCTools.getConnection();
String sql = "insert into borrow(bookid,readerid,borrowtime,returntime,state) values(?,?,?,?,0)";
PreparedStatement statement = null;
try {
statement = connection.prepareStatement(sql);
statement.setInt(1,bookid);
statement.setInt(2,readerid);
statement.setString(3,borrowtime);
statement.setString(4,returntime);
statement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCTools.release(connection,statement,null);
}
}
@Override
public List<Borrow> findAllByReaderId(Integer id) {
Connection connection = JDBCTools.getConnection();
String sql = "select br.id,b.name,b.author,b.publish,br.borrowtime,br.returntime,r.name,r.tel,r.cardid,br.state from borrow br,book b ,reader where readerid = ? and b.id = br.bookid and r.id=br.readerid";
PreparedStatement statement = null;
ResultSet resultSet = null;
List<Borrow> list = new ArrayList<>();
try {
statement=connection.prepareStatement(sql);
statement.setInt(1,id);
resultSet = statement.executeQuery();
while (resultSet.next()){
list.add(new Borrow(resultSet.getInt(1),
new Book(resultSet.getString(2),resultSet.getString(3),resultSet.getString(4)),
new Reader(resultSet.getString(7),resultSet.getString(8),resultSet.getString(9)),
resultSet.getString(5),
resultSet.getString(6),resultSet.getInt(10)));
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCTools.release(connection,statement,resultSet);
}
return list;
}
}
Borrow实体类多个变量
public class Borrow {
private Integer id;
private Book book;
private Reader reader;
private String borrowTime;
private String returnTime;
private Integer state;
public String getBorrowTime() {
return borrowTime;
}
public void setBorrowTime(String borrowTime) {
this.borrowTime = borrowTime;
}
public String getReturnTime() {
return returnTime;
}
public void setReturnTime(String returnTime) {
this.returnTime = returnTime;
}
public Integer getState() {
return state;
}
public void setState(Integer state) {
this.state = state;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Book getBook() {
return book;
}
public void setBook(Book book) {
this.book = book;
}
public Reader getReader() {
return reader;
}
public void setReader(Reader reader) {
this.reader = reader;
}
public Borrow(Integer id, Book book, Reader reader, String borrowTime, String returnTime, Integer state) {
this.id = id;
this.book = book;
this.reader = reader;
this.borrowTime = borrowTime;
this.returnTime = returnTime;
this.state = state;
}
}
再回到borrow.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ page isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'borrow.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
<link href="css/index.css" type="text/css" rel="stylesheet">
<script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$(function(){
$("#next").click(function(){
var pages = parseInt($("#pages").html());
var page = parseInt($("#currentPage").html());
if(page == pages){
return;
}
page++;
location.href = "/book?method=findAllBorrow&page="+page;
})
$("#previous").click(function () {
var page = parseInt($("#currentPage").html());
if(page == 1){
return;
}
page--;
location.href = "/book?method=findAllBorrow&page="+page;
})
$("#first").click(function () {
location.href = "/book?method=findAllBorrow&page=1";
})
$("#last").click(function(){
var pages = parseInt($("#pages").html());
location.href = "/book?method=findAllBorrow&page="+pages;
})
})
</script>
</head>
<body>
<%@ include file="top.jsp" %>
<div id="main">
<div class="navigation">
当前位置: <a href="/book?page=1">首页</a>
<div id="readerBlock">欢迎回来 :${reader.name } <a href="/logout">注销</a></div>
</div>
<div class="img_block">
<img src="images/main_booksort.gif" class="img" />
</div>
<table class="table" cellspacing="0">
<tr>
<td>编号</td>
<td>图书名称</td>
<td>图书作者</td>
<td>出版社</td>
<td>读者姓名</td>
<td>联系电话</td>
<td>证件编号</td>
<td>借书时间</td>
<td>还书时间</td>
<td>审核状态</td>
</tr>
<c:forEach items="${list}" var="borrow">
<tr>
<td>${borrow.id}</td>
<td>${borrow.book.name}</td>
<td>${borrow.book.author}</td>
<td>${borrow.book.publish}</td>
<td>${borrow.reader.name}</td>
<td>${borrow.reader.tel}</td>
<td>${borrow.reader.carid}</td>
<td>${borrow.borrowTime}</td>
<td>${borrow.returnTime}</td>
<td>${borrow.state}</td>
</tr>
</c:forEach>
</table>
<hr class="hr"/>
<div id="pageControl">
<div class="pageControl_item">每页<font id="dataPrePage">${dataPrePage }</font>条数据</div>
<div class="pageControl_item" id="last">最后一页</div>
<div class="pageControl_item" id="next">下一页</div>
<div class="pageControl_item"><font id="currentPage">${currentPage }</font>/<font id="pages">${pages }</font></div>
<div class="pageControl_item" id="previous">上一页</div>
<div class="pageControl_item" id="first">首页</div>
</div>
</div>
<%@ include file="footer.jsp" %>
</body>
</html>
运行项目,成功,现在开始分页,还有审核状态不能给显示数字,展示的时候把数字给翻译下
这样就翻译过来了
再次运行项目,成功
先写个过滤器,要不要页面刷新后点击借阅返回空指针异常
@WebServlet("/book")
public class ReaderFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//判断是否有读者登录
HttpSession session =((HttpServletRequest)servletRequest).getSession();
Reader reader = (Reader) session.getAttribute("reader");
if (reader == null){
((HttpServletResponse)servletResponse).sendRedirect("login.jsp");
}else {
filterChain.doFilter(servletRequest,servletResponse);
}
}
}
现在开始分页,根据上面分页的经验
借阅分页
接口
public interface BorrowRepository {
//插入一条借书信息
public void insert(Integer bookid,Integer readerid,String borrowtime,String returntime,Integer adminid,Integer state);
public List<Borrow> findAllByReaderId(Integer id,Integer index,Integer limit);
}
实现类,只需要更改sql语句,然后替换sql语句的值,具体的交给service业务层
public class BorroRepositoryImpl implements BorrowRepository {
@Override
public void insert(Integer bookid, Integer readerid, String borrowtime, String returntime, Integer adminid, Integer state) {
Connection connection = JDBCTools.getConnection();
String sql = "insert into borrow(bookid,readerid,borrowtime,returntime,state) values(?,?,?,?,0)";
PreparedStatement statement = null;
try {
statement = connection.prepareStatement(sql);
statement.setInt(1,bookid);
statement.setInt(2,readerid);
statement.setString(3,borrowtime);
statement.setString(4,returntime);
statement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCTools.release(connection,statement,null);
}
}
@Override
public List<Borrow> findAllByReaderId(Integer id,Integer index,Integer limit) {
Connection connection = JDBCTools.getConnection();
String sql = "select br.id,b.name,b.author,b.publish,br.borrowtime,br.returntime,r.name,r.tel,r.cardid,br.state from borrow br,book b ,reader r where readerid = ? and b.id = br.bookid and r.id = br.readerid limit ?,?";
PreparedStatement statement = null;
ResultSet resultSet = null;
List<Borrow> list = new ArrayList<>();
try {
statement=connection.prepareStatement(sql);
statement.setInt(1,id);
statement.setInt(2,index);
statement.setInt(3,limit);
resultSet = statement.executeQuery();
while (resultSet.next()){
list.add(new Borrow(resultSet.getInt(1),
new Book(resultSet.getString(2),resultSet.getString(3),resultSet.getString(4)),
new Reader(resultSet.getString(7),resultSet.getString(8),resultSet.getString(9)),
resultSet.getString(5),
resultSet.getString(6),resultSet.getInt(10)));
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCTools.release(connection,statement,resultSet);
}
return list;
}
}
回到servlet,获取页数,紧着发现这个addBorrow方法执行了两个业务
如何改变文本的样式
强调文本 强调文本
加粗文本 加粗文本
标记文本
删除文本
引用文本
H2O is是液体。
210 运算结果是 1024.
插入链接与图片
链接: link.
图片:
带尺寸的图片:
居中的图片:
居中并且带尺寸的图片:
当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。
如何插入一段漂亮的代码片
去博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片
.
// An highlighted block
var foo = 'bar';
生成一个适合你的列表
- 项目
- 项目
- 项目
- 项目
- 项目1
- 项目2
- 项目3
- 计划任务
- 完成任务
创建一个表格
一个简单的表格是这么创建的:
项目 | Value |
---|---|
电脑 | $1600 |
手机 | $12 |
导管 | $1 |
设定内容居中、居左、居右
使用:---------:
居中
使用:----------
居左
使用----------:
居右
第一列 | 第二列 | 第三列 |
---|---|---|
第一列文本居中 | 第二列文本居右 | 第三列文本居左 |
SmartyPants
SmartyPants将ASCII标点字符转换为“智能”印刷标点HTML实体。例如:
TYPE | ASCII | HTML |
---|---|---|
Single backticks | 'Isn't this fun?' | ‘Isn’t this fun?’ |
Quotes | "Isn't this fun?" | “Isn’t this fun?” |
Dashes | -- is en-dash, --- is em-dash | – is en-dash, — is em-dash |
创建一个自定义列表
-
Markdown
- Text-to- HTML conversion tool Authors
- John
- Luke
如何创建一个注脚
一个具有注脚的文本。1
注释也是必不可少的
Markdown将文本转换为 HTML。
KaTeX数学公式
您可以使用渲染LaTeX数学表达式 KaTeX:
Gamma公式展示 Γ ( n ) = ( n − 1 ) ! ∀ n ∈ N \Gamma(n) = (n-1)!\quad\forall n\in\mathbb N Γ(n)=(n−1)!∀n∈N 是通过欧拉积分
Γ ( z ) = ∫ 0 ∞ t z − 1 e − t d t . \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,. Γ(z)=∫0∞tz−1e−tdt.
你可以找到更多关于的信息 LaTeX 数学表达式[here][1].
新的甘特图功能,丰富你的文章
- 关于 甘特图 语法,参考 [这儿][2],
UML 图表
可以使用UML图表进行渲染。 Mermaid. 例如下面产生的一个序列图:
这将产生一个流程图。:
- 关于 Mermaid 语法,参考 [这儿][3],
FLowchart流程图
我们依旧会支持flowchart的流程图:
- 关于 Flowchart流程图 语法,参考 [这儿][4].
导出与导入
导出
如果你想尝试使用此编辑器, 你可以在此篇文章任意编辑。当你完成了一篇文章的写作, 在上方工具栏找到 文章导出 ,生成一个.md文件或者.html文件进行本地保存。
导入
如果你想加载一篇你写过的.md文件,在上方工具栏可以选择导入功能进行对应扩展名的文件导入,
继续你的创作。
注脚的解释 ↩︎