五分钟写一个VUE结合SpringBoot的单表增删改查带JWT登录功能界面

五分钟写一个VUE结合SpringBoot的单表增删改查带JWT登录功能界面,第1张

首先先准备WebStorm与IDEA

 数据库准备一个简单的表

CREATE TABLE `sys_user` (
  `id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
  `username` char(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '用户名',
  `password` char(16) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '密码',
  `nickname` char(30) COLLATE utf8mb4_unicode_ci DEFAULT 'NewUser' COMMENT '昵称',
  `email` char(30) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '邮箱',
  `phone` char(11) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '手机号',
  `address` char(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '地址',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_username` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

后端的Mybatis实现一下Mapper

package com.xiejianjun.vueproject.mapper;

import com.xiejianjun.vueproject.dto.Page;
import com.xiejianjun.vueproject.dto.UserDTO;
import com.xiejianjun.vueproject.entities.SysUser;
import org.apache.ibatis.annotations.*;
import org.springframework.stereotype.Repository;

import java.util.List;

@Mapper
@Repository
public interface SysUserMapper {
    @Select("select `id`," +
            "`username`," +
            "`nickname`," +
            "`email`," +
            "`phone`," +
            "`address`" +
            "from sys_user")
    List selectSysUserList();

    @Select("select `id`," +
            "`username`," +
            "`nickname`," +
            "`email`," +
            "`phone`," +
            "`address`" +
            "from sys_user where `id` = #{id}")
    SysUser selectSysUserById(@Param("id") Integer id);

    @Delete("delete from sys_user where `id` = #{id}")
    Integer deleteSysUserById(@Param("id") Integer id);

    Integer updateSysUserById(SysUser user);

    @Insert("insert into sys_user(username,password,nickname,email,phone,address) values(#{username},#{password},#{nickname},#{email},#{phone},#{address})")
    Integer insertSysUser(SysUser user);

    @Select("select `id`,`username`,`nickname`,`email`,`phone`,`address` from sys_user limit #{pageNum},#{pageSize}")
    List getPage(Page page);

    @Select("select count(*) from sys_user")
    Integer SysUserCount();

    @Select("select `id`,`username`,`nickname`,`email`,`phone`,`address` from sys_user where `username`=#{username} and `password`=#{password}")
    SysUser checkUser(UserDTO userDTO);
}

服务层调用一下Mapper,最好都在此处抛出异常

package com.xiejianjun.vueproject.service.impl;

import com.xiejianjun.vueproject.dto.Page;
import com.xiejianjun.vueproject.dto.UserDTO;
import com.xiejianjun.vueproject.exception.MyException;
import com.xiejianjun.vueproject.mapper.SysUserMapper;
import com.xiejianjun.vueproject.service.SysUserService;
import com.xiejianjun.vueproject.util.JWTUtil;
import com.xiejianjun.vueproject.vo.Constants;
import com.xiejianjun.vueproject.entities.SysUser;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class SysUserServiceImpl implements SysUserService {
    @Autowired
    private SysUserMapper sysUserMapper;

    @Override
    public List queryAllSysUser() {
        return sysUserMapper.selectSysUserList();
    }

    @Override
    public SysUser querySysUserById(Integer id) {
        SysUser user = sysUserMapper.selectSysUserById(id);
        if (user == null) {
            throw new MyException(Constants.Code_401.getCode(), "查无此人!");
        }
        return user;
    }

    @Override
    public Integer deleteUserById(Integer id) {
        return sysUserMapper.deleteSysUserById(id);
    }

    @Override
    public Integer updateUserById(SysUser user) {
        return sysUserMapper.updateSysUserById(user);
    }

    @Override
    public Integer addUser(SysUser user) {
        // 最好加一个判断数据库中是否有相同用户,我懒得加
        return sysUserMapper.insertSysUser(user);
    }

    @Override
    public List querySysUserPage(Page page) {
        page.setPageNum((page.getPageNum() - 1) * page.getPageSize());
        return sysUserMapper.getPage(page);
    }

    @Override
    public Integer querySysUserCount() {
        return sysUserMapper.SysUserCount();
    }

    @Override
    public UserDTO GetValidUser(UserDTO userDTO) {

        SysUser sysUser = sysUserMapper.checkUser(userDTO);
        if(sysUser == null) {
            throw new MyException(Constants.Code_500.getCode(), "用户名或密码错误");
        } else {
            Map map = new HashMap<>();
            map.put("id", String.valueOf(sysUser.id));
            map.put("username",sysUser.username);
            map.put("nickname",sysUser.nickname);
            map.put("email",sysUser.email);
            map.put("phone",sysUser.phone);
            map.put("address",sysUser.address);
            String token = JWTUtil.getToken(map);
            BeanUtils.copyProperties(sysUser,userDTO);
            userDTO.setPassword(null);
            userDTO.setToken(token);
        }
        return userDTO;
    }
}

控制器的异常捕获器,利用AOP的思想改变控制层的返回值参数,所以控制层的返回值要与捕获器返回值相同

package com.xiejianjun.vueproject.exception;

import com.xiejianjun.vueproject.vo.Constants;
import com.xiejianjun.vueproject.vo.Result;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.IOException;

@ControllerAdvice
public class MyExceptionHandler {
    @ExceptionHandler(value = MyException.class)
    @ResponseBody
    public Result userResult(MyException e) {
        return new Result(e.getCode(), e.getMessage(), null);
    }

    @ExceptionHandler(value = IOException.class)
    @ResponseBody
    public Result fileResult(IOException e) {
        return new Result(Constants.Code_500.getCode(), e.getMessage(), null);
    }
}

控制层提供一下服务前端的接口

package com.xiejianjun.vueproject.controller;

import com.xiejianjun.vueproject.dto.Page;
import com.xiejianjun.vueproject.dto.UserDTO;
import com.xiejianjun.vueproject.service.SysUserService;
import com.xiejianjun.vueproject.vo.Result;
import com.xiejianjun.vueproject.entities.SysUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/user")
public class SysUserController {
    @Autowired
    private SysUserService sysUserService;

/*    @GetMapping("/")
    public List getUserList() {
        return sysUserService.queryAllSysUser();
    }*/

    @GetMapping("/{id}")
    public Result getUser(@PathVariable("id") Integer id) {
        return Result.success(sysUserService.querySysUserById(id), "查询特定用户成功");
    }

    @PutMapping("/")
    public Result addUser(@RequestBody SysUser user) {
        return Result.success(sysUserService.addUser(user), "增加用户成功");
    }

    @DeleteMapping("/{id}")
    public Result deleteUser(@PathVariable("id") Integer id) {

        return Result.success(sysUserService.deleteUserById(id), "删除用户成功");
    }

    @PostMapping("/")
    public Result updateUser(@RequestBody SysUser user) {

        return Result.success(sysUserService.updateUserById(user), "更新用户成功");
    }

    @GetMapping("/page")
    public Result getUserPage(@RequestParam(
            required = false,
            value = "pageNum",
            defaultValue = "1") Integer pageNum,
                              @RequestParam(
                                      required = false,
                                      name = "pageSize",
                                      defaultValue = "2")
                                      Integer pageSize) {
        Map map = new HashMap<>();
        map.put("pageData", sysUserService.querySysUserPage(new Page(pageNum, pageSize)));
        map.put("total", sysUserService.querySysUserCount());

        return Result.success(map, "请求页数用户成功");
    }

    @PostMapping("/login")
    public Result login(@RequestBody UserDTO userDTO) {
        UserDTO user = sysUserService.GetValidUser(userDTO);
        return Result.success(user, "登录成功");
    }
}

最后把跨域设置一下

package com.xiejianjun.vueproject.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class CorsConfig {
    // 当前跨域请求最大有效时长。这里默认1天
    private static final long MAX_AGE = 24 * 60 * 60;

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*"); // 1 设置访问源地址
        corsConfiguration.addAllowedHeader("*"); // 2 设置访问源请求头
        corsConfiguration.addAllowedMethod("*"); // 3 设置访问源请求方法
        corsConfiguration.setMaxAge(MAX_AGE);
        source.registerCorsConfiguration("/**", corsConfiguration); // 4 对接口配置跨域设置
        return new CorsFilter(source);
    }

}

接下来是VUE的部分

首先打开WebStorm,我默认你已经装好Vue-cli了

随便在一个文件夹下运行vue create "你的项目名称"

选择创建vue2

随后在main.js上引入elementui以及路由插件

import ElementUI from 'element-ui';
// 引入elementUI所有的CSS样式
import 'element-ui/lib/theme-chalk/index.css';
// 引入router
import VueRouter from "vue-router"
import router from "./route";
import request from "@/network/request";


//关闭Vue的生产提示
Vue.config.productionTip = false
// 使用elementUI插件
Vue.use(ElementUI)
Vue.use(VueRouter)


new Vue({
  render: h => h(App),
  router,
  beforeCreate() {
    Vue.prototype.$request = request
  }
}).$mount('#app')

全局的网络过滤器,在请求数据时携带token判断身份信息,服务器响应的数据的msg用elementui打印,并在控制台输出完整信息方便调试

import axios from "axios";
import ElementUI from "element-ui";
const instance = axios.create({
    baseURL: 'http://localhost:8910/',
    timeout: 5000
})

instance.interceptors.request.use(config => {

    let token = window.sessionStorage.getItem('token')
    if (typeof token != "undefined" && token != null && token !== 'undefined'){
        config['headers'].token = JSON.parse(token)
    }
    return config;
},
    err => {
    //
    })

