day57(搜索功能,商品详情,浏览量,后台显示登陆者信息,退出登陆,过滤器Filter,表设计之权限管理及相关练习)

day57(搜索功能,商品详情,浏览量,后台显示登陆者信息,退出登陆,过滤器Filter,表设计之权限管理及相关练习)

1.搜索功能步骤:

  1. 让搜索框和某个变量进行双向绑定,给搜索按钮添加点击事件 index.html

    <!--搜索框开始-->
                       <div style="float: right;margin-top: 15px">
                           <el-input size="mini" @keydown.native.enter="search()" v-model="wd" placeholder="请输入关键字搜索"></el-input>
                           <el-button style="position: absolute;
                           border: 0;right: 0;top: 11px" @click="search()"
                                      icon="el-icon-search"></el-button>
                       </div>
                       <!--搜索框结束-->

     

  2. 点击时跳转到结果页面 并且把需要搜索的关键字传递过去

    search(){
                   //跳转到结果页面并且把搜索的关键字传递过去
                   location.href="/result.html?wd="+v.wd;
              }

     

  3. 在结果页面的created方法中 取出wd 然后发出搜索请求

    else{//包含wd搜索关键字
                   //得到搜索的关键字wd
                   let wd = location.search.split("=")[1];
                   axios.get("/search?wd="+wd).then(function (response) {
                       v.productArr = response.data;
                  })
              }

     

  4. 在ProductController中添加search方法处理/search请求, 方法中调用mapper的selectByWd方法

    //    搜索功能
       @RequestMapping("/search")
       public List<Product> selectByWd(String wd){
           System.out.println("wd = " + wd);
           return mapper.selectByWd(wd);
      }

     

  5. 实现mapper里面的selectByWd方法(需要用到模糊查询)

       //搜索功能:  concat是SQL语句中将多个字符串进行拼接的函数
       @Select("select id,title,url,price,old_price,sale_count from product where title like concat('%',#{wd},'%')")
       @Result(property = "oldPrice", column = "old_price")
       @Result(property = "saleCount", column = "sale_count")
       List<Product> selectByWd(String wd);

     

  6. 回车搜索功能

    <!--搜索框开始-->
                       <div style="float: right;margin-top: 15px">
                           <el-input size="mini" @keydown.native.enter="search()" v-model="wd" placeholder="请输入关键字搜索"></el-input>
                           <el-button style="position: absolute;
                           background-color: rgba(0,0,0,0);border: 0;right: 0;top: 11px" @click="search()"
                                      icon="el-icon-search"></el-button>
                       </div>
                       <!--搜索框结束-->

     

2.结果页面的搜索功能

  1. 给结果页面的文本框双向绑定wd 给文本框添加回车键按下事件 并且给搜索按钮添加点击事件 两个事件都调用search方法

<!--搜索框开始-->
<div style="float: right;margin-top: 15px">
  <el-input size="mini" @keydown.native.enter="search()" v-model="wd" placeholder="请输入关键字搜索"></el-input>
  <el-button style="position: absolute;border: 0;right: 0;top: 11px" @click="search()" icon="el-icon-search"></el-button>
                   </div>
<!--搜索框结束-->
  1. 在methods里面实现search方法, 在方法中向/search发出请求把搜索的关键字传递过去,把查询到的数据赋值给productArr数组即可 :result.html页面

search(){
               axios.get("/search?wd="+v.wd).then(function (response) {
                   v.productArr = response.data;
              })
          }

