jwt redis,微信登陆知识复习 uniapp 请求封装,统一异常处理 相关, HutoolDemo工具介绍)

第三节   后台布局搭建,代码可以人工智能来写,但是环境初步搭建需要我们先建起来,所以以下记录快带搭建的过程,

思路:

后台首页的搭建 第一   用到了element——UI 自带的页面布局组件,它就可以自动生成布局,左侧菜单用了了 <el-menu菜单

点击菜单高度是系统自带的,然后子菜单是写在 <el-menu-item-group>下面,每个菜单点击跳转的路由用的是to = 语法,详细请参看以下

以下代码为人工智能生成,经自己审核,参考代码为b站视视的部份文档
路由文件部份:
我们在写一面代码需要搞好环境,还需需要使用 Vue Router。以下是一个使用 Vue Router 的示例,展示了如何在点击菜单项时导航到不同的路由。
首先,确保您已经安装了 Vue Router 并在项目中进行了配置。以下是一个简单的 Vue Router 配置示文 件路由文件示例:// router.js
import Vue from 'vue';
import Router from 'vue-router';
Vue.use(Router);
export default new Router({
  routes: [
    {
      path: '/',
      name: 'Home',
      component: () => import('@/views/Home.vue'),
    },
    {
      path: '/admin',
      name: 'Admin',
      component: () => import('@/views/Admin.vue'),
    },
    {
      path: '/user',
      name: 'User',
      component: () => import('@/views/User.vue'),
    },
    {
      path: '/info',
      name: 'Info',
      component: () => import('@/views/Info.vue'),
    },
  ],
});

