当前位置:   article > 正文

SpringBoot项目----图书管理系统(详解)_springboot图书管理系统

springboot图书管理系统

目录

项目业务

 技术栈

数据库表的设计 

数据库表关系图

关于字典表 

前后端接口实现

1.初始化数据库、表、数据

2.数据库连接池配置

3.统一响应封装

 4.统一异常处理

5.实现统一会话管理(登录) 

5.通过Mybatis生成工具,生成mapper接口,xml文件,实体类

 6.准备所有的Controller和servise类

7.实现接口

(1)登录接口

(2)实现注销接口

 (3)实现数据字典下拉菜单

(4)获取班级信息

(5)获取学生信息

(6)班级管理页面-表格展示

说明 

(7)新增接口

(8)获取数据详情(每一条) 

(9)修改接口

(10) 删除接口

 总结


项目业务

使用者:图书馆管理员

业务:管理学校图书信息,记录并管理学生借阅图书信息

有以下几个模块 

 

 技术栈

  • SpringBoot
  • SpringMVC
  • MyBatis

数据库表的设计 

数据库表关系图

关于字典表 

数据字典表和数据字典标签表主要用在一些通用的下拉菜单选项。
像本项目在班级表中的专业和毕业年份

如果单独设计需要单独一张表,实际存放的数据也不会太多,可以考虑设计在整体的一张表中。

一般在设计上考虑为两张表:数据字典表和数据字典标签表(一对多关系)来保存。两张表都是 key、 value 的形式,字典表是父节点对应下拉菜单,字典标签表是子节点对应下拉菜单选项,下拉菜单通过父节点的 key 查询出所 有关联的子节点,再使用子节点的key、 value 进行下拉菜单选项的初始化。

 

前后端接口实现

我这里只给大家说后端接口的实现,前端大家可以在github上找

  • 需要说明的是,接口的定义一般是前后端约定好的,所以也和前端代码息息相关,前端需要什么数据, 需要什么格式的数据,也会在接口中体现。

1.初始化数据库、表、数据

这里大家就创建以上那几个表,然后插入一些数据,在自己的MySQL执行一下

2.数据库连接池配置

在pom.xml插入以下代码,并替换成自己的用户名和密码

  1. spring.datasource.driver-class-name=com.mysql.jdbc.Driver
  2. spring.datasource.url=jdbc:mysql://localhost:3306/数据库名?useUnicode=true&characterEncoding=UTF-8&useSSL=false
  3. spring.datasource.username=***
  4. spring.datasource.password=*******

3.统一响应封装

一次http请求,调用Controller请求映射方法(返回值Object)

正常返回:ResponseResult(success=true,data=obj)

出现异常:ResponseResult(success=false,message=错误信息)

 4.统一异常处理

若程序内部错误:如语法错误、SQL写错,这种错是一大段英文,不能给用户看,这里设置返回中文的json字符串

  1. @ExceptionHandler(Exception.class)
  2. @ResponseBody
  3. public Object handleException(Exception e){
  4. log.error("系统出错啦", e);
  5. ResponseResult json = new ResponseResult();
  6. json.setMessage("系统出错了,请联系管理员");
  7. return json;
  8. }

还有一种是返回自定义异常:如用户名不存在、密码错误……

  1. @ExceptionHandler(AppException.class)
  2. @ResponseBody
  3. public Object handleAppException(AppException e){
  4. log.debug("自定义异常", e);
  5. ResponseResult json = new ResponseResult();
  6. json.setMessage(e.getMessage());
  7. return json;
  8. }

5.实现统一会话管理(登录) 

