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);
- 初始化请求配置:设置全局请求配置,包括根域名、跨域请求相关配置等。
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; });- 请求拦截器:在请求发送之前对请求进行处理,可以进行异步操作。
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}`); -
统一异常处理,可以解决有类他是无返回修值,但是我们又要返回的的时候可以用到自定定异常和统一异常
@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; } } -
请求封装
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); - 请求拦截器:在请求发送之前对请求进行处理,可以进行异步操作。
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; } } }-
如果出现跨域头错误,后端加上配置
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); } }

浙公网安备 33010602011771号