instance.interceptors.response.use(res => {
    console.log(res.data)
    if (res.data.code === '200') {
        ElementUI.Message({
            message: res.data.msg,
            type: "success"
        })
    } else {
        ElementUI.Message({
            message: res.data.msg,
            type: "error"
        })
    }
    return res
})

export default instance




配置一下路由器,只用得到manage,home,user,login,person这五个路由

import VueRouter from "vue-router"

import About from "@/page/About";
import Login from "@/page/Login";
import User from "@/page/User";
import Home from "@/page/Home";
import Manage from "@/page/Manage";
import Person from "@/page/Person";
import MyFile from "@/page/MyFile";

export default new VueRouter({
    routes: [
        {
            path:'/',
            redirect: '/home',
            component: Manage,
            children: [
                {
                    path: 'user',
                    component: User
                },
                {
                    path: 'home',
                    component: Home,
                },
                {
                    path: 'person',
                    component: Person
                },
                {
                    path: 'file',
                    component: MyFile
                }
            ]
        },
        {
            path: '/about',
            component: About
        },
        {
            path: '/login',
            name: 'Login',
            component: Login
        }
    ]
})

App.vue只需要套个路由展示器就好了,什么都不用写





Manage.vue注入到App.vue的routerview标签内,且负责把最新的user信息传递给子组件Header






子路由组件Home.vue简单写一下,之后可以替换个echart图展示






Header.vue 作为manage.vue 的子组件,提供上边栏






Aside.vue 作为Manage.vue的子组件,提供侧边栏






User.vue 作为Manage.vue的子路由,提供用户的增删改查的功能






Person.vue 作为Manage.vue的子路由,提供修改用户个人信息的功能






Login.vue 登录的时候向后端发请求就好了,登陆成功就把用户信息和token放在浏览器的sessionStorage里面,让路由跳回首页,后端的拦截器如果没收到带有token信息的请求头的请求,则会返回无权限访问的Result类型的Json对象






验证token的后端代码,利用拦截器实现

package com.xiejianjun.vueproject.interceptor;

import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.xiejianjun.vueproject.service.SysUserService;
import com.xiejianjun.vueproject.util.JWTUtil;
import com.xiejianjun.vueproject.vo.Constants;
import com.xiejianjun.vueproject.vo.Result;
import jdk.nashorn.internal.ir.debug.JSONWriter;
import org.apache.tomcat.util.json.JSONParser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class MyInterceptor implements HandlerInterceptor {
    @Autowired
    private SysUserService sysUserService;


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        String token = request.getHeader("token");
        String json;
        if (token != null) {
            try{
                Integer validate = Integer.parseInt(JWTUtil.validate(token));
                if (sysUserService.querySysUserById(validate) == null) {
                    json = JSONObject.toJSON(new Result(Constants.Code_401.getCode(), "查无此人", null)).toString();
                    response.setHeader("Content-type", "text/html;charset=UTF-8");
                    response.setCharacterEncoding("utf-8");
                    response.setContentType("text/html;charset=UTF-8");
                    response.getWriter().println(json);
                    return false;
                }
                return true;
            } catch (TokenExpiredException e) {
                json = JSONObject.toJSON(new Result(Constants.Code_401.getCode(), "登录状态过期", null)).toString();
                response.setHeader("Content-type", "text/html;charset=UTF-8");
                response.setCharacterEncoding("utf-8");
                response.setContentType("text/html;charset=UTF-8");
                response.getWriter().println(json);
                return false;
            } catch (SignatureVerificationException e) {
                json = JSONObject.toJSON(new Result(Constants.Code_401.getCode(), "签名不一致", null)).toString();
                response.setHeader("Content-type", "text/html;charset=UTF-8");
                response.setCharacterEncoding("utf-8");
                response.setContentType("text/html;charset=UTF-8");
                response.getWriter().println(json);
                return false;
            } catch (Exception e) {
                json = JSONObject.toJSON(new Result(Constants.Code_401.getCode(), "绷不住了", null)).toString();
                response.setHeader("Content-type", "text/html;charset=UTF-8");
                response.setCharacterEncoding("utf-8");
                response.setContentType("text/html;charset=UTF-8");
                response.getWriter().println(json);
                return false;
            }
        }
        System.out.println("拦截器拦截成功");
        json = JSONObject.toJSON(new Result(Constants.Code_401.getCode(), "无权限访问", null)).toString();
        response.setHeader("Content-type", "text/html;charset=UTF-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().println(json);
        return false;
    }
}

页面展示

 

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/719805.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-25
下一篇 2022-04-25

发表评论

登录后才能评论

评论列表(0条)

保存