在近期的教学过程中,使用spring jdbc 和Thymeleaf完成一个教学案例,实现了基本的crud和分页、模糊、图片上传功能,希望能够给初学者起到抛砖引玉的作用,还请读者给予批评和指正。
项目环境:STS+Mysql5.6+JDK1.8+Maven3.5
项目架构:spring boot 数据层:spring jdbc 视图层:Thymeleaf +jQuery+bootstrap
项目结构:
application.yml:
spring:
datasource:
username: root
password: root
url: jdbc:mysql:///boot_db?serverTimezone=UTC
数据表结构:
IBookDao 接口:
package bw.swn.boot.dao;
import java.util.List;
import bw.swn.boot.entity.Book;
public interface IBookDao {
String INSERT_BOOK="INSERT INTO t_book(title,author,price,pub_date,photo) VALUES(?,?,?,?,?)";
String DELETE_BOOK="DELETE FROM t_book WHERE id=?";
String UPDATE_BOOK="UPDATE t_book SET title=?,author=?,price=?,pub_date=?,photo=? WHERE id=?";
String FIND_ALL_BOOK="SELECT * FROM t_book";
String FIND_BY_ID_BOOK="SELECT * FROM t_book WHERE id=?";
String PAGE_LIST_BOOK="SELECT * FROM t_book ORDER BY id DESC LIMIT ?,?";
String COUNT_BOOK="SELECT COUNT(id) FROM t_book";
List<Book> listBooks();
Book findById(int id);
int addBook(Book book);
int delete(int id);
int update(Book book);
Long getMohuTotal(String mohu);
List<Book> pagelist_book(Integer offset, Integer pagesize, String mohu);
}
BookDao 类:
package bw.swn.boot.dao;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import bw.swn.boot.entity.Book;
@Repository
public class BookDao implements IBookDao {
@Resource
private JdbcTemplate jdbcTemplate;
private class BookRowMapper implements RowMapper<Book>{
@Override
public Book mapRow(ResultSet rs, int arg1) throws SQLException {
final Book book=new Book();
book.setAuthor(rs.getString("author"));
book.setPhoto(rs.getString("photo"));
book.setId(rs.getInt("id"));
book.setTitle(rs.getString("title"));
book.setPub_date(rs.getDate("pub_date"));
book.setPrice(rs.getInt("price"));
return book;
}
}
@Override
public List<Book> listBooks() {
return this.jdbcTemplate.query(FIND_ALL_BOOK,new BookRowMapper());
}
@Override
public Book findById(int id) {
return this.jdbcTemplate.queryForObject(FIND_BY_ID_BOOK, new BookRowMapper(),id);
}
@Override
public int addBook(Book book) {
return this.jdbcTemplate.update(INSERT_BOOK,
book.getTitle(),book.getAuthor(),book.getPrice(),book.getPub_date(),book.getPhoto());
}
@Override
public int delete(int id) {
return this.jdbcTemplate.update(DELETE_BOOK,id);
}
@Override
public int update(Book book) {
return this.jdbcTemplate.update(UPDATE_BOOK,
book.getTitle(),book.getAuthor(),book.getPrice(),book.getPub_date(),book.getPhoto(),book.getId());
}
@Override
public Long getMohuTotal(String mohu) {
if(mohu!=null) return this.jdbcTemplate.queryForObject("SELECT COUNT(id) FROM t_book WHERE title LIKE '%"+mohu+"%'", Long.class);
return this.jdbcTemplate.queryForObject(COUNT_BOOK, Long.class);
}
@Override
public List<Book> pagelist_book(Integer offset, Integer pagesize, String mohu) {
if(mohu==null | mohu.isEmpty()) return this.jdbcTemplate.query(PAGE_LIST_BOOK, new BookRowMapper(),offset,pagesize);
return this.jdbcTemplate.query("SELECT * FROM t_book WHERE title LIKE '%"+mohu+"%' LIMIT ?,?", new BookRowMapper(),offset,pagesize);
}
}
分页工具类:
@Component
public class Pager<T> {
private Integer offset;
private Integer pagesize;
private Integer provPage;
private Integer nextPage;
private Integer pagePages;
private Long total;
private Integer pageNumber;
private List<T> datas;
private String mohu;
public Pager() {
}
public Pager(int current,int pagesize,Long total,String mohu){
this.total=total;
this.mohu=mohu;
this.pagesize=pagesize;
this.pageNumber=current;
this.offset=(current-1)*this.pagesize;
//得到总页数
this.pagePages = Integer.parseInt(this.total.toString())% this.pagesize > 0
? Integer.parseInt(this.total.toString())/this.pagesize +1
: Integer.parseInt(this.total.toString()) / this.pagesize;
// 计算上一页
this.provPage = this.pageNumber == 1 ? this.pageNumber : this.pageNumber - 1;
// 计算下一页
this.nextPage = this.pageNumber == Integer.valueOf(this.pagePages.toString())? Integer.parseInt(this.pageNumber.toString()) : this.pageNumber +1;
}
//省去 get ..和set
}
控制器:
package bw.swn.boot.web;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.List;
import java.util.UUID;
import javax.annotation.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import bw.swn.boot.entity.Book;
import bw.swn.boot.service.IBookService;
import bw.swn.boot.util.Pager;
@Controller
public class BookController {
private static final String IMG_PATH = "/resources/upload/";//文件路径
@Resource
private IBookService bookService;
@RequestMapping("/")//分页+模糊
public String pagelist_book(@RequestParam(defaultValue = "1") int current, Model model,
@RequestParam(required = false, name = "mohu", defaultValue = "") String mohu) {
Long total = this.bookService.getTotal(mohu);
Pager<Book> pager = new Pager<>(current, 5, total, mohu);
List<Book> datas = this.bookService.pagelist_book(pager.getOffset(), pager.getPagesize(), mohu);
pager.setDatas(datas);
pager.setMohu(mohu);
model.addAttribute("pager", pager);
model.addAttribute("path", IMG_PATH);
return "pagelist_book";
}
@RequestMapping("/add_book")//添加请求
public String toadd() {
return "add_book";
}
@RequestMapping(value="/add_book",method=RequestMethod.POST)//添加处理
public String add(Book book,MultipartFile pic,Model model) {
String path = null;
if (pic != null) {
try {
// 得到真实路径
path = ResourceUtils.getFile("classpath:static/resources/upload/").getPath();
System.out.println(path);
// 利用UUID和原文件名称得到一个新的文件名称(防止文件名冲突)
String new_name = UUID.randomUUID() + pic.getOriginalFilename();
File file = new File(path + File.separator + new_name);
//保存图片
pic.transferTo(file);
//修改图片
book.setPhoto(new_name);
System.out.println(" new file"+new_name);
} catch (Exception e) {
e.printStackTrace();
}
}
if(this.bookService.addBook(book)==1) return "redirect:/";
model.addAttribute("mess", "添加失败!");
return "add_book";
}
@RequestMapping("{id}/update")//修改请求
public String toupdate_book(@PathVariable("id") int id, Model model) {
model.addAttribute(this.bookService.findById(id));
model.addAttribute("path", IMG_PATH);
return "update_book";
}
@RequestMapping(value="{id}/update",method=RequestMethod.POST)//修改处理
public String update_book(Book book, Model model, MultipartFile pic) {
String path = null;
if (pic != null) {
try {
// 得到真实路径
path = ResourceUtils.getFile("classpath:static/resources/upload/").getPath();
System.out.println(path);
// 利用UUID和原文件名称得到一个新的文件名称(防止文件名冲突)
String new_name = UUID.randomUUID() + pic.getOriginalFilename();
File file = new File(path + File.separator + new_name);
//保存图片
pic.transferTo(file);
//修改图片
book.setPhoto(new_name);
} catch (Exception e) {
e.printStackTrace();
}
}
if(this.bookService.update(book)==1) return "redirect:/";
model.addAttribute("mess", "修改失败!");
return "update_book";
}
}
package bw.swn.boot.web;
import javax.annotation.Resource;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import bw.swn.boot.service.IBookService;
@RestController
public class JsonController {
@Resource
private IBookService bookService;
@RequestMapping("{id}/del_book")
public boolean delbook(@PathVariable("id")int id) {
return this.bookService.delete(id)==1;
}
}
分页:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="/resources/js/jquery-2.0.3.js"></script>
<link rel="stylesheet" href="/resources/css/bootstrap.min.css">
<script type="text/javascript">
$(function(){
//分页按钮与模糊
$(".btn-info").click(function(){
var current=$(this).val();
$("#current").val(current);
$("form").submit();
})
//删除图书
$(".btn-warning").click(function(){
var id=$(this).val();
if(confirm("确认吗?")){
$.get(
id+"/del_book",
function(obj){
if(obj){
alert("删除成功!");
location.reload();
}else{
alert("Sorry");
}
}
)
}
})
//修改请求
$(".btn-primary").click(function(){
var id=$(this).val();
location=id+"/update";
})
//添加请求
$(".btn-success").click(function(){
location="add_book";
})
})
</script>
</head>
<body>
<br><br>
<div class="container" >
<form >
<input type="text" name="mohu" th:value="${pager.mohu}">
<input type="hidden" id="current" name="current" th:value="${pager.pageNumber}">
<button class="btn btn-success" type="submit">模糊</button>
</form>
<hr><br>
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>图书编号</th><th>图书名称</th><th>图书作者</th><th>图书单价</th><th>出版日期</th><th>图书封面</th>
<th><button class="btn btn-success">添加图书</button></th>
</tr>
</thead>
<tbody>
<tr th:each="book:${pager.datas}">
<td th:text="${book.id}"></td>
<td th:text="${book.title}"></td>
<td th:text="${book.author}"></td>
<td th:text="${book.price}"></td>
<td th:text="${book.pub_date}"></td>
<td>
<img th:src="${path}+${book.photo}" width="50px" height="50px">
</td>
<td>
<button th:value="${book.id}" class="btn btn-primary">修改</button>
<button th:value="${book.id}" class="btn btn-warning">删除</button>
</td>
</tr>
<tr>
<td align="center" colspan="20">
共<span th:text="${pager.total}"></span>条数据,共<span th:text="${pager.pagePages}"></span>页,
当前是第<span th:text="${pager.pageNumber}"></span>页。
<button class="btn btn-info" value="1">首页</button>
<button class="btn btn-info" th:value="${pager.provPage}" th:disabled="${pager.pageNumber==1?true:false}">上页</button>
<button class="btn btn-info" th:disabled="${pager.pageNumber==pager.pagePages?true:false}" th:value="${pager.nextPage}">下页</button>
<button class="btn btn-info" th:value="${pager.pagePages}">末页</button>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>修改图书</title>
<script type="text/javascript" src="/resources/js/jquery-2.0.3.js"></script>
<link rel="stylesheet" href="/resources/css/bootstrap.min.css">
</head>
<body>
<br><br>
<div class="container" >
<font color='red'><span th:text="${mess}"></span></font>
<form method="post" enctype="multipart/form-data">
<input type="hidden" th:value="${book.id}" name="id">
图书名称:<input type="text" th:value="${book.title}" name="title"><br>
图书作者:<input type="text" th:value="${book.author}" name="author"><br>
图书单价:<input type="text" th:value="${book.price}" name="price"><br>
出版日期:<input type="text" th:value="${book.pub_date}" name="pub_date"><br>
图书图片:<img th:src="${path}+${book.photo}" width="50px" height="50px">
<input type="file" name="pic"><br>
<button class="btn btn-success" type="submit">修改</button>
</form>
</div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>添加图书</title>
<script type="text/javascript" src="/resources/js/jquery-2.0.3.js"></script>
<link rel="stylesheet" href="/resources/css/bootstrap.min.css">
</head>
<body>
<br>
<br>
<div class="container">
<font color='red'><span th:text="${mess}"></span></font>
<form method="post" enctype="multipart/form-data">
图书名称:<input type="text" name="title"><br>
图书作者:<input type="text" name="author"><br>
图书单价:<input type="text" name="price"><br>
出版日期:<input type="text" name="pub_date"><br>
图书图片:
<input type="file" name="pic"><br>
<button class="btn btn-success" type="submit">添加图书</button>
</form>
</div>
</body>
</html>