基 本 信 息
名: 张天山 别:
出生日期: 1987年10月15日 居 住 地: 北京市
工作年限: 二年以上 口: 吉林
目前年薪: 5万 人民币
电子邮件: lhm_work@sina.com
移动电话: 086- 13522726134
自 我 评 价
二年以上软件开发设计经验;平时注重团队精神,善于与客户沟通,能掌握客户需求;有过软件开发过程经验;熟悉J2EE编程技术,了解Java常用设计模式;熟悉MVC开发模式,能熟练运用struts1/2、spring、hibernate、ajax、EJB3、Jbpm、JSTL/EL、WebService、jdbc、dom4j、log4j、JPA、OSCache、Velocity、SSI、Compass、Lucene等技术。熟练应用MyEclipse,cvs,ROSE等开发工具;熟练运用mysql、oracle、SqlServer等数据库。
求 职 意 向
工作性质: 全职
希望行业: 计算机软件
目标地点: 北京市
期望工资: 5000/月
目标职能: 软件工程师
工 作 经 验
2007/3--2009/1:惠利至易高科技有限责任公司
所属行业: 计算机软件
开发部 软件工程师
在项目前期与客户进行需求分析,确定系统功能,参与系统设计以及功能模块的详细设计。项目编码阶段负责功能模块的实现。项目后期主要负责用户使用文档的编写。
汇报对象: 项目经理
离职原因: 寻求更大的发展平台
项 目 经 验
2010/3--2010/7:3G网络Android手机视频客户端
软件环境: Android2.1
开发工具: eclipse3.5+Android智能手机摸拟器+三星i6500U
项目描述: 提供在线播放视频、mp3、多线程断点续传视频下载,现场视频拍摄及视频上传,用户注册/登录及个人形像照拍摄、软件设置等功能,所有Android的手机用户都可以通过该客户端享受到全免费使用视频服务的超炫体验。
责任描述:

负责视频上传与下载、mp3播放器、现场视频拍摄、形像照拍摄功能。项目中用到了Pull解析器读写xml数据,使用Android自带的SQLite数据库存放用户数据,使用SharedPreferences保存软件参数设置,使用HttpURLConnection实现应用与Internet的数据上传下载。并利用Android自带的MMI(多媒体接口)实现MP3播放器,使用Android照相机API实现自动对焦拍照。应用严格按照MVC模式编写,在业务bean编写的过程中采用Android Junit3反复对业务方法进行单元测试,在确保业务bean正确的情况下再供UI进行调用。

各模块的技术要点:
1> 手机上显示的最新视频资讯数据来源于web服务器,客户端以HTTP请求的方式从服务器获取以XML数据格式返回的最新视频资讯,然后使用Pull技术完成对XML数据的解析,解析后的数据使用ListView显示。这里为何使用Pull技术解析XML而不是DOM或SAX,主要是因为DOM解析XML比较耗内存,用它解析数据量小的xml文件尚且可以;至于SAX技术,尽管它解析XML的性能比较高,但因为其实现代码可理解度比较差,所以放弃使用。统合性能与代码可理解度,本项目采用Pull技术,因为它解析XML的性能大于或等于SAX,代码的可理解度比SAX好,Pull允许在得到所需数据后停止解析,所以在不需解析完整个XML内容的场合,它的性能比SAX更高,Android系统本身解析xml采用的就是pull技术。

2> 软件具有视频下载功能,需要实现断点续传功能。
断点续传实现原理:当从服务器下载文件时,可以通过http中的头字段RANGE指定从文件的什么范围开始下载,如: bytes=100090-300080,要求从文件的100090位置开始下载,下载到300080位置停止(含该位置),发送到服务器的http协议部分如下:
GET /zhaodl.3gp HTTP/1.0
RANGE: bytes=100090-300080
为了加快下载速度,采用了多线程下载,先计算出每条线程应该从文件的哪个位置开始下载,然后使用RandomAccessFile类保存文件, RandomAccessFile类的seek(nPos)方法可以指定每条线程从文件的什么位置开始保存数据,当所有线程完成下载之后,文件数据就写入完整。
采用多线程下载之所以快,是因为其抢占了更多的服务器资源,服务器为之服务的时间多了,下载就会快些。
断点数据采用SQLite数据库存放,记录了文件的下载路径,每条线程的id和每条线程下载的数据长度。

