真棒!
真棒!
要是eladmin-mp能添加数据权限功能,一定会是非常好用的一个框架
eladmin-mp缺少仅本人数据权限,还有怎样自动处理数据权限
不能装centos8吗
谢谢分享
感谢分享,试试看
大佬,互换个友链, 已添加您了
{ "title": "SerMs", "screenshot": "https://bu.dusays.com/2023/10/11/65264d86ddebb.png", "url": "https://blog.serms.top/", "avatar": "https://bu.dusays.com/2023/10/11/65269ea6226c8.png", "description": "代码如诗,细节成就极致,逻辑成就完美。", "keywords": "SerMs" }
感谢大佬
博主已经添加了
名称: Fostmar博客地址: https://fostmar.online图标:https://fostmar.online/usr/uploads/2023/12/2354092855.webp简介:kali渗透、建站、数码,以博客为核心,打造生态圈
首页
统计
微语
留言
邻居
壁纸
推荐
我的开源
Search
1
快速解决 npm 安装 node-sass 速度慢/错误的问题
24,424 阅读
2
升级 element-ui 2.15.7 后遇到 el-date-picker 警告问题
10,295 阅读
3
Centos 7 彻底卸载清除 Docker 环境
8,712 阅读
4
vue 更新 sass 版本出现大量警告的坑
8,578 阅读
5
前端 axios 中 qs 介绍与使用
8,441 阅读
推荐分享
文章推荐
资源分享
软件开发
异常记录
Linux学习
日常杂记
开源
登录
Search
标签搜索
Java记录
Linux系统
eladmin开源
Web前端
Spring教程
Docker容器
其他
Git教程
Google插件
jpa
好文分享
Nginx配置
异常记录
持续集成工具
数据库
线程池
Typecho博客
Azure管理
Lambda表达式
PowerDesigner
知了小站
不怕学问浅,就怕志气短。
累计撰写
74
篇文章
累计收到
397
条评论
首页
栏目
推荐分享
文章推荐
资源分享
软件开发
异常记录
Linux学习
日常杂记
开源
页面
统计
微语
留言
邻居
壁纸
推荐
我的开源
用户登录
登录
搜索到
74
篇与
的结果
2020-09-14
记 com.mysql.jdbc.PacketTooBigException 解决方案
解决方案一、修改配置文件可以通过更改 mysql 的配置文件 my.cnf 或者 my.ini 来更改这一默认值[mysqld] max_allowed_packet = 20M二、修改MySql依赖版本将 mysql-connector-java 版本修改为 5.1.45 即可
2020年09月14日
1,507 阅读
0 评论
1 点赞
2020-08-24
Typecho 迁移到 Docker 的过程记录
前言之前博客搭建在阿里云的机器上,现在快过期了,加上原机器带宽太小,就不打算续费了,现在就需要将 Typecho 博客迁移到新机器上。以前使用的是宝塔面板搭建的,现在不想把机器环境搞得乱七八糟,因此选择使用 Docker 来搭建 Typecho。安装Docker使用一键脚本安装Dockercurl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun && systemctl start docker && systemctl enable docker如果提示 curl 命令不存在,就需要先安装 curl# Centos yum -y install curl # Ubuntu、Debian apt -y install curl配置镜像加速如果你机器是国内的机器,那么需要配置镜像加速阿里云镜像获取地址:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors修改 /etc/docker/daemon.json,文件不存在就创建一个{ "registry-mirrors": [ "你的加速地址" ] }安装数据库这里选择的是 Mariadb,可自行选择数据库镜像,这里配置参数就不做解释了,懂的都懂docker run -d -v /home/mysql:/var/lib/mysql \ -p 3306:3306 -e MYSQL_ROOT_PASSWORD=密码 \ --privileged=true --restart=always --name mariadb mariadb安装 PHP安装官方的 php:7.2-fpm 镜像后,还需要进入容器安装 mysql pdo 才能使用 Mysql 数据库,比较麻烦,这里我自己在 php:7.2-fpm 的基础上构建了个带 mysql pdo 的镜像,可以选择性使用。docker run -d -v /home/nginx/html:/var/www/html \ -p 8080:8080 --link mariadb:mariadb --name php dqjdda/php安装 Nginxdocker run -d \ --link php:php \ --name nginx --restart always \ -p 80:80 -p 443:443 \ -e "TZ=Asia/Shanghai" \ -v /home/nginx/nginx.conf:/etc/nginx/nginx.conf \ -v /home/nginx/conf.d:/etc/nginx/conf.d \ -v /home/nginx/logs:/var/log/nginx \ -v /home/nginx/cert:/etc/nginx/cert \ -v /home/nginx/html:/var/www/html \ nginx配置 Nginx/home/nginx/conf.d 用于放配置文件/home/nginx/logs 存放日志/home/nginx/cert 存放证书/home/nginx/html 存放网页在 /home/nginx/conf.d 目录创建文件 blog.confserver { listen 443 ssl http2; server_name izlzl.com; gzip on; # 缓存SSL ssl_session_cache shared:SSL:10m; ssl_session_timeout 1d; # 证书配置 ssl_certificate /etc/nginx/cert/ydyno.com/ydyno.com_chain.crt; ssl_certificate_key /etc/nginx/cert/ydyno.com/ydyno.com_key.key; root /var/www/html/ydyno; index index.php; # 伪静态 if (!-e $request_filename) { rewrite ^(.*)$ /index.php$1 last; } location ~ .*\.php(\/.*)*$ { include fastcgi_params; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_index index.php; fastcgi_pass php:9000; } location ~* \.(jpg|jpeg|gif|png|css|js|ico|xml)$ { expires 5d; } # deny access to . files, for security location ~ /\. { log_not_found off; deny all; } } server { listen 80; server_name izlzl.com ydyno.com; return 301 https://izlzl.com$request_uri; }迁移博客直接将老服务器的博客目录移动到 /var/www/html/ydyno ,然后将数据库导出,然后导入到新库即可
2020年08月24日
2,755 阅读
7 评论
2 点赞
2020-06-08
EL-ADMIN V2.5 版本发布,新增多项实用功能,代码多项优化
V2.4版本现基本稳定,V2.5版本都是基于现版本进行Bug修复与优化调整,新版本更新内容如下后端改动新增功能加入审计功能,继承 BaseEntity 后自动写入创建时间、修改时间、创建人、更新人,详见 AuditorConfigToken 自动续期功能,用户在快过期的时间内操作活跃,可将 Token 过期时间延长,详见 TokenFilter数据权限注解的实现,摈弃在 Controller 的操作方式,采用 @DataPermission 注解实现,详见 后端手册新的服务监控实现,后端采用 oshi,前端采用 echarts 做可视化借鉴了[宝塔监控],详见 预览地址定时任务创建时支持添加异常通知人,当定时任务执行失败发送邮件通知 [支持多邮箱], 详见 后端手册定时任务支持添加子任务,当主任务执行完后自动执行子任务 [支持多子任务,顺序执行], 详见 后端手册细节优化结构优化数据库脚本选择,见 脚本指南所有表按功能加入前缀:sys、tool、mnt 方便后续管理维护所有表字段的主键改为: 表名_id,方便与关联表的 id 统一所有表加入 create_by、update_by、create_time、update_time 字段,便于审计去除无用字段,加入必要索引加快查询速度,去除外键改为程序控制sys_user 表中加入 is_admin 字段用户区分是否为管理员删除 avatar 头像表,将头像的的头像名称与路径存入 sys_user 表代码优化去除首页 ip,pv 统计,此功能对于后台管理显得多余邮箱验证功能的验证码改为存储在 Redis 中,删除了原来从数据库中取的逻辑代码修改不规范的字段名/包名,将 mapper 包改为 mapstruct,避免与 mybatis 的 mapper 冲突重新设计缓存功能,去除不必要的缓存,去除监控模块,将新服务监控管理移入 system 模块用户管理、角色管理、菜单管理、部门管理中树形均采用懒加载方式实现,避免大量的数据导致页面卡顿加入RsaUtils工具类解决Hutool工具Rsa解密过慢的问题,IP 归属地查询改为用太平洋IP地址查询接口TokenFilter Token 验证逻辑优化,对于已放行的接口不去验证 Token 合法性文件上传优化,加入 FileProperties 配置,根据系统选择上传目录代码生成器前端 index.vue 模板查询优化,取消以前的下拉方式查询 详见错误修复运维管理解决不能向不同服务器部署应用的缺陷 #347运维管理解决部署到linux服务器路径拼接不正确问题 #347运维管理解决每次连接不同服务器都默认访问第一台服务器的问题 #347当前用户如果没有任何权限时,在输入用户名后,刷新验证码会抛IllegalArgumentException #333修复不存在账号登录时userService.findByName 抛出异常,loadUserByUsername未捕获处理的Bug 详见前端改动新增功能同一界面内,多CRUD共存,支持自定义数据id字段名 详见字典管理使用CRUD组件改写,CRUD组件增加对table延迟实例化支持,完善组件注册、注销 #83登录页背景使用本地图片,服务监控采用 v-echarts 实现用户管理、角色管理、菜单管理、部门管理,列表和弹窗数据懒加载用户头像裁剪上传节省空间 详见@crud/CRUD.operation中增加对列隐藏(初始阶段)支持 #95@crud/CRUD.operation中增加对列忽略支持 #95@crud/CRUD.operation中列可见性控制选项顺序跟随表格列顺序变更 #95细节优化优化主题切换按钮下移问题、优化tabs被footer遮挡问题、优化主题在页面刷新后重置的问题取消crud.props记录tableColumns,调整表格列可见性控制时插入位置计算 #95修改Token过期的提示,由原来的弹窗提示改为登录界面消息提示 详见错误修复修复V2.4版本中路由懒加载问题 详见修复菜单管理选择图标,backspace删除时不过滤数据 详见修复重定向到登录页,登录后参数丢失问题,比如文章详情/article?id=6 #94修复首页搜索菜单外链无法点击跳转问题 By RuoYi-Vue解决部署管理和数据库管理,选择记录不能启用自定义按钮的问题 详见修复字典管理模块点击编辑后再点击新增报错的问题 #366脚本指南项目根目录的 sql 文件夹内提供了本次数据库变更的脚本,脚本如何选择,以及执行的顺序如下操作数据库属于危险行为,请勿用于生产库,请事先做好备份!!!初次使用eladmin.sql 为 eladmin 项目完整的 sql 脚本,适合于初次使用的用户更新迭代对于老版本的,可以按下面的顺序执行删除所有外键.sql表名修改.sqlcode_ 相关表字段调整.sqlmnt_ 相关表字段调整.sqltool_ 相关表字段调整.sqlsys_ 相关表字段调整.sql用户岗位改动.sql相关数据更新.sql索引相关.sql删除无用表.sql脚本已经提供,其他的就需要自己慢慢调试了,祝成功!项目源码开发文档:https://el-admin.vip预览地址:https://el-admin.xin 后端源码前端源码Githubhttps://github.com/elunez/eladminhttps://github.com/elunez/eladmin-web码云https://gitee.com/elunez/eladminhttps://gitee.com/elunez/eladmin-web
2020年06月08日
6,874 阅读
18 评论
8 点赞
2020-02-20
快速解决 npm 安装 node-sass 速度慢/错误的问题
可通过配置淘宝的镜像源解决,首先配置淘宝的镜像源npm config set registry https://registry.npm.taobao.org然后在 ~/.npmrc 加入下面内容sass_binary_site=https://npm.taobao.org/mirrors/node-sass/.npmrc 文件位于win:C:\Users\[你的账户名称]\.npmrc linux:直接使用 vi ~/.npmrc完整配置如图
2020年02月20日
24,424 阅读
4 评论
19 点赞
2020-02-18
记一次 Centos 中因为 DNS npm 安装包失败的问题
在 centos 中使用 npm install 命令报错如下:09:13:56 npm WARN network SKIPPING OPTIONAL DEPENDENCY: request to https://registry.npm.taobao.org/nan failed, reason: getaddrinfo ENOTFOUND registry.npm.taobao.org registry.npm.taobao.org:443 09:13:56 npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.4 (node_modules/fsevents): 09:13:56 npm WARN network SKIPPING OPTIONAL DEPENDENCY: request to https://registry.npm.taobao.org/fsevents failed, reason: getaddrinfo ENOTFOUND registry.npm.taobao.org registry.npm.taobao.org:443于是经过长达半个小时的搜索也没有找到答案,最后猜测是不是服务器网络或者host有问题试了下 ping www.baidu.com[root@localhost ~]# ping www.baidu.com ping: www.baidu.com: Name or service not known发现找不到百度的服务器,证明了这台服务器的host存在问题,于是定位到 /etc/resolv.conf 文件打开查看[root@localhost ~]# vi /etc/resolv.conf # Generated by NetworkManager nameserver fd20:25f7:e485::1添加下DNS到 resolv.conf 文件中nameserver 114.114.114.114保存文件,再次 ping www.baidu.com[root@localhost ~]# ping www.baidu.com PING www.a.shifen.com (14.215.177.38) 56(84) bytes of data. 64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=1 ttl=51 time=36.1 ms至此问题解决
2020年02月18日
2,749 阅读
0 评论
1 点赞
2019-12-30
前端 axios 中 qs 介绍与使用
首先 qs 是一个 npm 仓库所管理的包,可通过 npm install qs 命令进行安装地址: https://www.npmjs.com/package/qsqs.parse()qs.parse() 将URL解析成对象的形式const Qs = require('qs'); let url = 'method=query_sql_dataset_data&projectId=85&appToken=7d22e38e-5717-11e7-907b-a6006ad3dba0'; Qs.parse(url); console.log(Qs.parse(url));qs.stringify()qs.stringify() 将对象序列化成URL的形式,以&进行拼接const Qs = require('qs'); let obj= { method: "query_sql_dataset_data", projectId: "85", appToken: "7d22e38e-5717-11e7-907b-a6006ad3dba0", datasetId: " 12564701" }; Qs.stringify(obj); console.log(Qs.stringify(obj));那么当我们需要传递数组的时候,我们就可以通过下面方式进行处理:默认情况下,它们给出明确的索引,如下代码:qs.stringify({ a: ['b', 'c', 'd'] }); // 'a[0]=b&a[1]=c&a[2]=d'也可以进行重写这种默认方式为falseqs.stringify({ a: ['b', 'c', 'd'] }, { indices: false }); // 'a=b&a=c&a=d'当然,也可以通过arrayFormat 选项进行格式化输出,如下代码所示:qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'indices' }) // 'a[0]=b&a[1]=c' qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'brackets' }) // 'a[]=b&a[]=c' qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'repeat' }) // 'a=b&a=c'在这里需要注意的是,JSON中同样存在stringify方法,但是两者之间的区别是很明显的,如下所示:{"uid":"cs11","pwd":"000000als","username":"cs11","password":"000000als"} uid=cs11&pwd=000000als&username=cs11&password=000000als如上所示,前者是采用 JSON.stringify(param) 进行处理,后者是采用 Qs.stringify(param) 进行处理的。对于JSON.stringify和JSON的使用可参见https://blog.csdn.net/suwu150/article/details/76100120原文地址:https://www.jianshu.com/p/67223e177aa6
2019年12月30日
8,441 阅读
2 评论
7 点赞
2019-12-27
解决 Vue 在 History 模式部署在 Nginx 上刷新报 404 的问题
教程适用于history模式,假设域名假设为:auauz.net原配置server { listen 80; server_name auauz.net; root /www/wwwroot/eladmin-web/dist; index index.html; error_page 404 /index.html; }修改如下server { listen 80; server_name auauz.net; location / { root /www/wwwroot/eladmin-web/dist; try_files $uri $uri/ @router; index index.html; } location @router { rewrite ^.*$ /index.html last; } }
2019年12月27日
3,902 阅读
6 评论
0 点赞
2019-12-23
EL-ADMIN v2.4 发布,升级 cli3,新增监控模块,运维管理等
EL-ADMIN 基于 Spring Boot 2.1.0 、 Jpa、 Spring Security、redis、Vue 的前后端分离的后台管理系统,项目采用分模块开发方式, 权限控制采用 RBAC,支持数据字典与数据权限管理,支持一键生成前后端代码,支持前端菜单动态路由。v2.4 版本更新内容如下后端1、新增服务监控模块 eladmin-monitor,监控服务器的负载情况 (by @zhy6599)2、代码生成器优化,支持配置更多信息,支持打包下载与预览生成(1) 界面(2) 配置(3) 预览3、加入了运维管理 (by @zhy6599)4、用户加入昵称与性别字段5、免费图床支持同步功能6、新增清空日志功能,需要相应的权限才能操作 (#217 by @zoulejiu)7、security 优化,密码加密方式采用BCryptPasswordEncoder方式:SHA-256 +随机盐+密钥对密码进行加密7、前后端用户登陆密码rsa加密,后端解密,避免撞库8、@Query新增 NOT_EQUAL 、BETWEEN 、NOT_NULL查询9、匿名访问统一使用 @AnonymousAccess去除 @PreAuthorize("hasRole('anonymous')")、@PreAuthorize("@el.check('anonymous')") 的匿名访问效果10、新增单点登录,多设备登录 (#217 by @zoulejiu)以最后登录为准,之前的登录都会被踢掉,可以使用single.login =false 关闭11、代码优化,2.4版本完全遵循阿里巴巴代码规范前端1、前端升级为 vue-cli3 ,加入主题配置,目录结构优化2、移除 initData.js,封装 crud.js ,只需要引入该 js 即可实现所有增删改查的功能(详情查看源码)3、封装crud通用组件,建议使用,2.4 前端页面几乎都是使用这种形式 (#57 by @moxun1639)(1) 组件路径(2) 如何使用<template> <div class="app-container"> <!--工具栏--> <div class="head-container"> <div v-if="crud.props.searchToggle"> <!-- 搜索 --> <el-input v-model="query.value" clearable placeholder="输入搜索内容" style="width: 200px;" class="filter-item" @keyup.enter.native="crud.toQuery" /> <!--略--> <rrOperation :crud="crud" /> </div> <!--如果想在工具栏加入更多按钮,可以使用插槽方式, slot = 'left' or 'right'--> <crudOperation :permission="permission" /> <!--表单组件--> <el-dialog :close-on-click-modal="false" :before-close="crud.cancelCU" :visible.sync="crud.status.cu > 0" :title="crud.status.title" width="500px"> <!--略--> <div slot="footer" class="dialog-footer"> <el-button type="text" @click="crud.cancelCU">取消</el-button> <el-button :loading="crud.cu === 2" type="primary" @click="crud.submitCU">确认</el-button> </div> </el-dialog> <!--表格渲染--> <el-table ref="table" v-loading="crud.loading" :data="crud.data" size="small" style="width: 100%;" @selection-change="crud.selectionChangeHandler"> <el-table-column type="selection" width="55" /> <el-table-column v-if="columns.visible('createTime')" prop="createTime" label="createTime"> <template slot-scope="scope"> <span>{{ parseTime(scope.row.createTime) }}</span> </template> </el-table-column> <el-table-column v-permission="['admin','genTest:edit','genTest:del']" label="操作" width="150px" align="center"> <template slot-scope="scope"> <udOperation :data="scope.row" :permission="permission" /> </template> </el-table-column> </el-table> <!--分页组件--> <pagination /> </div> </div> </template> <script> import crudGenTest from '@/api/genTest' import CRUD, { presenter, header, form, crud } from '@crud/crud' import rrOperation from '@crud/RR.operation' import crudOperation from '@crud/CRUD.operation' import udOperation from '@crud/UD.operation' import pagination from '@crud/Pagination' // crud交由presenter持有 const defaultCrud = CRUD({ title: '测试生成', url: 'api/genTest', sort: 'id,desc', crudMethod: { ...crudGenTest }}) const defaultForm = { id: null, name: null, sex: null, createTime: null } export default { name: 'GenTest', components: { pagination, crudOperation, rrOperation, udOperation }, mixins: [presenter(defaultCrud), header(), form(defaultForm), crud()], data() { return { permission: { add: ['admin', 'genTest:add'], edit: ['admin', 'genTest:edit'], del: ['admin', 'genTest:del'] }, rules: { id: [ { required: true, message: 'ID不能为空', trigger: 'blur' } ], name: [ { required: true, message: '名称不能为空', trigger: 'blur' } ] }, queryTypeOptions: [ { key: 'name', display_name: '名称' }, { key: 'sex', display_name: '性别' } ] } }, methods: { // 获取数据前设置好接口地址 [CRUD.HOOK.beforeRefresh]() { const query = this.query if (query.type && query.value) { this.crud.params[query.type] = query.value } return true } } } </script>(3) 界面如下3、异常日志详情加入代码高亮显示,生产环境移除console4、其他升级可以查看演示页面修复1、修复查询时输入 []{} 符号报错的问题#1852、修复本地存储预览关闭按钮被header遮挡的问题#1883、修复Menu排序问题 (#194 by CCCY0)4、修复ip2region 不会自动关闭连接问题 (#217 by @zoulejiu)5、QueryHelp 中 RIGHT_LIKE 缺少 break 的问题 (#214 by jhpx)指南新版本代码生成器:链接新版本服务监控:链接新版本运维管理:链接新版本免费图床:链接新版本@Query查询:链接
2019年12月23日
4,746 阅读
3 评论
2 点赞
2019-12-19
ES6 语法大全 export,import,for.of循环,promise等等
变量let 局部变量 const 常量 var 全局变量字符串的拓展let str = "123" str.includes("1")//true includes方法 是否包含 str.startsWith("2")//false 是否以2开头 str.endsWith("2")//false 是否以2结尾解构表达式//数组解构 let arr = [1,2,3] const [x,y,z] = arr;// x,y,z对应 1,2,3 //对象解构 const person = { name:"jack", age:21, language:['java','php'], } let {name,age,language} = person //自定义命名 let {name:n,age:a,language} = person 函数的优化//参数上面的优化=1,指当b没有值时默认为1 function test(a,b=1){ console.log(a+b) }箭头函数//Demo1 单个参数 var demo1= fucntion demo1(obj){ console.log(obj) } 箭头函数简化为: var demo1= obj =>console.log(obj); //Demo2 两个参数 var sum =function(a,b){ console.log(a+n) } 箭头函数简化为: var sum = (a,b)=>console.log(obj); //Demo3 没有参数 let sayHello = ()=>console.log("hello!"); //Demo4 代码不止一行 使用 {} var sum = (a,b)=>{ console.log(a+n); console.log(a+n) } //Demo5 对象的函数简写 let person ={ name:“jeck”; //原来 eat:function(food){ console.log(this.name +food) } //箭头函数 eat2:food=>console.log(this.name +food) //简写版 eat3(food){ console.log(this.name +food) } } //Demo6:箭头函数配合解构表达式 let person ={ name:“jeck”; eat2:food=>console.log(this.name +food) } function test1(person){ console.log(person.name); } //简化调用函数 使用{}传参数,传入对象 var test1=({name})=>console.log(name); test1(person );map和reduce函数map 让原来的集合经过 map 中的函数 进行处理回调let arr = ['1','2','3']; arr.map(s=>parseInt(s))//字符串转化为内证书 //reduce() 接收一个函数和一个初始值 第一个参数时上一次reduce的处理结果 第二个参数是数组中要处理的下一个元素 const arr = [1,20,30,40] arr.reduce((a,b)=>a+b)拓展运算符(三个点…)将一个数组转为用逗号分隔的参数序列function add(a,b){ return a+b; } var number = [1,2]; //数组合并 var arrs=[...[1,2,3],...[4,5,6]];//[1,2,3,4,5,6] //将字符串转为数组 console.log([...'hello'])//['h','e','l','l','o']promise// 函数格式 const promise = new promise(function(resolve,reject){ //操作 //if(success){ resolve(value);//成功 }else{ reject(error)//失败 } }) //执行完了在执行一些东西的话 promise.then(function(value){ //异步回调 }).catch(function(error){ //异常回调 })set和mapset 只能保存不同元素,相同的元素会被忽略let set = new set(); let set = new set([2,3,4,5]); //map接受一个数组,数组中的元素时键值对 let map = new map([ ['key','value'], ['key1','value1'], ])for.of循环for(let obj of h){ console.log(obj) }模块化export import// export 导出命令 calss Util{ sum=(a,b)=>a+b; } export default Util // import加载 import Util from './Util'原文链接:https://blog.csdn.net/qq_35349982/article/details/103581101
2019年12月19日
2,545 阅读
3 评论
1 点赞
2019-12-12
Spring Boot 如何优雅的校验参数
前言做web开发有一点很烦人就是要校验参数,基本上每个接口都要对参数进行校验,比如一些格式校验 非空校验都是必不可少的。如果参数比较少的话还是容易 处理的一但参数比较多了的话代码中就会出现大量的 IF ELSE就比如下面这样:这个例子只是校验了一下空参数。如果需要验证邮箱格式和手机号格式校验的话代码会更多,所以介绍一下 validator通过注解的方式进行校验参数。<!--版本自行控制,这里只是简单举例--> <dependency> <groupId>javax. validation</groupId> <artifactId>validation-api</artifactId> <version>2.0.0. Final</version> </ dependency> <dependency> <groupId>org. hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.1. Final</vers ion> </dependency>注解介绍validator内置注解注解详细信息@Null被注释的元素必须为 null@NotNull被注释的元素必须不为 null @AssertTrue被注释的元素必须为 true@AssertFalse被注释的元素必须为 false@Min(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值@Max(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值@DecimalMin(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值@DecimalMax(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值@Size(max, min)被注释的元素的大小必须在指定的范围内@Digits (integer, fraction)被注释的元素必须是一个数字,其值必须在可接受的范围内@Past被注释的元素必须是一个过去的日期@Future被注释的元素必须是一个将来的日期@Pattern(value)被注释的元素必须符合指定的正则表达式Hibernate Validator 附加的 constraint注解详细信息 @Email被注释的元素必须是电子邮箱地址@Length被注释的字符串的大小必须在指定的范围内@NotEmpty被注释的字符串的必须非空 @Range被注释的元素必须在合适的范围内@NotBlank验证字符串非null,且长度必须大于0注意:@NotNull 适用于任何类型被注解的元素必须不能与NULL@NotEmpty 适用于String Map或者数组不能为Null且长度必须大于0@NotBlank 只能用于String上面 不能为null,调用trim()后,长度必须大于0使用模拟用户注册封装了一个 UserDTO当提交数据的时候如果使用以前的做法就是 IF ELSE判断参数使用 validator则是需要增加注解即可。例如非空校验:然后需要在 controller方法体添加 @Validated不加 @Validated校验会不起作用然后请求一下请求接口,把 Email参数设置为空参数:{ "userName":"luomengsun", "mobileNo":"11111111111", "sex":1, "age":21, "email":"" }返回结果:后台抛出异常这样是能校验成功,但是有个问题就是返回参数并不理想,前端也并不容易处理返回参数,所以我们添加一下全局异常处理,然后添加一下全局统一返回参数这样比较规范。添加全局异常创建一个 GlobalExceptionHandler类,在类上方添加 @RestControllerAdvice注解然后添加以下代码:/** * 方法参数校验 */ @ExceptionHandler(MethodArgumentNotValidException.class) public ReturnVO handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { log.error(e.getMessage(), e); return new ReturnVO().error(e.getBindingResult().getFieldError().getDefaultMessage()); }此方法主要捕捉 MethodArgumentNotValidException异常然后对异常结果进行封装,如果需要在自行添加其他异常处理。添加完之后我们在看一下运行结果,调用接口返回:{ "code": "9999", "desc": "邮箱不能为空", "data": null }OK 已经对异常进行处理。校验格式如果想要校验邮箱格式或者手机号的话也非常简单。校验邮箱/** * 邮箱 */ @NotBlank(message = "邮箱不能为空") @NotNull(message = "邮箱不能为空") @Email(message = "邮箱格式错误") private String email;使用正则校验手机号校验手机号使用正则进行校验,然后限制了一下位数/** * 手机号 */ @NotNull(message = "手机号不能为空") @NotBlank(message = "手机号不能为空") @Pattern(regexp ="^[1][3,4,5,6,7,8,9][0-9]{9}$", message = "手机号格式有误") @Max(value = 11,message = "手机号只能为{max}位") @Min(value = 11,message = "手机号只能为{min}位") private String mobileNo;查看一下运行结果传入参数:{ "userName":"luomengsun", "mobileNo":"111111a", "sex":1, "age":21, "email":"1212121" }返回结果:{ "code": "9999", "desc": "邮箱格式错误", "data": null }自定义注解上面的注解只有这么多,如果有特殊校验的参数我们可以使用 Validator自定义注解进行校验首先创建一个 IdCard注解类@Documented @Target({ElementType.PARAMETER, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = IdCardValidator.class) public @interface IdCard { String message() default "身份证号码不合法"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }在 UserDTO中添加 @IdCard注解即可验证,在运行时触发,本文不对自定义注解做过多的解释,下篇文章介绍自定义注解message 提示信息groups 分组payload 针对于Bean然后添加 IdCardValidator 主要进行验证逻辑上面调用了 is18ByteIdCardComplex方法,传入参数就是手机号,验证身份证规则自行百度然后使用@NotNull(message = "身份证号不能为空") @IdCard(message = "身份证不合法") private String IdCardNumber;分组就比如上面我们定义的 UserDTO中的参数如果要服用的话怎么办?在重新定义一个类然后里面的参数要重新添加注解?Validator提供了分组方法完美了解决 DTO服用问题现在我们注册的接口修改一下规则,只有用户名不能为空其他参数都不进行校验先创建分组的接口public interface Create extends Default { }我们只需要在注解加入分组参数即可例如:/** * 用户名 */ @NotBlank(message = "用户姓名不能为空",groups = Create.class) @NotNull(message = "用户姓名不能为空",groups = Create.class) private String userName; @NotBlank(message = "邮箱不能为空",groups = Update.class) @NotNull(message = "邮箱不能为空",groups = Update.class) @Email(message = "邮箱格式错误",groups = Update.class) private String email;然后在修改Controller在@Validated中传入Create.class@PostMapping("/user") public ReturnVO userRegistra(@RequestBody @Validated(Create.class) UserDTO userDTO){ ReturnVO returnVO = userService.userRegistra(userDTO); return returnVO ; }然后调用传入参数:{ "userName":"", }返回参数:{ "code": "9999", "desc": "用户姓名不能为空", "data": null }OK 现在只对Create的进行校验,而 Updata组的不校验,如果需要复用 DTO的话可以使用分组校验校验单个参数在开发的时候一定遇到过单个参数的情况,在参数前面加上注解即可@PostMapping("/get") public ReturnVO getUserInfo(@RequestParam("userId") @NotNull(message = "用户ID不能为空") String userId){ return new ReturnVO().success(); }然后在 Controller类上面增加 @Validated注解,注意不是增加在参数前面。作者:孙罗蒙链接:https://lqcoder.com/p/4cd8a59d.html
2019年12月12日
3,079 阅读
3 评论
1 点赞
2019-11-06
Spring Boot 自定义异步线程池的两种方式
SpringBoot 使用异步线程池方式如下第一种创建自定义线程池配置类,AsyncTaskExecutePool@EnableAsync @Configuration public class AsyncTaskExecutePool { //核心线程池大小 private final int corePoolSize = 10; //最大线程数 private final int maxPoolSize = 15; //队列容量 private final int queueCapacity = 50; //活跃时间/秒 private final int keepAliveSeconds = 60; @Bean public Executor myAsyncTaskPool() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); //核心线程池大小 executor.setCorePoolSize(corePoolSize); //最大线程数 executor.setMaxPoolSize(maxPoolSize); //队列容量 executor.setQueueCapacity(queueCapacity); //活跃时间 executor.setKeepAliveSeconds(keepAliveSeconds); //设置线程池关闭的时候等待所有任务都完成再继续销毁其他的Bean executor.setWaitForTasksToCompleteOnShutdown(true); //线程名字前缀 executor.setThreadNamePrefix("my-async1--"); // setRejectedExecutionHandler:当pool已经达到max size的时候,如何处理新任务 // CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.initialize(); return executor; } }创建任务处理类AsyncTask@Component @Slf4j public class AsyncTask { /** * myAsyncTaskPool 线程池的方法名,此处如果不写,会使用Spring默认的线程池 * @param i */ @Async("myAsyncTaskPool") public void run(int i){ log.info("我是:" + i); } }测试线程池AppTests@SpringBootTest class AppTests { @Autowired private AsyncTask asyncTask; @Test void test(){ for (int i = 0; i < 100; i++) { asyncTask.run(i); } } } 运行查看效果第二种第二种方式是重写 spring 默认线程池,使用这种方式的好处是可以直接使用 @Async 注解创建配置类AsyncTaskExecutePool1 并且实现AsyncConfigurer 类@Slf4j @EnableAsync @Configuration public class AsyncTaskExecutePool1 implements AsyncConfigurer { //核心线程池大小 private final int corePoolSize = 10; //最大线程数 private final int maxPoolSize = 15; //队列容量 private final int queueCapacity = 50; //活跃时间/秒 private final int keepAliveSeconds = 60; @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); //核心线程池大小 executor.setCorePoolSize(corePoolSize); //最大线程数 executor.setMaxPoolSize(maxPoolSize); //队列容量 executor.setQueueCapacity(queueCapacity); //活跃时间 executor.setKeepAliveSeconds(keepAliveSeconds); //设置线程池关闭的时候等待所有任务都完成再继续销毁其他的Bean executor.setWaitForTasksToCompleteOnShutdown(true); //线程名字前缀 executor.setThreadNamePrefix("my-async-"); // setRejectedExecutionHandler:当pool已经达到max size的时候,如何处理新任务 // CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.initialize(); return executor; } /** * 异步任务异常处理 * @return */ @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return (throwable, method, objects) -> { log.error("===="+throwable.getMessage()+"====", throwable); log.error("exception method:"+method.getName()); }; } }修改AsyncTask 类,在类中加入方法run1@Async public void run1(int i){ log.info("我是:" + i); }测试,在AppTests 中加入方法test1@Test void test1(){ for (int i = 0; i < 100; i++) { asyncTask.run1(i); } }运行查看效果注意同类中调用带有@Async 的方法是不生效的例子中的参数根据具体的需求修改源码本文源码:https://github.com/elunez/spring-boot-learn
2019年11月06日
4,159 阅读
0 评论
2 点赞
1
...
5
6
7