基于SpringBoot和MySQL的图书管理系统

基于SpringBoot和MySQL的图书管理系统 1,前言 该图书管理系统是基于SpringBoot的项目,希望能够和小伙伴们一起学习,得到宝贵的意见

本文包含相关资料包-----> 点击直达获取<-------

基于SpringBoot和MySQL的图书管理系统

1.前言

该图书管理系统是基于SpringBoot的项目,希望能够和小伙伴们一起学习,得到宝贵的意见。

2.项目介绍

2.1 功能简介

系统分管理员界面与用户界面,基于SpringBoot 的图书管理系统,主要包括系统管理、图书管理、借阅者管理三部分。

  • 管理员 :实现对图书的增、删、改、查,对所有借阅历史的搜索及所有账户的信息,用户的权限与管理,设定密码,借阅图书及对自己账户的资料修改

  • 用户 :实现对图书的借阅功能、查看自己的借阅历史,在用户账户方面实现修改密码以及修改个人信息功能

2.2 功能模块图

2.3 组织结构

├─src │ ├─main │ │ ├─java │ │ │ └─io │ │ │ └─mvc │ │ │ └─web │ │ │ └─book │ │ │ ├─annotation 自定义注解类 │ │ │ ├─common 公共类 │ │ │ ├─config 配置类 │ │ │ ├─controller 控制层 │ │ │ ├─dao dao层接口 │ │ │ ├─exception 全局统一异常处理 │ │ │ ├─interceptor 过滤接口 │ │ │ ├─model 实体类 │ │ │ ├─service 业务层 │ │ │ │ └─impl 实现类 │ │ │ └─util 工具类 │ │ ├─resources │ │ │ └─mapper dao层对应mapper文件 │ │ └─webapp │ │ ├─static 静态资源文件 │ │ └─WEB-INF │ │ └─page jsp文件 │ │ ├─admin 管理员 │ │ └─common 普通用户

2.4 技术栈

2.5 开发环境

  • JDK(1.8+)

  • Maven (3.6.0+)

  • MySQL (5.6+)

  • IDEA(2019.3)

3.数据库设计

3.1 表结构

用户表

权限表

权限&用户表

菜单表

权限&菜单表

还书表

图书类型表

图书信息表

3.2 E-R图

4.项目开发

4.1 常用工具类

加密类

```java public class Md5Util {

public static final String SALT = "Book";

public static String md5(String str, String salt) {
    if (StringUtils.isEmpty(str)) {
        return null;
    } else {
        return new Md5Hash(str, salt).toString();
    }
}

//测试调用
public static void main(String args[]) {
    String password = "123456";
    System.out.println("Md5加密后" + Md5Util.md5(password, Md5Util.SALT));
}

} ```

JWT 安全校验类

```java public class JwtUtil {

//签发者
public static final String ISSUER = "曾冯周。-";

//公钥
public static final String SECRET = "zengfengzhou";

public static String createToken(User user) {
    // 签发时间
    Date iatDate = new Date();
    // 过期时间
    Calendar nowTime = Calendar.getInstance();
    nowTime.add(Calendar.MINUTE, 120);
    Date expiresDate = nowTime.getTime();
    // header
    Map<String, Object> map = new HashMap<>();
    map.put("alg", "HS256");
    map.put("typ", "JWT");
    String token = JWT.create()
            .withHeader(map)
            .withIssuer(JwtUtil.ISSUER)
            .withAudience(Long.toString(user.getUserId()))//接收者
            .withExpiresAt(expiresDate)
            .withIssuedAt(iatDate)
            .sign(Algorithm.HMAC256(JwtUtil.SECRET));
    return token;
}

public static String getUserId(String token) {
    String userId;
    DecodedJWT jwt = JWT.decode(token);
    userId = jwt.getAudience().get(0);
    return userId;
}

public static void main(String args[]) {
    String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiIxIiwiaXNzIjoi6IKG5oSP44CCLSIsImV4cCI6MTU1MjQzNjIwMywiaWF0IjoxNTUyNDM0NDAzfQ.rtpYANOHZE_tpkF0ChWsLOHMrdmWETjg2SVX3wjr6OQ";
    System.out.println(JwtUtil.getUserId(token));
}

} ```

随机数字类

```java public class IDUtils { /* * 生成用户ID(同时作为借书证编号) * @return / public static long genUserId() { //取当前时间的长整形值包含毫秒 long millis = System.currentTimeMillis(); //long millis = System.nanoTime(); //加上两位随机数 Random random = new Random(); int end2 = random.nextInt(99); //如果不足两位前面补0 String str = millis + String.format("%02d", end2); long id = new Long(str); return id; }

public static void main(String[] args) {
    for (int i = 0; i < 100; i++)
        System.out.println(genUserId());
}

} ```

