Spring Boot项目实战:BBT版西蒙购物网

目录

一、设计思路

1、采用MVC设计模式

2、西蒙购物网功能架构

二、运行效果

1、西蒙购物网首页

2、必须登录才能选购商品

3、选购商品,可以查看购物车

4、生成订单

5、支付

6、以管理员身份登录

7、单击商品管理下的查看商品

三、创建数据库

1、用户表结构及记录

2、类别表结构及记录

3、商品表结构及记录

4、订单表结构及记录

5、日志表结构及记录

四、项目结构图

五、项目实现步骤

1、创建Spring Boot项目simonshop_final

2、修改pom.xml文件,添加依赖

3、在net.hw.shop里创建bean子包,在里面创建实体类

(1)商品类别实体类Category

(2)日志实体类Log

(3)订单实体类Order

(4)页面实体类Page

(5)商品实体类Product

(6)用户实体类User

4、在net.hw.shop里创建mapper子包,在里面创建实体映射接口

(1)类别映射器接口CategoryMapper

(2)日志映射器接口LogMapper

(3)订单映射器接口OrderMapper

(4)商品映射器接口ProductMapper

(5)用户映射器接口UserMapper

5、在net.hw.shop里创建service子包,在里面创建服务类

(1)类别服务类CategoryService

(2)日志服务类LogService

(3)订单服务类OrderService

(4)商品服务类ProductService

(5)用户服务接类UserService

6、在net.hw.shop里创建aop子包,在里面创建日志切面LogAspect

(1)@Action注解接口

(2)日志切片类LogAspect

7、在net.hw.shop里创建interceptor子包,在里面创建拦截器LoginInterceptor

8、在net.hw.shop里创建webmvc子包,在里面创建控制器

(1)类别控制器CategoryController

(2)数据控制器DataController

(3)日志控制器LogController

(4)订单控制器OrderController

(5)商品控制器ProductController

(6)用户控制器UserController

9、在net.hw.shop里创建config子包,在里面创建WebMvConfig配置类

10、在util子包里创建实用工具类

(1)数据库连接管理类ConnectionManager

(2)加密类Encrypt

(3)SQL文件执行器SQLFileExector

11、在resources下的mapper里创建实体映射文件

(1)类别映射器配置文件CategoryMapper.xml

(2)日志映射器配置文件LogMapper.xml

(3)订单映射器配置文件OrderMapper.xml

(4)商品映射器配置文件ProductMapper.xml

(5)用户映射器配置文件UserMapper.xml

12、在static目录添加ace模板和bootstrap框架

13、创建样式表main.css

14、在static里的images目录里添加商品图片

15、JavaScript脚本文件

16、后台页面

17、前台页面

18、应用属性文件application.yaml

19、修改主程序SimonshopFinalApplication


BBT:采用Spring Boot框架、Bootstrap前端框架和Thymeleaf模板引擎

(1)Thymeleaf官网:Thymeleaf

(2)Bootstrap官网:Bootstrap · The most popular HTML, CSS, and JS library in the world.

(3)Spring Boot官网:Spring Boot

重点说明:采用Thymeleaf模板页面,通过${变量名}只能访问控制器放在model里的数据,而不能像JSP页面那样通过${变量名}访问存放在session里的数据,Thymeleaf模板页面要访问session里的数据,必须通过${session.变量名}的形式来访问。为了让模板页面访问数据简单,只供模板页面用一次的数据,都放在model里。当然,要供多个模板页面共用的数据还是得放在session里。


一、设计思路

1、采用MVC设计模式

分层架构:展现层(HTML)<——>控制层(Controller)<——>业务层(Service)<——>数据映射层(Mapper)<——>数据库(DB)

2、西蒙购物网功能架构

二、运行效果

1、西蒙购物网首页

单击左面类别菜单,可以查看某类商品:

2、必须登录才能选购商品

对用户名进行非空校验:

对密码进行非空校验:

输入正确用户名和密码,如果是普通用户,登录成功之后仍回首页。

单击登录按钮:

3、选购商品,可以查看购物车

4、生成订单

输入电话号码和送货地址:

单击【确定】按钮:

5、支付

6、以管理员身份登录

单击【注销】按钮,以管理员身份登录:

7、单击商品管理下的查看商品

三、创建数据库

创建MySQL数据库simonshop_final,包含五张表:用户表(t_user)、类别表(t_category)、商品表(t_product)、订单表(t_order)和日志表(t_log)。

1、用户表结构及记录

加密之后的登录密码是128位:

2、类别表结构及记录

3、商品表结构及记录

4、订单表结构及记录

5、日志表结构及记录

四、项目结构图

五、项目实现步骤

1、创建Spring Boot项目simonshop_final

package net.hw.shop;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SimonshopFinalApplication {	
	public static void main(String[] args) {
		SpringApplication.run(SimonshopFinalApplication.class, args);
	}
}

后面我们会修改主程序代码的。

2、修改pom.xml文件,添加依赖

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>

   <groupId>net.hw.shop</groupId>
   <artifactId>simonshop_final</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>

   <name>simonshop_final</name>
   <description>Demo project for Spring Boot</description>

   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.3.RELEASE</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.mybatis.spring.boot</groupId>
         <artifactId>mybatis-spring-boot-starter</artifactId>
         <version>1.3.0</version>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-thymeleaf</artifactId>
      </dependency>

      <dependency>
         <groupId>mysql</groupId>
         <artifactId>mysql-connector-java</artifactId>
         <scope>runtime</scope>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>

      <!-- 数据库连接池框架-->
      <dependency>
         <groupId>com.alibaba</groupId>
         <artifactId>druid</artifactId>
         <version>1.0.28</version>
      </dependency>

      <!--单元测试框架-->
      <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>4.12</version>
      </dependency>

      <dependency>
         <groupId>org.yaml</groupId>
         <artifactId>snakeyaml</artifactId>
         <version>1.18</version>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-aop</artifactId>
      </dependency>
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
</project>

3、在net.hw.shop里创建bean子包,在里面创建实体类

(1)商品类别实体类Category

package net.hw.shop.bean;

/**
 * Created by howard on 2017/4/23.
 */
