SpringBoot学习历程

67 阅读32分钟

SpringBoot

Web服务软件做了哪些事儿?

image.png

  • web服务软件就是传奇老师带着写的webServer, 也就是Tomcat
  1. 负责建立底层的网络连接

  2. 根据客户端请求的静态资源路径找到对应的静态资源文件并把该文件返回给客户端
    举例:http://localhost:8080/index.html

  3. 根据客户端请求的动态资源路径找到对应的Controller里面的方法并且执行
    举例:http://localhost:8080/hello

  • Web服务软件自身不提供任何业务功能,通过Controller给工程添加具体的业务功能

SSM三大框架

  • Spring框架

  • SpringMVC框架

  • Mybatis框架

SpringBoot框架

  • 如果创建一个空工程,在此工程中使用SSM框架时需要添加大量的依赖和书写大量的配置文件, 通过SpringBoot框架可以更加便捷的让工程中引入各种框架, SpringBoot框架帮助我们构建工程.

如何创建SpringBoot工程

  1. 第一个页面中可以修改创建工程的网址

    start.spring.io 默认

    start.springboot.io

    start.aliyun.com

image.png

image.png 2.设置以下内容

image.png 3.选择创建工程时添加的依赖

image.png 4.点击Finishi等待下载内容
5.如何检查工程是否创建成功?
在idea的底部 找到Build 然后看里面是否出现绿色的对勾

image.png 6.如果第五步没有绿色对勾,刷新maven

image.png
7.检查maven是否已经改成aliyun的配置文件

8.如果已经改成aliyun的 还有错的话, 找到.m2文件夹下的repository文件夹删除 ,删除完之后再次重复第6步 刷新maven

9.在工程的static文件夹中添加index.html 页面中显示HelloSpringBoot 启动工程 通过浏览器访问http://localhost:8080 检查是否显示了此页面

10.创建controller.HelloController类 在里面添加hello方法处理/hello请求,给客户端响应一句话, 重启工程,浏览器访问http://localhost:8080/hello 测试是否成功

day02

客户端发出请求的几种方式

  1. 通过浏览器的地址栏中发出请求

  2. 通过html页面中的超链接发出请求

  3. 通过html页面中的form表单发出请求

  4. 通过前端框架发出请求

工程中使用数据库需要做的几件事:

  1. 在pom.xml中添加 MySQL依赖和数据库连接池依赖,从jdbc01工程中去复制两个依赖粘贴到新工程中, 然后刷新maven(必须做)

  2. 把jdbc01工程中的DBUtils 复制到新工程的utils包下面

image.png

<!-- 连接MySQL数据库的依赖 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.15</version>
</dependency>
<!-- 数据库连接池 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.21</version>
</dependency>

Mybatis框架

  • 此框架是目前最流行的数据持久层框架,是对JDBC代码进行了封装, 程序员只需要通过注解或配置文件的方式提供需要执行的SQL语句,框架会自动根据SQL语句生成出JDBC代码,从而提高执行效率

  • 如何使用Mybatis框架?

  1. 创建boot2-1工程 , 创建工程时需要勾选3个内容分别是:

  2. Web->Spring Web

  3. SQL-> Mybatis Framework

  4. SQL-> MySQL Driver

image.png

  1. 在application.properties配置文件中书写连接数据库的信息
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/bootdb?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false

Mybatis框架添加英雄步骤:

  1. 创建boot2-3 打钩 3个
  1. 在application.properties配置文件中添加内容
  1. 停止之前工程, 运行新工程测试是否能正常运行
  1. 创建index.html 页面 里面添加超链接 添加英雄 访问地址为add.html
  1. 创建add.html页面 里面添加form表单 请求地址为 /add
  1. 创建controller.HeroController, 里面添加@Controller注解,添加@RequestMapping注解处理 /add请求 并添加add方法,
  1. 创建entity.Hero实体类 并提供get和set方法 还有tostring方法
  1. 在HeroController的add方法参数列表中声明Hero对象 用来接收传递过来的参数 ,此时打桩输出hero对象 检查是否接收到了参数
  1. 创建mapper.HeroMapper接口, 里面添加@Mapper注解, 声明一个insert方法通过@Insert注解修饰,注解里面添加插入数据的SQL语句
  1. 在HeroController里面 通过@Autowired注解把HeroMapper装配进来, 在add方法里面调用mapper.insert方法把接收到的hero对象传递进去, 重启工程测试即可!

删除英雄步骤:

  1. 在首页中添加删除英雄超链接 访问地址为 delete.html
  1. 创建delete.html页面 在里面添加form表单 提交地址为/delete
  1. 在HeroController 中创建delete方法 处理路径为/delete 参数列表中声明name 接收页面传递过来的名字
  1. 在HeroMapper里面添加deleteByName方法 通过@Delete注解修饰,里面填写 删除的SQL语句
  1. 在HeroController里面的delete方法中调用mapper的deleteByName方法

