xusong 2012-07-18
表单数据的检验是应用程序必不可少的组成部分,通常来讲,表单数据的校验分为前台校验和后台校验两部分,前台校验使用JS脚本在提交数据前进行校验,后台校验在数据提交后进行校验。
出于安全性的考虑,后台校验是必不可少的,当因为某种原因前台校验失效的情况下,由于有后台校验的存在,仍能保证提交数据的合法性和有效性。
后台校验有许多种方法,有基于配置文件的校验,有基于注释的校验等等,也有许多成熟的校验框架可以使用。本文向大家介绍一种基于Hibernate元数据的校验方法,笔者曾在多个项目中使用,效果非常好,在这里与大家分享。
应用本文提到的校验方法前应该满足以下几点:
public class ValidationInterceptor extends HandlerInterceptorAdapter { @Resource(name = "&sessionFactory") private LocalSessionFactoryBean sessionFactory; @Override @SuppressWarnings("unchecked") public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { final String uri = request.getRequestURI(); //通过请求的URI找到对应的校验实体类,这个需要在外部进行配置 final String entityName = getValidation(uri); //没有配置说明这个请求不需要校验 if (entityName == null) return true; //通过实体名返回Hibernate的PersistentClass final PersistentClass clazz = sessionFactory.getConfiguration().getClassMapping(entityName); //对应的表的元数据 final Table table = clazz.getTable(); final Iterator<Column> iterator = table.getColumnIterator(); final Map<String, String> errors = new HashMap<String, String>(); while (iterator.hasNext()) { //对应的列的元数据 final Column column = iterator.next(); //列名 final String name = column.getName(); //这是数据库列映射到JAVA中的属性 final Property property = clazz.getProperty(name); //这是前台表单提交上来的值 final String value = request.getParameter(name); //如果值为空,跳过该字段的校验 if (value == null) continue; //校验非空 if (!column.isNullable() && "".equals(value.trim())) { errors.put(name, "字段"+name+"的值不能为空!"); } //校验字符串长度 else if (property.getType() instanceof StringType) { if (value.length() > column.getLength()) { errors.put(name, "字段"+name+"的值超长了!"); } } //校验日期类型 else if (property.getType() instanceof DateType) { final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); try { format.parse(value); } catch (Exception e){ errors.put(name, "字段"+name+"必须是日期类型!"); } } //校验数字类型,包括浮点数 else if (property.getType() instanceof BigDecimalType) { int precision = column.getPrecision(); int scale = column.getScale(); int front = precision - scale; String patten = ""; for (int i = 0; i < front; i++) { patten += "#"; } if (scale > 0) { patten += "."; for (int i = 0; i < scale; i++) { patten += "#"; } } final NumberFormat format = new DecimalFormat(patten); try { format.parse(value); } catch (Exception e) { errors.put(name, "字段"+name+"必须是数字类型("+patten"+")!"); } } } //如果没有错误,直接放行 if (errors.isEmpty()) return true; //有错了,生成描述错误信息的JSON串,返回前台 response.setContentType("text/json;charset=UTF-8"); response.getWriter().write(JSONObject.fromObject(errors).toString()); response.getWriter().close(); return false; } }
/test/save_log.do=com.coolfancy.blog.entity.Log /test/save_reply.do=com.coolfancy.blog.entity.Reply