在csdn上记一次自己的课程设计过程(已经实习两个月了、感觉这个很容易做。支付可能需要多花点时间、):

在此框架基础之上权限认证管理设置成功:https://blog.csdn.net/weixin_43304253/article/details/121111530
动态搜索书籍信息(包括在一定价格范围内查询)https://blog.csdn.net/weixin_43304253/article/details/120920214
课程名称:企业项目实训II
设计题目:大学当图书商城

已知技术参数和设计要求:

1.问题描述(功能要求):
1.1 顾客端
1)注册登录:游客可浏览所有图书,只有注册用户才能添加购物车、下订单购买、评论;
2)图书分类浏览:图书分三个层级进行分类浏览;
3)动态搜索图书:可以按书名、作者、出版社及价格范围进行搜索,搜索的图书分页显示;
4)图书详情:可从图书列表中进一步看到图书的详细信息,包括书号、书名、作者、出版社、印次、内容简介等信息;
5)添加并管理购物车:登录用户可以选择图书加入到购物车,并可对购物车的图书进行增删改查的操作;
6)下订单:登录用户可对图书进行下订单,同时可查看订单当前的状态,订单状态包括待付款(模拟)、待发货(模拟)、待收货(模拟)、待评论;
7)模拟支付:所有注册用户都有一个余额钱包,可模拟充值,充值记录保存下来并可查看,利用余额钱包进行付款。或者使用支付宝的模拟支付接口进行支付;
8)商品评论:购买完图书后进行评价,给一个1-5等级及相应的评论内容。
1.2商家
1)商家注册登录:注册信息包括商家名称,商家地址、经营类型、注册资金、log图片等基本信息,刚注册的商家处于未审核状态,只有等待区域运营方审核后才能正常登录。区域运营方由管理员在后台直接添加;
2)商家管理自家商品:可对商品进行相应的增、删、改、查的操作;
3)商家管理自家店铺:商家可根据平台提供的模板,对店铺进行管理;
4)商家管理订单:商家可对顾客下的订单进行相应的操作,如查看订单、发货(模拟)、查看评论。

  1. 运行环境要求:
    (1)客户端:
    Windows操作系统
    浏览器
    (2)服务器:
    windows操作系统
    Tomcat 服务器
    MySQL 数据库服务器

  2. 技术要求:
    (1)需求分析规格说明书与用例规约
    (2)系统数据库设计,时序图,类图
    (3)系统采用SSM框架技术,完整编码(采用spring boot和vue)
    (4)为保证系统安全性,要求用到日志
    (5)在必要地方使用事务技术
    (6)在必要地方使用2个以上设计模式

设计工作量:
8周

工作计划:
共安排8周时间进行集中实训,软件开发步骤如下,
第1-2周:需求分析、数据库设计、系统设计
第3-7周:编码
第8周:系统测试、答辩、撰写设计说明书

工作进展:在开始编辑这篇文章的时候、距离课程设计已经过了两个周(本人在实习、只能抽出空闲时间来写和周六、周日的时间)现在这个系统的后台逻辑几乎都实现了、还有支付功能未实现。前端页面的美化后来进一步处理吧。

目前的目录结构、后续还需要改进


1、搭建框架
(我花了一天的时间将整个项目的框架搭建起来、使用spring boot整合mybatis、thymeleaf和shiro)
使用spring boot是真的爽到上天、spring简直就是配置地狱。

  • 整合mybatis的目的是简化sql的编写管理
  • 整合thymeleaf的目的是数据的交互
  • 整合shiro的目的是简化权限认证以及授权…

使用到的maven依赖

    <dependencies>
<!--整合shiro
subject:用户
security manager:管理所有的用户
realm:连接数据库 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency> <!--整合mybatis-->
<!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- JDBC-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency> <!-- Mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency> <dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.6</version>
</dependency> <!-- 导入页面依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency> --> <!-- thymeleaf,都是基于3.x开发的-->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
</dependency> <dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> <!-- 简化set和get方法-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
<scope>provided</scope>
</dependency> <!-- 导入日志依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency> <!-- 日志文件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j</artifactId>
<version>1.3.8.RELEASE</version>
</dependency> <!-- 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.5</version>
</dependency> </dependencies>

2、接下来就是编写相应的代码(太简单了、几乎是无脑操作)

随便展示一个书籍的操作、从前台页面到后端代码的编写

先看效果图

前端页面代码