修改英雄步骤:

  1. 在首页添加修改英雄超链接, 地址为update.html页面
  1. 创建update.html页面 并添加form表单 提交地址为/update
  1. 在Controller中添加update方法 处理/update请求
  1. 在HeroMapper里面添加update方法 通过@Update注解进行修饰,里面添加修改的SQL语句
  1. 在HeroController里面的update方法中调用mapper的update方法把接收到的hero对象传递到方法中

查询英雄步骤:

  1. 在首页添加查询的超链接,请求地址为/select
  1. 在HeroController中添加select方法处理/select请求
  1. 在HeroMapper里面添加select方法用@Select注解进行修饰,里面写查询的SQL语句
  1. 在HeroController的select方法中 调用mapper的select方法,把查询到的List集合返回给客户端展示

HeroController类

package cn.jyh.boot24.controller;

import cn.jyh.boot24.entity.Hero;
import cn.jyh.boot24.mapper.HeroMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
//此注解相当于在每一个方法上面都添加了一个@ResponseBody
@RestController
public class HeroController {
    @Autowired
    HeroMapper mapper;

    @RequestMapping("/insert")
    public String insert(Hero hero){
        mapper.insert(hero);
        return "添加成功!";
    }

    @RequestMapping("/delete")
    public String delete(Hero hero){
        mapper.delete(hero);
        return "删除成功!";
    }

    @RequestMapping("/update")
    public String update(Hero hero){
        mapper.update(hero);
        return "修改成功!";
    }

    @RequestMapping("/select")
    public String select(){
        List<Hero> list =  mapper.select();
        return list.toString();
    }
}

增删改查mapper接口

import org.apache.ibatis.annotations.*;

import java.util.List;

@Mapper
public interface HeroMapper {
    @Insert("insert into hero values(null,#{name},#{money})")
    void insert(Hero hero);

    @Delete("delete from hero where name = #{name}")
    void delete(Hero hero);

    @Update("update hero set name = #{name},money = #{money} where id = #{id}")
    void update(Hero hero);

    @Select("select * from hero")
    List<Hero> select();
}

day03

商品表的增删改查

  • 创建商品表

use empdb;

create table product(id int primary key auto_increment,title varchar(100),price double(10,2),sale_count int)charset=utf8;

  1. 创建boot3-1工程 打3个勾

  2. 从别的工程中复制application.properties配置文件的信息到新工程, 启动工程测试是否成功.

注:

image.png

@Result注解用于统一idea与数据库中字段成一一对应的关系 image.png

同步请求和异步请求

  • 同步: 指单线程依次做几件事
  • 异步: 指多线程同时做几件事
  • 同步请求: 指客户端浏览器只有一个主线程, 此线程负责页面的渲染和发出请求等操作, 如果此主线程发出请求的话则停止渲染而且会清空页面显示的内容 直到服务器响应了数据后才能再次显示, 由于主线程清空了原有显示的内容所以只能实现页面的整体刷新(整体改变)
  • 异步请求: 指客户端的主线程只负责页面渲染相关操作,发请求的事儿由新的子线程操作, 这样子线程发出请求时页面不需要清空,而且可以将查询回来的数据展示在原有页面基础之上, 这样实现的效果就叫做页面的局部刷新

客户端发出请求的几种方式

  1. 通过浏览器的地址栏中发出请求 同步请求

  2. 通过html页面中的超链接发出请求 同步请求

  3. 通过html页面中的form表单发出请求 同步请求

  4. 通过前端框架发出请求 异步请求

客户端如何发出异步请求

  1. 通过Axios框架发出异步请求

  2. 此框架就是一个普通的js文件 页面需要使用此框架时需要将此文件引入到页面中

  3. 从苍老师文档服务器中找到axios框架地址

<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>