public class Category {
    /**
     * 类别标识符
     */
    private Integer id;
    /**
     * 类别名称
     */
    private String name;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Category{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

(2)日志实体类Log

package net.hw.shop.bean;

import java.util.Date;

/**
 * Created by howard on 2017/5/5.
 */
public class Log {
    /**
     * 编号
     */
    private Integer id;
    /**
     * 用户名
     */
    private String username;
    /**
     * 请求网址
     */
    private String url;
    /**
     * 创建时间
     */
    private Date time;
    /**
     * 操作描述
     */
    private String operation;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public Date getTime() {
        return time;
    }

    public void setTime(Date time) {
        this.time = time;
    }

    public String getOperation() {
        return operation;
    }

    public void setOperation(String operation) {
        this.operation = operation;
    }

    @Override
    public String toString() {
        return "Log{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", url='" + url + '\'' +
                ", time=" + time +
                ", operation='" + operation + '\'' +
                '}';
    }
}

(3)订单实体类Order

package net.hw.shop.bean;

import java.util.Date;

/**
 * Created by howard on 2017/4/23.
 */
public class Order {
    /**
     * 订单标识符
     */
    private Integer id;
    /**
     * 用户名
     */
    private String username;
    /**
     * 联系电话
     */
    private String telephone;
    /**
     * 订单总金额
     */
    private Double totalPrice;
    /**
     * 送货地址
     */
    private String deliveryAddress;
    /**
     * 下单时间
     */
    private Date orderTime;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getTelephone() {
        return telephone;
    }

    public void setTelephone(String telephone) {
        this.telephone = telephone;
    }

    public Double getTotalPrice() {
        return totalPrice;
    }

    public void setTotalPrice(Double totalPrice) {
        this.totalPrice = totalPrice;
    }

    public String getDeliveryAddress() {
        return deliveryAddress;
    }

    public void setDeliveryAddress(String deliveryAddress) {
        this.deliveryAddress = deliveryAddress;
    }

    public Date getOrderTime() {
        return orderTime;
    }

    public void setOrderTime(Date orderTime) {
        this.orderTime = orderTime;
    }

    @Override
    public String toString() {
        return "Order{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", telephone='" + telephone + '\'' +
                ", totalPrice=" + totalPrice +
                ", deliveryAddress='" + deliveryAddress + '\'' +
                ", orderTime=" + orderTime +
                '}';
    }
}

(4)页面实体类Page

package net.hw.shop.bean;

import java.util.List;
import java.util.Map;

/**
 * Created by howard on 2017/5/6.
 */
public class Page<T> {
    private T entity;
    //总页数,通过总记录数和每页记录数计算得到
    private Integer totalPageCount = 0;
    //每页记录数,默认为3
    private Integer pageSize = 3;
    //总记录数
    private Integer totalCount = 0;
    //当前页码,默认为1
    private Integer currentPage = 1;
    //当前页的记录列表
    private List<T> list;
    //分页从第几条记录开始查询
    private Integer offset;
    //排序
    private String order;
    //额外的查询字段
    private Map<String, Object> extra;

    public T getEntity() {
        return entity;
    }

    public void setEntity(T entity) {
        this.entity = entity;
    }

    public Integer getTotalPageCount() {
        return totalPageCount;
    }

    public void setTotalPageCount(Integer totalPageCount) {
        this.totalPageCount = totalPageCount;
    }

    public Integer getPageSize() {
        return pageSize;
    }

    public void setPageSize(Integer pageSize) {
        this.pageSize = pageSize;
    }

    public Integer getTotalCount() {
        return totalCount;
    }

    public void setTotalCount(Integer totalCount) {
        this.totalCount = totalCount;
    }

    public Integer getCurrentPage() {
        return currentPage;
    }

    public void setCurrentPage(Integer currentPage) {
        this.currentPage = currentPage;
    }

    public List<T> getList() {
        return list;
    }

    public void setList(List<T> list) {
        this.list = list;
    }

    public Integer getOffset() {
        return offset;
    }

    public void setOffset(Integer offset) {
        this.offset = offset;
    }

    public String getOrder() {
        return order;
    }

    public void setOrder(String order) {
        this.order = order;
    }

    public Map<String, Object> getExtra() {
        return extra;
    }

    public void setExtra(Map<String, Object> extra) {
        this.extra = extra;
    }
}

(5)商品实体类Product

package net.hw.shop.bean;

import java.util.Date;

/**
 * Created by howard on 2017/4/23.
 */
public class Product {
    /**
     * 商品标识符
     */
    private Integer id;
    /**
     * 商品名称
     */
    private String name;
    /**
     * 商品单价
     */
    private Double price;
    /**
     * 商品上架时间
     */
    private Date addTime;
    /**
     * 商品图片路径
     */
    private String image;
    /**
     * 商品所属类别
     */
    private Category category;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public Date getAddTime() {
        return addTime;
    }

    public void setAddTime(Date addTime) {
        this.addTime = addTime;
    }

    public String getImage() {
        return image;
    }

    public void setImage(String image) {
        this.image = image;
    }

    public Category getCategory() {
        return category;
    }

    public void setCategory(Category category) {
        this.category = category;
    }

    @Override
    public String toString() {
        return "Product{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", price=" + price +
                ", addTime=" + addTime +
                ", image='" + image + '\'' +
                ", category=" + category +
                '}';
    }
}

(6)用户实体类User

package net.hw.shop.bean;

import java.util.Date;

/**
 * Created by howard on 2017/4/23.
 */
public class User {
    /**
     * 用户标识符
     */
    private Integer id;
    /**
     * 用户名
     */
    private String username;
    /**
     * 密码
     */
    private String password;
    /**
     * 电话号码
     */
    private String telephone;
    /**
     * 注册时间
     */
    private Date registerTime;
    /**
     * 权限(0:管理员;1:普通用户)
     */
    private Integer popedom;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getTelephone() {
        return telephone;
    }

    public void setTelephone(String telephone) {
        this.telephone = telephone;
    }

    public Date getRegisterTime() {
        return registerTime;
    }

    public void setRegisterTime(Date registerTime) {
        this.registerTime = registerTime;
    }

    public Integer getPopedom() {
        return popedom;
    }

    public void setPopedom(Integer popedom) {
        this.popedom = popedom;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", telephone='" + telephone + '\'' +
                ", registerTime=" + registerTime +
                ", popedom=" + popedom +
                '}';
    }
}

4、在net.hw.shop里创建mapper子包,在里面创建实体映射接口

(1)类别映射器接口CategoryMapper

package net.hw.shop.mapper;

import net.hw.shop.bean.Category;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * Created by howard on 2017/5/7.
 */
@Mapper
public interface CategoryMapper {
    // 插入类别
    int insert(Category category);

    // 按标识符删除类别
    int delete(int id);

    // 更新类别
    int update(Category category);

    // 按标识符查询类别
    Category findById(Integer id);

    // 查询类别列表
    List<Category> findList(Category category);
}

(2)日志映射器接口LogMapper

package net.hw.shop.mapper;

import net.hw.shop.bean.Log;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

/**
 * Created by howard on 2017/5/7.
 */
@Mapper
public interface LogMapper {
    // 插入日志
    int insert(Log log);

    // 按标识符删除日志
    int delete(Integer id);

    // 按标识符查询日志
    Log findById(Integer id);

    // 查询日志列表
    List<Log> findList(Log log);
}

(3)订单映射器接口OrderMapper

package net.hw.shop.mapper;

import net.hw.shop.bean.Order;
import net.hw.shop.bean.Page;
import org.apache.ibatis.annotations.Mapper;
import org.aspectj.weaver.ast.Or;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * Created by howard on 2017/5/7.
 */
@Mapper
public interface OrderMapper {
    // 插入订单
    int insert(Order order);

    // 按标识符删除订单
    int delete(Integer id);

    // 更新订单
    int update(Order order);

    // 按标识符查询订单
    Order findById(Integer id);

    // 查询订单列表
    List<Order> findList(Order order);
}

(4)商品映射器接口ProductMapper

package net.hw.shop.mapper;

import net.hw.shop.bean.Page;
import net.hw.shop.bean.Product;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * Created by howard on 2017/5/7.
 */
@Mapper
public interface ProductMapper {
    // 插入商品
    int insert(Product product);

    // 删除商品
    int delete(Integer id);

    // 按类别删除商品
    int deleteByCategoryId(Integer categoryId);

    // 更新商品
    int update(Product product);

    // 按标识符查询商品
    Product findById(Integer id);

    // 查询记录数
    int count(Page<Product> page);

    // 查询商品列表
    List<Product> findList(Product product);

    // 分页查询商品
    List<Product> findPage(Page<Product> page);
}

(5)用户映射器接口UserMapper

package net.hw.shop.mapper;

import net.hw.shop.bean.Page;
import net.hw.shop.bean.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * Created by howard on 2017/5/7.
 */
@Mapper
public interface UserMapper {
    // 插入用户
    int insert(User user);

    // 删除用户
    int delete(Integer id);

    // 更新用户
    int update(User user);

    // 按标识符查询用户
    User findById(Integer id);

    // 查询用户列表
    List<User> findList(User user);

    // 分页查询用户
    List<User> findPage(Page<User> page);

    // 记录数
    int count(Page<User> page);

    // 用户登录
    User login(@Param("username") String username, @Param("password") String password);
}

5、在net.hw.shop里创建service子包,在里面创建服务类

(1)类别服务类CategoryService

package net.hw.shop.service;

import net.hw.shop.bean.Category;
import net.hw.shop.mapper.CategoryMapper;
import net.hw.shop.mapper.ProductMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * Created by howard on 2017/5/7.
 */
@Service("categoryService")
@Transactional(readOnly = true)
public class CategoryService {
    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private ProductMapper productMapper;

    /**
     * 保存类别
     *
     * @param category
     * @return
     */
    @Transactional(readOnly = false)
    public int save(Category category) {
        if (category.getId() == null) {
            return categoryMapper.insert(category);
        } else {
            return categoryMapper.update(category);
        }
    }

    /**
     * 删除类别
     *
     * @param id
     * @return
     */
    @Transactional(readOnly = false)
    public int delete(int id) {
        return categoryMapper.delete(id);
    }

    /**
     * 按标识符查询类别
     *
     * @param id
     * @return
     */
    public Category findById(int id) {
        return categoryMapper.findById(id);
    }

    /**
     * 查询类别列表
     *
     * @param category
     * @return
     */
    public List<Category> findList(Category category) {
        return categoryMapper.findList(category);
    }

    /**
     * 批量删除
     *
     * @param ids
     */
    @Transactional(readOnly = false)
    public boolean deleteBatch(String ids) {
        String[] idArray = ids.split(",");
        for (String id : idArray) {
            int count = categoryMapper.delete(Integer.parseInt(id));
            if (count == 0) {
                return false;
            } else {
                productMapper.deleteByCategoryId(Integer.parseInt(id));
            }
        }
        return true;
    }
}

(2)日志服务类LogService

package net.hw.shop.service;

import net.hw.shop.bean.Log;
import net.hw.shop.mapper.LogMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * Created by howard on 2017/5/7.
 */
@Service("logService")
@Transactional(readOnly = true)
public class LogService {
    @Autowired
    private LogMapper logMapper;

    /**
     * 保存日志
     *
     * @param log
     * @return
     */
    @Transactional(readOnly = false)
    public int save(Log log) {
        return logMapper.insert(log);
    }

    /**
     * 按标识符删除日志
     *
     * @param id
     * @return
     */
    @Transactional(readOnly = false)
    public int delete(int id) {
        return logMapper.delete(id);
    }

    /**
     * 按标识符查询日志
     *
     * @param id
     * @return
     */
    public Log findById(Integer id) {
        return logMapper.findById(id);
    }

    /**查询日志列表
     *
     * @param log
     * @return
     */
    public List<Log> findList(Log log) {
        return logMapper.findList(log);
    }
}

(3)订单服务类OrderService

package net.hw.shop.service;

import net.hw.shop.bean.Order;
import net.hw.shop.mapper.OrderMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * Created by howard on 2017/5/7.
 */
@Service("orderService")
@Transactional(readOnly = true)
public class OrderService {
    @Autowired
    private OrderMapper orderMapper;

    /**
     * 保存订单
     *
     * @param order
     * @return
     */
    @Transactional(readOnly = false)
    public int save(Order order) {
        if(order.getId() == null) {
            return orderMapper.insert(order);
        } else {
            return orderMapper.update(order);
        }
    }

    /**
     * 按标识符删除订单
     *
     * @param id
     * @return
     */
    @Transactional(readOnly = false)
    public int delete(int id) {
        return orderMapper.delete(id);
    }

    /**
     * 按标识符查询订单
     *
     * @param id
     * @return
     */
    public Order findById(Integer id) {
        return orderMapper.findById(id);
    }

    /**
     * 查询订单列表
     *
     * @param order
     * @return
     */
    public List<Order> findList(Order order) {
        return orderMapper.findList(order);
    }
}

(4)商品服务类ProductService

package net.hw.shop.service;

import jdk.management.resource.internal.TotalResourceContext;
import net.hw.shop.bean.Page;
import net.hw.shop.bean.Product;
import net.hw.shop.mapper.ProductMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * Created by howard on 2017/5/7.
 */
@Service("productService")
@Transactional(readOnly = true)
public class ProductService {
    @Autowired
    private ProductMapper productMapper;

    /**
     * 保存商品
     *
     * @param product
     * @return
     */
    @Transactional(readOnly = false)
    public int save(Product product) {
        if (product.getId() == null) {
            return productMapper.insert(product);
        } else {
            return productMapper.update(product);
        }
    }

    /**
     * 删除商品
     *
     * @param id
     * @return
     */
    @Transactional(readOnly = false)
    public int delete(Integer id) {
        return productMapper.delete(id);
    }

    /**
     * 按类别删除商品
     *
     * @param categoryId
     * @return
     */
    public int deleteByCategoryId(Integer categoryId) {
        return productMapper.deleteByCategoryId(categoryId);
    }

    /**
     * 按标识符查询商品
     *
     * @param id
     * @return
     */
    public Product findById(Integer id) {
        return productMapper.findById(id);
    }

    /**
     * 查询记录数
     *
     * @param page
     * @return
     */
    public int count(Page<Product> page) {
        return productMapper.count(page);
    }

    /**
     * 查询商品列表
     *
     * @param product
     * @return
     */
    public List<Product> findList(Product product) {
        return productMapper.findList(product);
    }

    /**
     * 分页查询商品
     *
     * @param page
     * @return
     */
    public Page<Product> findPage(Page<Product> page) {
        // 总记录数
        page.setTotalCount(productMapper.count(page));
        // 总页数
        page.setTotalPageCount((page.getTotalCount() - 1) / page.getPageSize() + 1);
        // 如果页码大于了总页数,直接显示最后一页
        if (page.getCurrentPage() < 1) {
            // 如果页码小于1,则显示首页
            page.setCurrentPage(1);
        } else if (page.getCurrentPage() > page.getTotalPageCount()) {
            page.setCurrentPage(page.getTotalPageCount());
        }
        // 从第几条记录开始查询
        page.setOffset((page.getCurrentPage() - 1) * page.getPageSize());
        page.setList(productMapper.findPage(page));
        return page;
    }
}

(5)用户服务接类UserService

package net.hw.shop.service;

import net.hw.shop.bean.Page;
import net.hw.shop.bean.User;
import net.hw.shop.mapper.UserMapper;
import net.hw.shop.util.Encrypt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * Created by howard on 2017/5/7.
 */
@Service("userService")
@Transactional(readOnly = true)
public class UserService {
    @Autowired
    private UserMapper userMapper;

    /**
     * 保存用户
     *
     * @param user
     * @return
     */
    @Transactional(readOnly = false)
    public int save(User user) {
        user.setPassword(new Encrypt().SHA512(user.getPassword()));
        if (user.getId() == null) {
            return userMapper.insert(user);
        } else {
            return userMapper.update(user);
        }
    }

    /**
     * 删除用户
     *
     * @param id
     * @return
     */
    @Transactional(readOnly = false)
    public int delete(int id) {
        return userMapper.delete(id);
    }

    /**
     * 按标识符查询用户
     *
     * @param id
     * @return
     */
    public User findById(Integer id) {
        return userMapper.findById(id);
    }

    /**
     * 查询用户列表
     *
     * @param user
     * @return
     */
    public List<User> findList(User user) {
        return userMapper.findList(user);
    }

    /**
     * 分页查询用户
     *
     * @param page
     * @return
     */
    public Page<User> findPage(Page<User> page) {
        // 总记录数
        page.setTotalCount(userMapper.count(page));
        // 总页数
        page.setTotalPageCount((page.getTotalCount() - 1) / page.getPageSize() + 1);
        // 如果页码大于了总页数,直接显示最后一页
        if (page.getCurrentPage() < 1) {
            // 如果页码小于1,则显示首页
            page.setCurrentPage(1);
        } else if (page.getCurrentPage() > page.getTotalPageCount()) {
            page.setCurrentPage(page.getTotalPageCount());
        }
        // 从第几条记录开始查询
        page.setOffset((page.getCurrentPage() - 1) * page.getPageSize());
        page.setList(userMapper.findPage(page));
        return page;
    }

    /**
     * 用户登录
     *
     * @param username
     * @param password
     * @return
     */
    public User login(String username, String password) {
        return userMapper.login(username, new Encrypt().SHA512(password));
    }
}

6、在net.hw.shop里创建aop子包,在里面创建日志切面LogAspect

(1)@Action注解接口

package net.hw.shop.aop;

import java.lang.annotation.*;

/**
 * Created by howard on 2017/5/5.
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Action {
    String name();
}

(2)日志切片类LogAspect

package net.hw.shop.aop;

import net.hw.shop.bean.Log;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * Created by howard on 2017/5/5.
 */
@Aspect
@Component
public class LogAspect {
    // 注解声明切点
    @Pointcut("@annotation(net.hw.shop.aop.Action)")
    public void mypt() {}

    // 注解声明前置建言,并使用@PointCut定义的切点
    @Before("mypt()")
    public void before(JoinPoint joinPoint) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Action action = method.getAnnotation(Action.class);

        String username = (String) request.getSession().getAttribute("username");
        String url = request.getRequestURL().toString();
        Date time = new Date();
        String operation = method.getName() + "方法准备执行";

        Log log = new Log();
        log.setUsername(username == null ? "未登录用户" : username);
        log.setUrl(url);
        log.setTime(time);
        log.setOperation(operation);
    }


    // 注解声明后置建言,并使用@PointCut定义的切点
    @After("mypt()")
    public void after(JoinPoint joinPoint) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Action action = method.getAnnotation(Action.class);

        String username = (String) request.getSession().getAttribute("username");
        String url = request.getRequestURL().toString();
        Date time = new Date();
        String operation = method.getName() + "方法执行完毕";

        Log log = new Log();
        log.setUsername(username == null ? "未登录用户" : username);
        log.setUrl(url);
        log.setTime(time);
        log.setOperation(operation);
    }
}

