搜索词>>验证码获取 耗时0.0330
  • Jquery cookie插件实现点击获取验证码后60秒内禁止重新获取

    Jquery cookie插件实现点击获取验证码后60秒内禁止重新获取,可直接拿走用,jquery,验证码获取Jquery cookie插件实现点击获取验证码后60秒内禁止重新获取,可直接拿走用<br /> 注意:本例子依赖一下库<br /> 1.jQuery<br /> 2.jQuery cookie<br /> 可根据自身环境进行修改<br /> <br /> 代码: <pre> <code class="language-html"><!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>验证码获取按钮防止刷新</title> <link rel="stylesheet" type="text/css" href="../libs/bootstrap/bootstrap-3.3.7/css/bootstrap.css"> <style type="text/css"> .content{ margin: 20px 0px 0px 20px; } </style> </head> <body> <div class="form-inline content"> <h1>验证码获取按钮防止刷新</h1> <div class="alert alert-info base64-de-out"> 注意:<br> 1.本案例依赖jQuery;<br> 2.本案例依赖jQuery的cookie插件<br> </div> <input type="text" class="form-control" placeholder="请输入邮箱地址"><button class="btn btn-default test-btn">获取验证码</button> </div> <script type="text/javascript" src="../libs/jQuery/jquery.js"></script> <script type="text/javascript" src="../libs/jQuery/plugins/cookie/jquery.cookie.js"></script> <script type="text/javascript" src="../libs/bootstrap/bootstrap-3.3.7/js/bootstrap.js"></script> <script type="text/javascript"> $(function(){ var btn=$('.test-btn'); //1.默认检测验证码按钮 checkResendCode(btn); //2.绑定点击事件 $(btn).click(function(){ //do somthing //code .... //设置按钮状态 resendCode(this); }); }) /**检查cookie中的验证码统计是否存在***/ function checkResendCode(btnObject) { if($.cookie('captchaCount')){ var count=$.cookie('captchaCount'); //设置按钮的显示和不可用状态 $(btnObject).html(count+'秒重新获取').attr('disabled',true); var resend=setInterval(function(){ if (count > 0){ $(btnObject).html(count+'秒重新获取').attr('disabled',true).css('cursor','not-allowed'); $.cookie("captchaCount", count, {path: '/', expires: (1/86400)*count}); }else { clearInterval(resend); btn.html("获取验证码").attr('disabled',false); } count--; },1000); } } /**重新发送事件***/ function resendCode(btnObject) { var count=60; var resend = setInterval(function(){ if (count > 0){ $(btnObject).html(count+"秒重新获取"); $.cookie("captchaCount", count, {path: '/', expires: (1/86400)*count}); }else { clearInterval(resend); $(btnObject).html("&nbsp;获取验证码&nbsp;").attr('disabled',false); } count--; }, 1000); $(btnObject).attr('disabled',true); } </script> </body> </html></code></pre> <br /> 效果如下:<br /> <img alt="验证码重新获取按钮" class="img-thumbnail" src="/assist/images/blog/e8dbb0e355fd4a0cac29993fff3cf1ea.png" /><br />  
  • java实现生成彩色背景图片验证码

    java实现生成彩色背景图片验证码,在登陆和注册可以使用,工具类将图片的IO流通过response输出到浏览器,在浏览器中可以使用 img标签的src属性路径写上该工具类的访问路径即可。1.页面展现 <pre> <code class="language-html"><img id="cerificationCode" src="/front/user/cardCoupon/getCerificationCode" style="margin -left: 62px" onclick="javascript:this.src='/front/user/cardCoupon/getCerificationCode?'+Math.random()"> <a style="color: #dbb04f; font-size: 0.8em; position: relative; bottom: 8px; margin-left: 5px;" onclick="javascript:$('#cerificationCode').click();">换一个</a></code></pre> <!--StartFragment -->注意:onclick="javascript:this.src='/front/user/cardCoupon/getCerificationCode?'+Math.random()"是为了刷新验证码一般都会给个随机数,必须保证每次请求的url不同 ,浏览器才会去服务端获取最新数据,相同的url浏览器优先找自己本地缓存的.<br /> <br /> 2.控制层 <pre> <code class="language-java"> @Controller @RequestMapping("/front/user/cardCoupon") public class CardCouponController extends BaseController { @RequestMapping("/getCerificationCode") public void getCerificationCode(HttpServletRequest request, HttpServletResponse response) { try { response.setHeader("Pragma", "No-cache"); response.setHeader("Cache-Control", "no-cache"); response.setDateHeader("Expires", 0); response.setContentType("image/jpeg"); // 生成随机字串 String verifyCode = VerifyCodeUtils.generateVerifyCode(4); // 存入会话session HttpSession session = request.getSession(true); // 删除以前的 session.removeAttribute("cerificationCode"); session.setAttribute("cerificationCode", verifyCode.toLowerCase()); // 生成图片 int w = 100, h = 30; VerifyCodeUtils.outputImage(w, h, response.getOutputStream(), verifyCode); } catch (IOException e) { log.error("获取验证码失败", e); e.printStackTrace(); } }</code></pre> 3.生成图片验证码工具类 <pre> <code class="language-java">package com.xinfeng.util; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Arrays; import java.util.Random; import javax.imageio.ImageIO; public class VerifyCodeUtils { public static final String VERIFY_CODES = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ"; private static Random random = new Random(); /** * 使用系统默认字符源生成验证码 * * @param verifySize * 验证码长度 * @return */ public static String generateVerifyCode(int verifySize) { return generateVerifyCode(verifySize, VERIFY_CODES); } /** * 使用指定源生成验证码 * * @param verifySize * 验证码长度 * @param sources * 验证码字符源 * @return */ public static String generateVerifyCode(int verifySize, String sources) { if (sources == null || sources.length() == 0) { sources = VERIFY_CODES; } int codesLen = sources.length(); Random rand = new Random(System.currentTimeMillis()); StringBuilder verifyCode = new StringBuilder(verifySize); for (int i = 0; i < verifySize; i++) { verifyCode.append(sources.charAt(rand.nextInt(codesLen))); } return verifyCode.toString(); } /** * 生成随机验证码文件,并返回验证码值 * * @param w * @param h * @param outputFile * @param verifySize * @return * @throws IOException */ public static String outputVerifyImage(int w, int h, File outputFile, int verifySize) throws IOException { String verifyCode = generateVerifyCode(verifySize); outputImage(w, h, outputFile, verifyCode); return verifyCode; } /** * 输出随机验证码图片流,并返回验证码值 * * @param w * @param h * @param os * @param verifySize * @return * @throws IOException */ public static String outputVerifyImage(int w, int h, OutputStream os, int verifySize) throws IOException { String verifyCode = generateVerifyCode(verifySize); outputImage(w, h, os, verifyCode); return verifyCode; } /** * 生成指定验证码图像文件 * * @param w * @param h * @param outputFile * @param code * @throws IOException */ public static void outputImage(int w, int h, File outputFile, String code) throws IOException { if (outputFile == null) { return; } File dir = outputFile.getParentFile(); if (!dir.exists()) { dir.mkdirs(); } try { outputFile.createNewFile(); FileOutputStream fos = new FileOutputStream(outputFile); outputImage(w, h, fos, code); fos.close(); } catch (IOException e) { throw e; } } /** * 输出指定验证码图片流 * * @param w * @param h * @param os * @param code * @throws IOException */ public static void outputImage(int w, int h, OutputStream os, String code) throws IOException { int verifySize = code.length(); BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); Random rand = new Random(); Graphics2D g2 = image.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); Color[] colors = new Color[5]; Color[] colorSpaces = new Color[] { Color.WHITE, Color.CYAN, Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE, Color.PINK, Color.YELLOW }; float[] fractions = new float[colors.length]; for (int i = 0; i < colors.length; i++) { colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)]; fractions[i] = rand.nextFloat(); } Arrays.sort(fractions); // Color c = getRandColor(200, 250); Color c = new Color(241, 238, 231); g2.setColor(c);// 设置背景色 g2.fillRect(0, 0, w, h); // 绘制干扰线 Random random = new Random(); g2.setColor(getRandColor(160, 200));// 设置线条的颜色 for (int i = 0; i < 20; i++) { int x = random.nextInt(w - 1); int y = random.nextInt(h - 1); int xl = random.nextInt(6) + 1; int yl = random.nextInt(12) + 1; g2.drawLine(x, y, x + xl + 40, y + yl + 20); } // 添加噪点 float yawpRate = 0.05f;// 噪声率 int area = (int) (yawpRate * w * h); for (int i = 0; i < area; i++) { int x = random.nextInt(w); int y = random.nextInt(h); int rgb = getRandomIntColor(); image.setRGB(x, y, rgb); } shear(g2, w, h, c);// 使图片扭曲 // g2.setColor(getRandColor(100, 160)); g2.setColor(new Color(208, 153, 153)); int fontSize = h - 4; Font font = new Font("Algerian", Font.ITALIC, fontSize); g2.setFont(font); char[] chars = code.toCharArray(); for (int i = 0; i < verifySize; i++) { AffineTransform affine = new AffineTransform(); affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), (w / verifySize) * i + fontSize / 2, h / 2); g2.setTransform(affine); g2.translate(5, 5); g2.drawChars(chars, i, 1, ((w - 10) / verifySize) * i + 5, h / 2 + fontSize / 2 - 10); } g2.dispose(); ImageIO.write(image, "jpg", os); } private static Color getRandColor(int fc, int bc) { if (fc > 255) fc = 255; if (bc > 255) bc = 255; int r = fc + random.nextInt(bc - fc); int g = fc + random.nextInt(bc - fc); int b = fc + random.nextInt(bc - fc); return new Color(r, g, b); } private static int getRandomIntColor() { int[] rgb = getRandomRgb(); int color = 0; for (int c : rgb) { color = color << 8; color = color | c; } return color; } private static int[] getRandomRgb() { int[] rgb = new int[3]; for (int i = 0; i < 3; i++) { rgb[i] = random.nextInt(255); } return rgb; } private static void shear(Graphics g, int w1, int h1, Color color) { /* * shearX(g, w1, h1, color); shearY(g, w1, h1, color); */ } private static void shearX(Graphics g, int w1, int h1, Color color) { int period = random.nextInt(2); boolean borderGap = true; int frames = 1; int phase = random.nextInt(2); for (int i = 0; i < h1; i++) { double d = (double) (period >> 1) * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames); g.copyArea(0, i, w1, 1, (int) d, 0); if (borderGap) { g.setColor(color); g.drawLine((int) d, i, 0, i); g.drawLine((int) d + w1, i, w1, i); } } } private static void shearY(Graphics g, int w1, int h1, Color color) { int period = random.nextInt(40) + 10; // 50; boolean borderGap = true; int frames = 20; int phase = 7; for (int i = 0; i < w1; i++) { double d = (double) (period >> 1) * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames); g.copyArea(i, 0, 1, h1, 0, (int) d); if (borderGap) { g.setColor(color); g.drawLine(i, (int) d, i, 0); g.drawLine(i, (int) d + h1, i, h1); } } } } </code></pre> 4.展现结果<br /> <img src="file:///C:\Users\Administrator\AppData\Roaming\Tencent\Users\1023803178\QQ\WinTemp\RichOle\18955_V`_5P9O)YU]~}{U3R.png" /><img alt="" class="img-thumbnail" src="/assist/images/blog/7826a5549c5e47728c7e9dace3667280.png" /><br />  
  • java编程怎么生成二维码详细教程

    java生成带参数二维码,java怎么生成二维码?java生成二维码工具类。如果你还在寻求这些问题的解答就进来看看吧。java怎么生成二维码详细教程
  • Spring mvc文件下载IE/Edge中文乱码解决

    Spring mvc文件下载IE/Edge中文乱码解决,在spring mvc项目开发中,我们可能经常遇到文件的上传和下载操作。这里将讲解在IE/Edge浏览器中文件下载中文乱码的解决方法。<h2>引言</h2>     在spring mvc项目开发中,我们可能经常遇到文件的上传和下载操作。这里将讲解在IE/Edge浏览器中文件下载中文乱码的解决方法。 <h2>一.解决spring mvc IE/Edge浏览器乱码</h2> 编写controller测试代码: <pre> <code class="language-java">package net.xqlee.project.controller; import java.net.URLEncoder; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @Controller public class FileController { /** * 文件下载 * * @param request * @param response */ @GetMapping("download.do") public void downloadFile(HttpServletRequest request, HttpServletResponse response) { try { String fileName = "中文测试.DAT"; response.getWriter().write("中文测试你好"); fileName = dealFileName(request, fileName); response.addHeader("Content-Disposition", "attachment;filename=" + fileName); } catch (Exception e) { e.printStackTrace();// logger } } /** * 处理IE/Edge(win10)浏览器中文乱码 * * @param request * @param fileName * @return */ public String dealFileName(HttpServletRequest request, String fileName) { try { String codeFileName = ""; String agent = request.getHeader("User-Agent"); if (agent == null) { return fileName; } agent = agent.toUpperCase(); if (null == agent) { codeFileName = new String(fileName.getBytes("UTF-8"), "ISO8859-1"); } else if (-1 != agent.indexOf("MSIE") || -1 != agent.indexOf("TRIDENT") || -1 != agent.indexOf("EDGE")) { codeFileName = URLEncoder.encode(fileName, "UTF-8"); } else { codeFileName = new String(fileName.getBytes("UTF-8"), "ISO8859-1"); } return codeFileName; } catch (Exception e) { e.printStackTrace();// logger return fileName; } } } </code></pre> <br /> 注意观察上面的代码,解决乱码主要在dealFilename();这个方法中进行处理的。FileName进行get UTF8字符集是因为当前代码的编码格式为UTF-8如果是GBK则更改为GBK<br /> <br /> 二.测试IE/Edge浏览器中文乱码的解决 <h3>2.1启动刚才controller所在的项目。</h3> <h3>2.2访问文件下载地址查看结果</h3> 文件下载地址为:http://localhost:8080/download.do<br /> <br /> 观察IE浏览器:<br /> <img alt="Spring MVC IE浏览器乱码解决测试结果" class="img-thumbnail" src="/assist/images/blog/57cdaf3f0eca43ba8934d277eda4e82a.png" /><br /> <br /> 从上图可以看到中文已经正常显示。接下来测试win10的Edge浏览器:<br /> <img alt="Spring MVC Edge浏览器乱码解决测试结果" class="img-thumbnail" src="/assist/images/blog/6c691febe79746d3a742b487b00efb84.png" />从上图也能看到中午呢乱码问题已经得到解决。<br />  
  • Spring Boot 2.0 REST API 接口的数据验证

    1.概要在本Spring boot教程中,我们将学习如何验证发送到PUT/POST API请求的数据BODY1.概要在本Spring boot教程中,我们将学习如何验证发送到PUT/POST API请求的数据BODY。我们还将学习在API响应中添加自定义错误消息以提示错误。在这个演示中,我们将主要看到两个主要的验证案例 -HTTP POST /employees和请求正文不包含有效值或缺少一些字段。它将在响应主体中返回带有适当消息的HTTP状态代码400。/employees/{id}请求中会发送HTTP GET 和INVALID ID。它会在响应主体中返回HTTP状态码404和正确的消息。2.创建REST 模型和API类 EmployeeVO.java@XmlRootElement(name = "employee") @XmlAccessorType(XmlAccessType.FIELD) public class EmployeeVO extends ResourceSupport implements Serializable { private Integer employeeId; private String firstName; private String lastName; private String email; public EmployeeVO(Integer id, String firstName, String lastName, String email) { super(); this.employeeId = id; this.firstName = firstName; this.lastName = lastName; this.email = email; } public EmployeeVO() { } //Removed setter/getter for readability } EmployeeRESTController.java@PostMapping(value = "/employees") public ResponseEntity<EmployeeVO> addEmployee (@RequestBody EmployeeVO employee) { EmployeeDB.addEmployee(employee); return new ResponseEntity<EmployeeVO>(employee, HttpStatus.OK); } @GetMapping(value = "/employees/{id}") public ResponseEntity<EmployeeVO> getEmployeeById (@PathVariable("id") int id) { EmployeeVO employee = EmployeeDB.getEmployeeById(id); if(employee == null) { throw new RecordNotFoundException("Invalid employee id : " + id); } return new ResponseEntity<EmployeeVO>(employee, HttpStatus.OK); }3.应用请求验证和异常处理 默认请求支持spring的验证要应用默认验证,您只需在适当的位置添加相关注解。即使用所需的验证特定注释来注释模型类@XmlRootElement(name = "employee") @XmlAccessorType(XmlAccessType.FIELD) public class EmployeeVO extends ResourceSupport implements Serializable { private static final long serialVersionUID = 1L; public EmployeeVO(Integer id, String firstName, String lastName, String email) { super(); this.employeeId = id; this.firstName = firstName; this.lastName = lastName; this.email = email; } public EmployeeVO() { } private Integer employeeId; @NotEmpty(message = "first name must not be empty") private String firstName; @NotEmpty(message = "last name must not be empty") private String lastName; @NotEmpty(message = "email must not be empty") @Email(message = "email should be a valid email") private String email; //Removed setter/getter for readability }通过@Valid注释启用对请求主体的验证自定义验证以添加有意义的信息默认的弹簧验证工作,并提供有关错误的信息超载,这就是为什么你应该根据你的应用程序的需要定制它。您只能提供所需的错误信息,并且语句非常清晰。额外的信息也不建议。建立有意义的例外并且足够好地描述问题始终是一个很好的建议。一种方法是创建单独的类来表示特定的业务用例失败,并在该用例失败时返回它们。 例如,我已经RecordNotFoundException为所有buch场景创建了一个类,在这个场景中,资源被其ID所请求,并且系统中找不到资源。 import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; @ResponseStatus(HttpStatus.NOT_FOUND) public class RecordNotFoundException extends RuntimeException { public RecordNotFoundException(String exception) { super(exception); } } 同样,我写了一个特殊的类,它将被返回所有失败案例。为所有API提供一致的错误消息结构,帮助API消费者编写更健壮的代码import java.util.List; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "error") public class ErrorResponse { public ErrorResponse(String message, List<String> details) { super(); this.message = message; this.details = details; } //General error message about nature of error private String message; //Specific errors in API request processing private List<String> details; //Getter and setters } 现在添加一个类,ResponseEntityExceptionHandler并使用注释对其进行@ControllerAdvice注解。ResponseEntityExceptionHandler是一个方便的基类,@RequestMapping通过@ExceptionHandler方法提供跨所有方法的集中式异常处理。@ControllerAdvice更适用于在应用程序启动时启用自动扫描和配置。CustomExceptionHandler.javaimport java.util.ArrayList; import java.util.List; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.validation.ObjectError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.context.request.WebRequest; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; @SuppressWarnings({"unchecked","rawtypes"}) @ControllerAdvice public class CustomExceptionHandler extends ResponseEntityExceptionHandler { @ExceptionHandler(Exception.class) public final ResponseEntity<Object> handleAllExceptions(Exception ex, WebRequest request) { List<String> details = new ArrayList<>(); details.add(ex.getLocalizedMessage()); ErrorResponse error = new ErrorResponse("Server Error", details); return new ResponseEntity(error, HttpStatus.INTERNAL_SERVER_ERROR); } @ExceptionHandler(RecordNotFoundException.class) public final ResponseEntity<Object> handleUserNotFoundException(RecordNotFoundException ex, WebRequest request) { List<String> details = new ArrayList<>(); details.add(ex.getLocalizedMessage()); ErrorResponse error = new ErrorResponse("Record Not Found", details); return new ResponseEntity(error, HttpStatus.NOT_FOUND); } @Override protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { List<String> details = new ArrayList<>(); for(ObjectError error : ex.getBindingResult().getAllErrors()) { details.add(error.getDefaultMessage()); } ErrorResponse error = new ErrorResponse("Validation Failed", details); return new ResponseEntity(error, HttpStatus.BAD_REQUEST); } } 以上类处理各种异常情况,包括RecordNotFoundException:它还处理@RequestBody注释对象中的请求验证错误。让我们看看它是如何工作的。请求验证演示1)HTTP GET / employees / 1 [有效]HTTP Status : 200 { "employeeId": 1, "firstName": "firstName", "lastName": "lastName", "email": "email@gamil.com", } ​2)HTTP GET / employees / 23 [INVALID]HTTP Status : 404 { "message": "Record Not Found", "details": [ "Invalid employee id : 23" ] } ​3)HTTP POST / employees [INVALID]请求参数: { "lastName": "Bill", "email": "ibill@gmail.com" }响应结果: HTTP Status : 400 { "message": "Validation Failed", "details": [ "first name must not be empty" ] } ​4)HTTP POST / employees [INVALID]请求参数: { "email": "ibill@gmail.com" }响应结果: HTTP Status : 400 { "message": "Validation Failed", "details": [ "last name must not be empty", "first name must not be empty" ] } ​5)HTTP POST / employees [INVALID]请求参数: { "firstName":"Lokesh", "email": "ibill_gmail.com" //invalid email in request }响应内容: HTTP Status : 400 { "message": "Validation Failed", "details": [ "last name must not be empty", "email should be a valid email" ] }​可用的注解在上面的例子中,我们只使用了几个注释,如@NotEmpty和@Email。还有更多这样的注释来验证请求数据。需要时检查出来。注解使用说明@AssertFalse注释的元素必须是false。@AssertTrue注释的元素必须为true。@DecimalMax带注释的元素必须是其值必须小于或等于指定最大值的数字。@DecimalMin带注释的元素必须是其值必须高于或等于指定最小值的数字。@Future注释元素必须是未来的即时,日期或时间。@Max带注释的元素必须是其值必须小于或等于指定最大值的数字。@Min带注释的元素必须是其值必须高于或等于指定最小值的数字。@Negative带注释的元素必须是严格负数。@NotBlank带注释的元素不得null并且必须至少包含一个非空白字符。@NotEmpty带注释的元素不能null也不是空的。@NotNull注释的元素不能是null。@Null注释的元素必须是null。@Pattern注释的CharSequence必须与指定的正则表达式匹配。@Positive带注释的元素必须是严格的正数。@Size注释的元素大小必须在指定的边界之间(包含)。  总结 spring boot REST验证教程中,我们学到了 -通过ID获取资源时验证ID。验证POST / PUT API中的请求主体字段。在API响应中发送一致且结构化的错误响应。提示:项目源码下载demo-springboot2-rest-valid.zip
  • samba 中文乱码解决

    samba 中文乱码解决步骤一:查看系统编码​​​​​​​
  • Java Bean 基础验证

    在这篇快速文章中,我们将介绍使用标准框架 - JSR 380(也称为Bean Validation 2.0)来验证Java bean的基础知识。当然,在大多数应用程序中验证用户输入是超常见的需求,而Java Bean验证框架已成为处理这种逻辑的事实上的标准。<h2 style="margin-left:0px; margin-right:0px; text-align:start"><strong>1.概述</strong></h2> <blockquote> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway">在这篇快速文章中,我们将<strong>介绍</strong>使用标准框架 - JSR 380(也称为<em>Bean Validation 2.0)</em><strong>来验证Java bean的基础知识</strong><em>。</em></span></span><br /> <span style="color:#535353"><span style="font-family:raleway">当然,在大多数应用程序中验证用户输入是超常见的需求,而Java Bean验证框架已成为处理这种逻辑的事实上的标准。</span></span></p> </blockquote> <h2 style="margin-left:0px; margin-right:0px; text-align:start"><strong>2. JSR 380</strong></h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">JSR 380是用于Bean验证,JavaEE的和的JavaSE的一部分,这确保了一个bean的属性符合特定条件,使用注释如Java API的说明书中<em>@NotNull</em>,<em>@Min</em>,和  <em>@Max</em>。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">该版本需要Java 8或更高版本,并利用Java 8中添加的新功能(例如类型注释),并支持新类型(如<em>Optional</em>和<em>LocalDate)</em>。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">有关规格的完整信息,请继续阅读<a href="https://jcp.org/en/jsr/detail?id=380" rel="external nofollow" style="box-sizing:border-box; color:#63b175; text-decoration:none" target="_blank">JSR 380</a>。</span></span></span><br />  </p> <h2 style="margin-left:0px; margin-right:0px; text-align:start"><strong>3.依赖性</strong></h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">我们将使用Maven示例来显示所需的依赖关系,但当然,可以使用各种方式添加这些jar。</span></span></span><br />  </p> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>3.1。验证API</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">根据JSR 380规范,<em>validation-api</em>依赖包含标准验证API:</span></span></span></p> <pre> <code class="language-xml"><dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>2.0.0.Final</version> </dependency></code></pre>   <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>3.2。验证API参考实现</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff"><strong>Hibernate Validator是验证API的参考实现。</strong></span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">要使用它,我们必须添加以下依赖项:</span></span></span></p> <pre> <code class="language-xml"><dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.2.Final</version> </dependency> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator-annotation-processor</artifactId> <version>6.0.2.Final</version> </dependency></code></pre> 这里的一个快速提示:<strong><em>hibernate-validator</em>完全独立于Hibernate的持久化方面功能模块,</strong>并且通过添加它作为依赖项,我们不会将这些持久性方面功能模块添加到项目中。<br />   <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>3.3。表达式语言依赖关系</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">JSR 380提供了对变量插值的支持,允许违规消息中的表达式。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">要解析这些表达式,我们必须添加对表达式语言API和该API实现的依赖关系。GlassFish提供了参考实现:</span></span></span></p> <pre> <code class="language-xml"><dependency> <groupId>javax.el</groupId> <artifactId>javax.el-api</artifactId> <version>3.0.0</version> </dependency> <dependency> <groupId>org.glassfish.web</groupId> <artifactId>javax.el</artifactId> <version>2.2.6</version> </dependency></code></pre> 如果未添加这些JAR,则会在运行时收到错误消息,如下所示: <blockquote> <p><em>HV000183: Unable to load ‘javax.el.ExpressionFactory’. Check that you have the EL dependencies on the classpath, or use ParameterMessageInterpolator instead</em></p> </blockquote> <h2 style="margin-left:0px; margin-right:0px; text-align:start"><strong>4.使用验证注解</strong></h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">我们将在这里使用一个<em>用户</em> bean作为主要的例子,并且为它添加​​一些简单的验证:</span></span></span></p> <pre> <code class="language-java">import javax.validation.constraints.AssertTrue; import javax.validation.constraints.Max; import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import javax.validation.constraints.Email; public class User { @NotNull(message = "Name cannot be null") private String name; @AssertTrue private boolean working; @Size(min = 10, max = 200, message = "About Me must be between 10 and 200 characters") private String aboutMe; @Min(value = 18, message = "Age should not be less than 18") @Max(value = 150, message = "Age should not be greater than 150") private int age; @Email(message = "Email should be valid") private String email; // standard setters and getters }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">示例中使用的所有注释都是标准的JSR注释:</span></span></span></p> <ul style="list-style-type:disc"> <li><strong><em>@NotNull</em></strong> - 验证注释的属性值不为 <em> null</em></li> <li><strong><em>@AssertTrue</em></strong> - 验证注释的属性值是否为 <em>真</em></li> <li><strong><em>@Size </em></strong> - 验证注释的属性值的大小在属性<em> min</em>和<em> max之间</em> ; 可以应用于 <em> String</em>, <em> Collection</em>, <em> Map</em>和数组属性</li> <li><strong><em>@Min </em></strong> -<em>  v</em>验证注释的属性的值不小于<em>值 </em>属性</li> <li><strong><em>@Max </em></strong> - 验证注释的属性的值不大于<em>值</em>属性</li> <li><em><strong>@电子邮件</strong></em> - 验证注释的属性是一个有效的电子邮件地址</li> </ul> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">一些注释接受附加属性,但是<em>消息</em>属性对所有属性都是通用的。这是当相应属性的值未通过验证时通常会显示的消息。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">JSR中可以找到的一些附加注释是:</span></span></span></p> <ul style="list-style-type:disc"> <li><em><strong>@NotEmpty</strong></em> - 验证该属性不为空或空; 可以应用于<em> String</em>,<em> Collection</em>,<em> Map</em>或<em> Array</em>值</li> <li><em><strong>@NotBlank</strong></em> - 只能应用于文本值并验证属性不为空或空白</li> <li><em><strong>@Positive</strong></em>和<em><strong> @PositiveOrZero</strong></em> - 适用于数值并验证它们是严格正数,还是正数,包括0</li> <li><em><strong>@Negative</strong></em>和<em><strong> @NegativeOrZero</strong></em> - 应用于数字值并验证它们是严格否定的,或者是否定的,包括0</li> <li><em><strong>@Past</strong></em>和<em><strong> @PastOrPresent</strong></em> - 验证日期值是过去还是过去,包括现在; 可以应用于日期类型,包括在Java 8中添加的日期类型</li> <li><em><strong>@Future</strong>和<strong>@FutureOrPresent</strong></em> - 验证日期值是未来还是未来,包括现在</li> </ul> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff"><strong>验证注释也可以应用于集合的元素</strong>:</span></span></span></p> <pre> <code class="language-java">List<@NotBlank String> preferences;</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在这种情况下,任何添加到首选项列表的值都将被验证。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">规范<strong>还支持</strong> Java 8中<strong>的新的</strong><strong><em>可选</em></strong><strong>类型</strong>:</span></span></span></p> <pre> <code class="language-java">private LocalDate dateOfBirth; public Optional<@Past LocalDate> getDateOfBirth() { return Optional.of(dateOfBirth); }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在这里,验证框架将自动解包<em>LocalDate </em>值并对其进行验证。</span></span></span></p> <h2 style="margin-left:0px; margin-right:0px; text-align:start"><strong>5.程序化验证</strong></h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">一些框架 - 比如Spring--通过使用注释可以简单地触发验证过程。这主要是因为我们不必与编程验证API进行交互。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">现在让我们开始手动路线并以编程方式设置:</span></span></span></p> <pre> <code class="language-java">ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); Validator validator = factory.getValidator();</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">为了验证一个bean,我们必须首先有一个<em>Validator</em>对象,它是使用<em>ValidatorFactory</em>构造的  。</span></span></span></p> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>5.1。定义Bean</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">我们现在要设置这个无效的用户 - 具有空<em>名称</em>值:</span></span></span></p> <pre> <code class="language-java">User user = new User(); user.setWorking(true); user.setAboutMe("Its all about me!"); user.setAge(50);</code></pre> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>5.2。验证Bean</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">现在我们有了一个<em>Validator</em>,我们可以通过将它传递给<em>validate</em>方法来验证我们的bean 。任何违反<em>用户</em>对象中定义的约束条件  都将作为一个<em>Set</em>返回。</span></span></span></p> <pre> <code class="language-java">Set<ConstraintViolation<User>> violations = validator.validate(user);</code></pre> 通过遍历违规,我们可以通过使用<em>getMessage </em>方法来获取所有违规消息。 <pre> <code class="language-java">for (ConstraintViolation<User> violation : violations) { log.error(violation.getMessage()); }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在我们的示例(<em>ifNameIsNull_nameValidationFails</em>)中,该集合将包含一个  <em>ConstraintViolation</em>,其中消息“ <em>Name不能为null</em> ”。</span></span></span></p> <h2 style="margin-left:0px; margin-right:0px; text-align:start"><strong>六,总结</strong></h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">本教程重点介绍了通过标准Java验证API的简单传递,并说明了使用<em>javax.validation</em>注释和API 进行bean验证的基础知识。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">本文中的概念的实现可以在GitHub项目中找到。我们将在即将发布的文章中介绍JSR 380和Hibernate Validator的更多功能。</span></span></span></p> <br /> <br /> <br />  
  • Java Bean Validation 2.0的方法约束 Java自定义验证注解

    在本文中,我们将讨论如何使用Bean Validation 2.0(JSR-380)定义和验证方法约束。在前面的文章中,我们讨论了JSR-380及其内置的注释,以及如何实现属性验证。在这里,我们将重点讨论不同类型的方法约束,例如:<h2 style="margin-left:0px; margin-right:0px; text-align:start"><strong>1.概述</strong></h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在本文中,我们将讨论如何使用Bean Validation 2.0(JSR-380)定义和验证方法约束。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在前面的文章中(<a rel="" target="_blank"href="http://www.leftso.com/blog/389.html" rel="" style="box-sizing:border-box; color:#63b175; text-decoration:none" target="_blank">Java Bean 基础验证</a>),我们讨论了JSR-380及其内置的注释,以及如何实现属性验证。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在这里,我们将重点讨论不同类型的方法约束,例如:</span></span></span></p> <ul style="list-style-type:disc"> <li>单参数约束</li> <li>交叉<strong>复杂</strong>参数(自定义Java Bean验证注解)</li> <li>返回约束</li> </ul> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">另外,我们将看看如何使用Spring Validator手动和自动验证约束。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="font-family:raleway"><span style="background-color:#ffffff">对于以下示例,我们需要与<a rel="" target="_blank"href="http://www.leftso.com/blog/389.html" rel="" style="box-sizing:border-box; color:#63b175; text-decoration:none" target="_blank">Java Bean验证基础中</a>完全相同的依赖关系 。</span></span><br />  </p> <h2 style="margin-left:0px; margin-right:0px; text-align:start"><strong>2.方法约束声明</strong></h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">首先,<strong>我们将首先讨论如何声明方法参数的约束和方法返回的值</strong>。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">如前所述,我们可以使用来自<em>javax.validation.constraints的注解</em>  ,但我们也可以指定自定义约束(例如,对于自定义约束或交叉参数约束)。</span></span></span></p> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>2.1。单参数约束</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">定义单个参数的限制很简单。<strong>我们只需要根据需要为每个参数添加注解</strong>:</span></span></span></p> <pre> <code class="language-java">public void createReservation(@NotNull @Future LocalDate begin, @Min(1) int duration, @NotNull Customer customer) { // ... }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">同样,我们可以对构造函数使用相同的方法:</span></span></span></p> <div style="text-align:start"> <div style="margin-left:0px; margin-right:0px"> <pre> <code class="language-java">public class Customer { public Customer(@Size(min = 5, max = 200) @NotNull String firstName, @Size(min = 5, max = 200) @NotNull String lastName) { this.firstName = firstName; this.lastName = lastName; } // properties, getters, and setters }</code></pre> </div> </div> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>2.2。使用交叉复杂参数约束</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在某些情况下,我们可能需要一次验证多个值,例如,两个数值比另一个大一些。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">对于这些场景,我们可以定义自定义跨参数约束,这可能取决于两个或更多参数。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff"><strong>交叉参数约束可以被认为是等同于类级约束的方法验证</strong>。我们可以使用两者来基于多个属性来实现验证。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">让我们考虑一个简单的例子:上一节中的<em>createReservation()</em>方法的变体  接受两个<em>LocalDate</em>类型的参数<em>:</em>  开始日期和结束日期。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">因此,我们要确保<em>开始</em>是在未来,<em>结束</em>是在<em>开始</em>之后。与前面的例子不同,我们不能用单个参数约束来定义它。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">相反,我们需要一个交叉参数约束。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">与单参数约束相反,<strong>交叉参数约束在方法或构造函数中声明</strong>:</span></span></span></p> <pre> <code class="language-java">@ConsistentDateParameters public void createReservation(LocalDate begin, LocalDate end, Customer customer) { // ... }</code></pre> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>2.3。创建交叉参数约束</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">要实现<em>@ConsistentDateParameters</em>约束,我们需要两个步骤。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">首先,我们需要<strong>定义约束注解</strong>:</span></span></span></p> <pre> <code class="language-java">@Constraint(validatedBy = ConsistentDateParameterValidator.class) @Target({ METHOD, CONSTRUCTOR }) @Retention(RUNTIME) @Documented public @interface ConsistentDateParameters { String message() default "End date must be after begin date and both must be in the future"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">这里,这三个属性对于约束注释是强制性的:</span></span></span></p> <ol> <li><strong>message</strong><em>- </em>返回创建错误消息的默认密钥,这使我们能够使用消息插值</li> <li><strong>groups</strong>   - 允许我们为约束指定验证组</li> <li><strong>payload </strong> - 可由Bean Validation API的客户端使用,以将自定义有效载荷对象分配给约束</li> </ol> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">有关如何定义自定义约束的详细信息,请查看  <a href="https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#validator-customconstraints" rel="external nofollow" style="box-sizing:border-box; color:#63b175; text-decoration:none" target="_blank">官方文档</a>。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">之后,我们可以定义验证器类:</span></span></span></p> <pre> <code class="language-java">@SupportedValidationTarget(ValidationTarget.PARAMETERS) public class ConsistentDateParameterValidator implements ConstraintValidator<ConsistentDateParameters, Object[]> { @Override public boolean isValid( Object[] value, ConstraintValidatorContext context) { if (value[0] == null || value[1] == null) { return true; } if (!(value[0] instanceof LocalDate) || !(value[1] instanceof LocalDate)) { throw new IllegalArgumentException( "Illegal method signature, expected two parameters of type LocalDate."); } return ((LocalDate) value[0]).isAfter(LocalDate.now()) && ((LocalDate) value[0]).isBefore((LocalDate) value[1]); } }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">正如我们所看到的,<em>isValid() </em>方法包含实际的验证逻辑。首先,我们确保我们得到两个类型为<em>LocalDate的</em>参数<em>。</em> 之后,我们检查两者是否在未来,<em>结束</em>是在<em>开始</em>之后。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">此外,值得注意的是,很重要  <em>@SupportedValidationTarget(ValidationTarget <strong>。</strong>参数)</em>的注解  <em>ConsistentDateParameterValidator</em>类是必需的。原因是因为  <em>@ConsistentDateParameter</em>  是在方法级别上设置的,但是约束条件应该应用于方法参数(而不是方法的返回值,我们将在下一节讨论)。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">注意:Bean验证规范建议将<em>空值</em>视为有效。如果<em>null</em>不是有效值,则应该使用<em>@NotNull</em> -annotation。</span></span></span></p> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>2.4。返回值约束</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff"><strong>有时我们需要验证一个对象,因为它是由方法返回的。为此,我们可以使用返回值约束。</strong></span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">以下示例使用内置约束:</span></span></span></p> <pre> <code class="language-java">public class ReservationManagement { @NotNull @Size(min = 1) public List<@NotNull Customer> getAllCustomers() { return null; } }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">对于<em>getAllCustomers()</em>,以下约束条件适用:</span></span></span></p> <ul style="list-style-type:disc"> <li>首先,返回的列表不能为<em>空,</em>且必须至少有一个条目</li> <li>此外,该列表不能包含<em>空</em>条目</li> </ul> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>2.5。返回值自定义约束</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在某些情况下,我们可能还需要验证复杂的对象:</span></span></span></p> <pre> <code class="language-java">public class ReservationManagement { @ValidReservation public Reservation getReservationsById(int id) { return null; } }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在这个例子中,返回的<em>Reservation</em>  对象必须满足由<em>@ValidReservation</em>定义的约束,我们将在下面定义它。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">再次,<strong>我们首先必须定义约束注释</strong>:</span></span></span></p> <pre> <code class="language-java">@Constraint(validatedBy = ValidReservationValidator.class) @Target({ METHOD, CONSTRUCTOR }) @Retention(RUNTIME) @Documented public @interface ValidReservation { String message() default "End date must be after begin date " + "and both must be in the future, room number must be bigger than 0"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start">之后,我们定义类验证器:<br />  </p> <pre> <code class="language-java">public class ValidReservationValidator implements ConstraintValidator<ValidReservation, Reservation> { @Override public boolean isValid( Reservation reservation, ConstraintValidatorContext context) { if (reservation == null) { return true; } if (!(reservation instanceof Reservation)) { throw new IllegalArgumentException("Illegal method signature, " + "expected parameter of type Reservation."); } if (reservation.getBegin() == null || reservation.getEnd() == null || reservation.getCustomer() == null) { return false; } return (reservation.getBegin().isAfter(LocalDate.now()) && reservation.getBegin().isBefore(reservation.getEnd()) && reservation.getRoom() > 0); } }</code></pre> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>2.6。在构造函数中返回值</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">由于我们之前在我们的<em>ValidReservation</em>接口中定义了  <em>METHOD</em>和<em>CONSTRUCTOR</em>作为<em>目标</em>,<strong>我们也可以注释</strong><strong><em>Reservation</em></strong><strong>的构造函数</strong><strong>来验证构造的实例</strong>:</span></span></span></p> <pre> <code class="language-java">public class Reservation { @ValidReservation public Reservation( LocalDate begin, LocalDate end, Customer customer, int room) { this.begin = begin; this.end = end; this.customer = customer; this.room = room; } // properties, getters, and setters }</code></pre> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>2.7。级联验证</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">最后,Bean Validation API使我们不仅可以验证单个对象,还可以使用所谓的级联验证验证对象图。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff"><strong>因此,如果我们想验证复杂的对象,我们可以使用<em>@Valid</em>进行级联验证</strong>。这适用于方法参数以及返回值。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">假设我们有一个带有一些属性约束的<em>Customer</em>类:</span></span></span></p> <pre> <code class="language-java">public class Customer { @Size(min = 5, max = 200) private String firstName; @Size(min = 5, max = 200) private String lastName; // constructor, getters and setters }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start">一个<em>预定</em>类可能有一个<em>客户</em>的财产,以及与约束进一步特性:</p> <pre> <code class="language-java">public class Reservation { @Valid private Customer customer; @Positive private int room; // further properties, constructor, getters and setters }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start">如果我们现在引用<em>Reservation</em>作为方法参数,<strong>我们可以强制所有属性的递归验证</strong>:<br />  </p> <pre> <code class="language-java">public void createNewCustomer(@Valid Reservation reservation) { // ... }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">我们可以看到,我们在两个地方使用<em>@Valid</em>:</span></span></span></p> <ul style="list-style-type:disc"> <li>在<em>保留</em>参数上:当<em>createNewCustomer()</em>被调用时,它触发<em>Reservation-</em> object 的验证</li> <li>由于我们在这里有一个嵌套的对象图,我们还必须在<em>customer- </em><em>attribute</em>上添加一个<em>@Valid</em>:因此,它会触发验证这个嵌套属性</li> </ul> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">这也适用于返回<em>预留</em>类型对象的方法  :</span></span></span></p> <div style="text-align:start"> <div style="margin-left:0px; margin-right:0px"> <pre> <code class="language-java">@Valid public Reservation getReservationById(int id) { return null; }</code></pre> </div> </div> <h2 style="margin-left:0px; margin-right:0px; text-align:start"><strong>3.验证方法约束</strong></h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在上一节中声明约束之后,我们现在可以继续实际验证这些约束。为此,我们有多种方法。</span></span></span></p> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>3.1。使用Spring自动验证</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff"><strong>Spring Validation提供了与Hibernate Validator的集成。</strong></span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">注意:Spring验证基于AOP,并使用Spring AOP作为默认实现。因此,验证只适用于方法,但不适用于构造函数。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">如果我们现在希望Spring自动验证我们的约束,我们必须做两件事:</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff"><strong>首先,我们必须使用<em>@Validated</em></strong><strong>注释应该验证的  </strong><strong><em>bean</em></strong>:</span></span></span><br />  </p> <pre> <code class="language-java">@Validated public class ReservationManagement { public void createReservation(@NotNull @Future LocalDate begin, @Min(1) int duration, @NotNull Customer customer){ // ... } @NotNull @Size(min = 1) public List<@NotNull Customer> getAllCustomers(){ return null; } }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><strong>其次,我们必须提供一个<em>MethodValidationPostProcessor</em> bean:</strong></p> <pre> <code class="language-java">@Configuration @ComponentScan({ "org.baeldung.javaxval.methodvalidation.model" }) public class MethodValidationConfig { @Bean public MethodValidationPostProcessor methodValidationPostProcessor() { return new MethodValidationPostProcessor(); } }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">如果违反约束,容器现在将抛出  <em>javax.validation.ConstraintViolationException</em>。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">如果我们使用Spring Boot,只要<em>hibernate-validator</em>在类路径中,容器就会为我们注册一个  <em>MethodValidationPostProcessor </em> bean  。</span></span></span></p> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>3.2。CDI自动验证(JSR-365)</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">从版本1.1开始,Bean Validation与CDI(用于Java EE的上下文和依赖注入)协同工作。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">如果我们的应用程序在Java EE容器中运行,那么容器将在调用时自动验证方法约束。</span></span></span></p> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>3.3。程序化验证</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">对于  <strong>独立Java应用程序中的手动方法验证</strong>,我们可以使用  <em>javax.validation.executable.ExecutableValidator</em>接口。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">我们可以使用以下代码检索实例:</span></span></span></p> <pre> <code class="language-java">ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); ExecutableValidator executableValidator = factory.getValidator().forExecutables();</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">ExecutableValidator提供了四种方法:</span></span></span></p> <ul style="list-style-type:disc"> <li>用于方法验证的<em>validateParameters()</em>和<em>validateReturnValue()</em></li> <li>用于构造函数验证的<em>validateConstructorParameters()</em>和<em>validateConstructorReturnValue()</em></li> </ul> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">验证我们的第一个方法<em>createReservation()</em>的参数如下所示:</span></span></span></p> <pre> <code class="language-java">ReservationManagement object = new ReservationManagement(); Method method = ReservationManagement.class .getMethod("createReservation", LocalDate.class, int.class, Customer.class); Object[] parameterValues = { LocalDate.now(), 0, null }; Set<ConstraintViolation<ReservationManagement>> violations = executableValidator.validateParameters(object, method, parameterValues);</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff"><strong>注意:官方文档不鼓励直接从应用程序代码调用此接口,而是通过方法拦截技术(如AOP或代理)来使用它。</strong></span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">如果您有兴趣如何使用  <em>ExecutableValidator</em>接口,可以查看<a href="http://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#section-validating-executable-constraints" rel="external nofollow" style="box-sizing:border-box; color:#63b175; text-decoration:none" target="_blank">官方文档</a>。</span></span></span></p> <h2 style="margin-left:0px; margin-right:0px; text-align:start"><strong>4。总结</strong></h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在本教程中,我们快速浏览了如何使用Hibernate Validator的方法约束,同时我们还讨论了JSR-380的一些新功能。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">首先,我们讨论了如何声明不同类型的约束:</span></span></span></p> <ul style="list-style-type:disc"> <li>单参数约束</li> <li>跨参数</li> <li>返回值约束</li> </ul> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">我们还看了如何使用Spring Validator手动和自动验证约束。</span></span></span></p>
  • centos6源码安装MySQL5.6

    centos6源码安装MySQL5.6<p>1.安装mysql5.6依存包</p> <p>2.下载编译包</p> <pre> <code class="language-html">wget https://dev.mysql.com/get/Downloads/MySQL-5.6/mysql-5.6.35-linux-glibc2.5-x86_64.tar.gz tar xvf mysql-5.6.35-linux-glibc2.5-x86_64.tar.gz</code></pre> <p>3.复制到指定目录</p> <pre> <code class="language-html">mv mysql-5.6.35-linux-glibc2.5-x86_64 /usr/local/mysql</code></pre> <p>4.创建mysql用户和组</p> <pre> <code class="language-html">groupadd mysql useradd -r -g mysql mysql -d /usr/local/mysql passwd mysql</code></pre> <p>5.修改目录权限</p> <pre> <code class="language-html">chown -R mysql:mysql /usr/local/mysql</code></pre> <p>6.安装数据库</p> <pre> <code class="language-html">su mysql /usr/local/mysql/scripts/mysql_install_db --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data exit</code></pre> <p>7.复制mysql配置文件</p> <pre> <code class="language-html">cd /usr/local/mysql/support-files cp my-default.cnf /etc/my.cnf</code></pre> <p>8.添加系统服务</p> <pre> <code class="language-html">cp mysql.server /etc/init.d/mysql chkconfig mysql on</code></pre> <p>9.添加环境变量</p> <pre> <code class="language-html">vim /etc/profile</code></pre> <p>在最下面添加</p> <pre> <code class="language-html">export MYSQL_HOME="/usr/local/mysql" export PATH="$PATH:$MYSQL_HOME/bin"</code></pre> <p>保存退出后,执行生效代码</p> <pre> <code class="language-html">. /etc/profile</code></pre> <p>10.启动mysql</p> <pre> <code class="language-html">service mysql start</code></pre> <p>11.设置root密码</p> <pre> <code class="language-html">mysqladmin -u root password '123456'</code></pre> <p>12.设置默认端口</p> <pre> <code class="language-html">vim /etc/my.cnf</code></pre> <pre> <code class="language-html">[mysqld] basedir=/usr/local/mysql datadir=/usr/local/mysql/data port=3306 server_id=1 socket=/tmp/mysql.sock</code></pre> <p>13.允许所有外部链接访问(可选)</p> <pre> <code class="language-html">mysql -u root -p</code></pre> <p>mysql命令行输入</p> <pre> <code class="language-html">GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '123456' WITH GRANT OPTION; FLUSH PRIVILEGES;</code></pre> <br /> <br /> 相关文档:<br /> <a rel="" target="_blank"href="http://www.leftso.com/blog/224.html" rel="" target="_blank">yum安装MySQL数据库</a><br />  
  • Spring Boot 2.0 hibernate validate List 验证

    Spring Boot 2.0 hibernate validate List 验证Spring Boot 2.0 hibernate validate List 验证