如果您对day11Django:froms组件:数据校验显示错误信息渲染数据重置数据自定义规则局部钩子,全局钩子感兴趣,那么这篇文章一定是您不可错过的。我们将详细讲解day11Django:froms
如果您对day11 Django: froms组件: 数据校验 显示错误信息 渲染数据 重置数据 自定义规则 局部钩子,全局钩子感兴趣,那么这篇文章一定是您不可错过的。我们将详细讲解day11 Django: froms组件: 数据校验 显示错误信息 渲染数据 重置数据 自定义规则 局部钩子,全局钩子的各种细节,此外还有关于@Valid 数据校验 + 自定义全局异常信息、a-from 自定义规则使用,及初始默认值规则校验失效问题、c# 全局钩子实现扫码枪获取信息、c# 全局钩子实现扫码枪获取信息。的实用技巧。
本文目录一览:- day11 Django: froms组件: 数据校验 显示错误信息 渲染数据 重置数据 自定义规则 局部钩子,全局钩子
- @Valid 数据校验 + 自定义全局异常信息
- a-from 自定义规则使用,及初始默认值规则校验失效问题
- c# 全局钩子实现扫码枪获取信息
- c# 全局钩子实现扫码枪获取信息。
day11 Django: froms组件: 数据校验 显示错误信息 渲染数据 重置数据 自定义规则 局部钩子,全局钩子
@Valid 数据校验 + 自定义全局异常信息
关于javax.validation.Validator校验的使用
- 对于要校验的实体类:其需要校验的字段上需要添加注解
实际例子
使用:首先要拿到 validator的子类
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
其中方法可以参考 API
对实体类的校验
Set<ConstraintViolation<Object>> set = validator.validate(obj,Default.class);
本文链接:https://blog.csdn.net/qq_38193966/article/details/95990268
————————————————
@Valid 数据校验 + 自定义全局异常信息
我们常用@Valid做数据校验,比如现在前端要新增一个用户,我们可以这样校验:
@RestController
public class UserController {
@PostMapping("/user") public void addUser(@RequestBody @Valid RequestDTO requestDTO){ //其余业务处理 System.out.println(requestDTO.toString()); } }
传入的数据规则如下列代码所示:
@Data
public class RequestDTO {
@NotNull(message = "名字不能为空") String name; @NotEmpty(message = "密码不能为空") String password; @Override public String toString() { return "name=" + name + ",password=" + password; } }
假设我们模仿前端伪造了一个非法数据(例如密码为空):
{
"name": "string", "password": "" }
加了@Valid注解的程序就能按我们的预期报错:
{
"timestamp": "2019-08-26T14:12:02.542+0000", "status": 400, "error": "Bad Request", "errors": [ { "codes": [ "NotEmpty.requestDTO.password", "NotEmpty.password", "NotEmpty.java.lang.String", "NotEmpty" ], "arguments": [ { "codes": [ "requestDTO.password", "password" ], "arguments": null, "defaultMessage": "password", "code": "password" } ], "defaultMessage": "密码不能为空", "objectName": "requestDTO", "field": "password", "rejectedValue": "", "bindingFailure": false, "code": "NotEmpty" } ], "message": "Validation failed for object=''requestDTO''. Error count: 1", "path": "/user" }
报错信息改进
但这样的报错信息明显太冗余了,我们想简化下,只抛出有问题字段的报错信息,这回就可以结合我们的全局异常进行处理:
1.编写自定义异常处理类,绑定要处理的异常
这里我们注意到@Valid抛出的异常类是MethodArgumentNotValidException ,所以我们将捕获该异常,并对它重新自定义异常信息
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = MethodArgumentNotValidException.class) @ResponseBody public JsonResult MyExceptionHandle(MethodArgumentNotValidException exception){ exception.printStackTrace(); BindingResult result = exception.getBindingResult(); StringBuilder errorMsg = new StringBuilder() ; if (result.hasErrors()) { List<FieldError> fieldErrors = result.getFieldErrors(); fieldErrors.forEach(error -> { System.out.println("field" + error.getField() + ", msg:" + error.getDefaultMessage()); errorMsg.append(error.getDefaultMessage()).append("!"); }); } exception.printStackTrace(); return new JsonResult(-1,errorMsg.toString() ); } }
上面的代码就是取出里面的报错信息,组装成自己需要显示的信息(这里我们封装成一个json结构,包括状态码和信息返出去):
- 试验成果
将刚刚的请求再发一遍,现在就可以看到,错误信息已经按照我们规定的格式返回了:
{
"code": -1, "msg": "密码不能为空!" }
a-from 自定义规则使用,及初始默认值规则校验失效问题
- 自定义规则使用,下面以修改密码为例
<template> <a-form ref="formRef" :model="userPassword":label-col="{ style: { width: '100px' } }" :rules="rules" label-width="80px" > <a-form-item label="原密码" name="originalPassword">//name在我们使用规则校验时,这个字段必填,用来对应个字段规则的判定 <a-input-password v-model:value="userPassword.originalPassword" placeholder="请输入原密码" type="password" show-password /> </a-form-item> <a-form-item label="新密码" name="newPassword"> <a-input-password v-model:value="userPassword.newPassword" placeholder="请输入新密码" type="password" show-password /> </a-form-item> <a-form-item label="确认密码" name="confirmPassword"> <a-input-password v-model:value="userPassword.confirmPassword" placeholder="请确认密码" type="password" show-password /> </a-form-item> </a-form> </template> <script lang="ts" setup> import { ref, reactive } from "vue"; import { CloSEOutlined, CheckOutlined } from "@ant-design/icons-vue"; import { notification } from "ant-design-vue"; import { RuleObject } from "ant-design-vue/es/form/interface"; const Passwordvisible=ref(false); const formRef = ref(); const userPassword = reactive({ originalPassword: "", newPassword: "", confirmPassword: "", }); //新密码判定 let validatePass = async (rule: RuleObject, value: string) => { const reg = /^[\u4e00-\u9fa5]+$/; if (value === "") { return Promise.reject("新密码不能为空!"); } else if (reg.test(value)) { return Promise.reject("密码中不能出现汉字"); } else { if (userPassword.confirmPassword !== "") { formRef.value.validateFields("confirmPassword"); } return Promise.resolve(); } }; //确认密码判定 let validatePass2 = async (rule: RuleObject, value: string) => { const reg = /^[\u4e00-\u9fa5]+$/; if (value === "") {//校验是否为空,我们在写自定义规则的时候,就可以把其他的,比如必填判定等,都可以写进一个方法了 return Promise.reject("二次密码不能为空!");//reject报出警告 } else if (reg.test(value)) { return Promise.reject("密码中不能出现汉字"); } else if (value !== userPassword.newPassword) { return Promise.reject("两次输入密码不一致!"); } else { return Promise.resolve();//resolve验证通过 } }; const rules = { originalPassword: [ { required: true, message: "原密码不能为空", trigger: "blur" }, ], newPassword: [{ required: true, validator: validatePass, trigger: "blur" }],//validator为自定义校验,后面写自己需要的校验方法即可 confirmPassword: [ { required: true, validator: validatePass2, trigger: "blur" }, ], }; const emit = defineEmits<{ (event: "cancel", data: any): void; }>(); const cancel = () => { emit("cancel", { type: "cancel" }); };
//进行规则校验 const submit = () => { formRef.value .validate() .then(() => { passwordSubmit(); }) .catch(() => {}); }; //修改密码 const passwordSubmit = () => { notification.success({ message: "密码修改成功", }); }; </script> -
初始默认值,无法校验,明明存在默认值却一直警告未输入。
这个原因:
(1.)可以看下a-form绑定的:model="userPassword"是否和自己所要判定的值,比如a-input中的v-model:value="userPassword.originalPassword"一致,如果一致,就进行第二步,如果不一致,改后试下看看好了没,还是报未输入就进行第二步。
(2.)将规则校验中{ required: true, message: "原密码不能为空", trigger: "blur" }的trigger删除,再试下,应该就好了。
目前我就遇到了这两种情况。
c# 全局钩子实现扫码枪获取信息
转发 https://www.cnblogs.com/TBW-Superhero/p/8659306.html
1.扫描枪获取数据原理基本相当于键盘数据,获取扫描枪扫描出来的数据,一般分为两种实现方式。
a)文本框输入获取焦点,扫描后自动显示在文本框内。
b)使用键盘钩子,勾取扫描枪虚拟按键,根据按键频率进行手动输入和扫描枪扫描判断。
2.要实现系统钩子其实很简单,调用三个Win32的API即可。
SetwindowsHookEx 用于设置钩子。(设立一道卡子,盘查需要的信息)
CallNextHookEx 用于传递钩子(消息是重要的,所以从哪里来,就应该回到哪里去,除非你决定要封锁消息)
UnhookWindowsHookEx 卸载钩子(卸载很重要,卡子设多了会造成拥堵)
版本一:
using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; using System.Reflection; using System.Diagnostics; namespace SaomiaoTest2 { /// <summary> /// 获取键盘输入或者USB扫描枪数据 可以是没有焦点 应为使用的是全局钩子 /// USB扫描枪 是模拟键盘按下 /// 这里主要处理扫描枪的值,手动输入的值不太好处理 /// </summary> public class BardCodeHooK { public delegate void BardCodeDeletegate(BarCodes barCode); public event BardCodeDeletegate BarCodeEvent; //定义成静态,这样不会抛出回收异常 private static HookProc hookproc; public struct BarCodes { public int VirtKey;//虚拟吗 public int ScanCode;//扫描码 public string KeyName;//键名 public uint Ascll;//Ascll public char Chr;//字符 public string BarCode;//条码信息 保存最终的条码 public bool IsValid;//条码是否有效 public DateTime Time;//扫描时间,} private struct EventMsg { public int message; public int paramL; public int paramH; public int Time; public int hwnd; } [DllImport("user32.dll",CharSet = CharSet.Auto,CallingConvention = CallingConvention.StdCall)] private static extern int SetwindowsHookEx(int idHook,HookProc lpfn,IntPtr hInstance,int threadId); [DllImport("user32.dll",CallingConvention = CallingConvention.StdCall)] private static extern bool UnhookWindowsHookEx(int idHook); [DllImport("user32.dll",CallingConvention = CallingConvention.StdCall)] private static extern int CallNextHookEx(int idHook,int nCode,Int32 wParam,IntPtr lParam); [DllImport("user32",EntryPoint = "GetKeyNameText")] private static extern int GetKeyNameText(int IParam,StringBuilder lpBuffer,int nSize); [DllImport("user32",EntryPoint = "GetKeyboardState")] private static extern int GetKeyboardState(byte[] pbKeyState); [DllImport("user32",EntryPoint = "ToAscii")] private static extern bool ToAscii(int VirtualKey,int ScanCode,byte[] lpKeySate,ref uint lpChar,int uFlags); [DllImport("kernel32.dll")] public static extern IntPtr GetModuleHandle(string name); delegate int HookProc(int nCode,IntPtr lParam); BarCodes barCode = new BarCodes(); int hKeyboardHook = 0; string strBarCode = ""; private int KeyboardHookProc(int nCode,IntPtr lParam) { if (nCode == 0) { EventMsg msg = (EventMsg)Marshal.PtrToStructure(lParam,typeof(EventMsg)); if (wParam == 0x100)//WM_KEYDOWN=0x100 { barCode.VirtKey = msg.message & 0xff;//虚拟吗 barCode.ScanCode = msg.paramL & 0xff;//扫描码 StringBuilder strKeyName = new StringBuilder(225); if (GetKeyNameText(barCode.ScanCode * 65536,strKeyName,255) > 0) { barCode.KeyName = strKeyName.ToString().Trim(new char[] { ‘ ‘,‘\0‘ }); } else { barCode.KeyName = ""; } byte[] kbArray = new byte[256]; uint uKey = 0; GetKeyboardState(kbArray); if (ToAscii(barCode.VirtKey,barCode.ScanCode,kbArray,ref uKey,0)) { barCode.Ascll = uKey; barCode.Chr = Convert.tochar(uKey); } TimeSpan ts = DateTime.Now.Subtract(barCode.Time); if (ts.TotalMilliseconds > 50) {//时间戳,大于50 毫秒表示手动输入 strBarCode = barCode.Chr.ToString(); } else { if ((msg.message & 0xff) == 13 && strBarCode.Length > 3) {//回车 barCode.BarCode = strBarCode; barCode.IsValid = true; } strBarCode += barCode.Chr.ToString(); } barCode.Time = DateTime.Now; if (BarCodeEvent != null) BarCodeEvent(barCode);//触发事件 barCode.IsValid = false; } } return CallNextHookEx(hKeyboardHook,nCode,wParam,lParam); } //安装钩子 public bool Start() { if (hKeyboardHook == 0) { hookproc = new HookProc(KeyboardHookProc); //GetModuleHandle 函数 替代 Marshal.GetHINSTANCE //防止在 framework4.0中 注册钩子不成功 IntPtr modulePtr = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName); //WH_KEYBOARD_LL=13 //全局钩子 WH_KEYBOARD_LL // hKeyboardHook = SetwindowsHookEx(13,hookproc,Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]),0); hKeyboardHook = SetwindowsHookEx(13,modulePtr,0); } return (hKeyboardHook != 0); } //卸载钩子 public bool Stop() { if (hKeyboardHook != 0) { return UnhookWindowsHookEx(hKeyboardHook); } return true; } } }
在实践过程中,发现版本一的代码只能扫描条形码,如伴随二维码中的字母出现就不能正确获取数据。
版本二:
c# 全局钩子实现扫码枪获取信息。
转发 https://www.cnblogs.com/TBW-Superhero/p/8659306.html
1.扫描枪获取数据原理基本相当于键盘数据,获取扫描枪扫描出来的数据,一般分为两种实现方式。
a)文本框输入获取焦点,扫描后自动显示在文本框内。
b)使用键盘钩子,勾取扫描枪虚拟按键,根据按键频率进行手动输入和扫描枪扫描判断。
2.要实现系统钩子其实很简单,调用三个Win32的API即可。
SetWindowsHookEx 用于设置钩子。(设立一道卡子,盘查需要的信息)
CallNextHookEx 用于传递钩子(消息是重要的,所以从哪里来,就应该回到哪里去,除非你决定要封锁消息)
UnhookWindowsHookEx 卸载钩子(卸载很重要,卡子设多了会造成拥堵)
版本一:

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Diagnostics;
namespace SaomiaoTest2
{
/// <summary>
/// 获取键盘输入或者USB扫描枪数据 可以是没有焦点 应为使用的是全局钩子
/// USB扫描枪 是模拟键盘按下
/// 这里主要处理扫描枪的值,手动输入的值不太好处理
/// </summary>
public class BardCodeHooK
{
public delegate void BardCodeDeletegate(BarCodes barCode);
public event BardCodeDeletegate BarCodeEvent;
//定义成静态,这样不会抛出回收异常
private static HookProc hookproc;
public struct BarCodes
{
public int VirtKey;//虚拟吗
public int ScanCode;//扫描码
public string KeyName;//键名
public uint Ascll;//Ascll
public char Chr;//字符
public string BarCode;//条码信息 保存最终的条码
public bool IsValid;//条码是否有效
public DateTime Time;//扫描时间,
}
private struct EventMsg
{
public int message;
public int paramL;
public int paramH;
public int Time;
public int hwnd;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern bool UnhookWindowsHookEx(int idHook);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);
[DllImport("user32", EntryPoint = "GetKeyNameText")]
private static extern int GetKeyNameText(int IParam, StringBuilder lpBuffer, int nSize);
[DllImport("user32", EntryPoint = "GetKeyboardState")]
private static extern int GetKeyboardState(byte[] pbKeyState);
[DllImport("user32", EntryPoint = "ToAscii")]
private static extern bool ToAscii(int VirtualKey, int ScanCode, byte[] lpKeySate, ref uint lpChar, int uFlags);
[DllImport("kernel32.dll")]
public static extern IntPtr GetModuleHandle(string name);
delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);
BarCodes barCode = new BarCodes();
int hKeyboardHook = 0;
string strBarCode = "";
private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
{
if (nCode == 0)
{
EventMsg msg = (EventMsg)Marshal.PtrToStructure(lParam, typeof(EventMsg));
if (wParam == 0x100)//WM_KEYDOWN=0x100
{
barCode.VirtKey = msg.message & 0xff;//虚拟吗
barCode.ScanCode = msg.paramL & 0xff;//扫描码
StringBuilder strKeyName = new StringBuilder(225);
if (GetKeyNameText(barCode.ScanCode * 65536, strKeyName, 255) > 0)
{
barCode.KeyName = strKeyName.ToString().Trim(new char[] { '' '', ''\0'' });
}
else
{
barCode.KeyName = "";
}
byte[] kbArray = new byte[256];
uint uKey = 0;
GetKeyboardState(kbArray);
if (ToAscii(barCode.VirtKey, barCode.ScanCode, kbArray, ref uKey, 0))
{
barCode.Ascll = uKey;
barCode.Chr = Convert.ToChar(uKey);
}
TimeSpan ts = DateTime.Now.Subtract(barCode.Time);
if (ts.TotalMilliseconds > 50)
{//时间戳,大于50 毫秒表示手动输入
strBarCode = barCode.Chr.ToString();
}
else
{
if ((msg.message & 0xff) == 13 && strBarCode.Length > 3)
{//回车
barCode.BarCode = strBarCode;
barCode.IsValid = true;
}
strBarCode += barCode.Chr.ToString();
}
barCode.Time = DateTime.Now;
if (BarCodeEvent != null)
BarCodeEvent(barCode);//触发事件
barCode.IsValid = false;
}
}
return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
}
//安装钩子
public bool Start()
{
if (hKeyboardHook == 0)
{
hookproc = new HookProc(KeyboardHookProc);
//GetModuleHandle 函数 替代 Marshal.GetHINSTANCE
//防止在 framework4.0中 注册钩子不成功
IntPtr modulePtr = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
//WH_KEYBOARD_LL=13
//全局钩子 WH_KEYBOARD_LL
// hKeyboardHook = SetWindowsHookEx(13, hookproc, Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0);
hKeyboardHook = SetWindowsHookEx(13, hookproc, modulePtr, 0);
}
return (hKeyboardHook != 0);
}
//卸载钩子
public bool Stop()
{
if (hKeyboardHook != 0)
{
return UnhookWindowsHookEx(hKeyboardHook);
}
return true;
}
}
}