4.2 登陆拦截器实现

```java public class LoginInterceptor implements HandlerInterceptor { @Resource private UserService userService;

@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
    // 如果不是映射到方法直接通过
    if (!(object instanceof HandlerMethod)) {
        return true;
    }
    HandlerMethod handlerMethod = (HandlerMethod) object;
    Method method = handlerMethod.getMethod();
    //检查是否有passtoken注解,有则跳过认证
    if (method.isAnnotationPresent(PassToken.class)) {
        PassToken passToken = method.getAnnotation(PassToken.class);
        if (passToken.required()) {
            return true;
        }
    }
    //检查有没有需要用户登录的注解
    User currentUser = (User) httpServletRequest.getSession().getAttribute("user");
    if (method.isAnnotationPresent(LoginRequired.class)) {
        LoginRequired loginRequired = method.getAnnotation(LoginRequired.class);
        if (loginRequired.required()) {
            if (currentUser == null) {
                httpServletResponse.sendRedirect("/login.jsp");
                return false;
            }
        }
    }
    //检查有没有需要用户token的注解
    String token = httpServletRequest.getHeader("token");// 从 http 请求头中取出 token
    if (method.isAnnotationPresent(UserLoginToken.class)) {
        UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class);
        if (userLoginToken.required()) {
            // 执行认证
            if (token == null) {
                throw new RuntimeException("token为空,请重新登录");
            }
            // 获取 token 中的 user id
            String userId;
            try {
                userId = JWT.decode(token).getAudience().get(0);
            } catch (JWTDecodeException j) {
                throw new RuntimeException("无权限访问");
            }
            User user = userService.findUserByUserId(Long.parseLong(userId));
            if (user == null) {
                throw new RuntimeException("用户不存在,请重新登录");
            }
            // 验证 token
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(JwtUtil.SECRET)).build();
            try {
                jwtVerifier.verify(token);
            } catch (JWTVerificationException e) {
                throw new RuntimeException("token失效,无权限访问");
            }
            return true;
        }
    }
    return true;
}

@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {}

} ```

4.3 全局异常处理

```java /* * @Description:统一处理一个Controller中抛出的异常 /

@RestControllerAdvice public class AjaxExceptionHandler {

@ExceptionHandler(value = Exception.class)
public JsonData defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
    e.printStackTrace();
    return JsonData.fail(e.getMessage());
}

/**
 * 注解参数校验 全局异常补获
 */
@ExceptionHandler(BindException.class)
public JsonData handleBindException(BindException ex) {
    //校验 除了 requestbody 注解方式的参数校验 对应的 bindingresult 为 BeanPropertyBindingResult
    FieldError fieldError = ex.getBindingResult().getFieldError();
    return JsonData.fail(fieldError.getDefaultMessage());
}

} ```

4.4 登录校验

```java @PostMapping("/login") public JsonData login(@RequestParam(value = "userName") String userName, @RequestParam(value = "userPassword") String userPassword, @RequestParam(value = "vaptchaToken") String vaptchaToken, HttpServletRequest request, HttpSession session) throws Exception {

    if (StringUtils.isEmpty(userName)) {
        return JsonData.fail("用户名不能为空!");
    }
    if (StringUtils.isEmpty(userPassword)) {
        return JsonData.fail("密码不能为空!");
    }
    User user = userService.findUserByUserName(userName);
    if (user == null) {
        return JsonData.fail("用户不存在!");
    }
    if (user.getUserState() == 0) {
        return JsonData.fail("账号已被禁用!请联系管理员!");
    }
    if (Md5Util.md5(userPassword, Md5Util.SALT).equals(user.getUserPassword())) {
        //获取用户角色信息
        List<Role> roleList = roleService.findByUserId(user.getUserId());
        StringBuffer stringBuffer = new StringBuffer();
        for (Role role : roleList) {
            stringBuffer.append("," + role.getRoleName());
        }
        user.setRoles(stringBuffer.toString().replaceFirst(",", ""));
        session.setAttribute("user", user);
        //获取用户权限信息
        List<Permission> permissions = permissionService.queryPermissionsByUser(user);
        Map<Integer, Permission> permissionMap = new HashMap<>();
        Permission root = null;
        Set<String> uriSet = new HashSet<>();
        for (Permission permission : permissions) {
            permissionMap.put(permission.getPermissionId(), permission);
            if (permission.getPermissionUrl() != null && !"".equals(permission.getPermissionUrl())) {
                uriSet.add(permission.getPermissionUrl());
            }
        }
        session.setAttribute("authUriSet", uriSet);
        for (Permission permission : permissions) {
            Permission child = permission;
            if (child.getPermissionParentId() == null) {
                root = permission;
            } else {
                Permission parent = permissionMap.get(child.getPermissionParentId());
                parent.getChildren().add(child);
            }
        }
        session.setAttribute("rootPermission", root);
        return JsonData.success();
    } else {
        return JsonData.fail("用户名或密码错误!");
    }
}

```

4.5 借阅功能实现

```java @RestController @RequestMapping("/book") public class LendBookController { @Resource private LendBookService lendBookService; @Resource private BookInfoService bookInfoService; @Resource private UserService userService;

@PostMapping("/lendBook")
@LoginRequired
public JsonData lendBook(LendReturnList lendReturnList) throws ParseException {
    User user = userService.findUserByUserId(lendReturnList.getUserId());
    if (user == null) {
        return JsonData.fail("用户不存在");
    }
    if (user.getUserState() == 0) {
        return JsonData.fail("用户已被禁用,无法借阅");
    }
    BookInfo info = bookInfoService.selectBookInfoById(lendReturnList.getBookId());
    if (info == null) {
        return JsonData.fail("图书不存在");
    }
    if (info.getBookState() == 1) {
        return JsonData.fail("图书已被借出,无法借阅");
    }
    int i = lendBookService.lendBook(lendReturnList);
    //更新图书状态为借出
    BookInfo bookInfo = BookInfo.builder()
            .bookId(lendReturnList.getBookId())
            .bookState(1).build();
    bookInfoService.updateBookInfo(bookInfo);
    if (i > 0) {
        return JsonData.success(i, "借阅成功");
    } else {
        return JsonData.fail("借阅失败");
    }
}

/**
 * @description: 根据用户ID查询借还记录
 */
@PostMapping("/lendreturnrecord")
@LoginRequired
public DataGridDataSource<LendReturnList> selectLendReturnRecordByUserId(@RequestParam(value = "page", required = false, defaultValue = "1") Integer page,
                                                                         @RequestParam(value = "rows", required = false, defaultValue = "5") Integer rows,
                                                                         HttpSession session) throws ParseException {
    User currentUser = (User) session.getAttribute("user");
    PageBean pageBean = new PageBean(page, rows);
    Map<String, Object> map = new HashMap<>();
    map.put("userId", currentUser.getUserId());
    map.put("start", pageBean.getStart());
    map.put("size", pageBean.getPageSize());
    List<LendReturnList> lendReturnLists = lendBookService.selectLendReturnRecordByUserId(map);
    int totalRecord = lendBookService.getTotalRecord(map);
    DataGridDataSource<LendReturnList> list = new DataGridDataSource<>();
    list.setTotal(totalRecord);
    list.setRows(lendReturnLists);
    return list;
}

} ```

4.6 权限校验

```java @RestController @RequestMapping("/role") public class RoleController { @Resource private RoleService roleService; @Resource private PermissionService permissionService; /* * @description: 新增角色 / @PostMapping("/save") @LoginRequired public JsonData saveRole(Role role) { int count = roleService.saveRole(role); if (count > 0) { return JsonData.success(count, "添加成功"); } else { return JsonData.fail("添加失败"); }

}
/**
 * @description: 更新角色
 */
@PutMapping("/update")
@LoginRequired
public JsonData updateRole(Role role) {
    int count = roleService.updateRole(role);
    if (count > 0) {
        return JsonData.success(count, "更新成功");
    } else {
        return JsonData.fail("更新失败");
    }
}
/**
 * @description: 删除角色(先根据角色id删除角色权限关联信息, 再根据角色id删除用户角色关联信息)
 */
@DeleteMapping("/delete")
@LoginRequired
public JsonData deleteRole(@RequestParam(value = "roleId") Integer roleId) {

    //TODO 根据角色id删除角色权限关联信息,再根据角色id删除用户角色关联信息
    permissionService.deleteRolePermissionRsByRoleId(roleId);
    roleService.deleteRoleUserRsByRoleId(roleId);
    int count = roleService.deleteRole(roleId);
    if (count > 0) {
        return JsonData.success(count, "删除成功");
    } else {
        return JsonData.fail("删除失败");
    }
}
/**
 * @description: 服务端分页查询角色列表
 */
@PostMapping("/list")
@LoginRequired
public DataGridDataSource<Role> getRoleList(@RequestParam(value = "roleName", required = false, defaultValue = "") String roleName,
                                            @RequestParam(value = "page", required = false, defaultValue = "1") Integer page,
                                            @RequestParam(value = "rows", required = false, defaultValue = "5") Integer rows) {
    PageBean pageBean = new PageBean(page, rows);
    Map<String, Object> map = new HashMap<>();
    map.put("roleName", "%" + roleName + "%");
    map.put("start", pageBean.getStart());
    map.put("size", pageBean.getPageSize());
    List<Role> roleList = roleService.selectRoleList(map);
    int totalRole = roleService.getTotalRole(map);
    DataGridDataSource<Role> dataGridDataSource = new DataGridDataSource<>();
    dataGridDataSource.setRows(roleList);
    dataGridDataSource.setTotal(totalRole);
    return dataGridDataSource;
}
/**
 * @description: 角色权限设置(先删除当前角色拥有的权限关系, 再重新设置)
 */
@PostMapping("/savePermissionSet")
@LoginRequired
public JsonData savePermissionSet(Integer roleId, Integer[] permissionIds) {
    //先删除当前角色拥有的权限关系
    permissionService.deleteRolePermissionRsByRoleId(roleId);
    Map<String, Object> map = new HashMap<>();
    map.put("roleId", roleId);
    map.put("permissionIds", permissionIds);
    int count = roleService.insertRolePermissions(map);
    if (count > 0) {
        return JsonData.success(count, "设置成功");
    } else {
        return JsonData.fail("设置失败");
    }
}

} ```