3> 视频上传功能,视频文件一般都比较大(如200M),考虑到移动网络的不稳定性和手机电量不足导致关机的问题,视频上传需实现断点续传功能,因为需要实现断点续传功能,采用Http POST方式实现上传文件已经不可行,因为Http协议没有续传之功能,再加上由于web服务器软件一般对上传的文件大小有限制,所以采用Http协议上传超大文件并不可靠,因此项目决定采用TCP/IP协议通过SOCKET方式实现视频文件上传,实现原理如下:
(1) 编写socket服务器端软件,对指定端口进行监听,为实现多用户访问,采用线程池处理每一个连接请求.
(2) 在android中编写socket客户端代码,客户端一旦与服务器建立连接,发送自定义协议信息,如下:
Content-Length=143253434;filename=xxx.3gp;sourceid=1274773833264\r\n
sourceid用于标识文件,由服务端生成,如果用户初次上传文件,该值为空。服务器收到请求信息后,给客户端返回响应信息:
sourceid=1274773833264;position=100023\r\n
客户端收到响应信息后,从position指定的文件位置开始上传数据,初次上传文件时,position的值为0

4> 视频播放器,需要解决电话来电时暂停播放,并在挂断电话时继续播放功能。实现方式如下:
当电话来电时,会激活来电号码显示Activity,新Activity的打开会导致视频播放器activity生命周期方法onPause()被系统调用,可以重写onPause()方法,在方法里保存视频当前播放的位置,然后停止播放。在来电号码显示Activity关闭后(挂电话),从保存位置继续播放。虽然新activity关闭后导致视频播放器activity的生命周期方法onResume()被系统调用,但继续播放视频的处理代码不能写在onResume()里,如果写在onResume()里,继续播放视频时,视频画面将是黑屏,原因是SurfaceView在新Activity打开时会被销毁,在新Activity关闭后回到视频播放器activity,SurfaceView会被重新创建,创建行为是在onResume()之后,所以在SurfaceView尚未创建出来就企图在onResume()方法恢复播放视频,视频画面将是黑屏。解决办法是注册SurfaceView的回调方法surfaceCreated(),该方法是在SurfaceView创建完成时被系统调用的,可以在该方法里实现继续播放视频的处理代码。

5> 照片拍摄与上传,使用摄像头拍照时,如果有新的activity被打开,应该及时释放摄像头硬件,否则当新activity也需使用摄像头时,将会因为摄像头已经被使用而导致程序出错。正确的做法是在SurfaceView的回调方法surfaceCreated()打开摄像头,surfaceDestroyed()方法释放摄像头。用户拍摄的照片通过HTTP上传到他的相册,所以需要使用HttpURLConnection以multipart/form-data数据类型向服务器web应用上传照片。在实际的使用中发现,如果照片大于3M,HttpURLConnection类会报内存溢出错误,究其原因是HttpURLConnection使用了内存缓存,缓存跟文件大小有关,在缓存超出android限定值时就会报错,这个问题应该是HttpURLConnection的BUG,为了解决这个问题,在项目中直接使用Socket发送HTTP协议以multipart/form-data数据类型向服务器web应用上传照片,上传照片采用的是边读边上传,没有使用缓存,因此解决了此问题。

经验与感想: 采用Layout进行软件UI设计比较累人,几乎大量的时间都用在了界面设计上,并且维护更新都不太灵活。所以日后的项目开发可以采用HTML作为软件的界面,通过WebView进行显示,这样界面的开发工作就可以重新交回给网页设计人员来做。很多Layout控件的显示效果其实采用HTML+CSS+JS也是可以实现的。


2009/12--2009/12:来电知了
软件环境: Android2.1
开发工具: eclipse3.6+Android智能手机摸拟器
项目描述: 该项目用于显示来电号码的归属地和实现黑名单拦截功能
责任描述:

负责整个软件的开发
来电号码归属地显示功能的实现原理:在Service里面通过TelephonyManager对来电状态进行监听,在电话打进来时,根据来电号码查询号码归属地,号码归属地数据存放于SQLite数据库。得到号码的归属地后,通过WindowManager在窗口上添加一个View控件显示归属地信息,并指定View控件覆盖来电显示界面上的号码显示区域。代码如下:
/**
* 在来电界面上显示号码归属地信息
* @param incomingNumber 来电号码
* @param address 号码归属地
*/
private void showCallInfo(String incomingNumber, String address) {
final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
params.y = 20;
params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
params.format = PixelFormat.TRANSLUCENT;
params.type = WindowManager.LayoutParams.TYPE_TOAST;
view = inflater.inflate(R.layout.incallui, null);
TextView numberLabel = (TextView) view.findViewById(R.id.numberLabel);
numberLabel.setText(incomingNumber);
TextView addressLabel = (TextView) view.findViewById(R.id.addressLabel);
addressLabel.setText(address);
windowManager.addView(view, params);
}
添加在窗口上的View控件需要在用户挂断电话后,调用WindowManager.removeView(view)方法删除View控件,否则View控件会一直显示在屏幕上。
电话黑名单拦截功能的实现原理:在Service里面通过TelephonyManager对来电状态进行监听,在电话打进来时,查询来电号码是否属于黑名单,黑名单数据存放于SQLite数据库。如果属于黑名单,可以调用ITelephony.endCall()结束通话。Android并没有对外公开结束通话的API,但系统的电话管理服务却存在endCall()方法,为了调用此方法,我们需要使用AIDL进程通信技术直接访问电话管理服务中的endCall()方法。结束通话后通过ContentProvider删除通话记录
短信黑名单拦截功能的实现原理:当系统收到短信时,会发出一个广播Intent。Intent的action名称为android.provider.Telephony.SMS_RECEIVED,该Intent存放了系统接收到的短信内容,使用名称“pdus”即可从Intent中获取到短信。从短信中得到发送者号码,然后查询该号码是否属于黑名单,如果属于黑名单,调用abortBroadcast()方法终止短信广播Intent的传递,这样,用户就收不到短信了。


2008/7--2008/11:3G移动商城
软件环境: Struts+Spring2.5+JPA+Ajax+Lucene
开发工具: Myeclipse6.6+Rose+Android智能手机摸拟器
项目描述: 是一套面向3G智能手机开发的在线商品交易系统,整个系统包含二个子系统,分别是面向企业内部办公的OA系统(实现如产品管理\订单处理等功能)和手机前端用户的商品订购系统
责任描述:

参与项目的需求分析,使用Rose绘制所负责模块的UML用例图/活动图/时序图/状态图和编写项目设计文档,负责产品管理、产品前端显示、供应商管理、购物车、用户管理、产品全文搜索、购物流程、订单处理流程、用户评论管理、权限管理、系统优化等模块的代码实现与测试。在设计业务bean时,为实现软件各层之间解偶合,业务bean采用面向接口设计,在业务bean编写的过程中采用Junit反复对业务方法进行单元测试。在JSP页面使用JSTL/EL操作数据显示和使用Struts标签在表单中进行数据回显。

各模块的技术要点:
1>产品管理模块中的产品类别实现了无限级分类,购物车采用Session技术实现,解决了购物车在多个新打开浏览器共享的问题。产品搜索采用Compass+Lucene实现全文搜索,解决了增量索引的需求。
2>网站办公系统的权限管理采用采用粗/细粒度设计,粗粒度用于控制用户对那些页面具有访问的权限,细粒度用于控制用户对页面上的那些按钮具有访问的权限。在实现过程中,粗粒度控制使用Filter实现,细粒度控制使用AOP技术实现,即对Action中的方法进行拦截。

项目经验与心得:
1>为提高3G网站性能,本系统使用Velocity技术对产品页面和新闻页面实施静态化、使用OSCache对产品列表页面实施页面缓存,并采用数据源技术减少连接数量。
2>使用了三大门户网站都在使用的SSI技术实施页面包含,加快了页面包含解析输出性能,使用了SSI技术的网页后缀默认为.shtml。
3>在这个项目中我们选择使用了JPA技术,JPA技术是Sun提出的Java持久化规范,他充分吸收了现有Hibernate、TopLink等ORM框架的基础上发展而来。相对于Hibernate,他更易于使用,而且可以使我们的项目在任何实现了JPA规范的ORM框架中运行,可移植性很强。
4 >在项目中,对实体的添/删/改/查和分页都在DaoSupport抽象类中实现,业务层的bean只有继承该类就具有这些功能。
5>使用Spring的OpenEntityManagerInViewFilter过滤器解决了在JSP访问实体bean中的Lazy属性时,因EntityManager关闭导致的延迟加载例外问题。


2008/12--2008/12:易宝网上支付对接
软件环境: JavaBean+JSP+Servlet+log4j+dom4j
开发工具: Meclipse3.3 for JavaEE
项目描述: 本系统是为互联网客户提供在线支付功能
责任描述: 按照易宝支付的接入规范编写接入代码,项目分两个功能,第一个功能是向支付网关发起支付请求,支付请求中包含商户的ID、商户的订单号、支付金额、响应URL等等。在请求发起前需要使用请求参数和商户的密钥采用MD5技术生成用户身份签名,并把用户身份签名作为请求参数发送给支付网关。第二个功能是当客户在银行网页完成支付后,支付网关会把支付结果信息发送到商户提供的响应URL。响应URL由一个Servlet实现,该Servlet会接收支付网关发送过来的请求参数,并且使用商户的密钥和接收到的请求参数生成身份签名。用生成的身份签名与支付网关发送过来的身份签名比较是否相同,如果相同,证明请求来源合法,处理支付成功的业务。
采用Log4j记录交易信息,采用dom4j从XML文件中读取商户配置信息。

2008/03--2008/06:江西省燃料公司综合办公自动化系统(OA)
软件环境: Struts+Ajax+Jbpm+Hibernate+Jfreechart
开发工具: eclipse3.3 for JavaEE
项目描述: 本系统是一个基于互联网的高效协同工作平台和优秀的协同管理系统。它可把日常管理中的业务、事务、事件等信息在单位、部门、组群、个人之间进行及时高效、有序可控、全程共享的沟通和处理。包含文档系统/人事系统/公共信息系统/日程任务系统/消息系统/考勤系统/系统系统/公告系统/会议管理/审批管理/个人工具/办公用品/权限管理等模块。
责任描述: 参与了项目的功能划分的分析和设计的讨论,消息管理、考勤管理、公文流转、权限管理等的代码实现。负责公文流转管理及流程监控。实现公文的会签,流程的设计使用图形化的流程设计工具完成。同一个流程定义在系统中可以有多份,以版本来区分。在流程执行的过程中,可以全程监控流程实例,可以查看流程中的所有变量;可以图形化的监控流程,在流程图片上高亮显示当前正在执行的节点。对统计数据使用Jfreechart生成饼图与柱状图。

2007/12--2008/03:美特好超市进销存系统
软件环境: Struts2+Spring+Hibernate
开发工具: eclipse3.2+ROSE
项目描述: 这是一个对企业采购、销售、库存进行管理的系统,对企业的从采购到库存到销售等各个环节进行管理,实现了数据在各个部门之间的共享与流转,提高了企业的运行效率。项目主要分采购、销售、仓储三个主要子系统。
责任描述:

负责库存子系统的开发,主要开发入库单、出库单和盘点单三张单据的开发以及库存台帐、库存预警等模块的开发。

项目经验与心得:
展现层使用Struts2来实现MVC模式,把Domain Object和Action交由Spring容器进行管理,这样有助于更好的分层解耦。利用Spring可以管理对象的生命周期、注入依赖对象和使用容器声明式事务管理。持久化层使用hibernate来实现,使用泛型DAO把添/删/改/查/分页/统计这些操作进行了封装,子类只要继承该DAO就具备这些行为。在实现细粒度权限管理时使用了Struts2中提供的拦截器实现对Action方法的拦截,当发现用户具有某个权限时,才允许Action方法继续执行。粗粒度权限管理使用Filter实现。实现DAO代码时,我们并没有使用HibernateTemplate和HibernateDaoSupport,主要因为这两个类都是由Spring提供的,从无入侵性的角度来看,应用会跟Spring容器产生紧密的耦合。这里我们使用了Hibernate原生的API实现DAO,当然这种方式只能在Hibernate3以上版本中使用,而且必须通过getCurrentSession()方法获取当前被spring管理的session,而不能使用openSession(),因为openSession()得到的session是不受spring容器管理的,无法使用容器管理事务功能。