这里是用springMVC的HandlerInterceptor拦截器实现的,登录成功可以访问,未登录重定向到登录界面

  1. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  2. //判断是否登录
  3. HttpSession session = request.getSession(false);
  4. if(session != null){//获取登录时保存的用户信息
  5. User user = (User) session.getAttribute("user");
  6. if(user != null){//登录,允许访问
  7. return true;
  8. }
  9. }
  10. //未登陆,不允许访问
  11. String servletPath = request.getServletPath();//服务路径
  12. if(servletPath.startsWith("/api/")){//后端接口,未登陆返回401,json
  13. response.setCharacterEncoding("UTF-8");
  14. response.setContentType("application/json");
  15. response.setStatus(401);
  16. ResponseResult json = new ResponseResult();
  17. json.setMessage("未登陆,不允许访问");
  18. response.getWriter().println(objectMapper.writeValueAsString(json));
  19. }else{//前端页面,未登陆,重定向到登录页面
  20. String schema = request.getScheme();// http
  21. String host = request.getServerName();//服务端ip或域名
  22. int port = request.getServerPort();//port
  23. String contextPath = request.getContextPath();//应用上下文路径
  24. String basePath = schema+"://"+host+":"+port+contextPath;
  25. response.sendRedirect(basePath+"/index.html");
  26. }
  27. return false;
  28. }

添加要拦截的前端页面,和所有后端接口,除了注册、登录

  1. registry.addInterceptor(new LoginInterceptor(objectMapper))
  2. //前端:添加要拦截的页面
  3. .addPathPatterns("/page/main.html")
  4. //拦截所有后端接口,排除用户注册,登录
  5. .addPathPatterns("/api/**")
  6. .excludePathPatterns("/api/user/login")
  7. .excludePathPatterns("/api/user/register");

5.通过Mybatis生成工具,生成mapper接口,xml文件,实体类

 6.准备所有的Controller和servise类

每个实体类对应一个Controller和一个Service

