springboot模拟天猫整站,分类管理系统后端设计实现(查询)

11/21
(本文依照how2j思路,个人实现代码,仅供个人学习记录)
今天是做分类管理系统,用的工具是:
最新版IDEA(2020.2)

首先老套路,建立好基础的maven项目之后,在pom文件中设置各种依赖。
值得注意的是:
1.本项目学习的是1.5版本的springboot
2.mysql本人用的是5.1.47,其中在这里有个坑,就是有关时区的坑,后面讲述
3.删除src下的java和resources
4.开干

思路:

首先浏览器上访问路径 /admin
2. 这个路径被 AdminPageController 的admin方法匹配,然后客户端跳转到 admin_category_list
3. admin_category_list 被 AdminPageController 的 listCategory 方法匹配,服务端跳转到 admin/listCategory.html
4. listCategory.html 这个html页面通过http协议传输到浏览器端
5. 浏览器根据html 上的js代码,异步调用 categories 这个地址。 CategoryController 获取捕捉到这个请求,到数据库里查出所有的分类数据,并转换为 json数组返回给浏览器。
6. 浏览器根据这个json数组,通过 vue 的v-for 方式把其遍历到 多个 tr 元素上,用户就看到了表格里的多条数据了。
在这里插入图片描述

编写程序

首先是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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
<!--    更换为1.5.9版本的springboot-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.lzf</groupId>
    <artifactId>springboot_tmall</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot_tmall</name>
    <description>Demo project for Spring Boot</description>

<!--    设置jdk默认为1.8-->
    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
<!--        设置springboot web架构-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
<!--        设置提供Tomcat支持-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
<!--        设置热部署,让springboot自动更新-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
<!--        jpa-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
<!--        设置缓存redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
<!--        设置springboot的测试支持-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
<!--        使用thymeleaf-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
<!--        使用elasticsearch-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
<!--        与elasticsearch绑定的jna-->
        <dependency>
            <groupId>com.sun.jna</groupId>
            <artifactId>jna</artifactId>
            <version>3.0.9</version>
        </dependency>
<!--        legacyHTML5支持-->
        <dependency>
            <groupId>net.sourceforge.nekohtml</groupId>
            <artifactId>nekohtml</artifactId>
            <version>1.9.22</version>
        </dependency>
<!--        设置junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
<!--        设置Tomcat支持-->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <version>8.5.23</version>
        </dependency>
<!--        设置mysql版本-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.6.2</version>
            <scope>test</scope>
        </dependency>
<!--        commons-lang-->
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>
<!--        设置shiro依赖,用于加密-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.3.2</version>
        </dependency>
<!--        hsqldb-->
        <dependency>
            <groupId>org.hsqldb</groupId>
            <artifactId>hsqldb</artifactId>
        </dependency>
    </dependencies>

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

</project>

目录如下:
在这里插入图片描述然后建立java和resources路径

在这里插入图片描述先创建application.properties配置数据库的链接与各种配置

#database设置数据源
spring.datasource.url=jdbc:mysql://localhost:3306/tmall_springboot?serverTimezone=Asia/Shanghai&allowMultiQueries=true&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=admin
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.hibernate.ddl-auto = none

#thymeleaf配置
spring.thymeleaf.mode=LEGACYHTML5
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.content-type=text/html
spring.thymeleaf.cache=false

#context
server.context-path=/tmall_springboot

#设置上传文件大小,默认只有1 m
spring.http.multipart.maxFileSize=100Mb
spring.http.multipart.maxRequestSize=100Mb

#jpa对实体类的默认字段会把驼峰命名的属性,转换为字段名的时候自动加上下划线。 这个配置的作用就是去掉下划线
#比如属性名称是 createDate, jpa 默认转换为字段名 create_Date。 有了这个配置之后,就会转换为同名字段 createDate
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

#显示 hibernate运行的 sql 语句
spring.jpa.show-sql=true

然后顺便把文件里面前端的东西copy到项目中
现在项目目录是这个样子的:
在这里插入图片描述

实体类pojo.Category

在这里插入图片描述

package com.lzf.tmall.pojo;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import javax.persistence.*;

@Entity
@Table(name = "category")
//这里我们做的是前后端的分离,前后端交互所使用的的是json格式
//所以我们在这里把handler和hibernateLazyInitializer这两个无需json化的属性忽略掉
@JsonIgnoreProperties({"handler","hibernateLazyInitializer"})
public class Category {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")