注册登录步骤: 至少写3遍以上

  1. 创建工程boot3-2 打钩3个

  2. 从之前工程中复制application.properties里面的连接数据库的信息 ,复制完之后立即启动工程 测试是否创建成功, 如果工程启动不起来 检查报错是不是因为端口被占用, 如果不是 刷新maven 再次启动 ,如果还是启动不了 删除工程重新创建新工程 直至启动成功.

  3. 创建index.html页面 在里面添加两个超链接访问注册和登录页面

  4. 创建reg.html页面 在页面中引入vue和axios两个框架文件 从之前工程中复制js文件夹(检查里面是不是包含这两个框架文件) 在页面中 点击按钮时向/reg发出异步请求,同时把用户输入的信息提交给服务器,然后在then方法里面判断返回的response.data值为1代表注册成功 显示首页 值为2代表用户名已存在

  5. 创建controller.UserController 并且创建entity.User实体类

  6. 在Controller里面添加reg方法处理/reg请求 声明User变量用来接收传递过来的用户信息

  7. 创建mapper.UserMapper 在里面提供两个方法 分别是 selectByUsername 和 insert两个方法

  8. 回到Controller里面把UserMapper通过@Autowired装配进来,在reg方法中先调用mapper里面的selectByUsername方法 判断返回值是否有值 如果有值则给客户端返回2代表用户名已存在 如果没有值 则调用mapper的insert方法 把用户信息保存到数据库,最后返回1 代表注册成功

  9. 下一步开始实现登录功能, 步骤类似注册 先创建login.html页面 然后在页面中通过Vue对内容进行管理 当点击登录按钮的时候 向/login发出异步请求 同样把输入的用户信息提交给服务器, 在then方法中判断response.data的值为1代表登录成功显示首页 值为2 代表用户名不存在, 值为3 代表密码错误

  10. 在Controller里面添加login方法处理/login请求,声明User对象接收传递过来的用户信息, 在方法中调用mapper的selectByUsername 通过用户输入的用户名查询对应的用户信息,如果没有查询到 直接返回2代表用户名不存在,如果查询到了 继续通过输入的密码和查询到的密码比较如果一致返回1代表登录成功, 如果不一致返回2 代表密码错误.

端口被占用

  1. 检查是不是有其它正在运行的工程, 将其关闭后再运行新工程

  2. 如果没有正在运行的工程,可通过以下几种方式:

    a. 重启电脑

    b. 修改工程的端口号

image.png

c. 在命令行中 执行以下指令找到占用8080端口的进程,然后执行杀掉该进程的指令, 释放出8080端口

image.png

day04

后端的MVC设计模式

  • 把实现一个业务的代码划分为三部分,分别是: 页面相关(V),业务逻辑相关(C),数据相关(M)

  • M:Model 数据模型, 对应的代码是数据库相关的Mapper部分

  • V:View 视图, 对应所有页面相关内容

  • C:Controller 控制器,对应的是Controller相关代码

  • 实现一个业务的顺序: V页面相关代码->C Controller相关代码->M 数据库Mapper相关代码

  • 排错时也是从这三部分代码中找问题

  • 后端MVC涉及模式中的V页面相关,前端工程师将页面又划分为了MVC三部分

前后端分离

image.png

  • 如果前后端不分离, 后端服务器需要两套代码来应对 手机客户端和浏览器客户端, 因为不同的客户端的需求内容是不一样的,这样后端的开发效率就会受影响.

image.png

  • 前后端分离:指在Controller中不再处理页面相关内容, 浏览器客户端需要先请求页面,页面加载完之后从页面中再次发出请求获取数据, 得到数据后把数据展示在页面中,这个过程属于页面的局部刷新, 同步请求只能实现页面的整体刷新无法实现局部刷新, 所以以后不再使用同步请求, 全部使用异步请求,因为以后工作基本全是前后端分离思想.

JSON

  • JSON是一种轻量级的数据交换格式(数据封装格式)

  • 客户端和服务器之间需要互相传递数据,当需要传递复杂数据时需要按照特定的格式将数据进行封装,JSON就是这样一个通用格式.

登录成功

用户名已存在

密码错误

1

2

3

"id=1, title=手机 , price=1000, saleCount=500"

[{"id":1,"title":"阿迪袜子","price":10.0,"saleCount":1000},{"id":3,"title":"裤子","price":50.0,"saleCount":400},{"id":4,"title":"袜子","price":5.0,"saleCount":100}]

服务器和客户端之间如何传递复杂数据

image.png