例:

  1. @RestController //注册到容器中
  2. @RequestMapping("/book") //设置路径
  3. public class BookController {
  4. @Autowired //注入
  5. private BookService bookService;
  1. @Service
  2. public class BookService {
  3. @Autowired
  4. private BookMapper bookMapper;

7.实现接口

(1)登录接口

点击登录抓包可得:

可见请求路径为:POST http://localhost:8080/api/user/login

在UserController中写登录接口

  1. //POST http://localhost:8080/api/user/login
  2. @RequestMapping("/login")
  3. public Object login(@RequestBody User user, HttpServletRequest request){
  4. // 1.根据账号查询数据
  5. User param=new User();
  6. param.setUsername(user.getUsername());
  7. User exist=userService.selectOne(param);
  8. // 未查询到用户
  9. if(exist==null){
  10. throw new AppException("账号不存在");
  11. }
  12. // 2.若查询到用户校验密码是否正确
  13. if(!exist.getPassword().equals(user.getPassword())){
  14. throw new AppException("账号或密码错误");
  15. }
  16. // 3.验证成功,创建session,保存用户信息
  17. HttpSession session=request.getSession();
  18. // 保存用户信息,和拦截器的键一致
  19. session.setAttribute("user",exist);
  20. return null;
  21. }

然后生成selectOne方法,并返回 userMapper.selectOne();

 

  1. public User selectOne(User param) {
  2. return userMapper.selectOne(param);
  3. }

(2)实现注销接口

登录后会创建JSESSIONID及session,返回JSESSIONID(set-Cookie:JSEESION=xxx)

每次请求会自动携带Cookie:JSESSIONID=xxx

实现注销功能只用删除session即可

  1. // GET http://localhost:8080/api/user/logout
  2. @RequestMapping("/logout")
  3. public Object logout(HttpSession session){
  4. session.invalidate();
  5. return null;
  6. }

 (3)实现数据字典下拉菜单

  1. // 实现数据字典接口: 获取下拉菜单的选项
  2. // GET dict/tag/query?dictionaryKey=000002
  3. @RequestMapping("query")
  4. public Object query(String dictionaryKey){
  5. List<DictionaryTag> tags=dictionaryTagService.query(dictionaryKey);
  6. return tags;
  7. }
  1. public List<DictionaryTag> query(String dictionaryKey) {
  2. return dictionaryTagMapper.queryTagsByKey(dictionaryKey);
  3. }

Mybatis生成工具并未生成这个queryTagsByKey方法,需要自己写(关联查询)

  1. <select id="queryTagsByKey" resultMap="BaseResultMap">
  2. select
  3. concat(d.dictionary_key,dt.dictionary_tag_key) dictionary_tag_key,
  4. dt.dictionary_tag_value
  5. from
  6. dictionary d, dictionary_tag dt
  7. where
  8. d.id=dt.dictionary_id
  9. and
  10. d.dictionary_key=#{dictionaryKey}
  11. </select>

(4)获取班级信息

  1. // 获取班级(下拉菜单选项)信息接口
  2. // GET http://localhost:8080/api/classes/queryAsDict
  3. @RequestMapping("/queryAsDict")
  4. public Object queryAsDict(){
  5. List<Classes> classes=classesService.queryAsDict();
  6. return classes;
  7. }

(5)获取学生信息

  1. // 获取学生信息(下拉菜单)
  2. // GET student/queryAsDict?dictionaryKey=2
  3. @RequestMapping("/queryAsDict")
  4. public Object queryAsDict(@RequestParam("dictionaryKey") String classesId){
  5. List<Student> students=studentService.queryAsDict(classesId);
  6. return students;
  7. }

(6)班级管理页面-表格展示

  1. // 获取班级信息(表格展示)
  2. // GET /api/classes/query
  3. @RequestMapping("/query")
  4. public Object query(Classes cla){
  5. // 分页功能
  6. PageHelper.startPage(cla);
  7. List<Classes> classes=classesService.query();
  8. PageHelper.clearPage();
  9. return classes;
  10. }

说明 

每个页面都有5个接口 :

  • 获取数据(表格展示)
  • 新增
  • 修改删除
  • 获取数据详情

 

我这里以班级管理为例,实现的方法都是一样的(否则博客太长了,分两篇的话,第二篇内容又不多)

(7)新增接口

  1. // 新增班级
  2. // POST /api/classes/add
  3. @RequestMapping("/add")
  4. public Object add(@RequestBody Classes classes){
  5. int n=classesService.add(classes);
  6. return null;
  7. }
  1. public int add(Classes classes) {
  2. return classesMapper.insertSelective(classes);
  3. }

(8)获取数据详情(每一条) 

  1. // 获取班级详情
  2. // GET http://localhost:8080/api/classes/queryById?id=4
  3. @RequestMapping("/queryById")
  4. public Object queryById(@RequestParam Integer id){
  5. Classes classes=classesService.queryById(id);
  6. return classes;
  7. }
  1. public Classes queryById(Integer id) {
  2. return classesMapper.selectByPrimaryKey(id);
  3. }

(9)修改接口

  1. // 修改信息
  2. // POST http://localhost:8080/api/classes/update HTTP/1.1
  3. // 抓包
  4. // {"id":"4","classesName":"二年级(1)班","classesGraduateYear":"000001004","classesMajor":"000002001","classesDesc":"无"}
  5. @RequestMapping("/update")
  6. public Object update(@RequestBody Classes classes){
  7. int n=classesService.update(classes);
  8. return null;
  9. }

接收json格式的数据 加@RequestBody注解---(抓包看接收啥数据格式)

(10) 删除接口

  1. // 删除数据
  2. // GET http://localhost:8080/api/classes/delete?ids=2&ids=3
  3. @RequestMapping("/delete")
  4. public Object delete(@RequestParam List<Integer> ids){
  5. int n=classesService.delete(ids);
  6. return null;
  7. }
  1. public int delete(List<Integer> ids) {
  2. return classesMapper.deleteByIds(ids);
  3. }

 总结

项目到这里就结束了,其他四个页面大家可参考班级管理的代码实现,此外,还可以实现分页功能,搜索功能,忘记密码等等。如果大家想让自己的项目变得丰富起来的话,可以在网上找资料自己实现这些功能。

 

 也可以来问我哦~~

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/58228
推荐阅读
相关标签
  

闽ICP备14008679号