7、在net.hw.shop里创建interceptor子包,在里面创建拦截器LoginInterceptor

package net.hw.shop.interceptor;

import net.hw.shop.bean.Category;
import net.hw.shop.bean.Product;
import net.hw.shop.service.CategoryService;
import net.hw.shop.service.ProductService;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.List;

/**
 * Created by howard on 2017/4/23.
 */
public class LoginInterceptor extends HandlerInterceptorAdapter {
    @Resource
    private CategoryService categoryService;
    @Resource
    private ProductService productService;

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response,
                           Object handler, ModelAndView modelAndView) throws Exception {
        super.postHandle(request, response, handler, modelAndView);
        String url = request.getRequestURL().toString();
        HttpSession session = request.getSession();
        String username = (String) session.getAttribute("username");
        if (username == null) {
            if (url.contains("view") || url.contains("add")
                    || url.contains("edit") || url.contains("delete")
                    || url.contains("operateCart")) {
                List<Category> categories = categoryService.findList(null);
                session.setAttribute("categories", categories);
                List<Product> products = productService.findList(null);
                session.setAttribute("products", products);
                modelAndView.setViewName("frontend/login");
            }
        } else {
//            System.out.println("登录用户:" + username);
        }
    }
}

8、在net.hw.shop里创建webmvc子包,在里面创建控制器