2007/9--2007/12:宁夏企业征信系统
软件环境: Struts+Spring+Hibernate+Ajax+EHCahce
开发工具: eclipse3.2+ROSE
项目描述: 本系统是政府为解决中小企业融资难,由政府部门依法采集、保存、整理、提供企业的信用信息,满足从事放贷等信用活动的机构(担保公司或银行)在信用交易中对客户信用信息的需要。采集的内容包括企业各种纳税情况、环境评估、贷款还款等各种信用信息。
责任描述:

在收集客户的需求后,使用ROSE进行用例分析和编写设计文档。本人负责中小企业管理、文档管理、权限模块设计与开发。在这个项目中我们使用Spring对业务bean及Struts中的Action进行管理,实现了业务层与控制层的解偶合。在业务层中使用了spring的容器管理事务功能,减少了大量重复并且烦琐的事务控制代码。通过Spring的依赖注入功能很方便地实现了注入依赖对象的需求。使用Spring的OpenSessionInViewFilter过滤器解决了在JSP访问实体bean中的Lazy属性时,因Hibernate的session关闭而导致的延迟加载例外问题。使用Spring的CharacterEncodingFilter过滤器解决了Struts1的中文乱码问题。项目中使用了EHCache作为Hibernate的二级缓存实现,对经常访问的数据进行缓存,如客户信息等。项目中使用了C3P0数据源技术减少连接对象数来提升应用性能,在团队开发中使用了SVN版本控制器。


2007/8--2007/9:建设银行招聘系统(http://job.ccb.com)
软件环境: Struts+DBUtil+JavaBean
开发工具: eclipse3.2
项目描述: 实现中国建设银行在线招聘功能,用户可以管理简历、投递简历、查看面试信息等,建行管理员可以管理招聘信息、审核简历、面试通知等等。
责任描述: 完成简历管理、简历投递等功能以及信息展示。考虑到性能的要求,使用DBUtil发送SQL语句直接操作数据库,采用JavaBean作为业务层Bean,在Struts的Action中调用JavaBean完成业务功能。

2007/6--2007/7:公司内部论坛系统
软件环境: Struts+Spring+Hibernate+Lucene+WebSerivce
开发工具: eclipse3.2
项目描述: 包含用户模块,版面模块,文章模块,权限模块,搜索模块,系统模块,缓存模块等。版面模块:采用二级的版面结构(或叫做分类和版面),可以控制(调整)分类或版面的显示顺序;文章模块:文章分为主题和回复。主题有多种类型,比如公告帖,置顶帖,精华帖,推荐帖,普通帖等等。一个主题中可以带有一个投票,称之为投票帖。投票有两种:单选投票和多选投票。一个用户只能对同一投票主题投票一次。文章(主题和回复)中可以带有附件。每个附件都可以有说明,用于说明这个附件文件的内容,因为不是所有的文件的名字都是有意义的。文章搜索:使用lucene技术,实现了类似百度的站内全文搜索。优点为查询速度快,查询条件多样,比如可有前缀查询,通配符查询,短语查询,模糊查询等等,十分灵活快速。在后台有会员管理:可以锁定捣乱的会员;有搜索管理:查询或更新或重建lucene索引库;有系统设置和配置文件管理:查看和修改系统参数。
责任描述: 负责文章模块、搜索模块、内容管理的设计与开发。
文章模块:使用了FCKeditor可视化在线编辑器。文章中的附件存放到服务器的硬盘中,解决了文件名相同、危险文件类型、大文件、中文名附件下载乱码问题。
搜索模块:使用Compass+Lucene实现对站内文章的全文搜索,并使搜索结果中的关键字高亮显示,编写业务bean时反复使用Junit对业务方法进行单元测试。项目中大量使用了Factory(工厂模式)、Prototype(原型模式)、Singleton(单态模式)和Proxy等设计模式。
获取用户的IP地址,使用基于JAX-WS2.1规范的WebService技术从http://www.webxml.com.cn/WebServices/IpAddressSearchWebService.asmx查询IP所在国家、城市、所有者等信息。
教 育 经 历
2003/9--2007/6 长春理工大学 计算机科学与技术 本科
 
语 言 能 力
英语 一般