3.商品详情页面

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

    index.html

     <!--商品列表开始-->
               <el-row :gutter="20">
                   <el-col :span="6" v-for="p in productArr">
                       <el-card>
                           <div>
                               <a :href="'/detail.html?id='+p.id">
                                   <img class="p_img" :src="p.url" width="230" height="230" alt="">
                               </a>
                           </div>
                           <div>
                               <a style="color: #3f3f3f;text-decoration: none"
                                  :href="'/detail.html?id='+p.id">
                                   <p style="font-size: 15px;margin-top: 0;height: 38px">{{p.title}}</p>
                               </a>
                               <div style="color: #6c6c6c">
                                   <span>¥{{p.price}}</span>
                                   <span style="font-size: 12px;
                                   text-decoration: line-through">{{p.oldPrice}}</span>
                                   <span style="float: right">销量:{{p.saleCount}}</span>
                               </div>
                           </div>
                       </el-card>
                   </el-col>
               </el-row>
               <!--商品列表结束-->

    result.html

     <!--商品列表开始-->
               <el-row :gutter="20">
                   <el-col :span="6" v-for="p in productArr">
                       <el-card>
                           <div>
                               <a :href="'/detail.html?id='+p.id">
                                   <img class="p_img" :src="p.url" width="230" height="230" alt="">
                               </a>
                           </div>
                           <div>
                               <a style="color: #3f3f3f;text-decoration: none"
                                  :href="'/detail.html?id='+p.id">
                                   <p style="font-size: 15px;margin-top: 0;height: 38px">{{p.title}}</p>
                               </a>
                               <div style="color: #6c6c6c">
                                   <span>¥{{p.price}}</span>
                                   <span style="font-size: 12px;
                                   text-decoration: line-through">{{p.oldPrice}}</span>
                                   <span style="float: right">销量:{{p.saleCount}}</span>
                               </div>
                           </div>
                       </el-card>
                   </el-col>
               </el-row>
               <!--商品列表结束-->
  2. 在detail.html详情页面的created方法中得到地址栏中传递过来的商品id,然后向/product/selectById?id=xxx 发出请求 把查询到的一个商品的信息赋值给Vue里面的product对象

     //    得到地址栏的商品id
               let id=location.search.split("=")[1];
           //   通过id发请求获取商品数据
               axios.get("/product/selectById?id="+id).then(function (response) {
                   v.product=response.data;
              })
  3. 在页面中把product对象里面的数据展示到标签里面

      <el-main style="width: 1200px;margin: 0 auto">
               <!--商品详情开始-->
               <el-row :gutter="20">
                   <!--将一行划分为两等份 24/2=12-->
                   <el-col :span="12">
                       <el-card>
                           <img :src="product.url" width="100%" alt="">
                       </el-card>
                   </el-col>
                   <el-col :span="12">
                       <p style="font-size: 25px">{{product.title}}</p>
                       <el-divider></el-divider>
                   </el-col>
               </el-row>
               <!--商品详情结束-->
           </el-main>
  4. 在ProductController里面添加selectById方法处理/product/selectById请求,在方法中调用mapper的selectById方法

     //商品详情页面
       @RequestMapping("/product/selectById")
       public Product selectById(int id) {
           return mapper.selectById(id);
      }
  5. 实现mapper里面的selectById方法

    //    商品详情页面
       @Select("select id,title,url,price,old_price,sale_count,created,view_count from product where id=#{id}")
       @Result(property = "oldPrice", column = "old_price")
       @Result(property = "saleCount", column = "sale_count")
       @Result(property = "viewCount", column = "view_count")
       Product selectById(int id);

4.浏览量

//        让浏览量+1
       mapper.updateViewCount(id);
       return mapper.selectById(id);
  }
  //  浏览量+1
   @Update("update product set view_count=view_count+1 where id=#{id} ")
   void updateViewCount(int id);

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

  • 大部分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;

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

  1. 在登录成功时把用户对象保存到Session会话对象中

    package cn.tedu.coolshark.controller;

    import cn.tedu.coolshark.entity.User;
    import cn.tedu.coolshark.mapper.UserMapper;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;

    import javax.servlet.http.HttpSession;

    @RestController
    public class UserController {
       @Autowired(required = false)
       UserMapper mapper;
       @RequestMapping("/login")
       public int login(@RequestBody User user, HttpSession session){
           User u = mapper.selectByUsername(user.getUsername());
           if (u!=null){
               if (u.getPassword().equals(user.getPassword())){
    //               把当前登陆成功的用户对象保存到会话对象中
                   session.setAttribute("user",u);
                   return 1;//登录成功
              }
               return 3;//密码错误
          }
           return 2;//用户名不存在
      }
    }

     

  2. 在admin.html页面中 向/currentUser地址发请求获取当前登录的用户对象并且把对象赋值给Vue里面的user,如果没有得到当前登录的用户对象代表未登录状态跳转到登录页面

          //    获取当前登陆的用户对象
               axios.get("/currentUser").then(function (response) {
                   v.user=response.data;
                   //如果判断为空字符串,则代表未登录
                   if (v.user==null){
                       location.href="/login.html";
                  }
              })
  3. 在UserController中处理/currentUser请求 从Session对象中获取当前登录的用户对象并返回

        @RequestMapping("/currentUser")
       public User currentUser(HttpSession session){
    //       把登陆成功时保存的用户取出,返回给客户端
           return (User) session.getAttribute("user");
      }