(1)类别控制器CategoryController

package net.hw.shop.webmvc;

import jdk.nashorn.internal.runtime.JSONFunctions;
import net.hw.shop.bean.Category;
import net.hw.shop.service.CategoryService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by howard on 2017/4/23.
 */
@Controller
@RequestMapping("/category")
public class CategoryController {
    @Resource
    private CategoryService categoryService;

    @RequestMapping("/addCategory")
    @ResponseBody
    public Map<String, Object> addCategory(@RequestParam("categoryName") String categoryName) {
        Category category = new Category();
        category.setName(categoryName);
        int count = categoryService.save(category);
        Map<String, Object> map = new HashMap<String, Object>();
        if (count > 0) {
            map.put("success", true);
        } else {
            map.put("success", false);
        }
        return map;
    }

    @RequestMapping("/getCategoryName")
    @ResponseBody
    public Map<String, Object> getCategoryName(@RequestParam("categoryId") int categoryId) {
        Category category = new Category();
        category.setId(categoryId);
        String categoryName = categoryService.findList(category).get(0).getName();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("categoryName", categoryName);
        return map;
    }

    @RequestMapping("/listAll")
    public
    @ResponseBody
    List<Category> listAll() {
        List<Category> categories = categoryService.findList(null);
        return categories;
    }

    @RequestMapping("/editCategory")
    @ResponseBody
    public Map<String, Object> editCategory(@RequestParam("id") int id,
                                            @RequestParam("name") String name) {
        Category category = new Category();
        category.setId(id);
        category.setName(name);
        System.out.println(category);
        int count = categoryService.save(category);
        Map<String, Object> map = new HashMap<String, Object>();
        if (count > 0) {
            map.put("success", true);
        } else {
            map.put("success", false);
        }
        return map;
    }

    @RequestMapping("/deleteCategory")
    public
    @ResponseBody
    Map<String, Object> deleteCategory(@RequestParam("ids") String ids) {
        Map<String, Object> map = new HashMap<String, Object>();
        if (categoryService.deleteBatch(ids)) {
            map.put("success", true);
        } else {
            map.put("success", false);
        }
        return map;
    }
}

(2)数据控制器DataController

package net.hw.shop.webmvc;

import net.hw.shop.util.SQLFileExecutor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * Created by howard on 2017/5/11.
 */
@Controller
@RequestMapping("/data")
public class DataController {
    @RequestMapping("/restoreData")
    public String restoreData(Model model) {
        if (SQLFileExecutor.execute("simonshop_final.sql")) {
            model.addAttribute("dataMsg","恭喜,数据还原成功!");
        } else {
            model.addAttribute("dataMsg", "遗憾,数据还原失败!");
        }
        return "backend/restoreData";
    }
}

(3)日志控制器LogController

package net.hw.shop.webmvc;

import net.hw.shop.bean.Log;
import net.hw.shop.bean.Order;
import net.hw.shop.service.LogService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import java.util.List;

/**
 * Created by howard on 2017/5/5.
 */
@Controller
@RequestMapping("/log")
public class LogController {
    @Resource
    private LogService logService;

    @RequestMapping("/listAll")
    public
    @ResponseBody
    List<Log> listAll() {
        List<Log> logs = logService.findList(null);
        return logs;
    }
}

(4)订单控制器OrderController

package net.hw.shop.webmvc;

import net.hw.shop.bean.Order;
import net.hw.shop.service.OrderService;
import org.aspectj.weaver.ast.Or;
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 org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.Date;
import java.util.List;

/**
 * Created by howard on 2017/2/18.
 */
@Controller
@RequestMapping("/order")
public class OrderController {
    @Resource
    private OrderService orderService;

    @RequestMapping("/makeOrder")
    public String makeOrder(@RequestParam("username") String username,
                            @RequestParam("telephone") String telephone,
                            @RequestParam("totalPrice") double totalPrice,
                            @RequestParam("deliveryAddress") String deliveryAddress,
                            Model model) {
        Order order = new Order();
        order.setUsername(username);
        order.setTelephone(telephone);
        order.setTotalPrice(totalPrice);
        order.setDeliveryAddress(deliveryAddress);
        order.setOrderTime(new Date());
        int count = orderService.save(order);
        if (count > 0) {
            List<Order> orders = orderService.findList(null);
            Order lastOrder = orders.get(orders.size()-1);
            model.addAttribute("lastOrder", lastOrder);
            return "frontend/showOrder";
        } else {
            model.addAttribute("orderMsg", "订单生成失败!");
            return "frontend/showProduct";
        }
    }

    @RequestMapping("/pay")
    public String pay(HttpSession session) {
        session.removeAttribute("shoppingTable");
        session.removeAttribute("totalPrice");
        return "index";
    }

    @RequestMapping("/toMakeOrder")
    public String toMakeOrder(@RequestParam("totalPrice") double totalPrice,
                              Model model) {
        if (totalPrice == 0.0) {
            model.addAttribute("orderMsg", "您还未购物呢!请您选购商品!");
            return "frontend/showProduct";
        } else {
            model.addAttribute("totalPrice", totalPrice);
            return "frontend/makeOrder";
        }
    }

    @RequestMapping("/listAll")
    public
    @ResponseBody
    List<Order> listAll() {
        List<Order> orders = orderService.findList(null);
        return orders;
    }
}

(5)商品控制器ProductController

package net.hw.shop.webmvc;

import net.hw.shop.bean.Category;
import net.hw.shop.bean.Page;
import net.hw.shop.bean.Product;
import net.hw.shop.service.CategoryService;
import net.hw.shop.service.ProductService;
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 org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.net.ssl.HttpsURLConnection;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;

/**
 * Created by howard on 2017/4/24.
 */
@Controller
@RequestMapping("/product")
public class ProductController {
    @Resource
    private ProductService productService;
    @Resource
    private CategoryService categoryService;

    @RequestMapping("/toAddProduct")
    public String toAddProduct(HttpSession session) {
        List<Category> categories = categoryService.findList(null);
        session.setAttribute("categories", categories);
        return "backend/addProduct";
    }


    @RequestMapping("/addProduct")
    public String addCategory(@RequestParam("name") String name,
                              @RequestParam("price") double price,
                              @RequestParam("imageFile") MultipartFile file,
                              @RequestParam("category") int category,
                              Model model) {
        Product product = new Product();
        product.setName(name);
        product.setPrice(price);
        product.setAddTime(new Date());
        product.setCategory(categoryService.findById(category));
        // 获取上传文件原文件名
        String filename = file.getOriginalFilename();
        // 获取最后一件商品的id
        int lastId = productService.findList(null).get(productService.count(new Page<Product>()) - 1).getId();
        // 设置图片路径
        String image = "/images/product" + (lastId + 1) + ".jpg";
        product.setImage(image);
        // 上传图片到指定位置
        try {
            Files.copy(file.getInputStream(), Paths.get("src/main/resources/static", image));
        } catch (IOException e) {
            e.printStackTrace();
        }

        int count = productService.save(product);
        Map<String, Object> map = new HashMap<String, Object>();
        if (count > 0) {
            model.addAttribute("productMsg", "恭喜,添加商品成功!");
        } else {
            model.addAttribute("productMsg", "遗憾,添加商品失败!");
        }
        return "backend/addProduct";
    }

    @RequestMapping("/showProduct")
    public String showProduct(@RequestParam("categoryId") int categoryId,
                              @RequestParam("currentPage") int currentPage,
                              HttpSession session, Page<Product> page, Model model) {
        String categoryName = "全部类别";
        if (categoryId > 0) {
            Map<String, Object> extra = new HashMap<String, Object>();
            extra.put("categoryId", categoryId);
            Page<Product> pageParam = new Page<Product>();
            pageParam.setExtra(extra);
            pageParam.setCurrentPage(currentPage);
            page = productService.findPage(pageParam);
            Category category = categoryService.findById(categoryId);
            categoryName = category.getName();
            if (page.getList().size() == 0) {
                model.addAttribute("productMsg", "[" + categoryName + "]类没有商品");
            }
        } else {
            Page<Product> pageParam = new Page<Product>();
            pageParam.setCurrentPage(currentPage);
            page = productService.findPage(pageParam);
        }
        if (page.getList().size() > 0) {
            session.setAttribute("categoryId", categoryId);
            session.setAttribute("categoryName", categoryName);
            session.setAttribute("page", page);
        }
        return "frontend/showProduct";
    }

    @RequestMapping("/operateCart")
    public String operateCart(
            @RequestParam("operation") String operation,
            @RequestParam("id") int id,
            HttpSession session, Page<Product> page) {

        // 从session里获取购物车(键:商品标识符;值:购买数量)
        LinkedHashMap<Integer, Integer> cart = (LinkedHashMap<Integer, Integer>) session.getAttribute("cart");
        // 判断购物车是否为空
        if (cart == null) {
            // 创建购物车
            cart = new LinkedHashMap<Integer, Integer>();
            // 将购物车保存到session里,便于用户在不同页面访问购物车
            session.setAttribute("cart", cart);
        }

        if (operation.equals("add")) {
            // 将商品添加到购物车
            if (cart.containsKey(id)) { // 该商品已购买过
                // 购买数量增加1
                cart.put(id, cart.get(id) + 1);
            } else { // 该商品未曾购买
                // 购买数量设置为1
                cart.put(id, 1);
            }
        } else if (operation.equals("delete")) {
            // 将商品从购物车删除
            if (cart.get(id) > 1) {
                // 购买数量减少1
                cart.put(id, cart.get(id) - 1);
            } else {
                // 从购物车里删除该商品
                cart.remove(id);
            }
        }

        // 获取该商品的类别标识符
        int categoryId = productService.findById(id).getCategory().getId();
        // 判断购物车是否为空
        if (cart != null) {
            // 定义购物表
            List<HashMap<String, Object>> shoppingTable = new ArrayList<HashMap<String, Object>>();
            // 购物总金额
            double totalPrice = 0.0;
            // 遍历购物车
            for (Integer p_id : cart.keySet()) {
                // 获取商品对象
                Product product = productService.findById(p_id);
                // 生成购物表记录
                HashMap<String, Object> shoppingItem = new HashMap<String, Object>();
                shoppingItem.put("id", product.getId());
                shoppingItem.put("name", product.getName());
                shoppingItem.put("price", product.getPrice());
                shoppingItem.put("amount", cart.get(p_id));
                shoppingItem.put("sum", product.getPrice() * cart.get(p_id));
                // 将购物表记录添加到购物表中
                shoppingTable.add(shoppingItem);
                // 累加购买总金额
                totalPrice = totalPrice + (Double) shoppingItem.get("sum");
            }

            // 将购物表和购买总金额保存到session里
            session.setAttribute("shoppingTable", shoppingTable);
            session.setAttribute("totalPrice", totalPrice);
        }

        Category category = categoryService.findById(categoryId);
        Map<String, Object> extra = new HashMap<String, Object>();
        extra.put("categoryId", categoryId);
        Page<Product> pageParam = new Page<Product>();
        pageParam.setExtra(extra);
        page = productService.findPage(pageParam);
        String categoryName = category.getName();

        session.setAttribute("categoryId", categoryId);
        session.setAttribute("categoryName", categoryName);
        session.setAttribute("page", page);

        return "frontend/showProduct";
    }

    @RequestMapping("/listAll")
    public
    @ResponseBody
    List<Product> listAll() {
        List<Product> products = productService.findList(null);
        return products;
    }
}

(6)用户控制器UserController

package net.hw.shop.webmvc;

import net.hw.shop.bean.Category;
import net.hw.shop.bean.Order;
import net.hw.shop.bean.Product;
import net.hw.shop.bean.User;
import net.hw.shop.service.CategoryService;
import net.hw.shop.service.OrderService;
import net.hw.shop.service.ProductService;
import net.hw.shop.service.UserService;
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 org.springframework.web.bind.annotation.ResponseBody;
import sun.misc.resources.Messages_pt_BR;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by howard on 2017/4/28.
 */
@Controller
@RequestMapping("/user")
public class UserController {
    @Resource
    private UserService userService;
    @Resource
    private CategoryService categoryService;
    @Resource
    private ProductService productService;
    @Resource
    private OrderService orderService;

    @RequestMapping("/login")
    public String login(@RequestParam("username") String username,
                        @RequestParam("password") String password,
                        Model model, HttpSession session) {
        User user = userService.login(username, password);
        // 判断是否登录成功
        if (user != null) {
            session.setAttribute("username", username);
            // 判断用户的角色
            if (user.getPopedom() == 0) {
                return "backend/management";
            } else {
                List<Category> categories = categoryService.findList(null);
                session.setAttribute("categories", categories);
                return "index";
            }
        } else {
            model.addAttribute("loginMsg", "用户名或密码错误!");
            return "frontend/login";
        }
    }

    @RequestMapping("/register")
    public String register(@RequestParam("username") String username,
                           @RequestParam("password") String password,
                           @RequestParam("telephone") String telephone,
                           Model model) {
        // 设置注册时间(时间戳对象)
        Timestamp registerTime = new Timestamp(System.currentTimeMillis());
        // 设置用户为普通用户
        int popedom = 1;
        // 创建用户对象
        User user = new User();
        // 设置用户对象信息
        user.setUsername(username);
        user.setPassword(password);
        user.setTelephone(telephone);
        user.setRegisterTime(registerTime);
        user.setPopedom(popedom);
        // 调用UserService对象添加用户方法
        int count = userService.save(user);
        // 判断是否注册成功
        if (count > 0) {
            model.addAttribute("registerMsg", "恭喜,注册成功!");
            // 映射到登录页面
            return "frontend/login";
        } else {
            model.addAttribute("registerMsg", "遗憾,注册失败!");
            // 映射到前台注册页面
            return "frontend/register";
        }
    }

    @RequestMapping("/logout")
    public String logout(HttpSession session) {
        session.removeAttribute("username");
        session.removeAttribute("cart");
        session.removeAttribute("shoppingTable");
        session.removeAttribute("totalPrice");
        List<Category> categories = categoryService.findList(null);
        session.setAttribute("categories", categories);
        List<Product> products = productService.findList(null);
        session.setAttribute("products", products);
        return "index";
    }

    @RequestMapping("/infoCenter")
    public String infoCenter(HttpSession session) {
        String username = (String) session.getAttribute("username");
        User user = new User();
        user.setUsername(username);
        List<User> users = userService.findList(user);
        session.setAttribute("user", users.get(0));

        Order order = new Order();
        order.setUsername(username);
        List<Order> orders = orderService.findList(order);
        session.setAttribute("orders", orders);

        return "frontend/infoCenter";
    }

    @RequestMapping("/changePassword")
    @ResponseBody
    public Map<String, Object> changePassword(@RequestParam("password") String password,
                                              HttpSession session) {
        String username = (String) session.getAttribute("username");
        User userParam = new User();
        userParam.setUsername(username);
        User user = userService.findList(userParam).get(0);
        user.setPassword(password);
        int count = userService.save(user);
        Map<String, Object> map = new HashMap<String, Object>();
        if (count > 0) {
            map.put("success", true);
        }
        return map;
    }

    @RequestMapping("/listAll")
    public
    @ResponseBody
    List<User> listAll() {
        List<User> users = userService.findList(null);
        return users;
    }
}

9、在net.hw.shop里创建config子包,在里面创建WebMvConfig配置类

package net.hw.shop.config;

import net.hw.shop.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

/**
 * Created by howard on 2017/4/28.
 */
@Configuration
@ComponentScan("net.hw.shop.webmvc")
public class WebMvcConfig extends WebMvcConfigurerAdapter {
    /**
     * 添加视图控制器
     *
     * @param registry
     */
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("index");
        registry.addViewController("/toShowCart").setViewName("frontend/showCart");
        registry.addViewController("/user/toLogin").setViewName("frontend/login");
        registry.addViewController("/user/toRegister").setViewName("frontend/register");
        registry.addViewController("/todo").setViewName("backend/todo");
        registry.addViewController("/toMain").setViewName("backend/main");
        registry.addViewController("/user/viewUser").setViewName("backend/viewUser");
        registry.addViewController("/category/viewCategory").setViewName("backend/viewCategory");
        registry.addViewController("/category/editCategory").setViewName("backend/editCategory");
        registry.addViewController("/category/toAddCategory").setViewName("backend/addCategory");
        registry.addViewController("/category/toEditCategory").setViewName("backend/editCategory");
        registry.addViewController("/category/toDeleteCategory").setViewName("backend/deleteCategory");
        registry.addViewController("/product/viewProduct").setViewName("backend/viewProduct");
        registry.addViewController("/order/viewOrder").setViewName("backend/viewOrder");
        registry.addViewController("/log/viewLog").setViewName("backend/viewLog");
    }

    /**
     * 定义拦截器
     */
    @Bean
    public LoginInterceptor loginInterceptor() {
        return new LoginInterceptor();
    }

    /**
     * 添加拦截器
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor());
    }
}

10、在util子包里创建实用工具类

(1)数据库连接管理类ConnectionManager

package net.hw.shop.util;

import javax.swing.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

/**
 * Created by howard on 2017/5/11.
 */
public class ConnectionManager {
    /**
     * 数据库驱动程序
     */
    private static final String DRIVER = "com.mysql.jdbc.Driver";
    /**
     * 数据库统一资源标识符
     */
    private static final String URL = "jdbc:mysql://localhost:3306/simonshop_final";
    /**
     * 数据库用户名
     */
    private static final String USERNAME = "root";
    /**
     * 数据库密码
     */
    private static final String PASSWORD = "root";

    /**
     * 私有化构造方法,拒绝实例化
     */
    private ConnectionManager() {
    }

