网站首页 > 精选教程 正文
中北大学软件学院
实验报告
专业: | 软件工程 |
方向: | 云计算与大数据 |
课程名称: | JavaEE框架与应用开发 |
班 级: | |
学 号: | |
姓 名: | |
辅导教师: |
成绩:
实验时间 | 年 月 日 时 至 时 | 学时数 | 4学时 | |
1.实验名称 开发NUCSELL图书管理系统 | ||||
2.实验目的 1.图书管理:包括图书类型管理、每本图书详细信息管理 (1)图书类型管理:图书类型信息增、删、改、查询; (2)图书详细信息管理:图书信息的增、删、改、查询; a.其中图书信息包括图书编号、图书名称、图书类型、图书价格、图书封皮图片 b.查询要求可以按单条件查询(例如按图书编号或图书类型查询);按多条件查询,同时满足多个条件查询,例如上面5个条件中选择3个(图书名称、图书类型、图书价格(价格按某一范围))或选择两个条件(图书类型、图书价格(价格按某一范围)),查询结果满足条件的可能有多条数据。 c.图书类型管理及每本图书信息增、删、改操作必须由具有系统管理员权限的用户完成,具有普通权限的用户不能执行管理操作。 2.用户管理:包括两类用户:具有普通权限的用户和具有系统管理员权限的用户。 (1)用户权限分为0和1两种,0表示系统管理员权限,1表示普通用户权限。 例如:张三可以登录到系统,以系统管理员身份登录进去,可以进行图书管理;以普通用户身份登录,则只能浏览图书信息,查询图书信息(简单查询和高级查询)。 (2)普通用户、系统管理员用户均可有多个。 (3)用户信息(包括用户ID、用户名称、密码、用户权限)管理:增、删、改、查操作。 3.具有普通用户权限的用户可以完成注册、登录,信息浏览、查询功能; 具有系统管理员权限的用户可以完成图书管理、用户管理功能。 4.退出系统,用户注销。 二、系统其他要求: 1. 数据存储需使用数据库管理系统软件; 2. 使用Spring Boot整合MyBatis开发; 3. 前台界面采用UI框架。 | ||||
3.实验内容 1.NUCSELL是一个图书网站 2.用户可以登录,注册,查看分类书籍并查询 3.管理员登录后可以在后台对图书进行增删改查 4.管理员登录后可以在后台对图书类型进行增删改查 5.管理员登录后可以在后台对用户进行增删改查 6. 希望可以对此项目进行更多的优化和扩展 本项目由18130Y03张振东独立开发,本项目基于IDEA进行开发,使用到了Swagger接口文档进行开发,使用Github进行协同开发,使用SpringBoot+BootStrapUI进行开发,数据库使用云端数据库进行搭建并开发,使用nginx进行反向代理(本项目域名为www.nucsell.com:8080),本项目曾使用docker部署到阿里云服务器上,基本使用Restful风格的接口,符合阿里巴巴开发规范。 系统架构解读: 整个系统可以分为两部分:后台管理系统,前台展示系统。 后台管理: ①对图书的管理:包括图书封面,图书类型,图书价格等信息的管理 ②对图书类型的管理:对多种类型的图书分类进行管理 ③对用户的管理:包括用户的类型,用户的姓名,生日等进行管理。 后台系统采用SpringBoot+BootStrap进行开发,后台页面使用thymeleaf进行展示。 预览图: 前台展示: 前台门户面向的是普通用户,包含与用户交互的一切功能。例如:注册,登录,查看书籍,查询书籍等。 前台使用了BootstrapUI+SpringBoot,使用Ajax进行异步交互。 预览图: 技术选型: 前端技术: ①基础的HTML、CSS、JavaScript(基于ES6标准) ②使用Ajax进行异步交互 ③使用Jquery和BootStrapUI美化页面和简化开发 后端技术: ①基础的SpringMVC、Spring 5.0和MyBatis Plus ②Spring Boot 2.3.4.RELEASE版本 ③nginx-1.10.2 进行反向代理 ④Thymeleaf 简化开发HTML页面 ⑤Swagger 进行编写接口文档,开发标准的Restful风格的接口 ⑥devtools 热部署开发工具 | ||||
4.文件描述 java common: 下面有dto类体现了表现层与Model层之间的解耦 config:下面有关于mybatisplus的配置类,MVC的配置类,swagger的配置类 Controller:控制器类的包,负责处理DispatcherServlet 分发的请求 entity:实体类的包 handle:处理器的类,里面包括用户和管理员登录拦截的处理,i18n国际化拦截的处理和阿里巴巴规范中create_time和 update_time的处理 mapper:数据访问层 service:服务层 BookmanagersystemApplication:启动类 resources mapper:存放mapper数据访问层的配置文件等 i18n:国际化配置类 static:存放css,js,img文件 Templates:存放html文件 application.properties:主配置文件 nucsell.sql:数据库的sql文件 | ||||
5.实验源代码
表 5.1 对象设计表
表 5.2 user表设计
表 5.3 category表设计
在进行多表查询的时候,对目录表和书籍表进行了关联。 表 5.4 book表设计
1.Common文件 ① BookDto :表现层与Model层之间的解耦 @Data public class BookDto implements Serializable { private Long id; /** * 书籍名称 */ @ApiModelProperty("书籍名称") private String name; /** * 书籍价格 */ @ApiModelProperty("书籍价格") private String price; /** * 书籍介绍 */ @ApiModelProperty("书籍介绍") private String description; /** * 书籍名称 */ @ApiModelProperty("书籍类型ID") private int cid; } ②GlobalExceptionHandler:全局异常处理器 @Slf4j @RestControllerAdvice public class GlobalExceptionHandler { @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(value = MethodArgumentNotValidException.class) public Result handler(MethodArgumentNotValidException e) { log.error("实体校验异常:----------------{}", e); BindingResult bindingResult = e.getBindingResult(); ObjectError objectError = bindingResult.getAllErrors().stream().findFirst().get(); return Result.fail(objectError.getDefaultMessage()); } @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(value = IllegalArgumentException.class) public Result handler(IllegalArgumentException e) { log.error("Assert异常:----------------{}", e); return Result.fail(e.getMessage()); } @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(value = RuntimeException.class) public Result handler(RuntimeException e) { log.error("运行时异常:----------------{}", e); return Result.fail(e.getMessage()); } } ③Result:对前台返回结果的封装类 @Data public class Result implements Serializable { private int code; // 200是正常,非200表示异常 private String msg; private Object data; public static Result succ(Object data) { return succ(200, "操作成功", data); } public static Result succ(int code, String msg, Object data) { Result r = new Result(); r.setCode(code); r.setMsg(msg); r.setData(data); return r; } public static Result fail(String msg) { return fail(400, msg, null); } public static Result fail(String msg, Object data) { return fail(400, msg, data); } public static Result fail(int code, String msg, Object data) { Result r = new Result(); r.setCode(code); r.setMsg(msg); r.setData(data); return r; } }
①MyMvcConfig @Configuration public class MyMvcConfig implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/admin.html").setViewName("admin"); registry.addViewController("/index.html").setViewName("index"); registry.addViewController("/main.html").setViewName("dashboard"); registry.addViewController("/register.html").setViewName("register"); registry.addViewController("/header.html").setViewName("header"); registry.addViewController("/footer.html").setViewName("footer"); registry.addViewController("/login.html").setViewName("login"); registry.addViewController("/book_list.html").setViewName("book_list"); } @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/asserts/img/**"). addResourceLocations("file:D:/360MoveData/Users/张振东/Desktop/图书管理系统/bookmanagersystem/src/main/resources/static/asserts/img/"); } @Override public void addInterceptors(InterceptorRegistry registry) { // 2.0以前不会过滤.css,.js registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**"). excludePathPatterns("/admin.html","/","/login.html","/register.html", "/webjars/**", "/asserts/**", "/js/**", "/css/**"); registry.addInterceptor(new UserLoginHandlerInterceptor()).addPathPatterns("/**") .excludePathPatterns("/admin.html","/", "/webjars/**", "/asserts/**", "/js/**", "/css/**"); } @Bean public LocaleResolver localeResolver() { return new MyLocalResolver(); } } 3.Controller目录 ①AdminController @Controller @Api("管理员控制类") @RequestMapping("/admin") public class AdminController { @Autowired UserService userService; @ApiOperation("管理员登录") @PostMapping("/login") public String login(@ApiParam("管理员账号") @RequestParam("username") String username, @ApiParam("管理员密码")@RequestParam("password") String password, Map<String, Object> map, HttpSession session) { User admin = userService.getOne(new QueryWrapper<User>().eq("username", username).eq("password", password)); if (admin != null&&admin.getAuthority()==0) { // 为防止表单重复提交,可以重定向到主页 session.setAttribute("loginUser", username); return "redirect:/main.html"; } else { map.put("msg", "用户名密码错误"); return "admin"; } } @ApiOperation("登出") @GetMapping("/loginout") public String loginOut(HttpSession session){ session.removeAttribute("loginUser"); return "redirect:/admin.html"; } } ②BookController @Controller @Api("书籍控制类") public class BookController { @PostMapping("name") @ApiOperation("返回书籍名称") public String toBook(@ApiParam("书籍名称") @RequestBody String bookname) { return bookname; } @Autowired BookService bookService; @ApiOperation("查询所有书籍返回列表页面") @GetMapping("/books") public String list(Model model) { Collection<Book> all = bookService.list(); model.addAttribute("books", all); return "book/list"; } @ApiOperation("到书籍添加页面") @GetMapping("/book") public String toAddPage() { return "book/add"; } // springmvc自动将请求参数和入参对象的属性一一对应:要求请求参数的名字和javabean入参的对象里面的属性名是一样的 @ApiOperation("书籍添加") @PostMapping("/book") public String addBook(@ApiParam("书籍dto类") BookDto book, @ApiParam("书籍封面文件") @RequestParam(value = "cover", required = false) MultipartFile photo) { Book book1 = bookService.addCover(book, photo); System.out.println(book1); bookService.save(book1); // redirect:表示重定向到一个地址 / 表示当前项目路径 // forward:表示转发一个地址 return "redirect:/books"; } @ApiOperation("获取单个书籍的信息") @GetMapping("/book/{id}") public String toEditPage(@ApiParam("书籍id") @PathVariable("id") Integer id, Model model) { Book book = bookService.getById(id); model.addAttribute("book", book); // 回到修改页面(add是一个修改添加二合一的) return "book/add"; } @ApiOperation("修改书籍信息") @PutMapping("/book") public String updateBook(@ApiParam("书籍dto类") BookDto book, @RequestParam(value = "cover", required = false) MultipartFile photo) { Book book1 = bookService.addCover(book, photo); bookService.updateById(book1); return "redirect:/books"; } @ApiOperation("删除书籍信息") @DeleteMapping("/book/{id}") public String deleteBook(@ApiParam("书籍id") @PathVariable("id") Integer id) { bookService.removeById(id); return "redirect:/books"; } @ApiOperation("查询本类型书籍返回列表页面") @GetMapping("/booksInC/{id}") @ResponseBody public List<Book> list(@ApiParam("书籍类型id") @PathVariable("id") Integer id) { List<Book> all = bookService.list(new QueryWrapper<Book>().eq("cid", id)); return all; } @ApiOperation("查询所有书籍") @GetMapping("/getbooks") @ResponseBody public List<Book> getBooks() { List<Book> all = bookService.list(); return all; } @ApiOperation("根据书籍类型和书籍最低价格查询书籍") @GetMapping("/getBooks1") @ResponseBody public List<Book> getBooksByCidAndPrice(@ApiParam("书籍类型id") Integer cid, @ApiParam("书籍价格") String price) { List<Book> all = bookService.list(new QueryWrapper<Book>().eq("cid", cid).gt("price", price)); return all; } } ③CategoryController ④UserController 4.entity目录 ①Book:书籍实体类 @Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) @ApiModel("书籍实体") public class Book implements Serializable { private static final long serialVersionUID = 1L; /** * 主键ID */ @TableId(value = "id") private Long id; /** * 书籍名称 */ @ApiModelProperty("书籍名称") private String name; /** * 书籍名称 */ @ApiModelProperty("书籍类型ID") private int cid; /** * 书籍价格 */ @ApiModelProperty("书籍价格") private String price; /** * 书籍封面 */ @ApiModelProperty("书籍封面") private String cover; /** * 创建时间 */ @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8") @ApiModelProperty("书籍加入时间") @TableField(fill = FieldFill.INSERT) private Date createTime; /** * 更新时间 */ @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8") @ApiModelProperty("书籍更新时间") @TableField(fill = FieldFill.INSERT_UPDATE) private Date updateTime; /** * 书籍介绍 */ @ApiModelProperty("书籍介绍") private String description; } ②category:实际类型实体类 @Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) public class Category implements Serializable { private static final long serialVersionUID = 1L; @TableId(value = "cid") private Integer cid; private String cname; /** * 创建时间 */ @TableField(fill = FieldFill.INSERT) private Date createTime; /** * 更新时间 */ @TableField(fill = FieldFill.INSERT_UPDATE) private Date updateTime; } ③User 5.handle目录 ①LoginHandlerInterceptor:登录拦截 public class LoginHandlerInterceptor implements HandlerInterceptor { // 目标方法执行之前 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { Object loginUser = request.getSession().getAttribute("loginUser"); if (loginUser==null){ // 未登录 request.setAttribute("msg","没有权限请先登录"); request.getRequestDispatcher("/index.html").forward(request,response); return false; }else{ return true; } } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } } ②MyLocalResolver:启用国际化配置 public class MyLocalResolver implements LocaleResolver { @Override public Locale resolveLocale(HttpServletRequest httpServletRequest) { String l = httpServletRequest.getParameter("l"); Locale locale =Locale.getDefault(); if(!StringUtils.isEmpty(l)){ String [] spilt = l.split("_"); locale = new Locale(spilt[0],spilt[1]); } return locale; } @Override public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) { } } ③MyMetaObjectHandler ④UserLoginHandlerInterceptor 6.mapper ①BookMapper ②CategoryMapper ③UserMapper 7.service ①BookServiceImpl @Service public class BookServiceImpl extends ServiceImpl<BookMapper, Book> implements BookService { public Book addCover(BookDto book,MultipartFile photo) { String path = "D:/360MoveData/Users/张振东/Desktop/图书管理系统/bookmanagersystem/src/main/resources/static/asserts/img/"; // 保存路径 String fileName = null; if (!photo.isEmpty()) { fileName = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date()); String suffix = photo.getOriginalFilename() .substring(photo.getOriginalFilename().lastIndexOf(".")); System.out.println(suffix); if (!suffix.equals(".jpg") || !suffix.equals(".png") || !suffix.equals(".gif")) { } try { // Spring提供了文件操作类FileCopyUtils FileCopyUtils.copy(photo.getInputStream(), new FileOutputStream( path + fileName + suffix)); fileName = "http://www.nucsell.com:8080/asserts/img/" + fileName + suffix; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); // return dealResultMap(false, "上传失败"); } } System.out.println(path); Book book1 = new Book(); book1.setId(book.getId()); book1.setName(book.getName()); book1.setPrice(book.getPrice()); book1.setCover(fileName); book1.setDescription(book.getDescription()); book1.setCid(book.getCid()); return book1; } } ②CategoryServiceImpl ③UserServiceImpl ④BookService ⑤CategoryService ⑥UserService
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.zzd</groupId> <artifactId>bookmanagersystem</artifactId> <version>0.0.1-SNAPSHOT</version> <name>bookmanagersystem</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 热部署工具--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <!-- 简化开发--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!-- 数据库驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- 导入mybatis——plus 是自己开放的,不是官方的--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.0.5</version> </dependency> <!--mybatis代码生成器--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.2.0</version> </dependency> <!-- 代码生成里面需要模板,so加上了freemarker--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> <!--集成swagger2,生成接口文档并调试--> <!-- 引入swagger-bootstrap-ui包 /doc.html--> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>swagger-bootstrap-ui</artifactId> <version>1.9.1</version> </dependency> <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> <version>2.3.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>jquery</artifactId> <version>3.5.1</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>bootstrap</artifactId> <version>4.5.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> 以上为项目的基本介绍和部分代码 6.运行截图
图6.1接口文档页面
(1)普通用户登录界面 图6.2 普通用户登录界面
图6.3 管理员登录界面(zh) 图6.4 管理员登录界面(en)
图6.5注册界面
图6.6 用户前台主界面
图6.7查询分类界面
图6.8后台管理主界面
图6.9查询书籍 图6.10增加书籍 图6.11 修改书籍
图6.12查询书籍类型 图6.13增加书籍类型 图6.14修改书籍类型
图6.15查询用户 图6.16增加用户 图6.17修改用户 | ||||
6.实验结论及心得 这次实验花了我5天时间完成,在这期间我学到了好多东西,在通宵熬夜的时候,感觉只要做出来一切都是值得的。我使用到了Swagger接口文档进行开发,使用Github进行协同开发,使用SpringBoot+BootStrapUI进行开发,数据库使用云端数据库进行搭建并开发,使用nginx进行反向代理(本项目域名为www.nucsell.com:8080),本项目曾使用docker部署到阿里云服务器上,基本使用Restful风格的接口,符合阿里巴巴开发规范。 |
猜你喜欢
- 2024-10-13 Java工程师成神之路:程序员的学习路线规划以及书籍推荐
- 2024-10-13 一份c/c++Linux后台服务器开发者的技术拓展书单
- 2024-10-13 Java工程师成神之路:进阶架构师的学习路线规划以及书籍推荐
- 2024-10-13 web技术进阶:学习高并发技术书籍推介,看完从入门到跑路
- 2024-10-13 「妙手数评」给数据工程师推荐5本书
- 2024-10-13 Java学习书籍 学java的书籍推荐
- 2024-10-13 推荐10部嵌入式Linux开发有关的电子书
- 2024-10-13 [开源书籍]《微服务:从设计到部署》中文版
- 2024-10-13 数据工程师必读:这5本书堪称全能教科书
- 2024-10-13 IT架构师必备的书籍推荐及下载 架构师必看书籍推荐
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)