基于javaweb+mysql的ssm+maven图书租赁管理系统(java+ssm+jsp+bootstrap+echarts+mysql)
私信源码获取及调试交流
运行环境
Java≥8、MySQL≥5.7、Tomcat≥8
开发工具
eclipse/idea/myeclipse/sts等均可配置运行
适用
课程设计,大作业,毕业设计,项目练习,学习演示等
功能说明
基于javaweb的SSM+Maven图书租赁管理系统(java+ssm+jsp+bootstrap+echarts+mysql)
图书租赁管理系统
项目介绍
图书租赁管理系统,该系统分为管理员与普通读者两种角色; 管理员主要功能包括: 图书管理:添加、修改、删除; 图书分类管理:添加、修改、删除; 借阅信息:还书; 预定信息:确认借书; 归还信息; 统计管理:借书/归还、营业额、销量; 普通读者主要功能包括:预定图书、待拿图书、借阅中、归还信息等;
客户端的充值,使用的支付宝沙箱测试化境
环境需要
1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。 2.IDE环境:IDEA,Eclipse,Myeclipse都可以。推荐IDEA; 3.tomcat环境:Tomcat 7.x,8.x,9.x版本均可 4.硬件环境:windows 7/8/10 1G内存以上;或者 Mac OS; 5.是否Maven项目: 是;查看源码目录中是否包含pom.xml;若包含,则为maven项目,否则为非maven项目 6.数据库:MySql 8.0版本; 7.lombok插件安装:本项目需要安装lombok插件,否则运行会有异常;
技术栈
- 后端:Spring SpringMVC MyBatis 2. 前端:JSP+bootstrap+jQuery+echarts
使用说明
-
使用Navicat或者其它工具,在mysql中创建对应名称的数据库,并导入项目的sql文件; 2. 使用IDEA/Eclipse/MyEclipse导入项目,Eclipse/MyEclipse导入时,若为maven项目请选择maven;若为maven项目,导入成功后请执行maven clean;maven install命令,配置tomcat,然后运行; 3. 将项目中db.properties配置文件中的数据库配置改为自己的配置;
-
运行项目,输入localhost:8080/bm/
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
String url = basePath;
String aDocument = "<a href=\""+url+"\">"+url+"</a>";
//发送的邮箱内容
String emailMsg = mailTemplate.getTemplate()
.replace("{borrowBooksTime}",DateUtils.dateFormat("yyyy年MM月dd日",borrowBook.getBbTime()))
.replace("{dueTime}",DateUtils.dateFormat("yyyy年MM月dd日",borrowBook.getDueTime()))
.replace("{bookName}",borrowBook.getBName())
.replace("{userName}",borrowBook.getRName())
.replace("{remainingDay}",borrowBook.getRemainingDays()+"")
.replace("{systemUrl}",aDocument);
//发送邮箱提醒
try {
mailUtils.sendRemind(reader.getEmail(),emailMsg);
} catch (MessagingException e) { //发送邮箱还书提醒失败!
e.printStackTrace();
throw new LyException(ExceptionEnum.SEND_REMIND_FAIL);
}
}
}
@RequestMapping("reader/reserveBorrow")
@RestController
public class RReserveBorrowBooksController {
@RequestMapping("/reader/borrowBook")
@RestController
public class RBorrowBookController {
@Autowired
private BorrowBookService borrowBookService;
@Autowired
private BMSystemProperties bmProperties;
//分页查询 并可以带查询参数
@GetMapping("/{page}/{size}")
public ResponseEntity<Page<BorrowBooks>> borrowBookByPage(@PathVariable("page") Integer page,
@PathVariable("size") Integer size,
BorrowBooks borrowBooks,
HttpSession session){
Reader reader = (Reader) session.getAttribute(bmProperties.getReaderSessionName());
borrowBooks.setRName(reader.getRName());
return ResponseEntity.ok(borrowBookService.borrowBookByPage(page,size, borrowBooks,true));
}
}
@RequestMapping("/login")
@Controller
public class LoginController {
@Autowired
private LoginService loginService;
//用户登录
@PostMapping
@ResponseBody
public String login(@RequestBody LoginVo loginVo, HttpServletResponse response,
HttpServletRequest request){
String url = loginService.login(loginVo,response,request);
return url;
}
//读者自动登录
@GetMapping("/autoLogin")
public String autoLoginReader(HttpServletResponse response,HttpServletRequest request){
Boolean flag = loginService.autoLoginReader(response, request);
String url = "";
if(flag){ //登录成功
url = "/pages/reader/bookDatalist.jsp";
}else{ //登陆失败
url = "/pages/login.jsp";
}
return "redirect:"+ url;
}
}
@Autowired
private ReaderMapper readerMapper;
@Autowired
private ManagerMapper managerMapper;
@Autowired
private BMSystemProperties bmProperties;
//用户登录
public String login(LoginVo loginVo, HttpServletResponse response, HttpServletRequest request) {
//判断用户的类型
String type = loginVo.getType();
String url;
if(type.equals("读者")){
url = loginReader(loginVo,response,request);
}else{ //管理员
url = loginManager(loginVo,request);
}
return url;
}
//用户登录
@Transactional
public String loginReader(LoginVo loginVo, HttpServletResponse response,HttpServletRequest request){
//根据用户名和密码查询
Example example = new Example(Reader.class);
Example.Criteria criteria = example.createCriteria();
criteria.andEqualTo("account",loginVo.getAccount())
.andEqualTo("password",loginVo.getPassword());
example.or().andEqualTo("email",loginVo.getAccount())
.andEqualTo("password",loginVo.getPassword());
List<Reader> readers = readerMapper.selectByExample(example);
if(CollectionUtils.isEmpty(readers)){ //不存在该用户,账号或密码错误!
throw new LyException(ExceptionEnum.LOGIN_ACCOUNT_OR_PASSWORD);
}
//获取数据库中的读者信息
Reader reader = readers.get(0);
//判断是否有自动登录
if(loginVo.getAutoLogin()){ //有自动登录
Integer day = bmProperties.getReaderAutoLoginDay()*60*24;
String path = request.getContextPath()+"/pages/reader/";
//根据 账户名
Cookie cookie = new Cookie(bmProperties.getAutoCookieName(),reader.getAccount());
//设置路径
cookie.setPath(path);
//bm/login/autoLogin
//借书 一个
@PostMapping("/{resId}")
public ResponseEntity<Void> saveReserve(@PathVariable("resId") Integer resId){
reserveBookService.saveReserves(Arrays.asList(resId));
return ResponseEntity.status(HttpStatus.CREATED).build();
}
//借书 多个
@PostMapping
public ResponseEntity<Void> saveReserves(@RequestBody List<Integer> resIds){
reserveBookService.saveReserves(resIds);
return ResponseEntity.status(HttpStatus.CREATED).build();
}
}
@RequestMapping("reader/giveBack")
@RestController
public class RGiveBackController {
@Autowired
private GiveBackBookService giveBackBookService;
//借书 一个
@PostMapping("/{resId}")
public ResponseEntity<Void> saveReserve(@PathVariable("resId") Integer resId){
reserveBookService.saveReserves(Arrays.asList(resId));
return ResponseEntity.status(HttpStatus.CREATED).build();
}
//借书 多个
@PostMapping
public ResponseEntity<Void> saveReserves(@RequestBody List<Integer> resIds){
reserveBookService.saveReserves(resIds);
return ResponseEntity.status(HttpStatus.CREATED).build();
}
}
@RequestMapping("reader/giveBack")
@RestController
public class RGiveBackController {
@Autowired
private GiveBackBookService giveBackBookService;
}
//借书 多个
@PostMapping
public ResponseEntity<Void> saveReserves(@RequestBody List<Integer> resIds){
reserveBookService.saveReserves(resIds);
return ResponseEntity.status(HttpStatus.CREATED).build();
}
}
@RequestMapping("reader/giveBack")
@RestController
public class RGiveBackController {
@Autowired
private GiveBackBookService giveBackBookService;
@Autowired
private BMSystemProperties bmProperties;
//分页查询 并可以带查询参数
@GetMapping("/{page}/{size}")
public ResponseEntity<Page<GiveBackBooks>> giveBackBook(@PathVariable("page") Integer page,
@PathVariable("size") Integer size,
GiveBackBooks reserveGiveBack,
HttpSession session){
Reader reader = (Reader) session.getAttribute(bmProperties.getReaderSessionName());
reserveGiveBack.setRName(reader.getRName());
return ResponseEntity.ok(giveBackBookService.giveBackBook(page,size, reserveGiveBack,true));
}
}
//用户登录
@PostMapping
@ResponseBody
public String login(@RequestBody LoginVo loginVo, HttpServletResponse response,
HttpServletRequest request){
String url = loginService.login(loginVo,response,request);
return url;
}
//读者自动登录
@GetMapping("/autoLogin")
public String autoLoginReader(HttpServletResponse response,HttpServletRequest request){
Boolean flag = loginService.autoLoginReader(response, request);
String url = "";
if(flag){ //登录成功
url = "/pages/reader/bookDatalist.jsp";
}else{ //登陆失败
url = "/pages/login.jsp";
}
return "redirect:"+ url;
}
}
@RequestMapping("manager/giveBack")
@RestController
public class MGiveBackBookController {
@Autowired
private GiveBackBookService giveBackBookService;
@RequestMapping("manager/bookType")
@RestController
public class MBookTypeController {
@Autowired
private BookTypeService bookTypeService;
//获取图书分类
@RequestMapping
public ResponseEntity<List<BookType>> bookTypeList(){
return ResponseEntity.ok(bookTypeService.bookTypeList());
}
//获取图书分类
@RequestMapping("/all")
public ResponseEntity<List<BookType>> bookTypeListAll(){
return ResponseEntity.ok(bookTypeService.bookTypeListAll());
}
//添加图书分类
@PostMapping("/{tName}")
public ResponseEntity<Void> addBookType(@PathVariable("tName") String tName){
bookTypeService.addBookType(tName);
return ResponseEntity.status(HttpStatus.CREATED).build();
}
//删除多个图书分类
@DeleteMapping
public ResponseEntity<Void> deleteBookTypes(@RequestBody List<Integer> ids ){
bookTypeService.deleteBookTypes(ids);
return ResponseEntity.ok().build();
}
//删除一个图书分类
@DeleteMapping("/{btId}")
public ResponseEntity<Void> deleteBookType(@PathVariable("btId") Integer btId ){
bookTypeService.deleteBookTypes(Arrays.asList(btId));
return ResponseEntity.ok().build();
}
//修改一个图书分类
@PutMapping
public ResponseEntity<Void> modifyBookType(@RequestBody BookType bookType){
bookTypeService.modifyBookType(bookType);
return ResponseEntity.ok().build();
}
}
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}
@RequestMapping("register")
@RestController
public class RegisterController {
@Autowired
private ReaderService readerService;
//用户名是否存在
@PostMapping("/account/{accountName}")
@ResponseBody
public ResponseEntity<Void> accountName(@PathVariable("accountName") String accountName){
readerService.accountNameExist(accountName);
return ResponseEntity.ok().build();
}
//用户注册
@PostMapping
@ResponseBody
public ResponseEntity<Void> registerReader(@RequestBody Reader reader){
reader.builderReader();
readerService.saveReader(reader);
return ResponseEntity.ok().build();
}
//发送邮箱验证码
@PostMapping("/verifyMailCode/{account}/{email}")
@ResponseBody
public ResponseEntity<Void> verifyMailCode(@PathVariable("account") String account,
@PathVariable("email") String email){
readerService.verifyMailCode(account,email);
return ResponseEntity.ok().build();
}
@Service
public class MailTemplateService {
@Autowired
private MailTemplateMapper templateMapper;
@Autowired
private BorrowBookMapper borrowBookMapper;
@Autowired
private ReaderMapper readerMapper;
@Autowired
private MailUtils mailUtils;
@Autowired
private HttpServletRequest request;
public MailTemplate getMailTemplate(Integer id){
return templateMapper.selectByPrimaryKey(id);
}
public void modifyMailTemplate(Integer id,String template) {
templateMapper.updateByPrimaryKeySelective(new MailTemplate().setMtId(id).setTemplate(template));
}
public void modifyMailDefaultTemplate(Integer id, String defaultTemplate) {
templateMapper.updateByPrimaryKeySelective(new MailTemplate().setMtId(id).setDefaultTemplate(defaultTemplate));
}
//提醒还书
public void remind(Integer bbId) {
//查询借阅记录是否还存在
BorrowBooks borrowBook = borrowBookMapper.queryBorrowBookByBbId(bbId);
if(borrowBook == null){ //该图书已被归还
throw new LyException(ExceptionEnum.BORROW_BOOKS_IS_RETURN);
}
}
//将用户的信息保存到 session 中 并设置最后的登录时间
private void saveReaderToSession(HttpServletRequest request,Reader reader){
//将用户的登录信息保存到 session 中
HttpSession session = request.getSession();
session.setAttribute(bmProperties.getReaderSessionName(),reader);
}
}
@Service
public class MailTemplateService {
@Autowired
private MailTemplateMapper templateMapper;
@Autowired
private BorrowBookMapper borrowBookMapper;
@Autowired
private ReaderMapper readerMapper;
@Autowired
serverName = serverName.substring(7);
final int end = serverName.indexOf("/");
serverName = serverName.substring(0, end);
final String[] domains = serverName.split("\\.");
int len = domains.length;
if (len > 3) {
// www.xxx.com.cn
domainName = domains[len - 3] + "." + domains[len - 2] + "." + domains[len - 1];
} else if (len <= 3 && len > 1) {
// xxx.com or xxx.cn
domainName = domains[len - 2] + "." + domains[len - 1];
} else {
domainName = serverName;
}
}
if (domainName != null && domainName.indexOf(":") > 0) {
String[] ary = domainName.split("\\:");
domainName = ary[0];
}
return domainName;
}
}
@Service
public class LoginService {
@Autowired
private ReaderMapper readerMapper;
//redis中删除订单
jedis.expire(out_trade_no,-1);
}
}
//——请在这里编写您的程序(以上代码仅作参考)——
}catch (Exception e){
e.printStackTrace();
}
}
//异步通知
@Transactional
public void notify(HttpServletRequest request, HttpServletResponse response) {
response.setContentType("text/html;charset=UTF-8");
try {
//获取支付宝POST过来反馈信息
Map<String, String> params = getParams(request.getParameterMap());
boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type); //调用SDK验证签名
if (signVerified) {//验证成功
//商户订单号
String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
//交易状态
String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");
//交易金额
Double total_amount = Double.parseDouble(new String(request.getParameter("total_amount").getBytes("ISO-8859-1"), "UTF-8"));
if (trade_status.equals("TRADE_FINISHED")) {
} else if (trade_status.equals("TRADE_SUCCESS")) {
//获取订单信息
Map<String, String> map = jedis.hgetAll(out_trade_no);
if(!CollectionUtils.isEmpty(map)){ //订单未失效
if(map.get("status").equals("false")){ //订单未支付
//根据rId查询用户信息
Reader reader = readerMapper.selectByPrimaryKey(Integer.valueOf(map.get("rId")));
if(reader!=null){ //用户信息存在
//增加账户金额
reader.setBalance(reader.getBalance()+(int)(total_amount*100));
//持久化数据
readerMapper.updateByPrimaryKey(reader);
//设置订单已支付
map.replace("status","true");
//redis中设置订单已支付
//交易状态
String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");
//交易金额
Double total_amount = Double.parseDouble(new String(request.getParameter("total_amount").getBytes("ISO-8859-1"), "UTF-8"));
if (trade_status.equals("TRADE_FINISHED")) {
} else if (trade_status.equals("TRADE_SUCCESS")) {
//获取订单信息
Map<String, String> map = jedis.hgetAll(out_trade_no);
if(!CollectionUtils.isEmpty(map)){ //订单未失效
if(map.get("status").equals("false")){ //订单未支付
//根据rId查询用户信息
Reader reader = readerMapper.selectByPrimaryKey(Integer.valueOf(map.get("rId")));
if(reader!=null){ //用户信息存在
//增加账户金额
reader.setBalance(reader.getBalance()+(int)(total_amount*100));
//持久化数据
readerMapper.updateByPrimaryKey(reader);
//设置订单已支付
map.replace("status","true");
//redis中设置订单已支付
jedis.hmset(out_trade_no,map);
}
}
}
}
} else {//验证失败
}
} catch (Exception e) {
System.out.println(e);
e.printStackTrace();
}
}
//获取参数
private Map<String, String> getParams(Map<String, String[]> requestParams){
Map<String, String> params = new HashMap<String, String>();
for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
String name = (String) iter.next();
String[] values = (String[]) requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i]
: valueStr + values[i] + ",";
}
@GetMapping("/mailSetBtn")
public ResponseEntity<List<MailSymbol>> getMailSetBtn(){
return ResponseEntity.ok(symbolService.getMailSymbol());
}
/**
* 根据id获取邮箱模板
* @param id
* @return
*/
@GetMapping("/mailTemplate/{id}")
public ResponseEntity<MailTemplate> getMailTemplate(@PathVariable("id") Integer id){
return ResponseEntity.ok(templateService.getMailTemplate(id));
}
/**
* 根据id修改邮箱模板
* @param id
* @param template
* @return
*/
@PutMapping("/mailTemplate/{id}")
public ResponseEntity<Void> modifyMailTemplate(@PathVariable("id") Integer id,
@RequestBody String template){
templateService.modifyMailTemplate(id,template);
return ResponseEntity.ok().build();
}
/**
* 根据id修改默认邮箱模板
* @param id
* @param defaultTemplate
* @return
*/
@PutMapping("/mailTemplate/default/{id}")
public ResponseEntity<Void> modifyMailDefaultTemplate(@PathVariable("id") Integer id,
@RequestBody String defaultTemplate){
templateService.modifyMailDefaultTemplate(id,defaultTemplate);
return ResponseEntity.ok().build();
}
//提醒还书
@PostMapping("/remind/{bbId}")
public ResponseEntity<Void> remind(@PathVariable("bbId") Integer bbId){
/**
* 根据id获取邮箱模板
* @param id
* @return
*/
@GetMapping("/mailTemplate/{id}")
public ResponseEntity<MailTemplate> getMailTemplate(@PathVariable("id") Integer id){
return ResponseEntity.ok(templateService.getMailTemplate(id));
}
/**
* 根据id修改邮箱模板
* @param id
* @param template
* @return
*/
@PutMapping("/mailTemplate/{id}")
public ResponseEntity<Void> modifyMailTemplate(@PathVariable("id") Integer id,
@RequestBody String template){
templateService.modifyMailTemplate(id,template);
return ResponseEntity.ok().build();
}
/**
* 根据id修改默认邮箱模板
* @param id
* @param defaultTemplate
* @return
*/
@PutMapping("/mailTemplate/default/{id}")
public ResponseEntity<Void> modifyMailDefaultTemplate(@PathVariable("id") Integer id,
@RequestBody String defaultTemplate){
templateService.modifyMailDefaultTemplate(id,defaultTemplate);
return ResponseEntity.ok().build();
}
//提醒还书
@PostMapping("/remind/{bbId}")
public ResponseEntity<Void> remind(@PathVariable("bbId") Integer bbId){
templateService.remind(bbId);
return ResponseEntity.ok().build();
}
}
Books book = bookMapper.selectByPrimaryKey(reserveBorrowBooks.getBId());
//将数据插入 borrow_books表中
BorrowBooks borrowBook = new BorrowBooks(reserveBorrowBooks);
borrowBookMapper.insert(borrowBook);
//将预约借书 该预记录删除
reserveBookMapper.deleteByPrimaryKey(resId);
//持久化数据
bookMapper.updateByPrimaryKey(book);
}
}
//读者 预定借书
@Transactional
public Integer reserveBook(Integer bId, Integer rentDay, HttpSession session){
//读者信息
Reader reader = (Reader) session.getAttribute(bmProperties.getReaderSessionName());
reader = readerMapper.selectByPrimaryKey(reader.getRId());
//根据 bId查询图书信息
Books books = bookMapper.selectByPrimaryKey(bId);
if(books == null){ //抱歉,该图书信息已失效,请刷新页面!
throw new LyException(ExceptionEnum.BOOK_INFO_LOSE);
}
//是否是开启状态
if(books.getStatus() == false){ //抱歉,该图书信息正在维护中,暂时不可借阅该图书,请您刷新页面!
throw new LyException(ExceptionEnum.BOOK_STATUS_FALSE);
}
//在馆数
books.setInLibraryTotal(books.getTotal()-borrowBookMapper.selectCount(new BorrowBooks(books.getBId())));
//预定数
books.setReserveNum(reserveBookMapper.selectCount(new ReserveBorrowBooks(books.getBId())));
if(books.getInLibraryTotal() <= 0){ //抱歉,该图书已全部借出!
throw new LyException(ExceptionEnum.SORRY_BOOK_BORROW_ALL);
}
if(books.getInLibraryTotal() <= books.getReserveNum()){ //抱歉,图书预定人数已满! 在馆数(总数-借出数) == 预定数(预定表中数量)
throw new LyException(ExceptionEnum.RESERVE_BOOK_FULL);
}
//预定天数不能大于 {{maxBorrowBooksDay}} 最大结束天数
if(rentDay >= bmProperties.getMaxBorrowBooksDay()){
//抱歉,最大借书天数为{maxBorrowBooksDay}天!
ExceptionEnum em = ExceptionEnum.GREATER_THAN_MAX_BORROW_BOOKS_DAY;
em.setMsg(em.getMsg().replace("{maxBorrowBooksDay}",bmProperties.getMaxBorrowBooksDay()+""));
throw new LyException(em);
}
//账户至少有 多少钱才能预定图书
if(reader.getBalance()/100.0 < bmProperties.getBorrowBooksAccountLest()){
//抱歉,账户余额少于{balanceLess}元不能借书,请您点击右上角头像选择充值!
ExceptionEnum em = ExceptionEnum.ACCOUNT_BALANCE_LESS;
em.setMsg(em.getMsg().replace("{balanceLess}",bmProperties.getBorrowBooksAccountLest()+""));
throw new LyException(em);
}