7.退出登录步骤:

  1. 给退出登录超链接添加点击事件logout(),在事件方法中发出退出登录请求

    logout(){
                   //退出登陆
                   axios.get("/logout").then(function (response) {
                       location.href="/";//回到首页
                  })
              }

     

  2. 在UserController里面处理该请求

     //退出登陆
       @RequestMapping("/logout")
       public void logout(HttpSession session) {
    //       把登陆成功时保存的用户对象删除
           session.removeAttribute("user");
      }

8.过滤器Filter

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

  • 如何使用过滤器?

    1. 创建Filter类文件

      package cn.tedu.coolshark.filter;

      import cn.tedu.coolshark.entity.User;

      import javax.servlet.*;
      import javax.servlet.annotation.*;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import javax.servlet.http.HttpSession;
      import java.io.IOException;

      @WebFilter(filterName = "MyFilter",urlPatterns = {"/insertProduct.html","/admin.html"})
      public class MyFilter implements Filter {
      //   当过滤器初始化时执行的方法
         public void init(FilterConfig config) throws ServletException {
        }
         //   当过滤器摧毁时执行的方法
         public void destroy() {
        }

         //   当接收到请求时会执行的方法,需要在此方法中进行判断,是否允许访问Controller或静态资源文件
         @Override
         public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
      //       将父类转换为子类类型
             HttpServletRequest st=(HttpServletRequest) request;
             HttpServletResponse se=(HttpServletResponse) response;
             HttpSession session=st.getSession();
             User user=(User) session.getAttribute("user");
             if (user!=null){
      //           代表登陆过
                 chain.doFilter(request, response);//放行,允许访问资源

            }else {
      //           代表未登录
                 se.sendRedirect("/login.html");//重定向 让客户端重新向指定的地址发出请求
            }
             System.out.println("过滤器执行了");
        }
      }
    2. 在XXXXApplication.java文件中添加注解

      package cn.tedu.coolshark;

      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.boot.web.servlet.ServletComponentScan;
      //此注解的作用是在当前类所在的包以及子包下面扫描过滤器
      @ServletComponentScan

      @SpringBootApplication
      public class CoolsharkApplication {

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

      }

9.urlPatterns的配置方式

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

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

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

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

 

10.删除分类时删除商品

  1. 在CategoryController的delete方法中调用商品Mapper里面的通过分类id删除的方法

     @RequestMapping("/category/delete")
       public void delete(int id ){
           System.out.println("删除分类的id = " + id);
           mapper.deleteById(id);
    //       删除和该类相关的商品
           productMapper.deleteByCid(id);
      }

     

  2. 实现ProductMapper里面的通过分类id删除的方法

    // 删除和同分类相关的商品
       @Delete("delete from product where category_id=#{id}")
       void deleteByCid(int id);

 

11.表设计之权限管理

  • 任何网站中只要是存在权限管理的需求,表格都是设计成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,'女发帖')

  • 建立关系

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

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

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

  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 ur.rid=r.id where r.name="女会员";

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

    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 m.id=rm.mid where r.name="女会员";

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

    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 module m join r_m rm on m.id=rm.mid

    join u_r ur on rm.rid=ur.rid

    join user u on u.id=ur.uid where m.name="女发帖";

posted @ 2022-05-19 22:11  约拿小叶  阅读(156)  评论(0编辑  收藏  举报