- 浏览: 69801 次
- 性别:
- 来自: 绍兴
最新评论
很喜欢一本叫《走出软件作坊》的书,其中有一句话让我较为深刻,“架构师,客户和程序员之间走钢丝的人”,一个优秀的程序员过单行线都会左右都看看,更何况一个架构师肯定是需要非常谨慎的。那怎么样才能做到谨慎呢?在我看来对于架构师的谨慎其实就是一句话:不要让程序员写原本不应该是他写的代码,这句话说的好像有点抽象,但其实很好理解,就是尽可能让程序员的代码变的少,这样不但开发起来效率快,而且review代码以及排查bug都是很方便的,那怎么样才能让程序员写的代码变少呢?今天我想借java的反射来举几个例子,通过反射封装让编码变的更简单,当然这肯定不是唯一的办法。
1.excel文件导出
这个封装是在我工作两年的时候自己想的,当时真的被逼的没办法,十几个模块都需要添加excel导出功能,当做出来以后确实被自己感动了,同时感觉封装的重要性。首先要创建一个注解类
header标志列头名称,sort标志排第几列,columnWidth标志列宽,stateStr是状态转换,当数据库是int类型转成中文时用,然后在需要导出的实体类字段中按需求添加注解配置
看封装类投代码
用泛型类来配合反射是常用的手段,只需在调用时传递操作类型即可在封装类中反射出来了,调用方传递操作类型和该操作类型的数据集,封装类通过反射获取字段上的注解后去数据集中获取该字段的值即可完成导出逻辑,篇幅关系这里不做详细代码描述了
2.hibernate基类
这个方法我是看开涛的《跟我学springmvc》看到的,感觉还有点用,在基类中定义好每个数据库访问类对应的基本查询语句,方便后续开发不用重复写,看代码
通过 getClass().getGenericSuperclass()反射在父类的构造中获取到了子类传递的泛型
3.springmvc全局参数验证
参数为空的情况可能导致程序奔溃所以需要在程序中强制验证,但是文本参数的长度如果校验就显得有点累赘了,所以我通过反射封装了一个全局参数长度校验,在拦截器中插入即可
这个封装的关键点就在拦截器中操作类没人传递无法反射,但是拦截器中有当前访问的controller类和访问地址,所以我的思路是通过访问的地址链接来反射到controller类对应的@RequestMapping注解的方法,然后获取到该方法参数列表中类型为baseEntity子类的参数即是操作类,然后通过操作类获取字段及注解验证
4.全局埋点
这个功能我在前面的博客比较详细的说明了,主要还是在拦截器中以注解反射的方式来定位到用户的本次的操作记录到日志
这种例子在程序中还有很多,目的就是做好封装减少程序员的编码量,如果以后面试的时候碰到面试官问你用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反射做了什么,或许你可以借鉴这些例子
发表评论
-
Web开发学习12 浅谈设计模式
2016-07-01 13:33 1329在我刚接触 ... -
Web开发学习11 全局缓存控制
2015-10-12 14:27 749缓存用的好可以减少数据库的压力,在大并发的情况下极大的提升服务 ... -
Web开发学习10 hadoop实战
2015-10-09 14:02 767前一篇说到项目记录了很多埋点日志,当有一天项目需求需要对这些日 ... -
Web开发学习(9)全局埋点
2015-07-27 11:10 2029埋点的作用是把客户端每次访问服务端的操作记录下来,包括请求连接 ... -
Web开发学习8Struts2基类封装
2015-07-24 12:03 711一个好的基类可以帮助开发者减少很多开发工作,像我这种爱偷懒的人 ... -
Web开发学习7按钮级别权限控制
2015-07-23 16:21 13368这个功能的思路是自己原创的,没看过其他例子,其实是在做之前网上 ... -
Web开发学习6添加liqiubase
2015-07-22 14:29 1480开发过程中经常碰到数据库更改的情况,在日常环境下如果每位开发人 ... -
浅列JavaEnum
2014-01-05 16:42 794enum Province{ ZHEJIANG,SHANGHA ... -
maven常用命令
2013-07-08 10:20 7941、创建普通Java项目: ... -
canvas绘制科赫雪花
2012-12-20 17:24 2166<html> <head> ... -
html5 audio与video方法属性事件概括
2012-12-20 14:46 1126play() 继续播放 pause() ... -
spring 整合mina
2012-12-20 11:48 1127首先定义自定义过滤器 <bean id=" ... -
Web开发学习(5)添加springsecurity应用
2011-12-14 15:00 976我学习公司这个架构多半就是为了把springsecurity搞 ... -
Web开发学习(4)添加spring应用
2011-12-14 14:45 802印象中似乎没做过不用spring的项目,因为它在web开发中的 ... -
Web开发学习(3)配置struts-tiles插件(附带json插件)
2011-12-05 15:22 2577struts的tiles插件是非常实用的,从某些方面可以很好的 ... -
使用线程删除导出临时文件
2011-12-01 16:33 2285项目支持大数据量导出e ... -
jQuery实现表格行点击选中复选框
2011-11-23 12:36 6015这个需求是在项目完成后客户提出的要求,看似简单但是还需要一点小 ... -
Web开发学习(2)配置convention插件
2011-11-04 10:28 1401注解的方式某些程度上能减少xml的配置量,个人感觉使程序更加清 ... -
Web开发学习(1)使用eclipse搭建maven项目
2011-10-20 10:04 5753首先用eclipse创建工程 ne ... -
数据库连接泛型基类创建
2011-06-30 11:49 1004记录 以便以后参考---- 基类代码 public cl ...
相关推荐
Sparkweb 是一个超轻量级的简易高效的 Java WEB 开发框架,其设计思想结合了目前主流的 Spring、Struts2、Playframework、Nodejs-Expressjs、Ruby On Rails 等框架的优秀地方,完美支持 RESTful设计。 二、Sparkweb ...
- **Java核心技术**:列出你熟练掌握的Java语言特性,如面向对象编程、异常处理、多线程、集合框架、I/O流、反射等。 - **框架与库**:提及你熟悉的Java开发框架,如Spring、MyBatis、Hibernate等,以及你使用过的...
面试题包括以下十九部分:Java 基础、容器、多线程、反射、对象拷贝、Java Web 模块、异常、网络、设计模式、Spring/Spring MVC、Spring Boot/Spring Cloud、Hibernate、Mybatis、RabbitMQ、Kafka、Zookeeper、MySql...
b站狂神说课程笔记大全,每个部分都有 狂神说java系列笔记(java基础+javaweb+ssm+微服务)全套 狂神说上课笔记未删减 Java基础到技术升级 1、JavaSE:Java入门 ...28、SpringBootWeb开发提升(Swagger) 29、Spri
### Java基础知识概述 Java是一种广泛使用的面向对象编程语言,由Sun Microsystems公司于1995年推出,...无论是进一步深入学习Java高级特性还是转向其他领域如Web开发、移动开发等,这些基础知识都是不可或缺的基石。
- 使用Web在线流程设计器,允许用户通过图形化界面设计工作流。 - 可以预览流程XML,方便理解流程逻辑。 - 支持流程XML的导入与导出,便于流程的备份和迁移。 - 动态部署流程,实现快速响应业务需求。 2. **...
"Java-Projects"这个标题暗示我们即将探讨的是与Java相关的项目,可能是为了学习、实践或者开发目的而创建的一系列代码示例或应用程序。这些项目可能涵盖Java的基础到高级用法,包括核心Java、多线程、网络编程、GUI...
13. **Java EE**:如果涉及到Web开发,Java EE(企业版)的Servlet、JSP、EJB等技术也是必须掌握的。 14. **现代Java特性**:随着Java版本的更新,新特性如Lambda表达式、Stream API、Optional类等引入,让代码更...
此外,源码阅读也能让我们了解Spring如何利用反射、动态代理等Java核心技术实现其功能。 在这个开源项目中,你将有机会逐行解析Spring的源代码,跟随作者的思路,逐步理解每个模块的设计理念和实现细节。这将是一个...
Java被应用于各种领域,如Web开发、移动应用(尤其是Android)、企业级应用、大数据处理、云计算等。 在这个课程中,学习者可以期待涵盖以下Java编程的关键知识点: 1. **基础语法**:包括变量、数据类型、运算符...
在Android开发中,React Native和WebView的结合使用可以带来丰富的用户体验和高效的开发流程。...然而,这也需要开发者具备扎实的Java、JavaScript基础,以及对React Native和Android原生开发的深入理解。
10. **Java反射**:反射机制允许程序在运行时检查类的信息,如类名、属性、方法等,并能动态调用方法和修改属性值,增强了代码的灵活性。 11. **Java集合框架的并发工具类**:如ConcurrentHashMap、...