`
javaest
  • 浏览: 61522 次
  • 性别: Icon_minigender_1
  • 来自: 长春
文章分类
社区版块
存档分类
最新评论

基于JAVA标注实现统一的前台(JS层)后台(JAVA层)想法

    博客分类:
  • JAVA
阅读更多
原创,非转
基于JAVA标注实现统一的前台(JS层)后台(JAVA层)想法[/b]
通过标注的方式进行前后台的统一验证的好处是很多的,增强前后台验证的一致性,减少代码的重复,不需要前台与一份验证,后台再写一份了。

本人想基于这种方式写一个基于Annotation的完整的Validator的开源的小框架,但发现要做的事情很多,工作量很大,要一点一点的来,一点一点的完善,最后闲时写了个大 概,与大家一起探讨
  1. 通过JAVA标注将前台和后台的验证规则标到JAVA的值对象的类中。
  2. Validator在初始化的过程中,一次性读入JAVA的值对象的类中验证规则的标注信息,并生成前台需要的校验的JS文件。
  3. 前台页面可以直接引入自动生成的校验的JS文件,进行校验。a
  4. 后台得到从前台请求request绑定好值的JAVA的值对象,通过AnnotationValidator类进行验证。

以下是Annotation标注的代码。

进行不可以为空的校验标注
@Retention (RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)

public @interface CanNotNull {	

}

进行是否是整数的校验标注
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface IsInteger {
	public int minWidth() default 1;
	public int maxWidth() default Integer.MAX_VALUE;
	public  int minValue() default Integer.MIN_VALUE;
	public  int maxValue() default Integer.MAX_VALUE;

}


用于添写字段中文的标注


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface FieldDesc {
	public String value();

}


验证器的代码:
[size=x-small]package com.javaest.validity.process;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.javaest.util.StringUtils;
import com.javaest.validity.annotation.CanNotNull;
import com.javaest.validity.annotation.FieldDesc;
import com.javaest.validity.annotation.IsInteger;
import com.javaest.validity.test.pojo.Student;

public class PojoBeanAnnotationValiditer {
	private static Map<String, Map> allValidityRuleMap = new HashMap<String, Map>();
	private static Map<String, Map> allFieldDescMap = new HashMap<String, Map>();
	private static String jsValiditerFilePath;
	private static String[] pojoBeanPackageName;
	/**
	 * 
		将指定的包下边的所有Pojo类的标注信息一次性的读取到Map中,以备以后验证对象时使用
	 */
	public static void loadAllClassAnnotationValidityInfoInPackage(String[] packageNameArr)
			throws IllegalArgumentException, SecurityException, IllegalAccessException, NoSuchMethodException,
			InvocationTargetException, ClassNotFoundException, IOException {
		for (int i = 0; i < packageNameArr.length; i++) {
			List<Class> classList = ReflectUtils.getAllClassInPackage(packageNameArr[i]);
			for (int j = 0; j < classList.size(); j++) {
				Class currClass = classList.get(j);
				String classFullName = currClass.getPackage().getName() + "." + currClass.getName();
				Map[] validityRuleMapAndFieldDescMap = loadValidityRuleAndCreateValidityJsFile(currClass);
				allValidityRuleMap.put(classFullName, validityRuleMapAndFieldDescMap[0]);
				allFieldDescMap.put(classFullName, validityRuleMapAndFieldDescMap[1]);
			}
		}
	}
	/*
	 * 对具体的一个类的标注做处理,读入字段描述 信息,读入非空验证信息,读入整数验证信息,并根据这些信息生成JS代码。
	 */

	private static Map[] loadValidityRuleAndCreateValidityJsFile(Class currClass) throws IllegalArgumentException,
			IllegalAccessException, SecurityException, NoSuchMethodException, InvocationTargetException, IOException {
		StringBuffer validityCanNotNullJsStrBuf = new StringBuffer();
		StringBuffer validityIsIntegerJsStrBuf = new StringBuffer();
		Field[] fieldArr = currClass.getDeclaredFields();
		List<String> canNotNullFieldNameList = new ArrayList<String>();
		List<IsIntegerValiditerRuleInfo> isIntegerValiditerRuleInfoList = new ArrayList<IsIntegerValiditerRuleInfo>();
		Map<String, String> fieldDescMap = new HashMap<String, String>();
		for (int i = 0; i < fieldArr.length; i++) {
			String currFieldName = fieldArr[i].getName();
			//读入字段描述 信息
			FieldDesc fieldDescAnnotation = fieldArr[i].getAnnotation(FieldDesc.class);
			if (fieldDescAnnotation != null) {
				String fieldDesc = fieldDescAnnotation.value();
				System.out.println(fieldDesc);
				fieldDescMap.put(currFieldName, fieldDesc);
			}
			else {
				fieldDescMap.put(currFieldName, currFieldName);
			}
			//读入非空验证信息
			if (fieldArr[i].isAnnotationPresent(CanNotNull.class)) {				
				canNotNullFieldNameList.add(currFieldName);
				validityCanNotNullJsStrBuf.append("if(document.all." + currFieldName + ".value.trim()==\"\"){alert('"
						+ fieldDescMap.get(currFieldName) + "不可以为空');}\n");
			}
			//读入整数验证信息
			IsInteger isIntegerAnnotation = fieldArr[i].getAnnotation(IsInteger.class);
			if (isIntegerAnnotation != null) {
				int minWidth = isIntegerAnnotation.minWidth();
				int maxWidth = isIntegerAnnotation.maxWidth();
				int minValue = isIntegerAnnotation.minValue();
				int maxValue = isIntegerAnnotation.maxValue();
				IsIntegerValiditerRuleInfo isIntegerValiditerRuleInfo = new IsIntegerValiditerRuleInfo(currFieldName,
						minWidth, maxWidth, minValue, maxValue);
				isIntegerValiditerRuleInfoList.add(isIntegerValiditerRuleInfo);
				if (minWidth > 0) {
					validityIsIntegerJsStrBuf.append("if(document.all." + currFieldName
							+ ".value.length()<minWidth){alert('" + fieldDescMap.get(currFieldName) + "宽度不够!');}\n");
				}
				if (maxWidth < Integer.MAX_VALUE) {
					validityIsIntegerJsStrBuf.append("if(document.all." + currFieldName
							+ ".value.length()>maxWidth){alert('" + fieldDescMap.get(currFieldName) + "宽度太长!');}\n");
				}
				if (minValue > Integer.MIN_VALUE) {
					validityIsIntegerJsStrBuf.append("if(document.all." + currFieldName + ".value*1<minValue){alert('"
							+ fieldDescMap.get(currFieldName) + "的数值太小!');}\n");
				}
				if (maxValue < Integer.MAX_VALUE) {
					validityIsIntegerJsStrBuf.append("if(document.all." + currFieldName + ".value*1>maxValue){alert('"
							+ fieldDescMap.get(currFieldName) + "的数值太大!');}\n");
				}
			}
		}
		Map<String, List> classValidityRuleMap = new HashMap<String, List>();
		classValidityRuleMap.put("canNotNullFieldNameList", canNotNullFieldNameList);
		classValidityRuleMap.put("isIntegerValiditerRuleInfoList", isIntegerValiditerRuleInfoList);
		//根据这些信息生成JS代码
		BufferedWriter jsFileWriter = new BufferedWriter(new FileWriter(new File(jsValiditerFilePath
				+ java.io.File.separator + currClass.getName() + ".js")));
		jsFileWriter.write(validityCanNotNullJsStrBuf.toString());
		jsFileWriter.write(validityIsIntegerJsStrBuf.toString());
		jsFileWriter.close();
		return new Map[] { classValidityRuleMap, fieldDescMap };

	}
	/*
	 * 具体的后台验证过程
	 */

	public static ValidityResult validity(Object currObj) throws IllegalArgumentException, IllegalAccessException,
			SecurityException, NoSuchMethodException, InvocationTargetException {
		Class aClass = currObj.getClass();
		String classFullName = aClass.getPackage().getName() + "." + aClass.getName();
		Field[] fieldArr = aClass.getDeclaredFields();

		Map validityRuleMap = allValidityRuleMap.get(classFullName);
		Map fieldDescMap = allFieldDescMap.get(classFullName);
		List canNotNullFieldNameList = (List) validityRuleMap.get("canNotNullFieldNameList");
		List isIntegerValiditerRuleInfoList = (List) validityRuleMap.get("isIntegerValiditerRuleInfoList");
		ValidityResult validityResult = new ValidityResult();
		for (int j = 0; j < canNotNullFieldNameList.size(); j++) {
			String currFieldName = (String) canNotNullFieldNameList.get(j);
			String getMethodName = "get" + currFieldName.substring(0, 1).toUpperCase() + currFieldName.substring(1);
			Method getFieldValueMethod = aClass.getMethod(getMethodName);
			String fieldValue = ((String) getFieldValueMethod.invoke(currObj));
			if (fieldValue == null || fieldValue.equals("")) {
				System.out.println(fieldDescMap.get(currFieldName) + " 不可以为空 ! ");
				validityResult.addValidityInfo(fieldDescMap.get(currFieldName) + " 不可以为空 ! ");
			}
		}

		for (int j = 0; j < isIntegerValiditerRuleInfoList.size(); j++) {
			IsIntegerValiditerRuleInfo isIntegerValiditerRuleInfo = (IsIntegerValiditerRuleInfo) isIntegerValiditerRuleInfoList
					.get(j);
			String currFieldName = isIntegerValiditerRuleInfo.getFieldName();
			String getMethodName = "get" + currFieldName.substring(0, 1).toUpperCase() + currFieldName.substring(1);
			Method getFieldValueMethod = aClass.getMethod(getMethodName);
			String fieldValue = ((String) getFieldValueMethod.invoke(currObj));
			int minWidth = isIntegerValiditerRuleInfo.getMinWidth();
			int maxWidth = isIntegerValiditerRuleInfo.getMaxWidth();
			int minValue = isIntegerValiditerRuleInfo.getMinValue();
			int maxValue = isIntegerValiditerRuleInfo.getMaxValue();

			if (StringUtils.isInteger(fieldValue)) {
				if (fieldValue.length() < minWidth) {
					validityResult.addValidityInfo(fieldDescMap.get(currFieldName) + " 宽度不可以小于 " + minWidth + "! ");
				}
				if (fieldValue.length() > maxWidth) {
					validityResult.addValidityInfo(fieldDescMap.get(currFieldName) + " 宽度不可以大于 " + maxWidth + "! ");
				}
				if (Integer.parseInt(fieldValue) < minValue) {
					validityResult.addValidityInfo(fieldDescMap.get(currFieldName) + " 的值不可以小于 " + minValue + "! ");
				}
				if (Integer.parseInt(fieldValue) > maxValue) {
					validityResult.addValidityInfo(fieldDescMap.get(currFieldName) + " 的值不可以大于 " + maxValue + "! ");
				}

			}
			else {

				validityResult.addValidityInfo(fieldDescMap.get(currFieldName) + " 必须是整数格式 ! ");

			}
		}
		return validityResult;

	}

	public static String[] getPojoBeanPackageName() {
		return pojoBeanPackageName;
	}

	public static void setPojoBeanPackageName(String[] pojoBeanPackageName) {
		PojoBeanAnnotationValiditer.pojoBeanPackageName = pojoBeanPackageName;
	}

	public static String getJsValiditerFilePath() {
		return jsValiditerFilePath;
	}

	public static void setJsValiditerFilePath(String jsValiditerFilePath) {
		PojoBeanAnnotationValiditer.jsValiditerFilePath = jsValiditerFilePath;
	}

	public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException, SecurityException,
			NoSuchMethodException, InvocationTargetException, ClassNotFoundException, IOException {
		PojoBeanAnnotationValiditer.setPojoBeanPackageName(new String[] { "com.javaest.validity.test.pojo" });
		PojoBeanAnnotationValiditer.setJsValiditerFilePath("JS\\VALIDITY");
		PojoBeanAnnotationValiditer
				.loadAllClassAnnotationValidityInfoInPackage(new String[] { "com.javaest.validity.test.pojo" });
		Student aStudent = new Student();
		aStudent.setAddress("吉林省长春市二道区");
		aStudent.setId("");
		aStudent.setAge("9");
		ValidityResult validityResult = PojoBeanAnnotationValiditer.validity(aStudent);
	}

}[/size]


下边是一个加好了标注的Student类

public class Student {
	@CanNotNull 
	@FieldDesc("姓名")
	private String name;
	@CanNotNull 
	@FieldDesc("性别")
	private String sex;
	@IsInteger(minValue=18,maxValue=60)
	@CanNotNull
	@FieldDesc("年龄")
	private String age;
	@CanNotNull
	@FieldDesc("编码")
	private String id;
	private String address;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getSex() {
		return sex;
	}
。。。。。。。。。。
}


在家闲着写代码真好。
7
2
分享到:
评论
3 楼 chunchong 2009-02-16  
想法不错,值的学习。
2 楼 javaest 2008-05-04  
eway819 22 小时前
兄弟,跟你有同样的想法,一直太忙,没时间去写,有时间交流交流,这玩意写好了肯定火
哈,好的,我MSN:guanqingpeng@hotmail.com
1 楼 eway819 2008-05-03  
兄弟,跟你有同样的想法,一直太忙,没时间去写,有时间交流交流,这玩意写好了肯定火

相关推荐

    基于java的arcgis server开发

    同时,JSF与后台的JavaBeans(JSF Bean)和前端的JavaScript之间的联动也是讲座的重点,这使得能够实现实时的异步更新,提升用户界面的动态性。 总的来说,基于Java的ArcGIS Server开发利用JSF框架,不仅提高了开发...

    ArcGIS+Server+Java讲座

    9、ArcGIS Server JAVA讲座--实现后台JSF Bean和前台Javascript的联动 24 10、ArcGIS Server JAVA讲座 --AJAX基础 25 11、ArcGIS Server JAVA开发讲座--- ADF中的Ajax函数 27 12、ArcGIS Server Java讲座--如何在用...

    根据经纬度对离线地图进行标点示例(用Ajax调用后台接口返回Json数据)

    在本示例中,我们将探讨如何使用经纬度坐标在离线地图上标注点,并通过Ajax调用后台接口来获取Json数据。这个过程涉及到的技术栈包括Java、JavaScript、OpenLayers、HTML和CSS,这些都是构建Web地图应用的关键技术。...

    ArcGis.rar_Arcgis java_GIS 开发_arcgis_arcgis for java_java arcgis

    同时,ArcGIS API for JavaScript可以与Java后台进行无缝集成,实现客户端的动态地图展示和交互。 对于移动开发,ArcGIS for Java还提供了适用于Android和iOS平台的SDK,使得开发者能够构建原生的移动GIS应用,充分...

    arcgis server java讲座

    自定义命令则用于扩展ArcGIS Server的功能,例如用户权限控制,这些都可以通过JavaScript和后台Java bean的联动实现。 【标注(Labeling)】和【字体使用】的章节详细介绍了如何使用TrueType字体和图片来创建动态、...

    dwr课件,java,反向ajax

    2. 创建Java服务端接口,标注DWR注解以暴露给JavaScript。 3. 在Web应用的配置文件中配置DWR拦截器和允许调用的类。 4. 在JavaScript中,通过DWR生成的接口调用服务器端的方法。 5. 处理返回的数据,更新页面内容。 ...

    毕业设计-图像管理和标注系统.zip

    Java可能被用于实现系统的部分后台服务,如数据库连接、任务调度或者消息队列服务。Spring Boot框架可以简化开发流程,提供自动化配置和依赖注入功能。如果涉及到分布式系统,可能还会使用到Spring Cloud相关组件来...

    本项目(瑞吉外卖)是专门为餐饮企业(餐厅、饭店)定制的一款软件产品,系统管理后台主要提供给餐饮企业内部员工使用,可以对餐厅的菜品

    "瑞吉外卖项目的技术架构和实现" 本项目瑞吉外卖是一款专门为餐饮企业(餐厅、...系统使用 Vue.js 框架、Element UI 组件库、Java 语言、Spring Boot 框架和 MySQL 数据库,实现了登录功能、业务逻辑处理和数据访问。

    疫情地图项目.rar

    3. **短信发送代码包**:这可能涉及到使用Java或JavaScript来集成短信服务API,实现程序自动化发送短信的功能。这通常需要与第三方短信服务商进行接口对接,如阿里云、腾讯云等,并涉及HTTP请求、JSON解析等相关知识...

    计算机高级php工程师简历模板.doc

    * 使用JAVA语言实现网站后台开发 * 使用JAVA语言实现门户网站的开发 (3)ASP技术 * 使用ASP语言开发电子报 * 使用ASP语言实现网站开发 (4)XML技术 * 使用XML文件实现报纸数据的入库 * 使用XML文件实现网站...

    Java界面开发规范[归类].pdf

    《Java界面开发规范》是一份指导Java界面开发者遵循的详细准则,旨在确保代码的质量、可维护性和一致性。这份规范主要面向电子运维开发人员和开发经理,同时也对质管人员具有参考价值。 在开发规范部分,首先提到了...

    WebSocket双向通信(java+tomcat+html5)

    在本项目中,服务端基于Tomcat 7.0搭建,这是一个广泛使用的Java Servlet容器,能够支持WebSocket协议。Tomcat 7.0及以上版本已经内置了对WebSocket的支持,通过JSR 356(Java API for WebSocket)提供API来创建...

    Java毕业设计:基于SpringBoot的疾病科普知识网站(源码+录像演示).zip

    疾病科普知识网站 开发语言 前端:HTML5、CSS3、JavaScript、jsp。 后端:Java、MySQL,Springboot。 前台主要面向的是普通用户和医生,其主要功能包括: ...前台、后台所有模块的内容排列顺序均已更新时间排降序;

    js传值后台中文出现乱码的解决方法

    在“test.jsp”页面中,需要通过js将值传递到后台,后台根据传递的值进行数据查询时,通过test.jsp的js进行编码(标注部分的代码),后台Java解码(注释标注部分为解码),可以解决 test.jsp: [removed] function ...

    Node.js-一个现代的Android和Java的JSON库

    它能很好地与Android的异步机制如`AsyncTask`或`LiveData`结合,实现后台数据的加载和更新。 **使用Moshi的步骤** 1. **添加依赖**:在Android项目的`build.gradle`文件中添加Moshi的依赖。 2. **创建Model类**:...

    “红灯笼”网上汽车租赁系统的设计与实现-全文标注报告

    在实现阶段,论文可能会涉及以下技术:使用Java或.NET作为主要开发语言,Spring Boot或ASP.NET作为框架,MySQL或SQL Server作为数据库管理系统,前端可能采用HTML5、CSS3和JavaScript,可能还会涉及到AJAX异步通信以...

    基于Android平台的景区导览软件设计与实现(全文).docx

    “地图导航”功能是基于三维地图实现的,它允许用户以三维视角查看景区,同时标注有各个景点的位置。用户可以通过手指滑动、缩放来浏览地图,并选择特定景点进行导航。地图上还可以设置虚拟路线,帮助游客规划游览...

    基于ssh框架的自由交易系统的设计与实现-毕业论文.doc

    Struts提供了MVC(Model-View-Controller)设计模式的实现,使得业务逻辑和视图层分离;Hibernate是一个对象关系映射(ORM)框架,简化了数据库操作,将Java对象与数据库表之间的映射工作自动化;Spring框架则提供了...

    基于springboot+thymeleaf的理财管理系统源码.zip

    总结来说,基于SpringBoot+Thymeleaf的理财管理系统利用了SpringBoot的快速开发能力,Thymeleaf的便捷视图渲染,以及Java的MVC模式,实现了高效、易维护的财务管理。通过深入理解并实践这些技术,开发者不仅可以掌握...

Global site tag (gtag.js) - Google Analytics