<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>书籍列表</title>
<!-- 新 Bootstrap 核心 CSS 文件 -->
<link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> </head>
<body> <div class="container"> <!--导航栏部分-->
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<a class="navbar-brand" href="#">书籍商城</a>
</div> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li>
<a th:href="@{/customer/toCustomerIndex}">个人信息</a>
</li>
<li>
<a href="#">购买记录</a>
</li>
<li>
<a href="#">购物车</a>
</li>
<li>
<a th:href="@{/book/bookList}">书籍商城</a>
</li> </ul> </div>
<!-- /.navbar-collapse -->
</div>
<!-- /.container-fluid -->
</nav>
<hr> <div class="row ">
<form th:action="@{/book/bookList}" style="float: left"> <div class="col-md-2">
<input type="text" name="queryBookName" class="form-control" placeholder="书籍名">
</div>
<div class="col-md-2" >
<input type="text" name="queryBookAuthor" class="form-control" placeholder="作者名">
</div>
<div class="col-md-2" >
<input type="text" name="queryBookAddress" class="form-control" placeholder="出版社">
</div> <div class="col-md-4" >
<div class="col-row">
<div class="col-md-5">
<input type="text" name="minPrice" class="form-control" placeholder="最低价格">
</div>
<div class="col-md-1">
<span><strong>:</strong></span>
</div>
<div class="col-md-5">
<input type="text" name="maxPrice" class="form-control" placeholder="最高价格">
</div>
</div> </div>
<input type="submit" value="查询" class="btn btn-primary">
</form> </div>
<hr>
<div class="row clearfix">
<div class="col-md-12 column">
<table class="table table-hover table-striped">
<thead>
<tr>
<!-- <th>书籍编号</th>-->
<th>书籍名称</th>
<th>书籍作者</th>
<th>书籍价格</th>
<th>书籍出版社</th>
<th>操作</th>
</tr>
</thead>
<!--查询书籍处理-->
<tbody>
<tr th:each="book:${bookList}">
<!-- <td th:text="${book.getBookId()}">编号</td>-->
<td th:text="${book.getBookName()}">书名</td>
<td th:text="${book.getBookAuthor()}">作者</td>
<td th:text="${book.getPrice()}"></td>
<td th:text="${book.getAddress()}">出版社</td>
<td><a th:href="@{/book/todetail(bookId=${book.getBookId()})}" >详情</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a th:href="@{/shop/addshop(bookId=${book.getBookId()})}" >加入购物车</a></td> </tr>
</tbody>
</table>
<div class="col-md-3">
<a class="btn btn-primary" th:href="@{/book/bookList}">返回查询首页</a>
</div>
<div class="col-md-5">
<p ><strong>当前</strong> <span th:text="${pageInfo.pageNum}"></span><strong> 页,总 </strong><span th:text="${pageInfo.pages}"></span><strong> 页,共</strong> <span th:text="${pageInfo.total}"></span><strong> 条记录</strong></p> </div> <div class="col-md-4">
<div class="row">
<div class="col-md-12">
<a class="btn btn-primary" th:href="@{/book/bookList}">首页</a>
<a class="btn btn-primary" th:href="@{/book/bookList(pageNum=${pageInfo.hasPreviousPage}?${pageInfo.prePage}:1)}">上一页</a>
<a class="btn btn-primary" th:href="@{/book/bookList(pageNum=${pageInfo.hasNextPage}?${pageInfo.nextPage}:${pageInfo.pages})}">下一页</a>
<a class="btn btn-primary" th:href="@{/book/bookList(pageNum=${pageInfo.pages})}">尾页</a>
</div>
</div>
</div> </div>
</div> </div>
</body>
</html>

编写的书籍实体类

(没有使用lombox、失去了Java的灵魂、不喜欢用)

package com.example.zheng.pojo;

public class Books {
private String bookId;
private String bookName;
private String bookAuthor;
private Double price;
private String address;
private String impression;
private String introduce; //新增这两个字段的原因,将前台传入的价格范围封装、在编写sql语句的时候动态替换价格参数
private Double minPrice;//最小价格
private Double maxPrice;//最大价格 public Books(String bookId, String bookName, String bookAuthor, Double price, String address, String impression, String introduce, Double minPrice, Double maxPrice) {
this.bookId = bookId;
this.bookName = bookName;
this.bookAuthor = bookAuthor;
this.price = price;
this.address = address;
this.impression = impression;
this.introduce = introduce;
this.minPrice = minPrice;
this.maxPrice = maxPrice;
} public Double getPrice() {
return price;
} public void setPrice(Double price) {
this.price = price;
} public Double getMinPrice() {
return minPrice;
} public void setMinPrice(Double minPrice) {
this.minPrice = minPrice;
} public Double getMaxPrice() {
return maxPrice;
} public void setMaxPrice(Double maxPrice) {
this.maxPrice = maxPrice;
} public Books() { } public String getBookId() {
return bookId;
} public void setBookId(String bookId) {
this.bookId = bookId;
} public String getBookName() {
return bookName;
} public void setBookName(String bookName) {
this.bookName = bookName;
} public String getBookAuthor() {
return bookAuthor;
} public void setBookAuthor(String bookAuthor) {
this.bookAuthor = bookAuthor;
} public String getAddress() {
return address;
} public void setAddress(String address) {
this.address = address;
} public String getImpression() {
return impression;
} public void setImpression(String impression) {
this.impression = impression;
} public String getIntroduce() {
return introduce;
} public void setIntroduce(String introduce) {
this.introduce = introduce;
}
}