    /**
     * 获得数据库连接
     *
     * @return 数据库连接对象
     */
    public static Connection getConnection() {
        // 定义数据库连接
        Connection conn = null;
        try {
            // 安装数据库驱动程序
            Class.forName(DRIVER);
            // 获得数据库连接
            conn = DriverManager.getConnection(URL
                    + "?useUnicode=true&characterEncoding=UTF8", USERNAME, PASSWORD);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        // 返回数据库连接
        return conn;
    }

    /**
     * 关闭数据库连接
     *
     * @param conn
     */
    public static void closeConnection(Connection conn) {
        // 判断数据库连接是否为空
        if (conn != null) {
            // 判断数据库连接是否关闭
            try {
                if (!conn.isClosed()) {
                    // 关闭数据库连接
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 测试数据库连接是否成功
     *
     * @param args
     */
    public static void main(String[] args) {
        // 获得数据库连接
        Connection conn = getConnection();
        // 判断是否连接成功
        if (conn != null) {
            JOptionPane.showMessageDialog(null, "恭喜,数据库连接成功!");
        } else {
            JOptionPane.showMessageDialog(null, "遗憾,数据库连接失败!");
        }

        // 关闭数据库连接
        closeConnection(conn);
    }
}

(2)加密类Encrypt

package net.hw.shop.util;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * Created by howard on 2017/5/6.
 */
public class Encrypt {
    /**
     * 传入文本内容,返回SHA-256串
     *
     * @param strText
     * @return
     */
    public String SHA256(final String strText) {
        return SHA(strText, "SHA-256");
    }

    /**
     * 传入文本内容,返回SHA-512串
     *
     * @param strText
     * @return
     */
    public String SHA512(final String strText) {
        return SHA(strText, "SHA-512");
    }

    /**
     * 字符串SHA加密
     *
     * @param strText
     * @param strType
     * @return
     */
    private String SHA(final String strText, final String strType) {
        // 定义返回值
        String strResult = null;

        // 判断是否为有效字符串
        if (strText != null && strText.length() > 0) {
            try {
                // SHA 加密开始
                // 创建加密对象,并传入加密对象
                MessageDigest messageDigest = MessageDigest.getInstance(strType);
                // 传入待加密字符串
                messageDigest.update(strText.getBytes());
                // 得到加密字节数组
                byte byteBuffer[] = messageDigest.digest();

                // 创建字符串缓冲对象
                StringBuffer strHexString = new StringBuffer();
                // 遍历字节数组,将其元素放入字符串缓冲对象
                for (int i = 0; i < byteBuffer.length; i++) {
                    String hex = Integer.toHexString(0xff & byteBuffer[i]);
                    if (hex.length() == 1) {
                        strHexString.append('0');
                    }
                    strHexString.append(hex);
                }
                // 得到返回结果
                strResult = strHexString.toString();
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
        }

        return strResult;
    }
}

(3)SQL文件执行器SQLFileExector

package net.hw.shop.util;

import com.ibatis.common.resources.Resources;
import org.apache.ibatis.jdbc.ScriptRunner;

import java.io.IOException;
import java.sql.Connection;

/**
 * Created by howard on 2017/5/11.
 */
public class SQLFileExecutor {

    public static boolean execute(String sqlFile) {
        Connection conn = ConnectionManager.getConnection();
        ScriptRunner runner = new ScriptRunner(conn);
        try {
            runner.runScript(Resources.getResourceAsReader(sqlFile));
            return true;
        } catch (IOException e) {
            return false;
        }
    }

    public static void main(String[] args) {
        if (execute("simonshop_final.sql")) {
            System.out.println("SQL脚本文件执行成功!");
        } else {
            System.out.println("SQL脚本文件执行失败!");
        }
    }
}

11、在resources下的mapper里创建实体映射文件

(1)类别映射器配置文件CategoryMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="net.hw.shop.mapper.CategoryMapper">

    <insert id="insert" parameterType="net.hw.shop.bean.Category">
        insert into t_category (name) values (#{name});
    </insert>

    <update id="update" parameterType="net.hw.shop.bean.Category">
        update t_category
        <set>
            <if test="name != null">
                name = #{name}
            </if>
        </set>
         where id = #{id};
    </update>

    <delete id="delete" parameterType="Integer">
        delete from t_category where id = #{id};
    </delete>

    <select id="findById" parameterType="Integer" resultType="net.hw.shop.bean.Category">
        select * from t_category where id = #{id};
    </select>

    <select id="findList" parameterType="net.hw.shop.bean.Category"
            resultType="net.hw.shop.bean.Category">
        select * from t_category
        <where>
            <if test="name != null">
                name = #{name}
            </if>
        </where>
    </select>

</mapper>

(2)日志映射器配置文件LogMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="net.hw.shop.mapper.LogMapper">
    <insert id="insert" parameterType="net.hw.shop.bean.Log">
        insert into t_log (username, url, time, operation)
        values (#{username}, #{url}, #{time}, #{operation});
    </insert>

    <delete id="delete" parameterType="int">
        delete from t_log where id = #{id};
    </delete>

    <select id="findById" parameterType="int" resultType="net.hw.shop.bean.Log">
        SELECT * FROM t_log WHERE id = #{id}
    </select>

    <select id="findList" parameterType="net.hw.shop.bean.Log"
            resultType="net.hw.shop.bean.Log">
        select * from t_log
        <where>
            <if test="username != null">
                username = #{username}
            </if>
            <if test="url != null">
                and url = #{url}
            </if>
            <if test="time != null">
                and time = #{time}
            </if>
            <if test="operation != null">
                and operation = #{operation}
            </if>
        </where>
    </select>
</mapper>

(3)订单映射器配置文件OrderMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="net.hw.shop.mapper.OrderMapper">

    <resultMap id="orderMap" type="net.hw.shop.bean.Order">
        <result property="totalPrice" column="total_price"/>
        <result property="deliveryAddress" column="delivery_address"/>
        <result property="orderTime" column="order_time"/>
    </resultMap>

    <insert id="insert" parameterType="net.hw.shop.bean.Order">
        insert into t_order (username, telephone, total_price, delivery_address, order_time)
        values (#{username}, #{telephone}, #{totalPrice}, #{deliveryAddress}, #{orderTime});
    </insert>
    
    <update id="update" parameterType="net.hw.shop.bean.Order">
        update t_order
        <set>
            <if test="username != null">
                username = #{username},
            </if>
            <if test="telephone != null">
                telephone = #{telephone},
            </if>
            <if test="totalPrice != null">
                total_price = #{totalPrice},
            </if>
            <if test="deliveryAddress != null">
                delivery_address = #{deliveryAddress},
            </if>
            <if test="orderTime != null">
                order_time = #{orderTime}
            </if>
        </set>
        where id = #{id};
    </update>

    <delete id="delete" parameterType="int">
        delete from t_order where id = #{id};
    </delete>

    <select id="findById" parameterType="int" resultMap="orderMap">
        select * from t_order where id = #{id};
    </select>

    <select id="findList" parameterType="net.hw.shop.bean.Order"
            resultMap="orderMap">
        select * from t_order
        <where>
            <if test="username != null">
                username = #{username}
            </if>
            <if test="telephone != null">
                and telephone = #{telephone}
            </if>
            <if test="totalPrice != null">
                and total_price = #{totalPrice}
            </if>
            <if test="deliveryAddress != null">
                and delivery_address = #{deliveryAddress}
            </if>
            <if test="orderTime != null">
                and order_time = #{orderTime}
            </if>
        </where>
    </select>
</mapper>

(4)商品映射器配置文件ProductMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="net.hw.shop.mapper.ProductMapper">
    <sql id="field">
        a.id,
        a.name,
        a.price,
        a.add_time,
        a.image,
        a.category_id as "category.id",
        b.name as "category.name"
    </sql>

    <sql id="join">
        <!-- 在此处添加与其它表的关联 -->
        inner join t_category b on a.category_id = b.id
    </sql>

    <sql id="orderBy">
        order by a.id asc
    </sql>

    <resultMap id="productMap" type="net.hw.shop.bean.Product">
        <result property="addTime" column="add_time"/>
    </resultMap>

    <insert id="insert" parameterType="net.hw.shop.bean.Product">
        insert into t_product (name, price, add_time, image, category_id)
        VALUES (#{name}, #{price}, #{addTime}, #{image}, #{category.id});
    </insert>

    <update id="update" parameterType="net.hw.shop.bean.Product">
        update t_product
        <set>
            <if test="name != null">
                name = #{name},
            </if>
            <if test="price != null">
                price = #{price},
            </if>
            <if test="addTime != null">
                add_time = #{addTime},
            </if>
            <if test="image != null">
                image = #{image},
            </if>
            <if test="category != null">
                category_id = #{category.id}
            </if>
        </set>
        where id = #{id};
    </update>

    <delete id="delete" parameterType="Integer">
        delete from t_product where id = #{id};
    </delete>

    <delete id="deleteByCategoryId" parameterType="Integer">
        delete from t_product where category_id = #{categoryId};
    </delete>

    <select id="count" parameterType="net.hw.shop.bean.Page" resultType="Integer">
        select count(*) from t_product
        <where>
            <if test="extra != null">
                category_id = #{extra.categoryId}
            </if>
        </where>
    </select>

    <select id="findById" parameterType="Integer" resultMap="productMap">
        select
        <include refid="field"/>
        from t_product a
        <include refid="join"/>
        where a.id = #{id};
    </select>

    <select id="findList" parameterType="net.hw.shop.bean.Product"
            resultMap="productMap">
        select
        <include refid="field"/>
        from t_product a
        <include refid="join"/>
        <where>
            <if test="name != null">
                and a.name like CONCAT(#{name},'%')
            </if>
            <if test="price != null">
                and a.price = #{price}
            </if>
            <if test="addTime != null">
                and a.add_time = #{addTime}
            </if>
            <if test="image != null">
                and a.image = #{image}
            </if>
            <if test="category != null">
                and a.category_id = #{category.id}
            </if>
        </where>
        <include refid="orderBy"/>
    </select>

    <select id="findPage" parameterType="net.hw.shop.bean.Page" resultMap="productMap">
        select
        <include refid="field"/>
        from t_product a
        <include refid="join"/>
        <where>
            <if test="extra != null">
                category_id = #{extra.categoryId}
            </if>
        </where>
        <include refid="orderBy"/>
        <!-- 分页控制 -->
        <if test="offset != null">
            limit #{offset}, #{pageSize}
        </if>
    </select>

</mapper>

(5)用户映射器配置文件UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="net.hw.shop.mapper.UserMapper">

    <resultMap id="userMap" type="net.hw.shop.bean.User">
        <result property="registerTime" column="register_time"/>
        <result property="popedom" column="popedom"/>
    </resultMap>

    <insert id="insert" parameterType="net.hw.shop.bean.User">
        insert into t_user (username, password, telephone, register_time, popedom)
        values (#{username}, #{password}, #{telephone}, #{registerTime}, #{popedom});
    </insert>

    <update id="update" parameterType="net.hw.shop.bean.User">
        update t_user
        <set>
            <if test="username != null">
                username = #{username},
            </if>
            <if test="password != null">
                password = #{password},
            </if>
            <if test="username != null">
                telephone = #{telephone},
            </if>
            <if test="registerTime != null">
                register_time = #{registerTime},
            </if>
            <if test="popedom != null">
                popedom = #{popedom}
            </if>
        </set>
        where id = #{id};
    </update>

    <delete id="delete" parameterType="Integer">
        delete from t_user where id = #{id};
    </delete>

    <select id="count" parameterType="net.hw.shop.bean.Page" resultType="Integer">
        select count(*) from t_user
    </select>

    <select id="findList" parameterType="net.hw.shop.bean.User" resultMap="userMap">
        select * from t_user
        <where>
            <if test="username != null">
                and username = #{username}
            </if>
            <if test="password != null">
                and password = #{password}
            </if>
            <if test="telephone != null">
                and telephone = #{telephone}
            </if>
            <if test="registerTime != null">
                and register_time = #{registerTime}
            </if>
            <if test="popedom != null">
                and popedom = #{popedom}
            </if>
        </where>
    </select>

    <select id="findPage" parameterType="net.hw.shop.bean.Page" resultMap="userMap">
        select * from t_user
        <!-- 分页控制 -->
        <if test="offset != null">
            limit #{offset}, #{pageSize}
        </if>
    </select>

    <select id="findById" parameterType="Integer" resultMap="userMap">
        select * from t_user where id = #{id};
    </select>

    <select id="login" resultMap="userMap">
        select * from t_user where username = #{username} and password = #{password};
    </select>

</mapper>

12、在static目录添加ace模板和bootstrap框架

13、创建样式表main.css

body {
    margin: 0px;
    padding: 0px;
    background: url(../images/background.jpg) no-repeat;
    background-size: 100%;
}

14、在static里的images目录里添加商品图片

15、JavaScript脚本文件

check.js:

/**
 * 检验登录表单
 *
 * @returns {Boolean}
 */
function checkLoginForm() {
    if ($('#username').val() == "") {
        $('#message').html("用户名不能为空!");
        $('#dialog').css({visibility: "visible"});
        $('#username').focus();
        return false;
    }

    if ($('#password').val() == "") {
        $('#message').html("密码不能为空!");
        $('#dialog').css({visibility: "visible"});
        $('#password').focus();
        return false;
    }

    return true;
}

/**
 * 检验注册表单
 *
 * @returns {Boolean}
 */
function checkRegisterForm() {
    if ($('#username').val() == "") {
        $('#message').html("用户名不能为空!");
        $('#dialog').css({visibility: "visible"});
        $('#username').focus();
        return false;
    }

    if ($('#password').val() == "") {
        $('#message').html("密码不能为空!");
        $('#dialog').css({visibility: "visible"});
        $('#password').focus();
        return false;
    }

    var patrn = "/^(13[0-9]|14[0-9]|15[0-9]|18[0-9])\d{8}$/";
    if (!patrn.test($('#telephone').val())) {
        $('#message').html("非法手机号!");
        $('#dialog').css({visibility: "visible"});
        $('#telephone').focus();
        return false;
    }

    return true;
}


/**
 * 检查密码与确认密码是否一致
 *
 * @returns {boolean}
 */
function checkPassword() {
    if ($('#password').val() == "") {
        $('#message').html("密码不能为空!");
        $('#dialog').css({visibility: "visible"});
        $('#password').focus();
        return false;
    }

    if ($('#repassword').val() == "") {
        $('#message').html("确认密码不能为空!");
        $('#dialog').css({visibility: "visible"});
        $('#repassword').focus();
        return false;
    }

    if ($('#password').val() != $('#repassword').val()) {
        $('#message').html("密码与确认密码不一致!");
        $('#dialog').css({visibility: "visible"});
        return false;
    }

    return true;
}

/**
 * 检验类别名是否为空
 *
 * @returns {boolean}
 */
function checkCategoryName() {
    if ($('#categoryName').val() == "") {
        $('#message').html("类别名不能为空!");
        $('#dialog').css({visibility: "visible"});
        $('#categoryName').focus();
        return false;
    }
    return true;
}

/**
 * 检验商品名与单价是否为空
 *
 * @returns {boolean}
 */
function checkProduct() {
    if ($('#name').val() == "") {
        $('#message').html("商品名称不能为空!");
        $('#dialog').css({visibility: "visible"});
        $('#name').focus();
        return false;
    }
    if ($('#price').val() <= 0) {
        $('#message').html("商品单价必须为正数!");
        $('#dialog').css({visibility: "visible"});
        $('#price').focus();
        return false;
    }

    if ($('#imageFile').val() == "") {
        $('#message').html("必须设置商品图片!");
        $('#dialog').css({visibility: "visible"});
        return false;
    }
    return true;
}

16、后台页面

17、前台页面

18、应用属性文件application.yaml

#服务器配置
server:
  port: 8080
  tomcat:
    uri-encoding: UTF-8
    basedir: /data/simonshop/tomcat
    max-threads: 2000
    min-spare-threads: 10
    accesslog:
      pattern: common
      enabled: true
      directory: ../logs
      prefix: simonshop_access_log
      suffix: .log
      request-attributes-enabled: true
      rename-on-rotate: true

#日志配置
logging:
  level:
    root: INFO
    net.hw.shop: DEBUG

spring:
  #数据源配置
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    type: com.zaxxer.hikari.HikariDataSource
    url: jdbc:mysql://localhost:3306/simonshop_final
    username: root
    password: root
    hikari:
      minimum-idle: 10
      maximum-pool-size: 10
      idle-timeout: 600000
      max-lifetime: 1800000
      connection-timeout: 30000
      connection-test-query: SELECT 1
      pool-name: simonshop-pool
  #模板引擎配置
  thymeleaf:
    cache: false
    content-type: text/html
    mode: HTML5

#缓存配置
cache:
    ehcache:
      config: ehcache.xml

#MyBatis配置
mybatis:
  mapper-locations: classpath*:mapper/*.xml
  type-aliases-package: net.hw.shop.bean

19、修改主程序SimonshopFinalApplication

package net.hw.shop;

import net.hw.shop.bean.Category;
import net.hw.shop.bean.Product;
import net.hw.shop.service.CategoryService;
import net.hw.shop.service.ProductService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.List;

@Controller
@SpringBootApplication
public class SimonshopFinalApplication {
	@Resource
	private CategoryService categoryService;
	@Resource
	private ProductService productService;

	@RequestMapping("/")
	public String index(HttpSession session) {
		List<Category> categories = categoryService.findList(null);
		session.setAttribute("categories", categories);
		List<Product> products = productService.findList(null);
		session.setAttribute("products", products);
		return "index";
	}

	public static void main(String[] args) {
		SpringApplication.run(SimonshopFinalApplication.class, args);
	}
}

BBT版西蒙购物网项目下载:百度网盘 请输入提取码 提取码:s8q4 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

howard2005

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值