    int id;
    String name;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

编写dao层

package com.lzf.tmall.dao;

import com.lzf.tmall.pojo.Category;
import org.springframework.data.jpa.repository.JpaRepository;
//直接使用jpa的特性,不用编写分页和CRUD
public interface CategoryDao extends JpaRepository<Category,Integer> {
}

编写service层

package com.lzf.tmall.service;
import java.util.List;
import com.lzf.tmall.dao.CategoryDao;
import com.lzf.tmall.pojo.Category;
//这里sort的导包不要导错
import org.springframework.data.domain.Sort;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


//抛弃了接口+Impl实现类的组合方式,直接使用Service类来作为实现类
@Service
public class CategoryService {
    //自动装配dao层的对象
    @Autowired
    CategoryDao categoryDao;
    //创建sort对象来进行ID的DESC(倒序)然后填充到categoryDao中
    public List<Category> list(){
        Sort sort = new Sort(Sort.Direction.DESC, "id");
        return categoryDao.findAll(sort);
    }
}

编写控制器AdminPageController

package com.lzf.tmall.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class AdminPageController {
    //访问admin路径的时候,就会从admin跳转到admin_category_list
    //然后再跳转到admin_category_list
    @GetMapping(value = "/admin")
    public String admin(){
        return "redirect:admin_category_list";
    }
    @GetMapping(value = "/admin_category_list")
    public String listCategory(){
        return "admin/listCategory";
    }
}

因为是做前后端分离,所以数据是通过 RESTFUL接口来取的,而在业务上,除了 RESTFUL 服务要提供,还要提供页面跳转服务,所以所有的后台页面跳转都放在 AdminPageController 这个控制器里。 而RSTFUL 专门放在 Category 对应的控制器 CategoryController.java 里面。

编写控制器CategoryController

package com.lzf.tmall.web;

import com.lzf.tmall.pojo.Category;
import com.lzf.tmall.service.CategoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class CategoryController {
    @Autowired
    CategoryService categoryService;

    @GetMapping("/categories")
    public List<Category> list() throws Exception{
    // 因为是声明为 @RestController, 所以这个list集合,又会被自动转换为 JSON数组抛给浏览器。 
        return categoryService.list();
    }
}

编写配置类

package com.lzf.tmall.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;


@Configuration
public class CORSConfiguration extends WebMvcConfigurerAdapter {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        //令所有的请求都允许跨域
        /*
        因为是二次请求,第一次是获取 html 页面, 
        第二次通过 html 页面上的 js 代码异步获取数据,
        一旦部署到服务器就容易面临跨域请求问题,
        所以允许所有访问都跨域,就不会出现通过 ajax 获取数据获取不到的问题了
         */
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("*")
                .allowedHeaders("*");
    }
}

编写异常处理类

package com.lzf.tmall.exception;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

@RestController
@ControllerAdvice
public class GloabalExceptionHandler {
    @ExceptionHandler(value = Exception.class)
    public String defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
        e.printStackTrace();
        Class constraintViolationException =
                Class.forName("org.hibernate.exception.internal.CacheSQLExceptionConversionDelegate");
        if (null != e.getCause() && constraintViolationException == e.getCause().getClass()) {
            return "违反了外键的约束";
        }
        return e.getMessage();
    }
}

编写启动类,先别急着启动main方法

package com.lzf.tmall;

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

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

}

整个系统的目录现在是这个样子的:
在这里插入图片描述
先编写测试类,用jdbc来添加十条数据库数据

package com.lzf.tmall.test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
//不要导错包
import java.sql.Statement;

public class TestTmall {
    public static void main(String args[]){
        //准备分类测试数据:

        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        try (
                Connection c = DriverManager.getConnection("jdbc:mysql://localhost:3306/tmall_springboot?useUnicode=true&characterEncoding=utf8",
                        "root", "admin");
                Statement s = c.createStatement();
        )
        {
            for (int i = 1; i <=10 ; i++) {
                String sqlFormat = "insert into category values (null, '测试分类%d')";
                String sql = String.format(sqlFormat, i);
                s.execute(sql);
            }

            System.out.println("已经成功创建10条分类测试数据");

        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

然后启动测试类:
在这里插入图片描述
在这里插入图片描述
可以看出已经导入了十条测试数据。
然后我们再启动启动类
在这里插入图片描述表示启动成功无报错,打开我们的测试地址:

http://localhost:8080/tmall_springboot/admin

在这里插入图片描述
显示成功!
该分类系统就已经做完了。
接下来说中间的错误
错误都主要来源于pom文件中的依赖错误,还有数据库的时区设置问题,这方面我也搞不清楚,一会时区出错一会不出错,我的设置是如下的:

spring.datasource.url=jdbc:mysql://localhost:3306/tmall_springboot?serverTimezone=Asia/Shanghai&allowMultiQueries=true&characterEncoding=UTF-8

让他设置为上海的时区就可以了!
这个子系统的主要难点在于controller层的理解和config层的配置。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值