在实践过程中,发现版本一的代码只能扫描条形码,如伴随二维码中的字母出现就不能正确获取数据。
版本二:
版本二中的代码,实践中发现出现了获取扫描数据却省略“+”加号的情况出现。
因此在版本二中备选处添加

//判断是+ 强制添加+
else if (_key.Length == 5 && msg.paramH == 0&&msg.paramL==78&&msg.message==107)// && msg.paramH == 0
{
// 根据键盘状态和shift缓存判断输出字符
_cur = Convert.ToChar(''+'').ToString();
_result[_result.Count - 1] += _cur;
}

3.winform在无焦点情况下的使用方式:

using BarcodeScanner;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace BarCodeTest
{
public partial class Form1 : Form
{
private ScanerHook listener = new ScanerHook();
public Form1()
{
InitializeComponent();
listener.ScanerEvent += Listener_ScanerEvent;
}
private void Listener_ScanerEvent(ScanerHook.ScanerCodes codes)
{
textBox3.Text = codes.Result;
}
private void Form1_Load(object sender, EventArgs e)
{
listener.Start();
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
listener.Stop();
}
}
}

我们今天的关于day11 Django: froms组件: 数据校验 显示错误信息 渲染数据 重置数据 自定义规则 局部钩子,全局钩子的分享已经告一段落,感谢您的关注,如果您想了解更多关于@Valid 数据校验 + 自定义全局异常信息、a-from 自定义规则使用,及初始默认值规则校验失效问题、c# 全局钩子实现扫码枪获取信息、c# 全局钩子实现扫码枪获取信息。的相关信息,请在本站查询。
本文标签: