`
sdh88hf
  • 浏览: 67810 次
  • 性别: Icon_minigender_1
  • 来自: 绍兴
社区版块
存档分类
最新评论

Web开发学习13聊聊java反射

阅读更多
很喜欢一本叫《走出软件作坊》的书,其中有一句话让我较为深刻,“架构师,客户和程序员之间走钢丝的人”,一个优秀的程序员过单行线都会左右都看看,更何况一个架构师肯定是需要非常谨慎的。那怎么样才能做到谨慎呢?在我看来对于架构师的谨慎其实就是一句话:不要让程序员写原本不应该是他写的代码,这句话说的好像有点抽象,但其实很好理解,就是尽可能让程序员的代码变的少,这样不但开发起来效率快,而且review代码以及排查bug都是很方便的,那怎么样才能让程序员写的代码变少呢?今天我想借java的反射来举几个例子,通过反射封装让编码变的更简单,当然这肯定不是唯一的办法。

1.excel文件导出
这个封装是在我工作两年的时候自己想的,当时真的被逼的没办法,十几个模块都需要添加excel导出功能,当做出来以后确实被自己感动了,同时感觉封装的重要性。首先要创建一个注解类

/**
 * 
 * @author sdh 2012-7-26
 */
@Target(value={java.lang.annotation.ElementType.METHOD,java.lang.annotation.ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Export{

	/**
	 * @return 表头名称
	 */
	String header() default " ";

	/**
	 * @return 排序
	 */
	int sort();
	
	/**
	 * 设定列宽
	 * @return
	 */
	int columnWidth() default 100;
	
	/**
	 * 状态转换
	 * @return
	 */
	String stateStr() default "";
	
}

header标志列头名称,sort标志排第几列,columnWidth标志列宽,stateStr是状态转换,当数据库是int类型转成中文时用,然后在需要导出的实体类字段中按需求添加注解配置
public class Coupon implements IBasicBean {

	private static final long serialVersionUID = -8233437005461628357L;
	private Long id;
	@Export(header="业务类型",sort=0,stateStr="1:印刷品,2:DM,3:视频")
	private Integer businessType;
	@Export(header="产品编号",sort=1)
	private Integer productId;
	@Export(header="优惠券编号",sort=2)
	private String couponNum;
	@Export(header="优惠券名称",sort=3)
	private String couponName;
	@Export(header="优惠券价格",sort=4)
	private Float couponPrice;
}

看封装类投代码
public class ExcelExportUtils<T> {

	public ExcelExportUtils() {

	}

用泛型类来配合反射是常用的手段,只需在调用时传递操作类型即可在封装类中反射出来了,调用方传递操作类型和该操作类型的数据集,封装类通过反射获取字段上的注解后去数据集中获取该字段的值即可完成导出逻辑,篇幅关系这里不做详细代码描述了

2.hibernate基类
这个方法我是看开涛的《跟我学springmvc》看到的,感觉还有点用,在基类中定义好每个数据库访问类对应的基本查询语句,方便后续开发不用重复写,看代码

public class HibernateDaoImpl<T extends BaseEntity> extends HibernateDaoSupport
		implements HibernateDao<T>{

	protected final String COUNT_HQL = "select count(id) ";

	protected final String LIST_HQL;
	
	protected final String TABLE_NAME;

	/**
	 * 数据实体类型
	 */
	protected Class<T> entityClass;

	/**
	 * 默认构造函数
	 */
	@SuppressWarnings("unchecked")
	public HibernateDaoImpl() {
		Type superClassType = getClass().getGenericSuperclass();

		if (superClassType instanceof ParameterizedType) {
			Type[] paramTypes = ((ParameterizedType) superClassType)
					.getActualTypeArguments();
			this.entityClass = (Class<T>) paramTypes[0];
		}
		TABLE_NAME = this.entityClass.getSimpleName();
		LIST_HQL = "from " + this.entityClass.getSimpleName() + " where 1=1";
	}


通过 getClass().getGenericSuperclass()反射在父类的构造中获取到了子类传递的泛型

3.springmvc全局参数验证
参数为空的情况可能导致程序奔溃所以需要在程序中强制验证,但是文本参数的长度如果校验就显得有点累赘了,所以我通过反射封装了一个全局参数长度校验,在拦截器中插入即可

//对请求参数做校验(根据自定义验证注解)
    public boolean paramsValidate(BaseControler handler,HttpServletRequest request) throws Exception{
    	
    	//获取当前controll的所有方法
    	Method[] m = handler.getClass().getDeclaredMethods();
    	//遍历
    	for (int i = 0; i < m.length; i++) {
    		//获取RequestMapping注解
    		RequestMapping an = m[i].getAnnotation(RequestMapping.class);
    		//如果注解不是空的
    		if(an != null){
    			//把注解的值和当前请求的url做对比
    			String[] vs = an.value();
    			if(vs != null && vs.length > 0){
    				if(request.getRequestURI().endsWith(vs[0])){
    					//对比一致 获取当前方法的参数列表
    					@SuppressWarnings("rawtypes")
						Class[] c =  m[i].getParameterTypes();
    					for (int j = 0; j < c.length; j++) {
    						//如果当前参数是basebean的子类视为载体
							if(c[j].getSuperclass() != null && c[j].getSuperclass().equals(BaseBean.class)){
								
								Map<String, String[]> map = request.getParameterMap();
								
								for(String key : map.keySet()){
									//只对string类型的参数做校验
									Field f = c[j].getDeclaredField(key);

									//获取到当前字段的validation注解
									MyValidation valid = f.getAnnotation(MyValidation.class);
									String v1 = StringUtil.array2String(map.get(key));
									if(StringUtil.isEmpty(v1)){
										return true;
									}
									
									if(valid != null){
										//根据配置来验证参数
										int maxLen = valid.maxLen();
										if(v1.length() > maxLen){
											throw new Exception(f.getName() + " not accord with maxlenth");
										}
										
										String pattern = valid.pattern();
										if(!StringUtil.isEmpty(pattern)){
											Pattern p = Pattern.compile(pattern);
											Matcher matcher = p.matcher(v1);
											if(!matcher.matches()){
												throw new Exception(f.getName() + " not accord with pattern");
											}
										}
									}else{
										//按照默认的长度控制
										if(v1.length() > IConstans.PARAM_MAX_LEN){
											throw new Exception(f.getName() + " not accord with maxlenth");
										}
									}
									
									
								
								}
							}
						}
    				}
    			}
    		}
		}
    	return true;
    }

这个封装的关键点就在拦截器中操作类没人传递无法反射,但是拦截器中有当前访问的controller类和访问地址,所以我的思路是通过访问的地址链接来反射到controller类对应的@RequestMapping注解的方法,然后获取到该方法参数列表中类型为baseEntity子类的参数即是操作类,然后通过操作类获取字段及注解验证

4.全局埋点
这个功能我在前面的博客比较详细的说明了,主要还是在拦截器中以注解反射的方式来定位到用户的本次的操作记录到日志
@Override
	protected String doIntercept(ActionInvocation invocation) throws Exception {
		String result = null;
		try {
			//先执行action方法
			result = invocation.invoke();
			
			String enterMethod = invocation.getProxy().getMethod();
			//获取action方法上的WebOperateAnno 注解
			WebOperateAnno webOperateAnno = invocation.getAction().getClass().getMethod(enterMethod, new Class[0]).getAnnotation(WebOperateAnno.class);
			
			Object returnData = invocation.getAction();
			
			writeLog(webOperateAnno,returnData);
		} catch (Exception e) {
			sysLogger.error("操作日志记录失败",e);
		}
		
		
		return result;
	}


这种例子在程序中还有很多,目的就是做好封装减少程序员的编码量,如果以后面试的时候碰到面试官问你用java反射做了什么,或许你可以借鉴这些例子
分享到:
评论

相关推荐

    Java Web开发学习手册光盘源码

    Java Web开发学习手册随书光盘源码

    Java-JDK、数据库系统开发、Web开发学习笔记

    Java-JDK、数据库系统开发、Web开发学习笔记

    Java Web开发实例大全

    《Java Web开发实例大全(提高卷)》既适合Java Web程序员参考和查阅,也适合Java Web初学者,如高校学生、软件开发培训学员及相关求职人员学习、练习、速查使用。 目录 第1篇 流行组件应用篇 第1章 操作XML文件 第...

    Java web开发技术教程课件—Java Web 开发工具.pdf

    Java web开发技术教程课件—Java Web 开发工具.pdfJava web开发技术教程课件—Java Web 开发工具.pdfJava web开发技术教程课件—Java Web 开发工具.pdfJava web开发技术教程课件—Java Web 开发工具.pdfJava web开发...

    Java Web 整合开发 完全自学手册 源代码

    Java Web 整合开发 完全自学手册 源代码

    Java.Web开发学习手册

    Java.Web开发学习手册,Java web入门书籍,可以自己学习一下。

    java web开发技术大全1 pdf

    由于Java Web开发技术大全pdf文件太大120多M,上传资源要求在20M以内,所以大家必须要把Java Web开发技术大全.z01,Java Web开发技术大全.z02,Java Web开发技术大全.z03,Java Web开发技术大全.z04,Java Web开发...

    Java Web开发完全掌握

    为了方便读者学习,书中实例所涉及的源代码都收录到《Java Web开发完全掌握》的配套光盘中,供读者在学习过程中使用。《Java Web开发完全掌握》适合web应用开发的入门用户、程序设计员和各行各业需要进行web开发的...

    轻松学Java Web开发

    轻松学Java Web开发,很经典的一个学习课件,希望帮到大家。

    Tomcat与Java Web开发技术详解 孙卫琴 源码

    《Tomcat与Java Web开发技术详解(第2版)》结合最新的Tomcat 6版本,详细介绍了开发Java Web应用的各种技术。主要内容包括:Tomcat和Java Web开发的基础知识、Java Web开发的高级技术、在Java Web应用中运用第三方...

    Tomcat 与Java web开发技术详解(孙卫琴)

    内容简介 本书结合最新的Tomcat 6版本,详细...本书还可作为高校相关专业学生学习Java Web开发的参考书,以及企业Java Web培训教材,也可作为SUN公司的SCWCD(SUN Certified Web Component Developer)认证的辅导教材。

    java web开发学习手册光盘中的5个项目源码

    项目源码,适合学通java web作为实际开发项目的参考。

    Java Web开发技术大全5.z05 pdf

    由于Java Web开发技术大全pdf文件太大120多M,上传资源要求在20M以内,所以大家必须要把Java Web开发技术大全.z01,Java Web开发技术大全.z02,Java Web开发技术大全.z03,Java Web开发技术大全.z04,Java Web开发...

    Java web开发技术Java教程

    有关Java web开发技术\资料\Java教程 有关Java web开发技术\资料\Java教程 有关Java web开发技术\资料\Java教程 有关Java web开发技术\资料\Java教程 有关Java web开发技术\资料\Java教程 有关Java web开发技术\资料...

    基于SpringBoot+mysql的招聘网站系统,适合个人web开发学习,本科毕业设计,java课程设计等

    基于SpringBoot+mysql的招聘网站系统,适合个人web开发学习,本科毕业设计,java课程设计等 基于SpringBoot+mysql的招聘网站系统,适合个人web开发学习,本科毕业设计,java课程设计等 基于SpringBoot+mysql的招聘...

    java web开发技术大全3 z03 pdf

    由于Java Web开发技术大全pdf文件太大120多M,上传资源要求在20M以内,所以大家必须要把Java Web开发技术大全.z01,Java Web开发技术大全.z02,Java Web开发技术大全.z03,Java Web开发技术大全.z04,Java Web开发...

    java web开发实战1200例第i卷

    java web开发实战1200例第i卷 1-12源码 希望对你有所帮助,谢谢

    Java Web开发学习手册-高清-2011年4月

    Java Web开发学习手册-高清-2011年4月,分享给所有需要的人!

    java web开发技术大全4 z04 pdf

    由于Java Web开发技术大全pdf文件太大120多M,上传资源要求在20M以内,所以大家必须要把Java Web开发技术大全.z01,Java Web开发技术大全.z02,Java Web开发技术大全.z03,Java Web开发技术大全.z04,Java Web开发...

    Java Web开发基础知识

    Java Web开发基础知识Java Web开发基础知识Java Web开发基础知识Java Web开发基础知识

Global site tag (gtag.js) - Google Analytics