5.项目展示

5.1 借阅者

登录页

首页

还书

图书检索

借还记录

修改密码

5.2 管理员

首页(用户管理)

分配权限

角色管理

菜单管理

5.3 图书管理

分类管理

图书信息管理

借书管理

还书管理

6.总结

首先,恭喜自己(伪)独立完成了一个后台的图书管理系统。

在这一过程中,我最主要的问题是——呃,什么都不会!

没错,真的是什么都不会。一个月前,我所拥有的对这个项目唯一有帮助的基础是:使用eclipse自学过两周java编程算法。除此之外,没有任何web项目经验,没有任何spring经验,没有任何J2EE经验。在学校里只学过c++,而且仅限于算法。

老实说,当我面对这个项目命题时,我感到了深深的绝望和对以往荒废时光的惋惜。于是,我开始做的第一件事就是,登录b站,打开点击最高的spring,springmvc,mybatis,springboot视频。。。。。

咳咳,闲话扯远了,回到正题!

这篇博客我将尽可能完整地展示一个springboot系统的构建思路和业务逻辑。当然,项目还存在一些不够友好的bug,以及功能单薄的缺点(可我实在懒得改了)。博客的发布,最主要目的是我对过去一个月的思考和知识的巩固汇总,所以不会一一列举所有的项目内容(比如对对象的增删改查操作等),尤其是我自己觉得很简单的部分,所以可能会显得不够全面,如果你需要全面的代码,那么可以去git上搜索靠前的原码。

那么问题来了,依靠这篇博客你可以成功完成一个项目吗?

答案显然是no。因为我只是总结一些个人在项目中遇到的重点,我自己本身也是通过视频,博客,git等途径逐步学习完成的整个项目。也就是说,这不是一篇教学类的博客。

如果你要完成一个自己的项目,你需要看更多的视频,学更多的基础知识,看更多的博客,这只是一个参考,并且不一定是你能用到的参考。仅此。

基本来说,我将采取每天(???)更新的方式,逐步完成。

参考文献

  • 基于SSH框架的图书馆管理系统的设计与实现(山东大学·檀雪姣)
  • 基于JSP的图书管理系统的需求分析与设计(山东大学·杜鹏)
  • 基于.NET的图书管理系统的设计与实现(安徽大学·陈龙)
  • 基于JSP的图书馆管理系统的设计与实现(吉林大学·葛再立)
  • 基于SSH框架的图书馆管理系统分析与设计(云南大学·郑晨)
  • 基于B/S架构的图书管理系统的设计与实现(山东大学·蒲琼)
  • 基于B/S架构的图书管理系统的设计与实现(山东大学·蒲琼)
  • 基于RBAC的SSH架构下的图书管理应用研究(大连理工大学·姜楠)
  • 石化职业技术学院图书馆管理系统设计与实现(西安电子科技大学·县伟)
  • 基于RBAC的SSH架构下的图书管理应用研究(大连理工大学·姜楠)
  • 基于B/S架构的图书管理系统设计与实现(西安电子科技大学·龚玉)
  • 基于Spring架构的职业学院图书馆管理系统的构建(复旦大学·吕晶)
  • 基于.NET的图书管理系统的设计与实现(安徽大学·陈龙)
  • 基于B/S架构的网上书店系统的设计与实现(电子科技大学·陈云英)
  • 基于SSH框架的图书馆管理系统分析与设计(云南大学·郑晨)

本文内容包括但不限于文字、数据、图表及超链接等)均来源于该信息及资料的相关主题。发布者:代码驿站 ,原文地址:https://bishedaima.com/yuanma/35465.html

相关推荐

发表回复

登录后才能评论