day54(微博练习步骤:注册登陆,上传发表,内容保存到weibo数据库,会话管理,Session对象)

day54(微博练习步骤:注册登陆,上传发表,内容保存到weibo数据库,会话管理,Session对象)

1.微博练习步骤

  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;

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

  3. 创建微博表

    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;

2.注册登陆项目流程:

1.首页

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>Title</title>
</head>
<body>
<h1>微博首页</h1>
<div>

   <div v-if="isLogin">
       <p>欢迎{{user.nick}}回来</p>
       <a href="insert.html">发布微博</a>
       <a href="javascript:void(0)" @click="logout()">登出</a>
   </div>
   <div v-else>
       <a href="/reg.html">注册</a>
       <a href="/login.html">登陆</a>
   </div>
</div>
<script src="js/vue.js"></script>
<script src="js/axios.min.js"></script>
<script>
   let v = new Vue({
       el: "body>div",
       data: {
           isLogin: false,
           user: {
               nick: "刘德华"
          }
      },
       created: function () {
           axios.get("/currentUser").then(function (response) {
               v.user = response.data;
               //如果当前客户端没有登陆的话得到的是空字符串“”
               //如果是空字符串代表还没有登陆isLogin为false,如果不是空字符串代表登陆过
               v.isLogin = v.user == "" ? false : true;
          })
      },
       methods:{
           logout(){
           //   发出退出登陆的请求
               axios.get("/logout").then(function (response) {
                   location.reload();//刷新页面
              })
          }
      }

  })
</script>
</body>
</html>

2.注册

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>Title</title>
</head>
<body>
<h1>注册页面</h1>
<div>
 <input type="text" v-model="user.username" placeholder="用户名">
 <input type="text" v-model="user.password" placeholder="密码">
 <input type="text" v-model="user.nick" placeholder="昵称">
 <input type="button" value="注册" @click="reg()">

</div>
<script src="js/vue.js"></script>
<script src="js/axios.min.js"></script>
<script>
   let v=new Vue({
       el:"div",
       data:{
           user:{
               username:"",
               password:"",
               nick:""
          }
      },
       methods:{
           reg(){
               axios.post("/reg",v.user).then(function (response) {
                  if (response.data==1){

                      alert("注册成功")
                      location.href="/"
                  }else {
                      alert("用户已存在")
                  }
              })
          }
      }
  })
</script>
</body>
</html>

3.登陆

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>Title</title>
</head>
<body>
<h1>登录页面</h1>
<div>
   <input type="text" v-model="user.username" placeholder="用户名">
   <input type="password" v-model="user.password" placeholder="密码">
   <input type="button" value="登录" @click="login()">
</div>
<script src="js/vue.js"></script>
<script src="js/axios.min.js"></script>
<script>
   let v = new Vue({
       el:"div",
       data:{
           user:{username:"",password:""}
      },

       methods:{
           login(){
               axios.post("/login",v.user).then(function (response) {
                   if (response.data==1){
                       alert("登录成功!");
                       location.href="/";
                  }else if(response.data==2){
                       alert("用户名不存在!");
                  }else{
                       alert("密码错误!");
                  }
              })
          }
      }
  })
</script>
</body>
</html>

4.UserController

package cn.tedu.boot51.controller;


import cn.tedu.boot51.entity.User;
import cn.tedu.boot51.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("/reg")
   public int reg(@RequestBody User user) {

       System.out.println("user = " + user);
       User u = mapper.selectByUsername(user.getUsername());
       if (u != null) {
           return 2;
      }
       mapper.insert(user);
       return 1;
  }

   //   在参数列表里面声明session,即可得到当前客户端所对应的Session
   @RequestMapping("/login")
   public int login(@RequestBody User user, HttpSession session) {
       System.out.println("user = " + user);
       User u = mapper.selectByUsername(user.getUsername());
       if (u != null) {
           if (user.getPassword().equals(u.getPassword())) {
//               把当前登陆的用户对象保存到会话对象中
//               user代表用户输入的信息包括:用户名和密码
//               u代表从数据库中查询到的信息,包括:id,用户名和密码,昵称
               session.setAttribute("user", u);
               return 1;//登录成功
          }
           return 3; //密码错误
      }
       return 2;//用户名不存在
  }

   @RequestMapping("/currentUser")
   public User currentUser(HttpSession session) {
//       从会话对象中得到登陆成功时保存的用户对象
       User u = (User) session.getAttribute("user");
       return u;
  }

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

5.UserMapper

package cn.tedu.boot51.mapper;

import cn.tedu.boot51.entity.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface UserMapper {
   @Select("select * from user where username=#{username}")
   User selectByUsername(String username);

   @Insert("insert into user values(null,#{username},#{password},#{nick})")
   void insert(User user);
}

3.上传发表项目

1.发布微博页面insert.html

<!DOCTYPE html>
<html>
<head>
   <meta charset="UTF-8">
   <!-- import CSS -->
   <link rel="stylesheet" href="css/eui.css">
</head>
<body>
<h1>发布微博页面</h1>
<div id="app">
   <input type="text" v-model="weibo.content" placeholder="说点什么">