controller层

(这里的传输数据可以使用其他的方式ajax等等、我这里是暂时走通前后端。后期会进一步改造)

package com.example.zheng.controller;

import com.example.zheng.pojo.Books;
import com.example.zheng.service.BooksService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import java.util.List; @Controller
public class BooksController { @Autowired
BooksService booksService; @RequestMapping("/book/bookList")
public String bookList(@RequestParam(defaultValue = "1",value = "pageNum") Integer pageNum,Double minPrice,Double maxPrice, String queryBookAuthor, String queryBookAddress, String queryBookName, Model model){
PageHelper.startPage(pageNum,10);
Books books =new Books();
books.setBookAuthor(queryBookAuthor);
books.setBookName(queryBookName);
books.setAddress(queryBookAddress);
books.setMinPrice(minPrice);
books.setMaxPrice(maxPrice); try {
List<Books> list = booksService.queryBookList(books);
PageInfo<Books> pageInfo = new PageInfo<Books>(list);
model.addAttribute("pageInfo",pageInfo);
if(list == null){
model.addAttribute("error","书籍列表为空");
}else{
model.addAttribute("bookList",list);
}
} catch (Exception e) {
e.printStackTrace();
}
return "allBook"; } @RequestMapping("/book/todetail")
public String bookDetail(String bookId,Model model){
try {
Books books = booksService.queryBookById(bookId);
if(books == null){
model.addAttribute("error","查询书籍详细信息失败");
}else{
model.addAttribute("books",books);
}
} catch (Exception e) {
e.printStackTrace();
} return "bookDetail"; } }

service层

package com.example.zheng.service;

import com.example.zheng.pojo.Books;

import java.util.List;

public interface BooksService {
/**
* 查询图书
*/
public List<Books> queryBookList(Books books); /**
* 查询书籍的详细信息通过书籍编号
*/ public Books queryBookById(String bookId);
}

实现类

package com.example.zheng.service.impl;

import com.example.zheng.mapper.BooksMapper;
import com.example.zheng.pojo.Books;
import com.example.zheng.service.BooksService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import java.util.List; @Service
public class BooksServiceImpl implements BooksService { @Autowired
BooksMapper booksMapper; //查询所有书籍
@Override
public List<Books> queryBookList(Books books) {
return booksMapper.queryBookList(books);
} //根据id查询具体书籍信息
@Override
public Books queryBookById(String bookId) {
return booksMapper.queryBookById(bookId);
}
}

Dao层

package com.example.zheng.mapper;

import com.example.zheng.pojo.Books;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository; import java.util.List; @Mapper //这个注解表示这个是mybatis的mapeper
@Repository
public interface BooksMapper { /**
* 查询图书
*/
public List<Books> queryBookList(Books books); /**
* 查询书籍的详细信息通过书籍编号
*/ public Books queryBookById(String id); }

sql语句

<?xml version="1.0" encoding="UTF8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.zheng.mapper.BooksMapper"> <select id="queryBookList" parameterType="com.example.zheng.pojo.Books" resultType="com.example.zheng.pojo.Books">
select * from bookss
<where>
1=1
<if test="bookName != null and bookName != ''">
And bookName =#{bookName}
</if>
<if test="bookAuthor != null and bookAuthor != ''">
And bookAuthor =#{bookAuthor}
</if>
<if test="address != null and address !=''">
And address =#{address}
</if> <if test="minPrice !=null and minPrice !=''">
And price > #{minPrice}
<if test="maxPrice !=null and maxPrice !=''">
And price &lt; #{maxPrice}
</if>
</if> </where>
</select> <select id="queryBookById" resultType="com.example.zheng.pojo.Books">
select * from bookss where bookId=#{bookId}
</select> </mapper>

差不多整个流程就是这样。大差不差。

在开发中遇到的问题以及解决的办法?

一、在整合框架的时候遇到的奇葩问题:

1、跳转到指定页面出现问题?必须要在properties中配置,这样的目的是,说白了是个视图解析器。和我以前写的不一样,这个也太简单了
2、必须在pom依赖中添加试图解析的依赖。
3、图片路径的问题,添加static则不显示图片,这个是相对路径,找不出来。就很离谱。解决方法:把static删除,然后重启idea。
4、@Controller。跳转到指定页面中要使用这个注解,另外一个出现问题

二、使用thymeleaf在进行传输数据的时候遇到的奇葩

这里需要注意的是,怎样获取当前书籍的主键、以及怎样将这个主键传递到controller层对应的方法中。将这个主键作为查询条件。
解决的方法:<a th:href="@{/book/todetail(bookId=${book.getBookId()})}" >详情</a>
这个方法是thymleaf特有的传输形式

1、改进书籍展示的信息、将书籍编号隐藏。只给顾客展示、书名、作者、出版社、价格


解决办法:1、首先是想到隐藏该列信息、但是没能成功。2、直接将该列信息代码删除、在点击详情需要根据改行的图书主键搜索数据库。由于当前的对象中,已经包含该图书的所有信息。可以直接拿来使用。当前行图书主键存在的意义不是很大。

三、实现在一定价格区间内搜索图书。

遇到的问题:编写的问题sql语句中的价格参数是变动的。不能将其写死在sql中。

解决办法:直接在前端页面设置两个输入框,用来接受数据。同时在实体类书籍中添加最大价格和最小价格两个属性、将前端的数据封装到实体类中,然后将数据直接传输到sql中。

遇到的问题:在新增两个属性后、查询不到数据、爆空指针异常。

经过分析发现、在实体类中书籍的价格应使用Double而不是double.idea没有给我报错、离谱。这种错误我也是醉了。我还真找了好一会。

遇到的问题:获得了参数、在写入sql中,<号不能使用。总是爆红、上网搜索、需要使用转移字符:&lt;

四、遇到的问题? 怎样将查询到的用户权限放入shiro中、进行接下来的认证。

解决办法:将查询到的用户
已经查询到当前用户具有的权限

 //授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("执行了授权"); //拿到当前登录的这个对象
Subject subject = SecurityUtils.getSubject();
Customer currentCustomer = (Customer) subject.getPrincipal();//拿到对象
//设置当前用户的权限
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//设置集合
Collection<String> perStringCollection = new HashSet<String>(); //已经查询到当前用户具有的权限
Set<Roles> permissionSet =rolesService.queryRoles(currentCustomer.getUsercount());
for(Roles perm : permissionSet){
//将每一个当前用户的权限加入
perStringCollection.add(perm.getAuthName());
}
info.addStringPermissions(perStringCollection);
return info; }

五、根据登录用户、在查询购物车的时候、查询当前用户的购物车。在购买商品的时候加入到当前用户的购物车中

主要的代码是:

Customer parent = (Customer) SecurityUtils.getSubject().getPrincipal();

待编辑

最新文章

  1. 【Win 10应用开发】响应系统回退键的导航事件
  2. 深入理解PHP内核(三)概览-SAPI概述
  3. Linux 下源码包安装MariaDB
  4. ipconfig 无效
  5. 使用Navicat for Oracle新建表空间、用户及权限赋予---来自烂泥
  6. HTML5外包团队——技术分享:HTML5判断设备在线离线及监听网络状态变化例子
  7. 【socket】高级用法-异步
  8. Creating Lists and Cards 创建列表和卡片
  9. 给那些因为Firebug而舍不得FireFox的朋友
  10. nefu 943 黑屏
  11. Java curator操作zookeeper获取kafka
  12. javascript之DOM编程改变CSS样式(简易验证码显示)
  13. ELK入门使用-与springboot集成
  14. hadoop ha zkfc 异常自动切换机制和hdfs 没有空间问题解决
  15. mysql Navicat 导入导出
  16. 【Windows 7】发现一个奇怪的现象
  17. Hibernate session中的createCriteria方法
  18. git异常
  19. Python图像识别(聚类)
  20. 【ARM】AD转换器

热门文章

  1. Kafka部署安装
  2. WPF主窗体调用 User32的SetWindowPos 设置窗体置顶会导致与其他窗体抢夺焦点的问题
  3. SQL Server查询优化
  4. Map集合的遍历方式以及TreeMap集合保存自定义对象实现比较的Comparable和Comparator两种方式
  5. 杀死 Windows 某个端口
  6. iommu分析之---intel iommu初始化
  7. 【HMS core】【FAQ】典型问题合集7
  8. 域渗透-Kerberos身份验证流程
  9. 页面POST请求302重定向解决方案
  10. 运维利器-ClusterShell