接下来,我们来解决左侧菜单的点击跳转,在我们的 Vue 组件中使用 `router-link` 来包裹菜单项,以便在点击时导航到对应的路由。
以下是示列的代码:顺便请注意看二级菜单在那儿,看看二级菜单的写法,
```html<template> <div id="app"> <el-container> <el-header style="background-color: #409EFF;"> <img src="@/assets/logo.png" alt="" style="width: 40px; position: relative; top: 10px;"> <span style="font-size: 20px; margin-left: 15px; color: white;">手拉手带小自做毕设</span> </el-header> <el-container> <el-aside style="overflow: hidden; min-height: 100vh; background-color: #545c64; width: 250px;"> <el-menu default-active="1" background-color="#545c64" text-color="#fff" active-text-color="#ffd04b"> <router-link to="/"> <el-menu-item index="1"> <i class="el-icon-s-home"></i> <span slot="title">系统首页</span> </el-menu-item> </router-link> <el-submenu index="2"> <template slot="title"> <i class="el-icon-location"></i> <span>用户管理</span> </template> <el-menu-item-group> <router-link to="/admin"> <el-menu-item index="2-1">管理员信息</el-menu-item> </router-link> <router-link to="/user"> <el-menu-item index="2-2">用户信息</el-menu-item> </router-link> </el-menu-item-group> </el-submenu> <el-submenu index="3"> <template slot="title"> <i class="el-icon-location"></i> <span>信息管理</span> </template> <el-menu-item-group> <router-link to="/info"> <el-menu-item index="3-1">xxx信息</el-menu-item> </router-link> <router-link to="/info"> <el-menu-item index="3-2">yyy信息</el-menu-item> </router-link> </el-menu-item-group> </el-submenu> </el-menu> </el-aside> <el-main> <!-- 主要内容区域 --> <router-view/> </el-main> </el-container> </el-container> </div> </template> 

  修改组件的样式,需要强制修改属性,比如

<style>
.el-menu
border-right: none !important;
</style>

  element-UI 的菜单加入路由模式  可以简化使用路由:

<el-container>
  <el-aside style="overflow: hidden; min-height: 100vh; background-color: #545c64; width: 250px">
    <el-menu :default-active="$route.path" router background-color="#545c64" text-color="#fff" active-text-color="#ffd04b">
      <el-menu-item index="/"><i class="el-icon-s-promotion"></i><span slot="title">系统首页</span></el-menu-item>
      <el-submenu index="2">
        <template slot="title"><i class="el-icon-location"></i><span>用户管理</span></template>
        <el-menu-item-group>
          <el-menu-item index="/admiral">管理员信息</el-menu-item>
          <el-menu-item index="/user">用户信息</el-menu-item>
        </el-menu-item-group>
      </el-submenu>
      <el-submenu index="3">
        <!-- submenu items here -->
      </el-submenu>
    </el-menu>
  </el-aside>
</el-container>

  第二部份微信登陆部分,,以下二个方法可以单独用

    方法一: uni_gtUserInfo   获取用户信息,这个方法好像可以直接使用  

     方法二   uni.login   这个方法主要获取微信的code

methods: {
  wxLogin() {
    // 调用 uni.getUserInfo 方法获取用户信息
    uni.getUserInfo({
      desc: '登录的数据', // 描述信息,用于说明为什么需要获取用户信息
      success(ures) { // 获取用户信息成功后的回调函数
        console.log(ures, '返回的用户信息'); // 打印用户信息
        // 调用 uni.login 方法进行微信登录
        uni.login({
          success(lres) { // 登录成功后的回调函数
            console.log(lres, '请求微信登录返回的数据'); // 打印登录返回的数据
            let params = { code: lres.code }; // 从登录返回的数据中获取 code 参数
            // 调用 loginByWechat 方法进行微信一键登录
            loginByWechat(params).then(res => {
              console.log(res, '微信一键登录返回的数据'); // 打印一键登录返回的数据
            });
          }
        });
      }
    });
  }
}

  第三部份  uniapp 请封装,

public class HutoolDemo f
public static void main(string[] args){/1 读取文件内容
string content = Fileutil.readutfgstring("example.txt");
System.out.println(content);
/1 写入文件内容
Fileutil.writeutfgstring("Hello, Hutool!","output.txt");
/1 复制文件
Fileutil.copy("source.txt","target.txt",true);

  

  1. 初始化请求配置:设置全局请求配置,包括根域名、跨域请求相关配置等。
    uni.$u.http.setConfig((config) => {
      // config 为默认全局配置
      // config.baseURL = 'http://uat.banlu.xuexiluxian.cn'; // 根域名
    
      // 设置跨域请求相关配置
      config.withCredentials = true; // 允许携带凭证(如 cookies)
      config.headers['Access-Control-Allow-Origin'] = '*'; // 允许任何域名访问
    
      return config;
    });
    
      1. 请求拦截器:在请求发送之前对请求进行处理,可以进行异步操作。
        uni.$u.http.interceptors.response.use(
          async (response) => {
            // 对响应成功做点什么,可以使用 async/await
            const data = response.data;
            return data;
          },
          (response) => {
            // 对响应错误做点什么(statusCode 1 == 200)
            return Promise.reject(response);
          }
        );
        

          使用示例:

        const http = uni.$u.http;
        
        // 商品分页
        export const goodsPage = (data) => http.get('/mall/goods/page', { params: data });
        
        // 商品分类树
        export const categoryTree = (data) => http.get('/mall/category/tree', { params: data });
        
        // 商品分类列表
        export const categoryList = (data) => http.get(`/mall/category/list/${data}`);
        

         

      2.  统一异常处理,可以解决有类他是无返回修值,但是我们又要返回的的时候可以用到自定定异常和统一异常

        @ControllerAdvice(basePackages = "com.example.controller")
        public class GlobalExceptionHandler {
            private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
        
            // 统一处理异常
            @ExceptionHandler(Exception.class)
            @ResponseBody
            public Result error(HttpServletRequest request, Exception e) {
                logger.error("异常信息:", e); // 打印异常信息
                return Result.error("系统异常"); // 返回错误信息
            }
        
            // 处理自定义异常
            @ExceptionHandler(CustomException.class)
            @ResponseBody
            public Result customError(HttpServletRequest request, CustomException e) {
                return Result.error(e.getMsg()); // 返回自定义异常的错误信息
            }
        } 
        自定义异常
        package com.example.exception;
        
        public class CustomException extends RuntimeException {
            private String msg;
        
            public CustomException(String msg) {
                this.msg = msg;
            }
        
            public String getMsg() {
                return msg;
            }
        
            public void setMsg(String msg) {
                this.msg = msg;
            }
        }
        

          

      3.   请求封装

        const request = axios.create({
          baseURL: "http://localhost:8080",
          timeout: 5000,
        });
        
        // request 拦截器
        // 可以在请求发送前对请求进行一些处理,比如统一加 token,对请求数据进行加密等
        request.interceptors.request.use(
          (config) => {
            config.headers["Content-Type"] = "application/json;charset=utf-8";
            // config.headers["token"] = user.token; // 设置请求头
            return config;
          },
          (error) => {
            return Promise.reject(error);
          }
        );
        
        // response 拦截器
        // 可以在接口响应后统一处理结果,比如对返回的数据进行解密等
        request.interceptors.response.use(
          (response) => {
            // response.data 即为后端返回的数据
            let res = response.data;
            // 兼容服务端返回的字符串形式数据
            if (typeof res === "string") {
              res = res ? JSON.parse(res) : res;
            }
            return res;
          },
          (error) => {
            console.log("err" + error); // for debug
            return Promise.reject(error);
          }
        );
        

          

              后端登陆示例:
    public void add(Admin admin) {
        // 1. 用户名一定要有,否则不让新增(后面需要用户名登录)
        if (admin.getName() == null || "".equals(admin.getName())) {
            throw new CustomException("用户名不能为空");
        }
    
        // 2. 进行重复性判断,同一名字的管理员不允许重复新增:只要根据用户名去数据库查询一下就可以了
        Admin user = adminDao.findByName(admin.getName());
        if (user != null) {
            // 说明已经有了,这里我们就要提示前台不允许新增了
            throw new CustomException("该用户名已存在,请更换用户名");
        }
    
        // 初始化一个密码
        if (admin.getPassword() == null) {
            admin.setPassword("123456");
        }
    
        adminDao.insertSelective(admin);
    }
    
    public void update(Admin admin) {
        adminDao.updateByPrimaryKeySelective(admin);
    }
    

      

    cn.hutool是一个 Java 工具类库,它提供了许多实用的工具类和方法,以帮助简化 Java 开发过程.。这个库包含许多常用的功能,如文件操作、日期处理、加密解密、JSON 处理等。以下是一些使用示例:
    1.引入依赖
    在 Maven 项目的 pom.xml 文件中添加以下依赖:

    public class HutoolDemo {
    public static void main(string[] args){/1 读取文件内容
    string content = Fileutil.readutfgstring("example.txt");
    System.out.println(content);
    /1 写入文件内容
    Fileutil.writeutfgstring("Hello, Hutool!","output.txt");
    /1 复制文件
    Fileutil.copy("source.txt","target.txt",true);
    

      


  2. JWT 使用,新建一个类 
    import javax.annotation.PostConstruct;
    import javax.annotation.Resource;
    import javax.servlet.http.HttpServletRequest;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    import com.auth0.jwt.JWT;
    import com.auth0.jwt.algorithms.Algorithm;
    import java.util.Date;
    import cn.hutool.core.date.DateUtil;
    
    @Component
    public class JwtTokenUtils {
        private static AdminService staticAdminService;
        private static final Logger log = LoggerFactory.getLogger(JwtTokenUtils.class);
    
        @Resource
        private AdminService adminService;
    
        @PostConstruct
        public void setUserService() {
            staticAdminService = adminService;
        }
    
        // 生成 token
        public static String genToken(String adminId, String sign) {
            return JWT.create()
                    .withAudience(adminId) // 将 user id 保存到 token 里面,作为承载
                    .withExpiresAt(DateUtil.offsetHour(new Date(), 2)) // 2 小时后 token 过期
                    .sign(Algorithm.HMAC256(sign)); // 以 password 作为 token 的密钥
        }
    
        // 获取当前登录的用户信息
        public static Admin getCurrentUser() {
            String token = null;
            try {
                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
                token = request.getHeader("token");
                if (StrUtil.isBlank(token)) {
                    token = request.getParameter("token");
                    if (StrUtil.isBlank(token)) {
                        log.error("获取当前登录的 token 失败,token: {}", token);
                        return null;
                    }
                }
    
                // 解析 token,获取用户的 id
                String adminId = JWT.decode(token).getAudience().get(0);
                return staticAdminService.findByById(Integer.valueOf(adminId));
            } catch (Exception e) {
                log.error("获取当前登录的管理员信息失败,token: {}", token, e);
                return null;
            }
        }
    }
    

      

  3.   如果出现跨域头错误,后端加上配置   CorsConfig 类:


    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 {
    
        @Bean
        public CorsFilter corsFilter() {
            UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            CorsConfiguration corsConfiguration = new CorsConfiguration();
            corsConfiguration.addAllowedOrigin("*"); // 1. 设置允许访问的源地址
            corsConfiguration.addAllowedHeader("*"); // 2. 设置允许访问的源请求头
            corsConfiguration.addAllowedMethod("*"); // 3. 设置允许访问的源请求方法
            source.registerCorsConfiguration("/**", corsConfiguration); // 4. 对所有接口配置跨域设置
            return new CorsFilter(source);
        }
    }
    

      


      

 

posted @ 2024-05-30 08:03  谢双元小号  阅读(85)  评论(0)    收藏  举报