<!--    name表示上传时,文件的参数名  limit="1" 设置只能选择一张图片-->
   <el-upload
           action="/upload"
           name="picFile"
          :limit="1"
           list-type="picture-card"
          :on-preview="handlePictureCardPreview"
          :on-success="handleSuccess"
          :on-remove="handleRemove">
       <i class="el-icon-plus"></i>
   </el-upload>
   <el-dialog :visible.sync="dialogVisible">
       <img width="100%" :src="dialogImageUrl" alt="">
   </el-dialog>
   <input type="button" value="发布微博" @click="insert()">
</div>
</body>
<!-- import Vue before Element -->
<script src="js/vue.js"></script>
<!-- import JavaScript -->
<script src="js/eui.js"></script>
<script src="js/axios.min.js"></script>

<script>
   let v = new Vue({
       el: '#app',
       data: function () {
           return {
               dialogImageUrl: '',
               dialogVisible: false,
               weibo:{
                   content:"",
                   url:""
              }
          }
      },
       methods: {
           handleRemove(file, fileList) {
               console.log(file, fileList);
               //当点击删除图片时方法会执行
               //file代表要删除的文件
               //file.response代表文件上传成功时 服务器响应的数据(文件名)
               console.log("文件名="+file.response);
               //http://localhost:8080/remove?name=xxx.jpg
               axios.get("/remove?name="+file.response).then(function (response) {
                   console.log("服务器图片已经删除")
              })
          },
           handlePictureCardPreview(file) {
               this.dialogImageUrl = file.url;
               this.dialogVisible = true;
          },
           insert(){
               //得到用户输入的微博文本内容和图片名 一起提交给服务器
               if (v.weibo.content.trim()==""||v.weibo.url==""){
                   alert("微博内容或图片不能为空!")
                   return;
              }
               axios.post("/insert",v.weibo).then(function (response) {
                   if (response.data==1){
                       alert("添加完成!");
                       location.href="/"; //回到首页
                  }else{
                       alert("请先登录!");
                       location.href="/login.html";//显示登录页面
                  }

              })
          },
           handleSuccess(response,file,fileList){
               //response=file.response
               console.log("文件上传完成, 图片名="+response);
               v.weibo.url = response;
          }
      }
  })
</script>

</html>

2.UploadController

package cn.tedu.boot51.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.UUID;

@RestController
public class UploadController {
   @RequestMapping("upload")
   public String upload(MultipartFile picFile) throws IOException {
       System.out.println("picFile=" + picFile);
       //得到文件原始文件名 a.jpg
       String fileName = picFile.getOriginalFilename();
       //得到后缀名 从最后一个.出现的位置截取到最后
       String suffix = fileName.substring(fileName.lastIndexOf("."));
       //得到唯一文件名 UUID.randomUUID()得到一个唯一标识符
       fileName = UUID.randomUUID()+suffix;
       System.out.println("文件名:"+fileName);
       //准备保存图片的文件夹路径
       String dirPath = "D:/files";
       File dirFile = new File(dirPath);
       //如果该文件夹不存在 则创建此文件夹
       if (!dirFile.exists()){
           dirFile.mkdirs();//创建文件夹
      }
//       完整路径
       String filePath = dirPath+"/"+fileName;
       //把文件保存到此路径   异常抛出
       picFile.transferTo(new File(filePath));
       System.out.println("文件保存完成! 请去此路径检查文件是否存在 "+filePath);
       return fileName;

  }

   @RequestMapping("/remove")
   public void remove(String name){
       String filePath = "D:/files/"+name;
       new File(filePath).delete();//删除文件
  }
}

4.内容保存到weibo数据库项目

1.WeiboController

package cn.tedu.boot51.controller;

import cn.tedu.boot51.entity.User;
import cn.tedu.boot51.entity.Weibo;
import cn.tedu.boot51.mapper.WeiboMapper;
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;
import java.util.Date;

@RestController
public class WeiboController {
   @Autowired(required = false)
   WeiboMapper mapper;
   @RequestMapping("/insert")
   public int insert(@RequestBody Weibo weibo, HttpSession session){
//       得到当前的用户对象
       User u=(User) session.getAttribute("user");
       if (u==null){
           return 2;//代表我未登录
      }
//       new Date()得到新的系统时间
       weibo.setCreated(new Date());
//       将当前用户的信息,添加到weibo对象中
       weibo.setUserId(u.getId());
       weibo.setNick(u.getNick());
       System.out.println("weibo:"+weibo);
       mapper.insert(weibo);
       return 1;//代表微博发布成功
  }
}

2.WeiboMapper

package cn.tedu.boot51.mapper;

import cn.tedu.boot51.entity.Weibo;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface WeiboMapper {
   @Insert("insert into weibo values" +
           "(null,#{content},#{url},#{nick},#{created},#{userId})")
   void insert(Weibo weibo);
}

 

 

5.会话管理

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

 

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

    • 只能保存字符串数据

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

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

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

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

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

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

 

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

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

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

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