• 【平台开发】— 6.从[登录]看前后端交互


    上次了解到了后端代码的大概分层,作用都是干嘛的。那今天就结合着前端,一起看下它们是怎么交互的。 其实简单来讲,就是前端把数据传递给后端,后端拿到数据后一通处理再返回给前端。

    一、登录功能

    前面提到的前端模板vue-admin-template,在本地run起来后,其实就可以看出一些端倪。 打开登录页后,按下F12,点击到network下,再点击登录按钮。

    可以看到有2个请求:

    • login
    • info

    其中,login接口的返回中,有一个token值。 而在info接口的请求参数中,带有这个token值。 这就是常见的登录了,后端验证用户名密码是否存在,存在的话返回一个token值给用户,那此用户后面的请求都需要带上这个token值。

    不过这个前端框架run起来里的数据,都是通过mock模拟返回的,路径如图所示: 那其实一个道理,我在后端实现同样的返回给前端处理不就可以了嘛?

    二、登录-后端

    根据前面讲过的后端代码分层,我这里直接贴上代码:

    1.实体类User

    @Entity
    @Table(name = "user")
    @JsonIgnoreProperties({"handler", "hibernateLazyInitializer"})
    @Data
    public class User {
        @Id //声明一个字段“id”为数据库表的主键
        @GeneratedValue(strategy = GenerationType.AUTO) //标注主键的生成策略,通过strategy 属性指定
        @Column(name = "id") //被标注字段在数据库表中所对应字段的名称
        private int id; //用户id
        private String username; //用户名称
        private String password; //密码
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
        private Date createTime; //创建时间
    }
    

    2.DAO类UserDAO

    /**
     * UserDAO类继承JpaRepository,就提供了CRUD和分页 的各种常见功能。
     * JpaRepository<User, Integer>,参数分别是实体类,和这个实体类id的类型。
     */
    public interface UserDAO extends JpaRepository<User, Integer> {
    
    }
    

    3.Service层UserService

    这里的isUserExist方法就是用来判断输入的用户名密码是否可以查询到。 并且我在数据库里已经手动的插入了用户名“admin”``密码“111111”的数据。

    @Service //标记这是一个service类
    public class UserService {
        @Autowired //自动装配UserDAO对象
        UserDAO userDAO;
    
        /**
         * 判断用户是否存在,存在则返回true,不存在则返回false
         * @param username 用户名
         * @param password 用户密码
         * @return true,false
         */
        public boolean isUserExist(String username, String password) {
            List<User> userList = userList();
            boolean isExist = false;
            for (User user: userList) {
                if (user.getUsername().equals(username) && user.getPassword().equals(password)) {
                    isExist = true;
                }
            }
            return isExist;
        }
    }
    

    4.Controller类UserController

    这里就是调用了userService.isUserExist()判断用户是否在数据库的user表里. 存在的话,就返回一个code:20000 和一个写死的tokenadmin-token; 不存在的话就返回code :50000和一个错误信息“msg”

    @RestController //标记这是控制器,下面每个方法的返回值都会直接转换成json数据格式
    @RequestMapping("user")
    public class UserController {
        @Autowired //自动装配 CategoryService
        UserService userService;
    
        @PostMapping("/login")
        public Map<String, Object> login(@RequestBody JSONObject data) throws Exception {
            String username = JSONPath.eval(data,"$.username").toString();
            String password = JSONPath.eval(data,"$.password").toString();
            Map<String, Object> result = new HashMap<>();
            Map<String, Object> userToken = new HashMap<>();
            Map<String, Object> msg = new HashMap<>();
            if (userService.isUserExist(username, password)) {
                userToken.put("token","admin-token");
                result.put("code", 20000);
                result.put("data", userToken);
            } else {
                msg.put("msg", "用户或密码错误");
                result.put("code", 50000);
                result.put("data", msg);
            }
            return result;
        }
    

    三、登录-前端

    1. api目录下的user.js

    看过这个前端框架介绍你就知道了,要请求的后端API都是在这里写的,模块你自己分,好维护就行。 这里我的后端接口url就是/my_platform/user/login。 这个接口请求要提交的参数是usernamepassword

    import request from '@/utils/request'
    
    export function login(username, password) {
      return request({
        url: '/my_platform/user/login',
        method: 'post',
        data: { // 提交的数据
          username,
          password
        }
      })
    }
    

    2. store目录下的/modules/user.js

    这里代码比较多,我只贴改动的地方。那就是actions里的login方法。 里面的login方法就是调用了上面api模块下的login ,其他地方的代码暂时未动,以实现本章目标为主。

      login({ commit }, userInfo) { //定义 login 方法,在组件中使用 this.$store.dispatch() 调用
        const username = userInfo.username.trim()
        const password = userInfo.password
        return new Promise((resolve, reject) => {
          login(username, password).then(response => { //使用 login 接口进行网络请求
            const { data } = response
            commit('SET_TOKEN', data.token)
            setToken(data.token)
            resolve()
          }).catch(error => {
            reject(error)
          })
        })
      } 
    

    3. views目录下的/login/index.vue

    上面template和下面style都没动,中间script 是重点。 其中,我注释掉了一些代码,因为这是项目里demo用的演示,必须用户名填admin。 但是我的目的是只要是数据库里有的,就可以登录,所以不要这个前端验证。

    <script>
      import { validUsername } from '@/utils/validate'
      import { login } from '@/api/user'
    
      export default {
        name: 'Login',
        data() {
          // const validateUsername = (rule, value, callback) => {
          //   if (!validUsername(value)) {
          //     callback(new Error('Please enter the correct user name'))
          //   } else {
          //     callback()
          //   }
          // };
          // const validatePassword = (rule, value, callback) => {
          //   if (value.length < 6) {
          //     callback(new Error('The password can not be less than 6 digits'))
          //   } else {
          //     callback()
          //   }
          // };
          return {
            loginForm: {
              username: '',
              password: ''
            },
            // loginRules: {
            //   username: [{ required: true, trigger: 'blur', validator: validateUsername }],
            //   password: [{ required: true, trigger: 'blur', validator: validatePassword }]
            // },
            loading: false,
            passwordType: 'password',
            redirect: undefined
          }
        },
        watch: {
          $route: {
            handler: function(route) {
              this.redirect = route.query && route.query.redirect
            },
            immediate: true
          }
        },
    
        methods: {
          showPwd() {
            if (this.passwordType === 'password') {
              this.passwordType = ''
            } else {
              this.passwordType = 'password'
            }
            this.$nextTick(() => {
              this.$refs.password.focus()
            })
          },
          handleLogin() {
            this.$refs.loginForm.validate(valid => {
              if (valid) {
                this.loading = true
                this.$store.dispatch('user/login', this.loginForm).then(() => {
                  this.$router.push({ path: this.redirect || '/' })
                  this.loading = false
                }).catch(() => {
                  this.loading = false
                })
              } else {
                console.log('error submit!!');
                return false
              }
            })
          }
        }
      }
    
    </script>
    

    handleLogin()就是对于登录的处理了, $store.dispatch会调用 /modules/user.js里的login()

    四、验证登录功能

    终于到了验证时刻了,我已经在数据库user表里添加了其他用户,所以我输入正确的用户名和密码就可以登录。

    登录成功。

    当然了,不管是前端还是后端代码,我知道都埋了很多坑,也写的不规范,但是目前处于初级阶段,一步步来。 有错误的地方,也欢迎各位指出,谢谢!

  • 相关阅读:
    c语言 11
    c语言中atoi、atol、atof函数,字符串转换函数
    c语言中strncmp函数,函数原型,头文件
    c语言中strcmp函数, 函数原型、头文件
    c语言中strncat函数、函数原型、头文件
    c语言中strcat函数,函数原型、头文件
    c语言中strncp函数,函数原型、头文件
    c语言中strcpy函数,函数原型、头文件
    c语言 11-6
    tyvj2059 元芳看电影
  • 原文地址:https://www.cnblogs.com/pingguo-softwaretesting/p/13347318.html
Copyright © 2020-2023  润新知