商品管理添加商品步骤:

  1. 创建工程 3个打钩 修改application.properties配置文件, 启动工程测试是否成功

  2. 创建index.html首页 和 insert.html页面

  3. 在insert.html页面中添加三个文本框和一个添加按钮, 通过Vue对页面内容进行管理,此时需要把之前工程中的js文件夹复制到新工程, 当点击添加按钮时向/insert地址发出异步post请求把用户输入的商品信息提交

  4. 创建controller.ProductController 添加insert方法处理/insert请求 创建Product实体类 在insert方法中声明用来接收传递过来的参数(此参数需要通过@RequestBody注解进行修饰

  5. 创建ProductMapper 在里面添加insert方法通过@Insert注解修饰

  6. 在Controller中将ProductMapper装配进来, 在insert方法中调用mapper的insert方法把接收到的Product对象传递过去

商品管理商品列表步骤:

  1. 在index.html页面中添加商品列表超链接 请求地址为/list.html页面

  2. 创建list.html页面, 在页面中添加表格,并且通过Vue进行管理,在Vue的created方法中发出异步的get请求,把请求回来的数据交给一个数组变量, 然后让页面中表格的内容和数据变量进行绑定, 当数组有值时页面会自动显示数据

  3. 在ProductController中添加select方法 处理/select请求,方法中调用mapper的select方法 把得到的List集合直接返回给客户端

  4. 实现 mapper里面的select方法

商品管理删除商品步骤:

  1. 在商品列表页面中添加删除的超链接 ,废掉超链接的跳转功能添加点击事件,调用del方法, 在方法中向/delete发出异步get请求并且把商品的id传递过去

  2. 在ProductController中 添加delete方法处理/delete请求在方法中调用mapper的deleteById方法把接收到的id传递进去

  3. 实现mapper里面的deleteById方法

商品管理修改商品步骤:

  1. 给列表页面添加 修改超链接 往/update.html页面跳转 并且传递过去商品id

  2. 创建update.html页面 在Vue的created方法中得到传递过来的id 然后向/selectById 发出异步的get请求 把id传递过去 把服务返回的数据用一个product对象接收, 并且页面内容和此对象进行绑定 这样对象有值页面就能跟着显示

  3. 在ProductController里面添加selectById方法 处理/selectById请求, 在方法中调用Mapper的selectById方法

  4. 实现mapper里面的selectById方法

  5. 给update.html页面中的修改按钮添加点击事件, 点击时向/update地址发出异步的post请求把商品的信息一起提交

  6. 在ProductController里面添加update方法处理/update请求,在方法中掉用mapper的update方法

  7. 实现mapper里面的update方法 .

day05

微博练习步骤

  1. 创建boot5-1工程 3个打钩

  2. 配置文件中添加以下内容(empdb改成weibo) ,并启动工程检查是否能够成功运行

spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/weibo?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false

spring.servlet.multipart.max-file-size=10MB
  1. 创建数据库和表

create database weibo charset=utf8; use weibo; create table user(id int primary key auto_increment,username varchar(50),password varchar(50),nick varchar(50))charset=utf8;

  1. 在工程中添加首页index.html 在工程中添加js和css文件夹(从4-2工程中复制),添加完之后 Buil->ReBuild

  2. 创建微博表

use weibo;

create table weibo(id int primary key auto_increment,content varchar(100),url varchar(255),nick varchar(50),created timestamp,user_id int)charset=utf8;

会话管理

  • 客户端和服务器之间进行数据传输遵循的是HTTP协议,此协议属于无状态协议(一次请求对应一次响应,响应完之后链接就会断开) 服务器是无法跟踪客户端的请求.通过Cookie服务器可以给客户端添加一个标识,当客户端再次发出请求时会带着这个Cookie这样服务器就能识别此客户端了, 但是由于Cookie是保存在客户端的存在被篡改的风险,Session的出现解决了此问题

  • Cookie: 打孔式会员卡, 数据保存在客户端

    • 只能保存字符串数据

    • 默认数据是保存在浏览器内存中,当会话结束(浏览器关闭)数据会删除, 也可以设置自定义的保存时长,设置完之后数据会保存在磁盘中时间到了之后清除.

    • 应用场景: 需要长时间保存的数据,比如:记住用户名和密码

  • Session:相当于银行卡, 数据保存在服务器内存中(工程重新启动会清空所有Session)

    • 可以保存任意对象类型的数据

    • 默认数据只能保存半小时左右,而且不建议修改保存时长,因为数据是保存在服务器的内存中的, 服务器只有一个所以不能占用太多的内存.

    • 应用场景: 保存登录状态,涉及敏感数据,因为数据保存在服务器会更安全

image.png

如何通过Session对象记住登录状态

  1. 在登录成功时把当前客户端登录的user用户对象保存到当前客户端所对应的Session对象里面,

  2. 每个客户端进入到首页index.html时会立即发请求获取当前客户端登录的用户对象, 服务器接收到请求后会从当前客户端所对应的Session对象里面获取曾经保存过的用户对象(前提是登陆过),如果没有登录直接获取得到的是null返回给客户端,此时客户端得到的是""空字符串, 客户端判断是否是空字符来表示是否登录过, 通过给isLogin赋值true或false来控制页面显示的内容

Day06

上传图片注意事项

  1. 在application.properties里面填写最大上传文件大小的配置信息

image.png

  1. 在application.properties里面填写配置静态资源文件夹的信息

image.png

酷鲨商城项目步骤:

  1. 创建coolshark项目, 打3个勾

  2. 从上一个工程中复制application.propertise 里面所有内容到新工程,然后停掉之前工程 运行新工程测试是否能够正常启动(如果不能启动 删除工程重新创)

  3. 把讲前端时做好的页面添加到工程中, 3个文件夹和4个页面, 添加完之后Rebuild工程 , 然后运行工程访问首页检查是否正常显示

  4. 修改application.propertise里面数据库的名字为cs

image.png
5. 建库建表

create database cs charset=utf8; use cs; create table user(id int primary key auto_increment,username varchar(50),password varchar(50),nick varchar(50))charset=utf8;

insert into user values(null,'admin','123456','管理员');

登录功能步骤:

  1. 修改登录页面 给按钮添加点击事件, 点击时向/login发出请求

  2. 创建UserController 添加login方法处理/login请求

  3. 创建User实体类

  4. 创建UserMapper 添加 登录相关方法

首页分类展示功能步骤:

  1. 创建表和准备数据

create table category(id int primary key auto_increment,name varchar(50))charset=utf8;

insert into category values(null,"男装"),(null,"女装"),(null,"医药"),(null,"美食"),(null,"百货"),(null,"数码");

b. 创建Category实体类

c. 创建CategoryMapper,里面提供select方法

d. 创建CategoryController 里面添加select方法处理/category/selec

e. 在首页index.html页面中的created方法中向/category/select发出请求获取所有分类信息, 把查询到的数据赋值给一个数组变量 , 让页面中显示分类的地方 和数组进行绑定 通过v-for指令显示出所有分类信息

首页轮播图展示步骤:

1.创建保存轮播图的表和轮播图数据

a.创建保存轮播图的表和轮播图数据

create table banner(id int primary key auto_increment,url varchar(255))charset=utf8;

insert into banner values(null,'/imgs/b1.jpg'),(null,'/imgs/b2.jpg'),(null,'/imgs/b3.jpg'),(null,'/imgs/b4.jpg');

b. 在首页index.html页面中的created方法里面向/banner/select发出请求把得到的数据赋值给vue里面的bannerArr数组

//发出请求获取所有轮播图信息
axios.get("/banner/select").then(function (response){
    v.bannerArr = response.data
})

c. 创建BannerController 添加select方法处理/banner/select请求

@RestController
public class BannerController {
    @Autowired
    BannerMapper mapper;

    @RequestMapping("/banner/select")
    public List<Banner> select(){
        return mapper.select();
    }
}

d. 创建Banner实体类

public class Banner {
    private Integer id;
    private String url;

e. 创建BannerMapper 里面提供select方法

@Mapper
public interface BannerMapper {
    @Select("select * from banner")
    List<Banner> select();
}

后台管理页面分类管理步骤

  1. 在admin.html页面中先引入 axios框架

  2. 在页面中添加created方法 在里面向/category/select发请求获取所有分类数据, 把得到的数据赋值给categoryArr数组,页面会自动展示 image.png

  3. 给删除添加点击事件调用categoryDelete方法,参考Web阶段day07的员工列表练习 image.png

  4. 在方法中向/category/delete发出请求并且把分类的id传递过去 image.png

  5. 在CategoryController中添加delete方法 处理/category/delete请求,方法中调用mapper里面的deleteById方法 image.png

  6. 实现mapper里面的deleteById方法

image.png

添加分类步骤:

  1. 在点击添加分类时弹出文本输入框 image.png
  2. 在then方法里面 向/category/insert发出异步请求 把分类的名称拼接到请求地址的后面 image.png
  3. CategoryController里面创建insert方法处理/category/insert, 在参数列表中声明Category对象 用来接受传递过来的参数,调用mapper里面的insert方法 image.png
  4. 实现CategoryMapper里面的insert方法

管理页面轮播图展示

  1. 在admin.html页面中的created方法中 向/banner/select发出请求获取所有轮播图数据 把请求到的数据赋值给bannerArr数组,页面即可显示正确数据 image.png

删除轮播图

  1. 在admin.html页面中给删除按钮添加点击事件调用bannerDelete方法 image.png
  2. 在方法中发出删除请求 image.png
  3. 在BannerController中添加delete方法处理/banner/delete请求 方法中调用mapper的deleteById方法

image.png

  1. 实现mapper中的deleteById方法 image.png

网站图标ico

  • 在工程的static里面他添加favicon.ico图片文件

删除轮播图同时删除文件

image.png

添加轮播图

  1. 在admin.html中添加跳转页面的代码 image.png

  2. 从微博练习中把insert.html页面复制到新工程中 改名为insertBanner.html, 把微博练习中的UploadController复制到新工程的controller包里面

  3. 修改insertBanner.html页面 发请求的地址改成了/banner/insert

  4. 在BannerController里面添加insert方法 处理/banner/insert,方法中调用mapper的insert方法 把banner的数据保存到数据库中 image.png

  5. 实现mapper里面的banner方法

image.png

添加商品步骤:

  1. 建表
    use cs;
    create table product(id int primary key auto_increment,title varchar(100),url varchar(255),price double(10,2),old_price double(10,2),view_count int,sale_count int,created timestamp, category_id int)charset=utf8;

  2. 创建添加商品的页面insertProduct.html

  3. 修改admin.html页面中点击添加商品侧边栏时 操作的代码

  4. 在insertProduct.html页面中添加created方法,在方法中向/category/select发请求 得到所有的分类信息 赋值给Vue里面的categoryArr数组

  5. 遍历categoryArr数组 在下拉选中添加显示的分类

  6. 点击发布按钮时请求的地址改为/product/insert image.png

  7. 在ProductController中 处理/product/insert请求 方法中调用mapper的insert方法 image.png

  8. 创建ProductMapper实现insert方法 image.png

管理页面商品列表展示功能

  1. 在admin.html页面中的created方法里面 向/product/select发出请求 把查询到的数据给到productArr数组 image.png
  2. 在ProductController里面添加select方法 处理/product/select请求, 在方法中调用mapper的select方法 image.png
  3. 实现mapper里面的select方法 image.png

删除商品步骤: 整体流程参考删除轮播图

  1. 在admin.html页面中修改点击删除时调用的方法 把handleDelete改成productDelete image.png
  2. 在methods里面添加productDelete方法,在方法中向/product/delete发出请求 同时把商品的id传递过去 image.png
  3. 在ProductController中添加delete方法处理/product/delete请求,方法中先通过id查询到商品图片的url,然后得到商品图片的完整路径 删除图片文件, 然后在调用mapper的deleteById方法 image.png
  4. 实现mapper里面deleteById方法 image.png

首页展示商品步骤:

  1. 在index.html页面的created方法中向/product/select/index发出请求,把得到的数据赋值给productArr数组 image.png
  2. 在ProductController中添加selectIndex方法处理/product/select/index请求, 在方法中调用mapper的selectIndex方法 image.png
  3. 在mapper中实现selectIndex方法(首页展示什么则查询什么) image.png

排行榜步骤:

  1. 在首页created方法里面 向/product/select/top发出请求 把得到的数据赋值给topArr数组 image.png
  2. 在ProductController里面添加selectTop处理/product/select/top请求,在处理请求的方法中调用mapper的selectTop方法 image.png
  3. 在Mapper里面实现selectTop方法, 查询数据时按照销量排序并且只查询6条数据 image.png
  4. 在index.html页面中查询到数据的时候如果长度超过3个字符则变成前三个字符+... 非常漂亮的上衣 非常漂... 处理代码写在ProductController中的selectTop方法中 image.png

在application.properties里面配置自定义的值

image.png

image.png

点击分类查看分类下的商品

  1. 复制index.html页面 改名为result.html页面, 把新页面中的轮播图和排行榜删除

  2. 在index.html页面点击某个分类的时候跳转到result.html页面并且把分类的id传递过来 image.png

  3. 在result.html页面的created方法中,之前请求所有商品,现在改成请求某个分类下的商品 image.png

  4. 在ProductController中创建selectByCid方法 处理/product/select/category请求, 方法中调用mapper的selectByCid方法

  5. 实现mapper里面的selectByCid方法

day08

搜索功能步骤:

  1. 让搜索框和某个变量进行双向绑定,给搜索按钮添加点击事件 image.png
  2. 点击时跳转到结果页面 并且把需要搜索的关键字传递过去 image.png
  3. 在结果页面的created方法中 取出wd 然后发出搜索请求 image.png
  4. 在ProductController中添加search方法处理/search请求, 方法中调用mapper的selectByWd方法 image.png
  5. 实现mapper里面的selectByWd方法(需要用到模糊查询) image.png
  6. 回车搜索功能 image.png

结果页面的搜索功能

  1. 给结果页面的文本框双向绑定wd 给文本框添加回车键按下事件 并且给搜索按钮添加点击事件 两个事件都调用search方法 image.png
  2. 在methods里面实现search方法, 在方法中向/search发出请求把搜索的关键字传递过去,把查询到的数据赋值给productArr数组即可 image.png

商品详情页面

  1. 给首页和结果页的商品添加点击跳转功能,并把商品的id传递过去 image.png

  2. 在detail.html详情页面的created方法中得到地址栏中传递过来的商品id,然后向/product/selectById?id=xxx 发出请求 把查询到的一个商品的信息赋值给Vue里面的product对象 image.png

  3. 在页面中把product对象里面的数据展示到标签里面

  4. 在ProductController里面添加selectById方法处理/product/selectById请求,在方法中调用mapper的selectById方法 image.png

  5. 实现mapper里面的selectById方法 image.png

浏览量

image.png

image.png

当浏览量发生改变发布时间跟着改变的原因

  • 大部分MySQL数据库软件timestamp字段的默认效果是当表中任何一个字段的值发生改变时timestamp字段会自动变为当前的系统时间
  • 关闭自动更新

alter table product change created created timestamp not null default current_timestamp;

  • 打开自动更新

alter table product change created created timestamp not null default current_timestamp on update current_timestamp;

后台管理页面显示当前登录的用户信息

  1. 在登录成功时把用户对象保存到Session会话对象中 image.png
  2. 在admin.html页面中的created方法中 向/currentUser地址发请求获取当前登录的用户对象并且把对象赋值给Vue里面的user,如果没有得到当前登录的用户对象代表未登录状态跳转到登录页面 image.png
  3. 在UserController中处理/currentUser请求 从Session对象中获取当前登录的用户对象并返回

image.png

退出登录步骤:

  1. 给退出登录超链接添加点击事件,在事件方法中发出退出登录请求 image.png
  2. 在UserController里面处理该请求 image.png

过滤器Filter

image.png

  • 作用: 过滤器里面的代码会在执行Controller代码之前和执行完Controller代码之后执行, 这样的话可以将多个Controller中重复的操作写在过滤器里面,这样可以起到代码重用的作用

  • 如何使用过滤器?

  1. 创建Filter类文件
@WebFilter(filterName = "MyFilter",urlPatterns = {"/insertProduct.html","/admin.html"})
public class MyFilter implements Filter {
    //当过滤器销毁时执行的方法
    public void destroy() {
    }
    //当接收到请求时会执行此方法,需要在此方法中进行判断 是否允许访问Controller或静态资源文件
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //将父类类型转换成子类类型
        HttpServletRequest st = (HttpServletRequest) req;
        HttpServletResponse se = (HttpServletResponse) resp;
        //得到会话对象
        HttpSession session = st.getSession();
        //从会话对象中得到登录成功时保存的用户对象
        User user = (User) session.getAttribute("user");
        if (user!=null){//代表登录过
            chain.doFilter(req, resp);//放行 允许访问资源
        }else{//代表未登录
            se.sendRedirect("/login.html"); //重定向 让客户端重新向指定的地址发出请求
        }
        System.out.println("过滤器执行了");
    }
    //当过滤器初始化时执行的方法
    public void init(FilterConfig config) throws ServletException {

    }

}
  1. 在XXXXApplication.java文件中添加注解

image.png

urlPatterns的配置方式

  1. 精确匹配 /admin.html /insertProduct.html

  2. 后缀匹配 *.jpg *.png *.html

  3. 路径匹配: /product/* /user/*

  4. 全部匹配: /* (客户端发出的所有请求都会被过滤器拦截)

工作中查询数据时不推荐使用*

因为表字段有修改的可能,如果原表只有2个字段,某个地方只需要2个字段的数据

此时写号没有问题, 但是如果增加的新的需求需要改动原表的字段改成5个字段, 那么之前只需要查询两个字段的地方由于使用的是也会变成查询5个字段的数据但是多查询的3个字段数据是没有用的这样就造成了网络资源的浪费.

删除分类时删除商品

  1. 在CategoryController的delete方法中调用商品Mapper里面的通过分类id删除的方法 image.png
  2. 实现ProductMapper里面的通过分类id删除的方法 image.png

表设计之权限管理

  • 任何网站中只要是存在权限管理的需求,表格都是设计成5张表,其中三张主表(用户表,角色表,权限表) 两张关系表(用户-角色关系表, 角色权限关系表)

  • 创建三张主表

create database lastdb charset=utf8;

use lastdb;

create table user(id int primary key auto_increment,name varchar(50))charset=utf8;

create table role(id int primary key auto_increment,name varchar(50))charset=utf8;

create table module(id int primary key auto_increment,name varchar(50))charset=utf8;

  • 创建两张关系表

用户角色关系表:create table u_r(uid int,rid int);

角色权限关系表:create table r_m(rid int,mid int);

  • 准备数据

insert into user values(null,'刘德华'),(null,'王菲');

insert into role values(null,'男游客'),(null,'女会员');

insert into module values(null,'男浏览'),(null,'男发帖'),(null,'女浏览'),(null,'女发帖');

  • 建立关系

刘德华->男游客和女会员 王菲->女会员

男游客->男浏览, 女会员->女浏览,女发帖

insert into u_r values(1,1),(1,2),(2,2);

insert into r_m values(1,1),(2,3),(2,4);

权限管理关联查询相关练习题

  1. 查询刘德华有哪些角色?

select r.name

from user u join u_r ur on u.id=ur.uid

join role r on r.id=ur.rid where u.name="刘德华";

  1. 查询女会员这个角色对应的用户都有谁?

select u.name

from user u join u_r ur on u.id=ur.uid

join role r on r.id=ur.rid where r.name="女会员";

  1. 查询男游客这个角色拥有什么权限?

select m.name

from role r join r_m rm on r.id=rm.rid

join module m on rm.mid=m.id where r.name="男游客";

  1. 查询女会员这个角色拥有什么权限?

select m.name

from role r join r_m rm on r.id=rm.rid

join module m on rm.mid=m.id where r.name="女会员";

  1. 查询刘德华这个用户拥有什么权限?

select m.name

from user u join u_r ur on u.id=ur.uid

join r_m rm on ur.rid=rm.rid

join module m on m.id=rm.mid

where u.name="刘德华";

  1. 查询拥有女发帖这个权限的用户都有谁?

select u.name

from user u join u_r ur on u.id=ur.uid

join r_m rm on ur.rid=rm.rid

join module m on m.id=rm.mid

where m.name="女发帖";

SpringBoot常见错误列表:

解决问题的思路:

a. 检查页面中是否报错,在浏览器中按F12 查看console控制台的报错, 此时可能会得到前端的错误提示信息和后端相关的错误码(404,500,400),

b. 查看idea控制台里面的报错

c. 如果页面中没有展示出数据可以通过浏览器直接向异步请求的地址发出请求,检查是否得到了数据,如果浏览器中显示了JSON格式的数据说明服务器正常返回了数据此时Controller和Mapper是没有问题的,说明此时出错的是页面, 如果说没有数据代表服务器的问题检查Controller和Mapper相关的代码

d. 万能解决方案: 有正确代码的前提下, 实现一个功能总共设计到三部分代码:VCM, 从正确的代码中按照VCM划分三部分,替换一部分后立即测试看问题是否解决,如果没有解决继续替换其它部分,如果解决了那么错误的范围已经确定好, ctrl+z撤销回来检查具体出错的位置

e. 代码全部正确(前提是已经用老师代码替换过) 还有错:

i.  刷新mave+Rebuild工程+重启工程

ii.  检查数据库中的表是否有错

iii.  检查application.properties配置文件是否有错

iv.  重启idea测试 有时idea会莫名出错
  1. 浏览器中显示400状态码, 是传参出错, 比如接收参数的类型是数值类型,测试时传递过去一个字符串内容,这时会报400错误

  2. 浏览器中显示404状态码

  • 404代表找不到资源

    • 找不到静态资源: 比如 *.html *.jpg *.xxx

      • 检查浏览器请求路径是否正确

      • 检查文件是否保存在了正确的位置(一般放在static文件夹下面)

      • 如果上面两种情况都没有问题,重新编译工程并重启工程 Build->ReBuild

    • 找不到动态资源: 比如 /hello 由controller处理的路径称为动态资源

      • 检查浏览器请求路径是否正确

      • 检查Controller是否创建在了工程自带的包的里面

      • 检查是否在Controller类里面的类名上面添加@Controller注解

      • 检查Controller里面RequestMapping注解中处理的路径是否正确

      • 如果上面两种情况都没有问题,重新编译工程并重启工程 Build->ReBuild

  1. 浏览器显示500状态码
  • 500代表服务器执行错误, 此时第一时间查看idea控制台的错误,里面会有错误相关的提示,根据提示信息再分析具体哪里错了.
  1. Controller中处理了相同的路径 image.png
  2. 创建完包含Mybatis框架的工程直接运行时会报以下错误,需要在application.properties配置文件中添加以下内容
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/empdb?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false

image.png
5. 查询单个对象的信息时查询结果中包含了多个结果会报以下错误 image.png
6. 在Vue对象实例化之前访问对象报错, 目前我们接触到的写代码的位置只有created方法中是实例化过程中的方法,在此方法中访问Vue对象需要用this而不是变量名v, 如果使用v则会在浏览器控制台中报以下错误

image.png

如果上传的图片不显示按照以下步骤检查:

a. 检查文件是否保存到了指定的文件夹

b. 检查数据库里面保存的图片路径是否正确 和文件夹中图片名是否一致

c. 检查配置的静态资源文件夹是否成功(往文件夹中放一张文件名比较简单的图片, 通过localhost:8080/图片名 访问)

d. 在页面中图片标签上面右键检查 查看图片的路径是否正常