2010年1月31日
巴巴运动网的权限模块总结
因为巴巴运动网的权限设计模块对我来说,可以实现,打算好好整理一下思路,面试时说不定还能起点作用,看了两遍,自己总结下:
权限定义/权限组(角色)模块
1.对系统的所有功能定义相应的权限
2.由网管针对不同部门不同员工分配权限组(角色),在分配角色时,
可以选择该角色具有的权限
3.权限拦截模块
具体步骤:
1.设计权限实体
联合主键(SystemPrivilegePK),该类有module和privilage两个属性
2.初始化权限
3.设计权限组(角色)PrivilegeGroup实体,如果我们希望通过修改权限组添加或删除权限,那么权限和角色之间的多对多关系的维护端由角色来维护
private String groupid;
private String name;
private Set<SystemPrivilege> privileges = new HashSet<SystemPrivilege>();
同时加上到数据库表的映射
当然由于权限和角色之间的多对多关系是双向关联,所以要在SystemPrivilege实体bean中加上和PrivilegeGroup实体Bean之间的映射
4.实现权限组的添删改
路径:/control/
新建接口PrivilegeGroupService,继承Dao<PrivilegeGroupService>,
新建PrivilegeGroupService,继承DaoSupport
当然这些Bean都需要交给Spring管理,加上相应的注解即可
5.实现权限组的分页,这个简单
6.实现添加权限,分页列表上的Action,新建Action,名称为PrivilegeGroupManageAction,
①.第一个方法是AddUI,主要是显示页面
接下来就是增删该操作了(...)
7.权限做完后要新建一个Action用于完成SystemPrivilege,权限组,超级管理员的初始化,初始化完成后点击“确定”,进入登陆页面
权限模块的核心: 权限拦截模块
1.员工要访问control开头的路径,必须登陆,即粗粒度的权限拦截,这是通过Fileter实现的,这里我们定义为PrivilegeFilter,先从session范围中得到employee对象,如果对象为空,就浏览器重定向到登陆界面,,如果登陆了,就chain.doFilter(request,response);之后在web.xml配置,这样就实现粗粒度的权限控制了3
2.对于界面上的某些功能,不是每一个登陆到系统的员工对页面的功能都有操作权限,这就是细粒度的权限拦截
关键是怎样细粒度的权限控制
怎样实现细粒度的权限控制?
每点击页面上的按钮,都会提交给相应的Action处理,细粒度的权限拦截就是对Action拦截,在不修改原代码情况下,增加拦截代码,使用的是AOP技术
每一个功能Action都有相应的方法处理,我们用JDK5中的注解为Action中的方法注解相应的权限,因为我们有时会修改方法名称,用注解维护起来比较方便比如:
@Permission(module="order",privilege="modify")
public ActionForward OrderModify(){}
实现过程:
①.新建注解Permission,
@Retention(PetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Permission{
String module();
String privilege();
}
为Action中的方法,加上注解
只有拦截到Action中的这个方法,才能实现权限拦截,现在我们的Action已经交给Spring管理,所以我们可以使用Spring的AOP技术进行权限拦截,有必要复习一下AOP的知识:
在Action类上加一个注解如下:@Aspect,当然要使这个注解起作用,我们必须在Spring的配置文件里配置:
<aop:aspectj-autoproxy> <!--注解解析器-->
要实现切面编程,抽象过程体现在代码上, 就是一个采用类来描述,要是这个类起作用,我们必须要把它交给Spring管理,很郁闷
@Aspect@Component
public class Interceptor{
@Pointcut("exception(org.apache.struts.action.ActionForward cn.itcast.web.action.. * *(org.apache.struts.actionMapping,...))")
private void actionMethod(){}
@Around("actionMethod")
public Object interceptor(ProceedingJoinPoint pjp) throw Throwable{
System.out.println("拦截到了"+pjp.getSignature().getName()+"方法");
return pjp.proceed();
}
}
注意:
通知:
前置通知,在拦截的方法前加通知,这个通知执行后,被拦截的方法仍然会执行。
所以使用环绕通知,但是这样的拦截只能是拦截Action实现的,他不能拦截继承自DispatchAction
原因:Spring的动态代理技术的问题
Spring不能对通过反射调用的方法应用上通知(Advice)
当Spring发现我们的继承的DispatchAction的那个类符合他拦截的要求,就会生成一个代理对象,因为无接口,默认使用cglib为这个Action生成代理对象,根据cglib生成代理对象的特点,继承目标类,并且重写所有非final的方法来实现
注:spring只会为本类定义的方法应用通知
posted @
2010-04-01 07:10 d66380022|
编辑 收藏
今天初步学习了一下Struts2,对于Struts2,企业中已应用十分广泛,由于他是在Struts基础上发展而来,技术上比struts高,比如
struts2对同一个路径的每个请求分别使用一个独立Action实例对象,所有使用struts2不用考虑线程安全问题,还有就是修改下配置文件,不用重启服务器
1.struts2的建立过程:
配置过程:
1.新建web项目
2.导入struts2类库. [blank项目中含有最少的jar文件]
3.配置web.xml
<filter>[...SrutsPrepareAndExecuteFilter]
4.写Action类
public class HelloWorldAction {
public String execute(){
System.out.println("hello world!");
try {
ServletActionContext.getResponse().getWriter().printf("hello!");
} catch (Exception e) {
e.printStackTrace();
}
return null ;
}
}
5.创建struts.xml
①.struts2默认在类路径下查找struts.xml文件
关于struts.xml配置,可以参看struts2-blank-2.1.8.1.war解压后的配置
设置环境为开发模式.设置为开发模式,有利于编程和调试,
<constant name="struts.devMode" value="true" />
3.让struts.xml中的Package继承struts-default.xml中的默认包.
所有的默认包中的元素配置就引入进来.
4.配置默认值.
<action name="HelloWorldAction" class="cn.itcast.struts2.helloworld.HelloWorldAction">
<result name="success">
<param name="location">/index.jsp</param>
</result>
</action>
5.strtus2中的action不是单例的,它会为每个请求单独分配一个action实例,所以可以在action类中声明实体属性.
Struts2的Action是模型层,不是控制层,原因它是需要携带业务数据的.
6.struts2中的拦截器是负责每个独立的一项任务.例如,参数传递,国际化,异常处理,StrutsPrepareAndExecuteFilter是Struts 2框架的核心控制器,它负责拦截由<url-pattern>/*</url-pattern>指定的所有用户请求,当用户请求到达时,该Filter会过滤用户的请求。
7.在struts2的jsp中输出数据,借助于struts-tag.tld标签库.该库在[struts-core.jar/META-INF/struts-tag.tld,但是其重要作用还是用于回显数据
8.Struts2可以数据的范围:ActionContext request session application
ActionContext是数据中心,ValueStack不过是该数据中心中的一个特殊对象.
在jsp中访问ActionContext中的数据的话,可以使用OGNL语言.
9.struts2中包的名字空间搜索原则:
1.<package name="xxPkg">
2.<package name="xxPkg" namespace="">
3.<package name="xxPkg" namespace="/">
4.<package name="xxPkg" namespace="/HelloWorld">
1.和2.效果一样,都是默认的包.
2.都会自后向前搜索,直到找到为止,"/" 和 "/HelloWorld"唯一不同就是也可以作为搜索目录.
3.空包是默认包,如果每个包都没有找到相应的action的话,就去默认包下去找.
10.struts2中进行动态方法调用.
http://localhost:8085/struts2/Hell/HelloWorldAction!toRewView.do
11.struts2中使用标签库
<s:form action="HelloWorldAction_doReg" [namespace=""]>
<s:textfield name="name" label="UserName" />
<s:submit />
</s:form>
namespace:如果不写,会使用当期的名字空间.
struts给的所有控件标签,主要目的用于回显数据.
12.struts2中进行基本的校验,需要Validateable和ValidationAware两个接口的支持,同时还需要
workflow拦截器的支持.
13.在struts2中,默认的表达式语言是OGNL,Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目。 Struts 2框架使用OGNL作为默认的表达式语言。相对EL表达式,它提供了平时我们需要的一些功能,如:支持对象方法调用,支持类静态方法调用和值访问,操作集合对象。例如():
访问值栈中的action的普通属性: username = <s:property value="username"/>
由于下午有公司来面试,耽误了一些时间,老徐说明天再多补一个小时,太敬业了啊,佩服!
posted @
2010-03-25 16:39 d66380022|
编辑 收藏
在线支付时针对易宝支付的网关而开设的,众所周知,易宝已是三大网上支付平台之一,正好明天易宝来招聘,正好练练,呵呵,下午是面试技巧
好好学习,毕业倒计时:15天
1.支付宝是不能立即拿到现钱的,这也是商家喜欢在线支付的一个原因吧,在线支付是直接和银行对接的,这样商家可以立即拿到现钱,避免了和买家产生矛盾后,钱被封的风险。
下面就来实现在线支付吧,首先提出请求,如果通过,会得到账号和密钥
我们要做的事有两项
1.向支付网关发起请求,就是向http发起请求,所谓请求就是我们平常使用Http请求(http://www.xxx.cn/xxx.do),请求方式:Get/Post
<form method=”” action=”https://www.yeepay.com/app-method”>
<input name=”?”,value=””/>
<input name=”url” value=”http://www.itcast.cn/re.do”/>
<input name=”hmac” value=””>
…..
Hmac
= MD5(pd_FrpId + p0_Cmd + p8_Url,key);32位,不可逆
支付网关:其实就是一个http路径
2.接收支付网关返回的支付结果信息
第一次使用浏览器重定向技术,
把支付信息发送给:http://www.itcast.cn/re.do?id=21432&result=1
2.相关知识点:
一.接入方式:两种接入方案
①.直接与银行对接
优点:因为直接与银行进行财务结算,交易资金结算比较安全
缺点:开发工作量比较大,而且银行会不定期升级交易系统,随着银行系统的升级,企业也需要作相应改动,所以维护工作量也是比较大的,而且企业每年还需要向银行交纳一定数量的接口使用费。
②.通过中间公司间接与银行对接
优点:开发工作量较少,因为使用的是中间企业提供的接入规范,所以银行升级系统,不需要企业作相应修改,除非中间企业的接入规范发生了改变,企业才作相应修改。
缺点:因为是与中间企业进行资金结算,目前所有中间企业都是私企,资金安全是个大问题。
3. 对支付数据进行Md5加密
4. 支付流程:
通过http请求方式向易宝支付网关发起一个支付请求,请求可以是get或post方式提交。
易宝支付网关对企业发来的数据使用用户的密钥生成MD5-hmac码,然后跟企业发来的MD5-hmac码(即上面表单由hmac字段提供的值)比较是否相同,如果相同即把请求转发到银行网关,当用户支付完成后,银行网关会引导用户的浏览器重定向到易宝支付网关,然后易宝支付网关再引导用户的浏览器重定向到企业提供的url(即上面表单由p8_Url提供的地址)
接下来我们只需处理结果了
下午是面试技巧:
薪水:一定要写 ,不要写区间 4000
心得体会:具体点
责任描述:多写,详细,写开发难点,描述清楚,介绍清楚
对某一模块详细描述,对难点的解决过程
描述自己负责的模块,抓住一点,详细说,千千不要泛泛而谈
不能写培训经验
三好学生,写一等奖学金是应届的
爱好还是要写的
身份证不能造假,教育经历,通常企业筛选简历过程:
从1-2千封中选,让前台做/人力去筛选简历,要求:
A.只提取两年工作年限以上(一般企业都是这样干的)
B.连人力都能判断出造假的简历,排除
C.经过人力,剩下100封
D.面试官
88年可以写两年,教育经历:把毕业信息提前,证书造假
简历上可适当造假
薪水:
写2年,月薪(北京,上海,广州):
初级:3000 – 4000
4500 -- 8-12
中级:4500 – 6000
7K 其中5K-6K比较多 --
高级:7000 –
1.2W (3-5)
从事Android,薪水如下:
Android 2年 最长就2年
原来做过j2se开发3-4年 8K-1.2W
android 3个月(j2ee 1-2)6K
Android 干半年 4.5K
如果我们老老实实干半年,编码能力就会没问题
工作经验:
1.为什么离职?
我在深圳那边4K,也不知道北京这边的行情。
2.当公司准备要你的时候,会让你填以前公司的地址信息,联系人信息
造假呗,找个外地的同学
3.入职后,离职证明,随便盖个章,离职证明模版网上有一大堆
新公司不想惹麻烦,已经和原来公司解除了劳动合同
4.关于android面试
基础:
多线程(并发控制),Socket通信,http通信
android:
android的什么项目
项目针对那些手机型号的手机HTC
如何适应各个分辨率的问题,大分辨率靠前
ContentProvider(难度),共享数据
联系人(如何获取联系人)
Activity的生命周期:运行
暂停 停止
前台生命周期
完整生命周期
意图:隐式,显式
组件:广播,内容提供者,Service
四大组件
MMI:多媒体接口
SQLite:数据库访问
项目开发
3人
2-3月
公司部门 人员
研发部/技术部 50-60人
测试部 8-10人
客服部/售后服务
市场部
行政部
posted @
2010-03-24 00:49 d66380022|
编辑 收藏
今天学习从网上获得数据,以xml文件输出。流程:android客户端 -----已经开发好的CRM(220.113.15.23)
-----[客户资料]--à屏幕
用的是struts1.3的环境
1.搭建环境
1.web.xml配置struts servlet
2.添加jar
3.复制struts-config.xml
环境搞定后,新建jsp文件,写好文件头:<?xml
version="1.0"
encoding="UTF-8"?> 注意
接着新建一个ContactAction
最后配置struts-config.xml文件
新建contact.jsp文件,得到数据
访问路径,测试得到的数据,以验证是否正确,若正确的话,第一步完成
下面是Android应用
2 .①.设计要显示的界面
②.新建service,可以调用
关键代码:
String
path = “http://192.168.1.100:8080/crm/contacts.do”;
URL
url = new
URL(path);
HttpURLConnection
conn
= (HttpURLConnection)url.openConnection();
conn.setConnectionTimeout(5*1000);
conn.setRequestMethod(“POST”);
return
conn.getInputStream();
在该类中还应该新建sax解析方法,解析文档,保存数据
③.新建android测试类,以日志形式打印出xml文件中的数据
3.应用HttpURLConnection对象,我们可以向网络发送请求参数.下面以POST发送为例,写一些关键代码点
Map<String, String> params =
new
HashMap<String, String>();
params.put("age", "22");
params.put("name", "浪淘沙");
StringBuilder
params = new StringBuilder();
for(Map.Entry<String, String>
entry : params.entrySet()){
params.append(entry.getKey());
params.append("=").append(URLEncoder.encode(entry.getValue(),
"UTF-8"));
params.append("&");
}
if (params.length() > 0)
params.deleteCharAt(params.length() - 1);
byte[] data =
params.toString().getBytes();
4. 为应用添加新的Activity
①:新建一个继承Activity的类
②:需要在功能清单AndroidManifest.xml文件中添加进上面Activity配置代码
打开新的Activity,不传递参数
通过意图打开Activity,Intent,用于激活Activity的,在组件之间传递数据
在新的Activity中接收前面Activity传递过来的参数:
添加参数的另一种方法:Bundle
Bundle类用作携带数据,它类似于Map,用于存放key-value名值对形式的值。相对于Map,它提供了各种常用类型的putXxx()/getXxx()方法, putXxx()用于往Bundle对象放入数据,getXxx()方法用于从Bundle对象里获取数据。Bundle的内部实际上是使用了HashMap<String,
Object>类型的变量来存放putXxx()方法放入的值:
5. Intent过滤器
Android鼓励减少组件间的耦合,因此Android提供了Intent (意图) ,Intent提供了一种通用的消息系统,它允许在你的应用程序与其它的应用程序间传递Intent来执行动作和产生事件。使用Intent可以激活Android应用的三个核心组件:活动、
服务和广播接收器。
Intent可以划分成显式意图和隐式意图。
posted @
2010-03-20 23:30 d66380022|
编辑 收藏
使用SharedPreferences进行数据存储,是专门用来向用户提供软件参数设置功能,
1.
SharedPreferences类,它是适合用于保存软件配置参数。使用SharedPreferences保存数据,其背后是用xml文件存放数据。
2. SharedPreferences使
用xml文件保存
数据,getSharedPreferences(name,mode)方法的第一个参数用于指定该文件的名称,不用带后缀,后缀由Android自动加上,方法的第二个参数指
定文件的操作模式,共有四种操作模式。
3.设置软件参数过程:
①.当用户点击保存按钮时,就激发保存事件
在Activity中的匿名内部类中,得到用户输入值
需要注意的是:android.content.SharedPreferences.Editor用于保存参数,该editor最后要commit一下。
最后要Toast.makeText(PreferencesActivity.this,
"保存参数成功",
1).show();用于提示保存参数成功
②.如果访问其他应用中的Preference,前提条件是:该preference创建时指定了Context.MODE_WORLD_READABLE或者Context.MODE_WORLD_WRITEABLE权限。如:有个<package
name>为cn.itcast的应用使用下面语句创建了preference。
getSharedPreferences("itcast",
Context.MODE_WORLD_READABLE);
其他应用要访问上面应用的preference,首先需要创建上面应用的Context,然后通过Context 访问preference ,访问preference时会在应用所在包下的shared_prefs目录找到preference :
Context
otherAppsContext = createPackageContext("cn.itcast",
Context.CONTEXT_IGNORE_SECURITY);
4. 使
用SQLite数
据库存储数据
在Android平台上,集成了一个嵌入式关系型数据库—SQLite,SQLite3支持 NULL、INTEGER、REAL(浮点数字)、TEXT(字符串文本)和BLOB(二进制对象)数据类型,虽然它支持的类型只有五种,
SQLite最大的特点是你可以保存任何类型的数据到任何字段中,无论这
列声明的数据类型是什么。SQLite可以解析大部分标准SQL语句。
5.开发3g数据库
软件需求:
①.用户初次使用软件,初始化数据库
②.用户升级软件,自动更新数据库
为此,类对应提供了两个重要的方
法,分别是onCreate(SQLiteDatabase db)和onUpgrade(SQLiteDatabase
db, int oldVersion, int newVersion),
6.利用继承自SQLiteOpenHelper的DatabaseHelper类实现增删改查,和我们以前的用JDBC实现的增删改查语法基本一样,举例:
SQLiteDatabase
db
= ....;
db.execSQL("insert
into person(name,
age) values(?,?)", new Object[]{"传智播客",
4});
db.close();
需要注意的是SQLiteDatabase的rawQuery()
用于
执行select语句
7.将数据动态显示在手机屏幕上,用SimpleAparter实现
今天到此结束!
posted @
2010-03-17 23:53 d66380022|
编辑 收藏
3G的第二天,单元测试,老黎讲的东西当天基本可以掌握,很喜欢
1.单元测试步骤:
第一步:首先在AndroidManifest.xml中加入下面红色代码:
①.在<application>中加入:
<uses-library android:name="android.test.runner" />
②.在最后的标签前加上:
<instrumentation
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="cn.itcast.action"
android:label="Tests for My App" />
注意:上面targetPackage指定的包要和应用的package相同。
第二步:编写单元测试代码(选择要测试的方法,右键点击“Run As”--“Android Junit Test” ):
2.数据存储和访问
软件需要对处理后的数据存储,Android为数据存储提供了5种方式:
文件,SharedPreferences,SQLite数据库,内容提供者(Content provider),网络
使用文件对数据进行存储,Activity提供了openFileOutput()方法可以用于把数据输出到文件中。openFileOutput()方法的第二参数用于指定操作模式,有四种模式,分别为:
Context.MODE_PRIVATE
Context.MODE_APPEND
Context.MODE_WORLD_READABLE
Context.MODE_WORLD_WRITEABLE
3.SAX解析XML
SAX是一个解析速度快并且占用内存少的xml解析器,解析采用的是事件驱动,这些方法定义在ContentHandler接口中,下面是一些ContentHandler接口常用的方法:
startDocument()
当遇到文档的开头的时候,调用这个方法,可以在其中做一些预处理的工作。
endDocument()
和上面的方法相对应,当文档结束的时候,调用这个方法,可以在其中做一些善后的工作。
startElement(String
namespaceURI, String localName, String qName, Attributes atts)
当读到一个开始标签的时候,会触发这个方法。
endElement(String
uri, String localName, String name)
这个方法和上面的方法相对应,在遇到结束标签的时候,调用这个方法。
characters(char[]
ch, int start, int length)
这个方法用来处理在XML文件中读到的内容,第一个参数为文件的字符串内容,后面两个参数是读到的字符串在这个数组中的起始位置和长度,使用new String(ch,start,length)就可以获取内容。
4.使用Pull解析器读取XML文件
如果需要生成一个XML文件,生成XML文件的方法有很多,如:可以只使用一个StringBuilder组拼XML内容,然后把内容写入到文件中;
或者使用DOM API生成XML文件,或者也可以使用pull解析器生成XML文件,推荐使用Pull解析器。
最后,
巴巴运动网,好好学习权限和优化等技术,面试特别有帮助
posted @
2010-03-16 00:29 d66380022|
编辑 收藏
今天是黎老师的3G应用开发Android项目的第一天,Android相当火,从事Android开发的人员不太多,接下来开始Android之旅。
1.3G简介:
3G,即3rd Generation,目前中国联通使用的是WCDMA,中国电信使用的是CDMA2000
中国,移动使用的是具有自主知识产权的TD-SCDMA,3G的最大优点:速度上的提升
2.wml标签,比Html标签简单,1-2天就可以搞定,工作中用到再学,因为他是2.5G中用到的技术,如果3G普及的话,这门技术就Over了。
3.智能手机操作平台
我们学Android操作系统,RIM BlackBerry,黑莓我比较喜欢,但在国内还不怎么流行,
Symbian手机硬件比较好,所以占用很大市场,在3G时代,手机基本上可以当做电脑,用户更看重手机是否能满足日常生活和工作的需要。这就好像大多电脑
用户都安装了Windows操作系统,很少安装Linux系统。开发Android的人员的增多,必然会带来手机软件的增多,软件的多少会决定以后操作系统的市场份额,windows mobile比Android,iPhone的界面差远了。我们关注:Android,iPhone,Symbian智能手机平台,因为我们搞Java开发,只能学Android了
4.Android资料
买Android手机就买多普达和Moto的,质量好。Android最好的资料是android.pdf。Google Android SDK开发范例大全提供了Android的全部功能,在学完课程之后可以看
5. 开发环境的搭建:
JDK
5 或 JDK 6
(仅有JRE不够)
Eclipse
3.5 (galileo)
①.下载ADT 的Eclipse 插件
http://dl.google.com/android/ADT-0.9.5.zip
②.安装 Eclipse
插件 (ADT)
启动 Eclipse,选择 Help >
Install New Software,在出现的对话框里,点击Add按钮,在对话框的name一栏输入“ADT”, 然后点击Archive...,浏览和选择已经下载的ADT插件压缩文件。
点击 OK.。返回可用软件的视图,你会看到这个插件,然后选择Developer Tools (会选中下
面的“Android Developer Tools”和
“Android Editors“),点击 Next,最后重启 Eclipse。
③.下载Android
SDK:
http://dl.google.com/android/android-sdk_r04-windows.zip
下载完SDK后,把.zip文件解压到你电脑上合适位置。启动
Eclipse,选择window->preferences,
在打开的视图左边点击android,在右边的SDK Location中选择Android
SDK所在位置。
6.开发Android的第一个应用:
1.点击工具栏上手机形状的虚拟设备管理器(简称“AVD“)
2.在打开的虚拟设备管理器中创建一个虚拟手机
3.在项目上右键点击run as
?Android application
OK,第一个应用就OK了
7.端口号:127.0.0.1:5554
8.Activity
就像struts中的Action,处理用户请求,除此之外,Activity还代表一个用户界面
9. Android应用程序架构
src/ java原代码存放目录
gen/
自动生成目录
gen
目录中存放所有由Android开发工具自动生成的文件。目录中最重要的就是R.java文件。 这个文件
由Android开
发工具自动产生的。Android开发工具会自动根据你放入res目录的xml界面文件、图标与常量,同步更新修改R.java文件。
res/
资源(Resource)目录
在这个目录中我们可以存放应用使用到的各种资源,如xml界面文件,图片或数据。具体请看ppt下方备注栏。
AndroidManifest.xml
功能清单文件
这个文件列出了应用程序所提供的功
能,相当于struts的config文件,只有配置好后,才能调用此Activity。
default.properties
项目环境信息,一般是不需要修改此文件中
10.短信发送器
注意:因为应用要使用手机的短信服务,所以要在清单文件AndroidManifest.xml中添
加短信服务权限:
11.通知
关于这些东西,还是看看文档,拷过来运行一下,测试测试看看效果就差不多了。
posted @
2010-03-16 00:20 d66380022|
编辑 收藏
一.使用poi
1.参见poi的文档,添加jar包
2.workbook表示一个Excel文档
3.下载Excel模版,必须按格式
1.创建workbook对象
2.创建下载Excel文件的第一行
3.从数据库中读取到需要的Employee列表
5.利用Servlet Api 对准备好的Excel下载
4.上传excel
①.配置Action
②.导入两个jar包commons-io,commons-fileupload.jar
③.上传
1.根据ActionForm的FormFile属性读取上传数据,获得Workbook对象
2.读取Workbook对象中的内容:遍历Workbook对象除标题行以外的行
3.把每一行都转换为一个Employee对象
4.调用方法,把Employee对象的集合保存到数据库中,注意:有可能不能保存,其原因可能违反格式或者违反数据库的唯一性约束
二.PDF文档输出
1.iText介绍:iText是著名的开放源码的站点sourceforge一个项目, 是用于生成 PDF 文档的一个java类库.
2.Pdf 文件输出的 5 个步骤
1. 创建一个 Document 对象.
public Document()
public Document(Rectangle pageSize): 定义页面的大小
public Document(Rectangle pageSize, int marginLeft, int marginRight,
int marginTop, int marginBottom): 定义页面的大小, 后边的四个参数分别指定左, 右, 上, 下页边距
2.建立一个书写器
(Writer) 与document对象关联, 通过书写器(Writer)可以将文档写入到磁盘中
3. 打开文档
4. 在文档中添加文字
5. 关闭文档
其中:
①。设定文档属性
当新的页面产生之前, 可以设定页面的大小、书签、脚注(HeaderFooter)等信息,调用的方法是:
②。添加文档内容
所有向文档添加的内容都是以对象为单位的, 如Phrase、Paragraph、Table等. 比较常用的是段落(Paragraph)对象, 用于向文档中添加一段文字
③。文本处理
iText中用文本块(Chunk)、短语(Phrase)和段落(paragraph)处理文本。
文本块(Chunk)是处理文本的最小单位, 由一串带格式(包括字体、颜色、大小)的字符串组成:
注意:在 iText 中没有行的概念, 一个表格里直接放单元格, 如果一个 3 列的表格中放进 6 个单元格, 那就是两行的表格. 如果放入 5 个基本的没有任何跨列设置的单元格, 表格就会出错. 此时表格不会添加到文档中, 并且没有任何提示
三.面试
老佟给我们找了一个简历,介绍了一些面试的注意点,要点:
1.符合自身条件,各种技术。
2.最好写点权限设计,Compass+Lucene实现全文搜索,流程采用JBPM管理。
3.项目三个:小汤的OA和老佟的权限整合为一个项目,网上商城(巴巴运功网),3g,数据采集
OA用到的技术:SSH
jQuery + Ajax
jbpm 完成审批流程
spring-security
lucence :全文检索
posted @
2010-03-13 23:40 d66380022|
编辑 收藏
接着昨天的实现将拦截的url,权限信息,用户信息放到数据库中,并将spring-security集成到项目中
1. 实现资源信息存放到数据库中:
访问资源时, spring-security 能区分出访问该资源需要哪些权限
1. 自定义ObjectDefinitionSource 接口的实现类, 将该类的实例装配给
FilterSecurityInterceptor 的 objectDefinitionSource 的属性. 即可实现自定义的资源获取.
2. 通过继承 DefaultFilterInvocationDefinitionSource
类的方法定义ObjectDefinitionSource 接口的实现类有困难, 因为
DefaultFilterInvocationDefinitionSource中没有无参的构造器
3.通过查看 spring-security 核心 jar 包的 META-IN 下 的 spring.handlers 找到
SecurityNamespaceHandler, 在该类中查看
registerBeanDefinitionParser(Elements.HTTP, new
HttpSecurityBeanDefinitionParser()); 方法在
HttpSecurityBeanDefinitionParser 类中可以看到如何创建
DefaultFilterInvocationDefinitionSource 实例.
4. 通过 FactoryBean 在 IOC 容器中注册
DefaultFilterInvocationDefinitionSource 实例
5. 实现ResourceDetailsService 接口
2.关于MD5加密:
1.网上的关于MD5已经很多了,MD5算法对密码进行摘要加密,这是一种单项加密手段,无法通过加密后的结果反推回原来的密码明文。
为了使用MD5对密码加密,我们需要修改一下配置文件
<authentication-provider>
<password-encoder hash="md5" >
<jdbc-user-service data-source-ref="dataSource" >
< authentication-provider>
上述代码中新增的黄色部分,将启用md5算法。
3.管理会话(HttpSession)
多个用户不能使用同一个账号同时登陆系统。
添加监听器
在web.xml中添加一个监听器,这个监听器会在session创建和销毁的时候通知Spring Security。
这种监听session生命周期的监听器主要用来收集在线用户的信息,比如统计在线用户数之类的事。后登陆的将先登录的踢出系统默认情况下,后登陆的用户
会把先登录的用户踢出系统。
============================================================================================
集成spring-security框架
1. 集成 spring-security 框架
1. 加入 spring-security 的两个 jar 包
2. 在 web.xml 文件中加入加入 spring-security 框架的过滤器
3. 新建 applicationContext-security.xml 配置文件,并且把 security 作为默认的命名空间,
并将其导入到 applicationContext.xml 中
4. 设计领域模型:
Authority -- 权限
Resource -- 资源
Role -- 角色
Employee -- 添加 Set<Role> roleSet 属性
Resource 和 Authority 为多对多的对应关系
Authority 和 Role 为多对多的对应关系
Role 和 Employee 为多对多的对应关系
需要 3 个关联表
5.
1. 修改当前系统的 login.jsp 页面, 改为 spring-security 的登录页面, 并且在
<http> 节点中进行配置.
注意: spring-security 在登录成功后, 利用
"重定向" 转到 form-login 节点对应的 default-target-url 属性对应的页面. 所以不能直接将其配置为
WEB-INF 目录下的任何页面
2. 新建 UserDetailsService 接口的实现类, 以实现从数据库中获取用户信息(需要查询 Employee,
Role, Authority, 参见 spring-security-2 的UserDetailsServiceImpl, 基于
Hibernate 实现),并把该类的 Bean 引用装配给 <authentication-provider> 节点的
user-service-ref 属性
6. 向 ems_resource_table, ems_authority_table,
ems_resource_authority_table 数据表中添加数据
7. 新建 ResourceDetailsService 接口的实现类,
实现从数据库中读取需要被保护的资源信息及其可以访问这些资源的权限信息
8. 利用 FactoryBean 新建 DefaultFilterInvocationDefinitionSource 接口的
Bean, 并把 ResourceDetailsService 的 Bean 注入进来, 再把该 Bean 配置为
filterSecurityInterceptor 过滤器的 objectDefinitionSource 属性
2. 实现权限模块:
1. 实现 Role 的增, 删, 改, 查
角色的添加:
页面 UI:
a. 对字段的 jQuery validation 验证
b. struts validator 验证 **
c. Action的复杂验证: 角色名不能重复 **.
d. 角色名的 ajax 验证, 角色名不能重复 **.
e. 勾选权限时的级联选择. 例如: 勾选 "员工删除" 的同时必须勾选 "员工查询", 即不能让用户只有
"员工删除" 权限, 而没有 "员工查询" 权限.
f. 使用到 Authority 的如下两个字段: relatedAuthorites(与当前权限关联的权限信息,
多个权限使用 "," 分隔), parentAuthority(当前权限的父权限)
subAuthorities(当前权限的子权限)
若验证都通过, 在 Action 中受理请求, 录入角色
注意:
不能通过以下代码获取 parentAuthority 为 null 的 Authority 集合
List list = authorityDao.findBy("parentAuthority", null);
System.out.println(list.size());
而应该使用:
List list = authorityDao.find("FROM Authority auth WHERE
auth.parentAuthority IS null");
为 #select 添加 change 相应事件, 当选取某个父权限时, 子权限显示
今天就此为止,明天继续!
posted @
2010-03-13 23:21 d66380022|
编辑 收藏
今天主要实现的是员工信息的修改和权限管理基础,修改用AJAX实现的,权限看了不少的源代码,感觉蛮难的,不过今天只是初步介绍,还有时间再学习一下!
1.员工信息的修改
1.struts对表单信息的回显
2.对可以进行修改的字段
1.当该字段值发生改变时,confirm”确定修改该信息吗?”
点击”取消”:使该字段恢复为以前的默认值,不做改变,需要使用隐藏域
点击“确定”:用AJAX改变字段,在配置文件中不需返回任何信息
<script type=”text/javascript”>
$(function(){
$(“:text,select”).change(function(){
var flag = confirm(“确定要修改” +
$(this).prev(“label”).text()+”信息吗?”);
...
});
}):
</script>
信息
2.集成spring-security 框架
1.
Spring Security 能用
于保护各种 Java 应
用程序(权限管理框架).
2.spring-security入门
需
求:1. Spring-security 应用的根目录下有两个 Jsp 页面: index.jsp 和 admin.jsp. admin 用户有权限访问这两个页面, 而 user 用户只能访问 index.jsp
2.提供”登出”功能
搭建环境:
首先添加spring环境
1.加入spring-security 的jar 包:
spring-security-2.0.5"dist"spring-security-core-2.0.5.RELEASE.jar
2.在web.xml 文件中加入加入spring-security 框架的过滤器
3.新建applicationContext-security.xml 配置文件,并且把security 作为默认的命名
空间, 并将其导入到applicationContext.xml 中
applicationContext-security.xml中,有几种重要配置:
1. 配置 spring-security 的 http 安全属性
<http
auto-config="true">
2. 配置需要保护那些
资源, 以及访问这些资源
所需要的权限, 若有多个
权限使用 ',' 分隔
<intercept-url
pattern="/admin.jsp" access="ROLE_ADMIN"/>
<intercept-url
pattern="/index-1.jsp" access="ROLE_USER"/>
3.配置登出服务
<logout
logout-url="/logout"
logout-success-url="/loguot-success.jsp"
invalidate-session="false"
/>
4.配置登录页面,
default-target-url:
若直接请求登录页面, 那么该属性配置登录成功之后的相应页面
always-use-default-target:
若请求的目标页面受保护,
则
spring-security 会相应 login-page 属性对应的页面, 默认情况下, 若登录成功将相应刚才请求的目标页面,
但这相当麻烦,每次都要配置不少信息。下面
有更好的实现,即
把需要拦截的url,权限,用户信息放到放数据库中,实现如下:
1.实体类:
Authority
-- 权限
Resource
-- 资源
Role
-- 角色
Employee
-- 添加Set<Role>
roleSet 属性
2.关系
Resource
和Authority
为多对多的对应关系
Authority
和Role
为多对多的对应关系
Role
和Employee 为多对多的对应关系
所以还需要3 个额外的关联表
3.实现把用户信息,权限信息存放到数据库中
1.
实现把用户信息, 权限信息存放到数据库中
1). 自定义 UserDetailsService 接口的实现类, 将该类配置到 Spring 的 IOC 容器中, 并在
<authentication-provider
user-service-ref=""> 节点的 user-service-ref 属性中引用该 Bean.
2). 通过 debug 查看 UserDetailsService 接口的实现类返回的 UserDetails 对象
4. 实现资源信息存放到数据库中: 访问资源时, spring-security 能区分出访问该资源需要哪些权限
1). 自定义
ObjectDefinitionSource 接口的实现类, 将该类的实例装配给
FilterSecurityInterceptor 的 objectDefinitionSource 的
属性.即可实现自定义的资
源获取.
2). 通过继承
DefaultFilterInvocationDefinitionSource 类的方法定义 ObjectDefinitionSource
接口的实现类有困难, 因为
DefaultFilterInvocationDefinitionSource
中没有无参的构
造器, 该构造器有两个参
数: UrlMatcher
urlMatcher, LinkedHashMap requestMap.
urlMatcher 参数可
以通过 bean 的形式
事先配置, 但 requestMap 参数类似于:
{[/admin.jsp]=[ROLE_ADMIN], [/index.jsp]=[ROLE_USER]}, 需要访问数据库才能对其初始化, 但这不可能.
3). 通过查看 spring-security 核心 jar 包的 META-IN 下的 spring.handlers 找到
SecurityNamespaceHandler, 在该类中查看 registerBeanDefinitionParser(Elements.HTTP,
new HttpSecurityBeanDefinitionParser()); 方法
在
HttpSecurityBeanDefinitionParser 类
中可以看到如何创建 DefaultFilterInvocationDefinitionSource 实例.
4). 通过 FactoryBean 在 IOC 容器中注册 DefaultFilterInvocationDefinitionSource
实例
posted @
2010-03-10 01:00 d66380022|
编辑 收藏
今天主要实现的是员工信息的翻页设计,用AJAX实现的,接着实现了员工信息的删除实现,总结
一天的知识,感觉jQuery确实是十分有用的一门技术。
1.带复杂条件的分页:(非AJAX分页)
直接把deptid属性过滤加上会导致出现:org.hibernate.QueryException:
这时因为在
Employee 实体类中根本就没有 deptid 属性(并非指在 Employee 类中有该属性,而是要在映射文件中映射该属性).
解决方法:
在 EmployeeDao 中重写 Page<T> findPage(final
Page<T> page, final List<PropertyFilter> filters) 方法, 以解决表单页
面的 deptid和实体类的
dept属性的对应问题
注
意:1.增强 for 循环时, 不能 remove 其元素
2.在
循环时删除集合的元素, 会改变集合的 size 属性
2.AJAX分页设计
1.需要在EmployeeAction的对应方法中,返回JSON数据,在页面上进行解析即可
2.实现过程:
1.点击上一页连接时,需要使用AJAX分页:因为ajax分页时,页面没有刷新,
下一页连接添加AJAX支持
<script
type=”text/javascript”>
$(function(){
$(“#nextpage”).click(function(){
Var
url=”${cp}/employee-list-2.do?pageNo=” + (parseInt($(“#pageNo”).val()) +
1);
var args = $(“:hidden:not(#pageNo)”).serialize();
$.getJSON(url,args,function(data){
$(“.pagebanner”).html(“共”+data.totalCount+”条记录 ”);
$(“#pageNo”).val(data.pageNo);
});
return false;
});
});
</script>
服务器端实现(employeeList2)
1.获取请求参数
String
pageNoStr = request.getParameter(“pageNo”);
2.从页面获取PropertyFilter集合
3.调用service的findPage方法,得到分页数据Page对象
4.将page对象转化为对应的JSON数据格式。那么需要转化为什么样的JSON数据
{totalCount:,totalPages:,pageNo:,employees:[{employeid,:loginName:,gender:,...}] }
5.返回JSON数据
response.setContentType(“text/javascript”);
response.getWritter().print(jsonResult);
3.员工信息
删除功能
1.AjAX删除功能的实现:
1.若当前页已经是最后一页,且当前记录是当前页的最后一条记录,则不能再请求当前页的信息, totalPages不能代表服务器端的总页数
2.Ajax 删除要实现的功能:
1. 弹出confirm(): 确
定要删除吗?
2. 若点击"否",
则文本框或下拉框的值恢复为刚才的默认
值: 使用隐藏域.
3. 若点击"是",
进行ajax
删除
4. 若
员工信息有外键关联时,注
意:通过 ajaxError 函数进行提示,弹出“不能删除该记录”
关键代码:
4.查看员工的详细信息
这样的功能实现在现在来说,已不难实现,我实现了一下,不难!还用了下插件!显示Employee
的头像!
posted @
2010-03-07 23:03 d66380022|
编辑 收藏
员工的录入和查询(带
条件查询)
今天做的是员工信息录入和服务器端的验证,目标是使用jQuery更熟悉,掌握分页设计,更好理解Hibernate的一些以前未用过的类中的一些方法。
一. 员工的录入,并进行验证
1.显示员工的录入页面
1.用jQuery 的validator
为表单做前台验证
2.对登录名的Ajax 校验
3.使用jQuery 的blockUI
插件提示Ajax 操作
4.录入员工信息
2.服务器端的简单验证
1.使用struts的validator框架
2.以email为例,email非空,且符合email格式
3.员工录入服务器端的复杂验证
1.数据库,EmployeeAction中,得到登录名
2.对登录名的可用性进行验证,验证登录名在数据库中是否存在
3.这时可以采用struts的声明式异常
4.使用py4j 解决把汉字转为对应的拼音: 佟刚--> tg, 张孝祥--> zxx, 黎活明--> lhm
二.员工的查询
1.显示员工信息:AJAX分页
使用displaytag 分页显示员工信息,记
录不超过百万条。简单,使用。比如OA。
1.在tomcat的webapps目录下展示其实例。
2. OpenSessionInView:
1使用OpenSessionInView
若Hibernate中某一个类的引用属性(也
包括集合属性)采取懒加载策略,则可能出现懒加载异常,但没有对其懒加载属性进行初始化,此时关闭Session,然后再来获取属性,就会异常
声明使用spring的声明式事务:
<aop:config>
<aop:pointcut
expression="execution(* cn.itcast.ems.service.*.*(..))"
id="emsTxPointcut"/>
<aop:advisor
advice-ref="emsTxAdvice" pointcut-ref="emsTxPointcut"/>
</aop:config>
OpenSessionInView可以解决这个问题,因为OpenSessionInView的使用流程是:
request à open
session 并开始transaction
–>controller à view(jsp)à
2.如何使用:
在web.xml配置:
3.缺点:
如果流程中的某一步被阻塞, 而这期间的 connection 却一直被占用不被释放. 例如输出页面时, 一方面可能是页面内容大, response.write的时间长; 另一方面可能是网速慢, 服务器与用户间传输时间久. 当大量这样的情况出现时,就有连接池连接不足, 造成页面假死现
象.
所以在内容多流量大的网站需慎用.
3.翻页相关的类:
1.Page:
与具体 ORM
实现无关的分页参数及查询结果封装
2.
PropertyFilter: 与具体 ORM 实现无关的属性过滤条件封装类, 主要记录页面中简单的搜索过滤条件
3.
HibernateDao: 扩展
SimpleHibernateDao, 功能包括分页查询, 按属性过滤条件列表:
1.不带任何查询条件时, 需要使用的方法:
--countCriteriaResult
--setPageParameter
--findPage(Page<T>
page, Criterion...criterions)
HibernateWebUtils
分页:
不带查询的分页
employee-list-1.do --> Action
--> Service -->
DAO
2.查询条件的翻页:使用jQuery 的一个thickbox 插件完成查询页面的弹出
1.jQuery的分页插件
2.在获取第一页的内容以后,如何
把查询条件带到第二页
--把封装了查询条件的List放到session域中,下一次从session中取。
--把查询条件放在隐藏域中
3.携带查询条件
使用jQuery提供的serialize()方法携带查询条件(行不通)
var url = this.href + “&” +
$(“:hidden”).serialize();
window.location.href=url;
注意:上述方法在第一次不能起作用: 即不能再第一次把隐藏域中的参数带过去, 因为在第一次点击该链接时, href 的属性值已经固定了, 不能再发生变化,
而第二次点击时, 因为第一次已经改变了该属性的值, 所以好用
所以必须在第一次点击该链接之前让
this.href = this.href + "&" +
$(":hidden").serialize(); 起作用
解决方案:
$("#criteria").attr("href",
$("#criteria").attr("href")
+ "&" +
$(":hidden").serialize());
今天就到这儿,明天continue!
posted @
2010-03-06 23:50 d66380022|
编辑 收藏
今天接着昨天的整合,由佟老师总指挥,基于xml配置的Action,这涉及struts整合.今天先把登陆实现了,最后使用两个插件把员工信息录入功能
实现,页面效果在当今还是主流的。
2.服务器端验证
1.查询数据库,得到信息
2.若用户名不存在,则提示用户名不存在
errors.add("",new ActionMessage(" "));
若用户名和密码不匹配,则提示用户名和密码不匹配
若errors.isEmpty()为true,则登陆,并将其保存在session中,
方法:
使用 struts 的声明式异常来转发页面和显示提示信息.
详细解决:
由 EmployeeService 的方法抛出异常, Action 不进行处理, 而由 struts 框架根据当前的
action 节点配置来进行相应的处理:
如果出现对应的异常, 会利用当前 excpeption 配置节点的 key 生成对应的 ActionMessage
对象, 再放入 ActionMessages 中,
把页面派发到 input 对应的页面中, 在前台页面利用 <html:errors
property="key"> 进行显示
4.ReflectUtils类的作用:
1.convertValue:beanUtils1.8提供了DateConverter
2. PropertyUtils: 提供了读写 Bean 的属性的方法
3. fetchElementPropertyToString: StringUtils.join 方法可以把指定集合的元素用分隔符链接起来
4. getSuperClassGenricType: ParameterizedType
5.SimpleHibernateDao 类介绍:SimpleHibernateDao<T,PK extends
Serializable> 说明:该类在service层中使用,
T:Dao操作的对象类型
PK:主键类型
1.getIdName():
2.distinct(List list):通过 Set 将不唯一的对象列表唯一化,主 要用于 HQL/Criteria
预加载关联集合形成重复记 录, 又不方便使用 distinct 查询语句时
6.CreateCriteria:
createQuery(String queryString, Object... values)
7. ReflectionUtils
1 convertValue: beanUtils 1.8 提供了 DateConverter
2. PropertyUtils: 提供了读写 Bean 的属性的方法
3. fetchElementPropertyToString: StringUtils.join
方法可以把指定集合的元素用分隔符链接起来
4. getSuperClassGenricType: ParameterizedType
8. SimpleHibernateDao:
1. getIdName: ClassMetadata 该类可以获取到对应的 class 的 hbm 配置文件的几乎所有信息
2. 标准查询:
-->创建 Criteria 对象: session.createCriteria(clazz);
-->为 Criteria 对象添加查询条件: criteria.add(criterion);
-->获取 Criterion 对象: 通过 Restrictions 来获取
9.struts的导航组件:struts-menu的使用方法:
1. 把 struts-menu.war 文件复制到服务器下, 运行
2. 在 struts-config.xml 文件中加入 struts-menu 插件
3. 复制 struts-menu\WEB-INF\menu-config.xml 到 conf 目录下.
4. 复制 struts-menu-2.4.3\struts-menu-2.4.3.jar 到 classpath 下
5. struts-menu 的去除默认背景色问题:
①. 通过 jQuery: 把 left.jsp 页面的第三个 table 的
style="background-color:lightgrey" 属性清除
②. 通过修改默认的配置文件: 修改 struts-menu=2.4.3.jar
net.sf.navigator.displayer 包的的 DisplayerStrings.properties 文件,
把 dd.menu.top=<table width\="150"
style\="background-color\:lightgrey" cellpadding\=1
cellspacing\=1><tr align\=left><td nowrap
class\=normal><b>
的 style\="background-color\:lightgrey" 去除
10.员工录入前台验证,用的是jQuery的插件jquery-validate
5.对输入的登陆名进行ajax验证:验证该登录名在数据库中是否存在。
11.在loginname字段已经给出对应的“该登录名已经被占用”的基础上,再一次点击“提交”按钮,则需要进行服务器端验证,再返回录入页面
12.若验证都通过,则需要进行服务器端的验证。
13.员工的录入操作:
1). 显示员工的录入页面
①. 查询数据库, 获取所有的部门信息和职位信息, 并在页面上加以显示
②. 页面使用 jQuery 的 validator 插件作为表单的前台验证
1. 在当前 jsp 页面中导入 jquery.validate.js
2. 为需要验证的字段添加 class 属性, 在其中指定验证规则, 获取添加 minlength 等属性
今天就到此了!
posted @
2010-03-05 23:16 d66380022|
编辑 收藏
SVN版本控制
今天有毛伟老
师讲版本控制,版本控制(Revision control)是维护工程蓝图的标准做法,能追踪工程蓝图从诞生一直到定案的过程,确保由不同人员所编辑的同一文
件档案都能得以同步。最新的Spring3.0已经提供了更高级的版本控制,但是国内没几个用,先掌握SVN,以后有机会再用高级的。下面详细总结
一下:
1.Subversion介绍:是一种开放源码的全新版本控制系统。是新一代的版本控
制工具,他不但提供了常见的比较、修补、标记、提交、回复和分支等功能,适于 Web 开发和其他
在传统方式下未采纳版本控制功能的领域
2.svn安装
1.运行svn的server端,运行setup.exe,就OK
检验安装好了:
运行dos窗口
,输入svn ,回车,出现svn help 提示,安装成功
2.svn服务器启动(我安装目录:D:"Program
Files"Subversion"bin)
cmd:
svn根目录 svnserve -d 即D:"Program
Files"Subversion"bin>svnserve
–d
是否启动成功
.当前是否启动3690端口号
3.版本库目录介绍:
dav目录:是提供给Apache与mod_dav_svn使用的目录,让它们存储内部数据,当前我们使用的版本没有这个目录(与你下载的Subversion版
本有关系)。
db目录:就是所有版本控制的数据存放文件。
hooks目录:放置hook脚本文件的目录。
locks目录:用来放置Subversion文件库锁定数据的目录,用来追踪存取文件库的客户端。
format文件是一个文本文
件,里面只放了一个整数,表示当前文件库配置的版本号。
conf目录:是这个仓库的配置文件(仓库的用户访问帐号、权限等)。
4.创建版本库、导入、检出
1、创建版本库
右键--->TortoiseSVN--->Create
repository
here
2.导入
右键--->TortoiseSVN--->导入(一般在项目创建初始化数据时使用,当然也可用于把任意文件或目录从外部导入到指定仓库中)
3.检出(提醒:检出项目后客户端文件夹
的变化.svn)
右键--->SVN Checkout...
5.SVN基本功能:
清理、更新到指定版本
日志记录、提交日志限定必填。
锁定、解锁:基本权限控制(可以限制被锁定的文件只能由被锁定用户修改提交)
误删除恢复操作:直接重更新或通过日志列表
单个文件过滤:选中文件-->TortoiseSVN---->增加到忽略列表
导出:使项目脱离版本控制。
6.总结SVN的使用:
在其文件夹上右键
"SVN Checkout..."写上对应SVN地址
在其文件夹上右键
"SVN Update" 来更新我们的本地版本
在其文件夹上右键
"SVN Commit"
来提交我们的本地版本
在其文件夹上右键
"TortoiseSVN" --> "Export..." 来
发布、导出
在其文件上右键
"TortoiseSVN" --> 增加(A)" 来向版本库中增加一
个受版本控制的文件
7.关于SVN的各种颜色提示说明:
CVS客户端的使用基本上同SVN客户端一样,更简单些,就不多说了
posted @
2010-03-03 00:02 d66380022|
编辑 收藏
spring对事务的管理
今天讲了Spring的事务,及对hibernate的整合,对struts的整合。以后还得学习,记不住,用到再整理。
1.事务的四大特点:
atomic:要么都发生,要么都不发生。
consistent:数据应该不被破坏。
Isolated:用户间操作不相混淆
Durable:永久保存
2.介绍spring的事务管理器
spring没有直接管理事务,而是将管理事务的责任委
托给某个特定平台的事务实现。
3.Hibernate事务:
<bean
id="transactionManager"
class="…HibernateTransactionManager">
<property
name="sessionFactory" ref="sf" />
</bean>
其中sessionFactory属性必须和一个Hibernate的SessionFactory绑定
HibernateTransactionManager把事务管理委托给一个从Hibernate
session
中取得的net….Transaction对象。当一个事务成功完成时,
HibernateTransactionManager将调用Transaction对象的commit()
方法。类似的,当一个事务失败时,Transaction对象的rollback()方
法将被调用。
4.事务属性
1.隔离级别:设定事务的并发程度
脏读:一个事务读取了另一个事务改写但还未
提交的数据,如果这些数据被回滚,则
读到的数据是无效的。
不可重复读:一个事务执行相同的查询两次或两次以
上,但每次查询结果都不同。
幻读:一个事务读取了几行记录后,另一个事务插入一
些记录,幻读就发生了。再后来的查询中,第一
个事务就会发现有些原来没有的记录。
2.只读 若对数据库只进行读操作,可设置事务只读的属性,使用某些优化措施。数据库会进行优化处理。若使用hibernate作为持久化机制,声明一个只读事务会使hibernate的flush模式设置为FLUSH_NEVER。避免不必要的数据同步,将所有更新延迟到事务的结束。
3.事务超时 若事务在长时间的运行,会不必要的占用数据库资源。设置超时后,会在指定的时间片回滚。将那些具有可能启动新事务的传播行为的方法的事务设置超时才有意义
5.CMT:容器管理事务
BMT:bean 管理事务
<tx:annocation-driven
transaction-manager="hibernateTransactionManager"/>
类上加@Transactional
6.总结:
事务策略
在业务中不能加try
catch ,因为Spring的环绕通知在出现异常时会回滚事务,你已捕获,就会提交事务(任何情况下)
7.Spring整合Struts
1.web服务器启动时,完成Spring容器的实例化。plugin|listener
2.struts中的action交给Spring容器管理。
3.基本操作
注意:在spring上下文中,作为普通bean配置action,但action的不能用id,只能用name,
因为需要struts-config.xml文件中action的path一致.
bean.xml
<bean name="/loginAction" class="..LoginAction">
<property name="xxxService" ref="xxxService"
/>
</bean>
posted @
2010-03-01 01:04 d66380022|
编辑 收藏
今天主要是AOP编程,徐老师先讲了原理,由浅入深,最
后让开发由aspectJ来完成,使开发更简单,收获蛮大
1.Aspect术语
通知:切面的实际实现,他通知系统新的行为。如在日志通知包含了实
现日志功能的代码,如向日志文件写日志。通知在连接点插入
到应用系统中。
连接点::应用程序执行过程中插入切面的地点,可以是
方法调用,异常抛出,或者 要修改的字段。
切入点:定义了通知应该应用在哪些连接点,
通知可以应用到AOP框架支持的任何 连接点。
引入:不变源代码的情况下,为类添加新方法
和属性。
目标对象::被通知的对象。既可以是你编写的类也可以是
第三方类。
代理对象:崭新的对象,将通知应用到目标对
象后创建的对象,应用系统的其他部 分不用为了支持代理对象而 改变。
织入:将切面应用到目标对象从而创建一个新代理对
象的过程。织入发生在目标
对象生命周期的多个点上:
编译期:切面在目标对象编译时织入.这需要一个特殊的编译器.
类装载期:切面在目标对象被载入JVM时织入.这需要一个特殊的类载入器.
运行期:切面在应用系统运行时织入.
4.切入点:定义了通知应该应用在哪些连接点,通知可以应用到AOP框架支持的任何连接点。
两种:jdk动态代理(接口,松耦合),cglib(对类代理)
2.方法介绍
一.通知类型
1.前置通知
public interface MethodBeforeAdvice{
void before(Method m,Object[]
os
,Object target){
}
}
该接口提供了获得目标方法、参数和目标对象的机会。不能够改变运行时参数,即不能替换参数对象和目
标对象。
注意在方法结束后不返回任何值东西。原因是该接口返回后,目标方法将会被调用,应该返回目标对象的
返回值。该接口唯一能
阻止目标方法被调用的途径是抛出异常或(System.exit())。
2.动态代理对象ProxyFactoryBean是一个在BeanFactory中显式创建代理对象的中心类,可以给它一个
要实现的接口、一个要代理的目标对象、一个
要织入的通知,并且他将创建一个崭新的代理
对象。
3.后置通知
同前置通知类似。
public interface AfterReturningAdvice{
public void afterReturning(Object
returnValue,Method
m,Object[] os,Object target);
}
多了一个返回值。
4.环绕通知
public
interface
MethodInterceptor extends Interceptor{
Object invoke(MethodInvocation invocation);
}
该接口同前两种通知有两个重要区别:1.该通知能够控制目标方法
是否真的被调用。通过invocation.proceed()方法来调用。
2.该通知可以控制返回的对象。可以返回一个与proceed()方法返回对象完全不同的对象。但要谨慎使用。
5.异常通知
public interface ThrowsAdvice{
}
该接口为标识性接口,没有任何方法,但实现该接口的类必须要有如下形
式的方法:
void
afterThrowing(Throwable
throwable);
void
afterThrowing(Method
m,Object[] os,Object
target,Throwable
throwable);
第一个方法只接受一个参数:需要抛出的异常。
第二个方法接受异常、被调用的方法、参数以及目标对象。
二.创建切入点方法
1. 切入点根据方法和类决定何处
织入通知。ClassFilter接口决定了一个类
是否符合通知的要求:
public interface ClassFilter{
boolean matches(Class clazz);
}
实现该接口的类决定了以参数传递
进来的类是否应该被通知。实现该接
口的类一般根据类名决定,但不一
定必须如此。
注意: 为减少系统负担,尽量使用静态切入点
2.定义切入点 spring提供了Advisor类。他把通知和切入点组合到一个对象中。更确切地说PointcutAdvisor提供了这些功
能
3.使用aspectJ开发
1.添加类库:aspectjrt.jar和aspectjweaver.jar
2.添加aop schema.
3.定义xml元素:<aop:aspectj-autoproxy>
4.编写java类,并用@Aspect注解成通知
AspectJ 支持 5 种类型的通知注解:
@Before: 前置通知, 在方法执行之前执行
@After: 后置通知, 在方法执行之后执行
@AfterRunning: 返
回通知, 在方法
返回结果之后执行
@AfterThrowing: 异
常通知, 在方法
抛出异常之后
@Around: 环绕通知, 围绕着方法执行
配置成普通bean元素即可.
注意:
JoinPoint参数可访问连接点细节,入方法名和参数等.
今天知识点蛮多的,对面试挺有用的,好好掌
握!
posted @
2010-02-28 01:11 d66380022|
编辑 收藏
Spring
对这个框架并不陌生,spring是一个开源的控制反转(Inversion
of Control
,IoC)和面向切面(AOP)的容器框架.它的主要目得是简化企业开发...
1.为Spring添加jar
支持
2.Spring:1.xml + 反射
2.不需要实例化
3.不需要set方法
以前 至上而下,
按部就班
之下而上,反的
3. bean的生命周期
bean被载入到容器中时,他的生命周期就开始
了。bean工厂在一个bean可以使用前完成很多
工作:
1.容器寻找bean的定义信息并实例化。
2.使用依赖注入,spring按bean定义信息配置bean的所有属性。
3.若bean实现了BeanNameAware接口,工厂调用Bean的setBeanName
()方法传递bean的ID。
4.若bean实现了BeanFactoryAware接口,工厂调用setBeanFactory()
方法传入工厂自身。
5.若BeanPostProcessor和bean关联,则它们的
postProcessBeforeInitialization()方法被调用。
6.若bean指定了ini-method方法、,它将被调用。
7.最后,若有BeanPostProcessor和bean关联,则它们的
postProcessAfterInitialization()方法被调用、。
4.set注入的缺点:
无法清晰表达哪些属性是必须的,哪些是可选
的,构造注入的优势是通过构造强制依赖关系,不可能实例化不
完全的或无法使用的bean。
5.自动装配
<bean id=" " class="" autowire="autowire 类型">
有四种自动装配类型:
1.byName:寻找和属性名相同的bean,若找不到,则装不上。
2.byType:寻找和属性类型相同的bean,找不到,装不上,找到多个抛异常。
3.constructor:查找和bean的构造参数一致的一个或
多个bean,若找不到或找到多个,抛异常。按照参数的类型装配
4.autodetect: (3) 或者(2)方式选一个。不确定
性的处理与(3)和(2)一致。
注意:
spring2.5提供了<context:annotation-config
/>配置.
该配置可激活在类中探测到的各种注解,@Required
@Autowire
@PostConstrct @PreDestroy @Resource @EJB @PersistenceContext
@WebServiceRef等等,
也可以选择为这些注解激活单独的后处理器.
6.属性的外部化
分散配置
将配置文件分成几个分散的配置文件。如数据源。
<bean class="...PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>jdbc.properties</value>
<value>securtiy.properties</value>
</list>
</property>
</bean>
当然在Spring2.5可以简化为
<context:property-placehoder location>
7.AOP
有一些模块是每个系统都需要的,切面是系统
模块化的一个切面或领域。如日志记录。不改变源代码,还给类增加新的功能
2.连接点:应用程序执行过程中,可以应用切面的地点,可以是方法调用,异常抛出,或者要修改的
字段。
3.通知:切面的实际实现,他通知系统新的行为。
4.切入点:定义了通知应该应用在哪些连接点,通知可以应用到AOP框架支持的任何连接点。
5.引入:为类添加新方法和属性。
6.目标对象:被通知的对象。既可以是你编写的类也可以是第三方类。
7.代理:将通知应用到目标对象后创建的对象,应用系统的其他部分不用为了支持代理对象而
改变。
8.织入:将切面应用到目标对象从而创建一个新代理对象的过程。织入发生在目标
对象生命周期的多个点上:
编译期:切面在目标对象编译时织入.这需要一个特殊的编译器.
类装载期:切面在目标对象被载入JVM时织入.这需要一个特殊的类载入器.
运行期:切面在应用系统运行时织入.
今天到此结束,明天继续!
posted @
2010-02-26 23:02 d66380022|
编辑 收藏
UML
今天学习UML,uml是unified modeling language,是一种基于面向对象的可视化建模语言. 老徐讲了很多与开发有关的东西,很不错,还介绍了软件的发展等,开始整理下
1. UML 采用了一组形象化的图形(如类图)符号作为建模语言, 使用这些符号可以形象地描述系统的各个方面。oop:ooa(分析) + ood(设计)
2.软件的生命周期
瀑布模型:
需求分析(可行性分析:)
1.时间可行性
2.技术可行性
3.经济可行性
系统分析和设计(系分)
实现
测试
维护
角色分配:项目经理技术总监代码人员测试人员 db管理人员系统分析人员
project leader 系统架构师
3. 统一软件开发过程(Rational Unified Process,RUP): 一个通用的软件流程框架, 以架构为中心, 用例驱动的迭代化开发流程.
4.uml:图(图元)
UML 中一共有 10 种图:
类图**** 对象图 包图 组件图 部署图 用例图** 时序图*** 协作图 状态图
活动图*
5.用例图
是从软件需求分析到最终实现的第一步, 它是从客户的角度来描述系统功能.
用例图包含 3 个基本组件: 参与者(Actor), 用例(Use Case),关系
6.类图
类图是面向对象系统建模中最常用的图. 是定义其他图的基础.
类图主要是用来显示系统中的类,
接口以及它们之间的关系.
类图包含的主要元素有类, 接口和关系. 其中关系有关联关系, 泛化关系, 依赖关系和实现关系. 在类图中也可以包含注释和约束.
7.类之间的几种关系:实现依赖关联聚合组成
实现关系:在 UML 中, 实现关系用来表示类与接口之间的实现关系.
依赖关系:对于两个相对独立的系统,当一个系统负责构造另一个系统的实例,或者依赖另一个系统的服务时,这两个系统之间体现为依赖关系.
关联:对于两个相对独立的系统,当一个系统的实例与另一个系统的一些特定实例存在固定的对应关系时,这两个系统之间为关联关系。
聚合:聚合关联是一种特殊的关联. 它表示类间的关系是整体与部分的关系.
组合关系: 整件拥有部件的生命周期, 所以整件删除时, 部件一定会跟着删除. 而且, 多个整件不可以同时共享同一个部件。
8. 时序图
时序图用于描述对象之间的传递消息的时间顺序, 即用例中的行为顺序.
当执行一个用例时, 时序图中的每条消息对应了一个类操作或者引起转换的触发事件.
对象: 时序图中对象使用矩形表示, 并且对象名称下有下划线. 将对象置于时序图的顶部说明在交互开始时对象就已经存在了. 如果对象的位置不在顶部, 表示对象是在交互的过程中被创建的.
生命线:生命线是一条垂直的虚线. 表示时序图中的对象在一段生命周期内的存在. 每个对象底部中心的位置都带有生命线.
9. 活动图
在 UML 中, 活动图本质上就是流程图. 它用于描述系统的活动, 判定点和分支等.
10.临时
持久化 游离 删除
11.状态图
状态图: 通过建立对象的生存周期模型来描述对象随时间变化的动态行为.
状态: 用圆角矩形表示. 状态名称表示状态的名字, 通常用字符串表示. 一个状态的名称在状态图所在的上下文中应该是唯一的.
12.包图:
由包和包之间的关系组成. 包的图标就如同一个带标签的文件夹.
13.组件图
用来建立系统中各组件之间的关系, 各组件通过功能组织在一起.
14.部署图
用来帮助开发者了解软件中的各个组件驻留在什么硬件位置, 以及这些硬件之间的交互关系。
今天就讲了这些知识,挺琐碎的,关键是看懂就OK了!
posted @
2010-02-25 23:29 d66380022|
编辑 收藏
JPA第二天
今天JPA的第二天,继续学习关联,还有分页,设置参数,单值检索等重点,下午是EJB的介绍,实现。这其中足见老师水平之高,经验太丰富了。好 ,作总结:
1. 多对一单向关联
2.一对多
@OneToMany(mappedBy=””) 忽略关联关系
mappedBy让对端忽略关系的变化,相当于HibernateSet集合中的inverse,缓存就不再负责set的
em.find(Order.class,1);默认迫左/延迟
3.一对一外键关联
<many-to-one
name=”addr” column=”aid”
class=”Addr” unique=”true”/>
<one-to-one
name=”” column=”” property-ref=”addr”/>
JPA中的实现
@OneToOne[观察自动创建出来的表结构]
class User{
@OneToOne
protected Addr addr;
class Addr{
@OneToOne(mappedBy=“addr", optional="false");
protected User user;
}
mappedBy:控制权问题
optional:false 表示没有用户的BillingInfo是不能单独存在的.
4.多对多
@ManyToMany
@ManyToMany
protected Set<Student> students;
@ManyToMany(mappedBy=“students")
protected Set<Teacher> teachers;
5.继承关系
以Employee为例
Employee{id
name age}
HourEmployee(HE){rate} SalaryEmployee(SE){salary}
映射继承关系树:整个继承关系树对应一张表
游离,临时,持久 详解:
1.位于一个session缓存中,总是被一个
session关联。
2.持久化对象和数据库记录相对应。
3.清理缓存时,会根据对象属性变化,同步
更新数据库。
4.save把临时对象转变为持久化对象。
5.load或find或get返回的对象总是持久化状态。
6.find方法返回的list存放的都是持久化对象。
7.update、save、SaveOrUpdate和Lock方法使游离对象装变
为持久化对象。
6、分页:
("findCustomerByName");
query.setParameter("name", "t,om");
query.setMaxResults(10);
query.setFirstResult(3); query = em.createNamedQuery
List customers = query.getResultList();
7、设置参数:
SELECT o FROM Order i WHERE i.orderNo = ?1
query.setParameter(1, 100.00);
SELECT o FROM Order i WHERE o.price = :price
query.setParameter("price", 100.00);
8.单个实体检索
query.getSingleResult();
9.
查询集合:
WHERE c.orders IS EMPTY
WHERE CONCAT(c.fname, c.lname) = 't,om'
SELECT c.id, c.name FROM Customer c
10.多态查询
SELECT c FROM Customer c WHERE c.name LIKE :name
11.分组
SELECT o.customer, COUNT(o.id) FROM Order o
GROUP BY
o.customer
12.排序
order by
13.子查询
SELECT o FROM Order I WHERE o.customer IN
(SELECT c FROM Customer c WHERE c.name LIKE ?1)
EJB
1.ejb简介:enterprise
java bean就是开发分布式组件的。in
ejb容器具有负载均衡 容
错 线程池 安全 高并发性等功
能。
EJB = pojo + @
spring:业务层 管理bean的,容器key-value.没有ejb的java ee
j2ee
: 开发分布式企业级应用的规范(jsp servlet jpa ejb)
2.开发EJB步骤:
1.下载安装jboss
2.配置环境变量:
JBOSS_HOME JBOSS安装目录
3.web服务器端口(${jboss_home}"server"default"deploy"jboss-web.deployer"server.xml)[22行]
4.启动。${jboss_home}"bin"run.bat
IDE中配置服务器:
windows/首选项/myeclipse/servers/jboss/4.x/运行模式(非调式模式) + jdk1.5.
5.启动服务器,进入管理页面.http://localhost:8088/
点击[JMX Console]超链接
点击Jboss/service=JNDIView
ok.
今天就OK了!
posted @
2010-02-22 00:14 d66380022|
编辑 收藏
JPA
今天讲的是JPA规范,还是由经验丰富的徐老师讲的,JPA是一门解决了各个ORM“诸侯争霸”的局面。详细点就是
1.JPA概述
JPA(Java Persistence API)是Sun官方提出的Java持久化规范。它为Java开发人员提供了一种对象/关系映射工具来管理Java应用中的关系数据。JPA是在充分吸收了现有Hibernate(数据库平台无关)、TopLink等ORM框架的基础上发展而来的,达到平台无关性(持久化技术产品)。
JPA是EJB的一部分。
2.jar包支持
Hiberante核心包(8个文件)
hibernate-distribution-3.3.1.GA,加上mysql的驱动jar
3. JPA规范要求在类路径的META-INF目录下放置persistence.xml,文件的名称是固定的。
事务的特点:acid: atomic consistent isolate durable
4.JPA编程建模
映射关系
代理主键:( 采用一种增长策略) @id
定义id属性,相当于Hibernate中的OID.这两个注解必须显式指定,其他的映射是隐
式(默认)的.
5.方法上注解优先,测试CRUD操作
em.persist(order);
em.find(Order.class,new Long(1));
em.remove(order);
em.merge(order);
6.JPA语法严谨,语句:select p from Person p where p.name=’tom’ select要写
7.不想往数据库中存,就注解 @Transient
8. @Lob
@Basic(fetch=FetchType.LAZY)
protected byte[] picture;
映射temporal(精确度)
@Temporal(TemporalType.DATE)//该注解只能注util.Date和Canlendar.
protected Date creationDate;
9.组成关系
Customer homeAddress comAddress
Address{
}
在类上加@Embeddable
10.JPA关系 重点
JPA关系 ManyToOne/OneToMany
@ManyToOne/@OneToMany
Class Order{
@ManyToOne
Customer customer ;
Class Customer{
@OneToMany(mappedBy=“”)
Set<Order> orders = ..
}
注:如果集合不采用泛型的话,如何才知道集合与谁关联.
@OneToMany(targetEntity=Order.class,mappedby=“customer”)
今天就到此了!
posted @
2010-02-21 01:18 d66380022|
编辑 收藏
今天复习知识点:
一.工作流,审批流程。举例,比如请假流程:
提交申请-->部门经理 -->
后面是一层一层的审批...
审批流转就是把单位内部的审批电子化。经过的环节和人不一样
四点要求:
流程定义:
二.分页设计
<a href="javascript:gotoPage(1)">[首页]</a>
<c:if test="${pageView.currentPage gt 1}">
<a href="javascript:gotoPage(${pageView.currentPage-1})">[上一页]</a>
</c:if>
<c:if test="javascript:gotoPage(${pageView.currentPage lt pageView.totalPage})">
<a href="javascript:gotoPage(${pageView.currentPage-1})">[下一页]</a>
</c:if>
<a href="javascript:gotoPage(${totalPage})">[尾页]</a>
<c:forEach begin="${startPageIndex}" end="endPageIndex" var="n">
${n}
</c:forEach>
转到:<input type="text" id="txtPageNum"/>
<input type="button" value="Go" onclick="gotoPage(document.getElementById('txtPageNum').value"/>
<script type="text/javascript">
function gotoPage(pageNum){
if(isNaN(pageNum)){
alert("请输入正确的页码");
document.getElementById('txtPageNum').focus();
return false;
}
window.location.href = getPageViewUrl(pageNum);
}
//提供分页用的地址。由具体的引用页面提供
function getPageViewUrl(pageNum){
return "/xxx.do?pageNum="+pageNum;
}
</script>
3.Hibernate的分页
getSession().createQuery(//
"SELECT COUNT(pd) FROM org.jbpm.ProcessDefinition pd")//
.uniqueResult();
getSession().createQuery(//
"FROM ProcessDefinition")//
.setFirstResult(firstResult)//
.setMaxResults(pageSize)//
.list();
4.表单模板设计
表单定义(FormDefinition)
表单名称
所用流程
表单代码文件路径
保存数据:不能用ActionForm,
表单中要填写的数据量,数据类型未知。用原始方法
for(Enumeration<String> e= request.getParameterNames();e.hasMoreElements();){
String name = e.nextElement();
String value=request.getParameter(name);
}但是我们无法解决2个问题:
1.保存成什么类型
2.保存哪些参数值?
解决办法:
Map<String,Class> fieldDefinitionList = new HashMap<String,Class>();
之后在Action中可以用
for(String name:formDefinition.getFieldDefinitionList().keySet()){
String stringValue = request.getParameter(name);
Class clazz=formDefinition.getFieldDefinitionList().get(name);
}
保存一次填写的所有信息,就是表单实例,就是表单定义的具体实现
明天就是JPA了,要好好休息,继续努力,春节已过去,踏上新的起点!
posted @
2010-02-20 00:20 d66380022|
编辑 收藏
今天是大年初一,赶快开学吧,每天很无聊,唯一感
觉还有点新年的味道就是昨天公司老师带我们去海丽
轩吃年夜饭,兄弟还是挺多的,心情也很好的!今天
复习OA的映射,对这不熟悉啊,还得努力。。。
一.
多对多:对role.java文件,其中映射文件如下:
<set name="employees" table="itcast_employee_role">
<key column="roleId"></key>
<many-to-many class="Employee"
column="employeeId"></many-to-many>
</set>
对员工Employee.java来说,映射文件如下:
<set name="roles" table="itcast_employee_role">
<key column="employeeId"></key>
<many-to-many class="Role"
column="roleId"></many-to-many>
</set>
一对一:员工和帐号,对于附属类帐号,映射文件如
下:
<id name="id">
<generator class="foreign">
<param name="property">employee</param>
</generator>
</id>
<one-to-one name="employee" constrained="true"></one-to-one>
主类(employee),映射文件:
<one-to-one name="user"></one-to-one>
二.方法:
/** 列表 */
public ActionForward list(ActionMapping mapping,
ActionForm form, HttpServletRequest request, HttpServletResponse
response)
throws Exception {
return mapping.findForward("list"); // list.jsp
}
/** 添加页面 */
public ActionForward addUI(ActionMapping mapping,
ActionForm form, HttpServletRequest request, HttpServletResponse
response)
throws Exception {
return mapping.findForward("saveUI");
}
/** 添加 */
public ActionForward add(ActionMapping mapping,
ActionForm form, HttpServletRequest request, HttpServletResponse
response)
throws Exception {
return mapping.findForward("toList"); }
/** 修改页面 */
public ActionForward editUI(ActionMapping mapping,
ActionForm form, HttpServletRequest request, HttpServletResponse
response)
throws Exception {
return mapping.findForward("saveUI");
}
/** 修改 */
public ActionForward edit(ActionMapping mapping,
ActionForm form, HttpServletRequest request, HttpServletResponse
response)
throws Exception {
return mapping.findForward("toList");
}
/** 删除 */
public ActionForward del(ActionMapping mapping,
ActionForm form, HttpServletRequest request, HttpServletResponse
response)
throws Exception {
return mapping.findForward("toList");
}
三.
标签复习:
<html:form>
<html:text>
<html:hidden>
<html:textarea>
javascript复习:
<html:link action="/role?method=del&id=${role.id}" onlick="return
window.confirm('您确定要删除一条记录吗?');">删除
</html:link>
在页面中
<html:rewrite action="/role?method=addUi"/>
<script type="text/javascript">
funcion addUI(){
window.location.href="<html:rewrite action='/role?method=addUI'";
}
</script>
<srcipt type="text/java"
<script type="text/javascript">
funcion checkForm(form){
if($.trim(form.name.value) == "" ){}
alert("");
form.name.focus();
return false;
}
return true;
}
</script>
四.在Action中进行验证
ActionErrors errors = form.validate(mapping,request);
if(errors!=null&&errors.size()>0){
saveErrors(request,errors);
return mapping.findForward("addUI");
}
五.HQL语句
getSession().createQuery("FROM Department d WHERE d.parent is
NULL")//
.list();
六.树形展示菜单
List<Department> list = new ArrayList<Department>();
printInfo(topLevel,"",list);
return list;
注意空格是全角空格,全角空格是中文字符,不会合
并。
public static void printInfo(Collection<Department>
departmentList,String prefix,List<Department> list){
for(Department department : departmentList){
department.setName(prefix + "|-" + department.getName());
list.add(department);
printInfo(department.getChildren(),prefix+" ",list);
}
}
今天就做到这了!
posted @
2010-02-16 01:06 d66380022|
编辑 收藏
大学生创业网讯
关心蚁族就是关心我们国家的未来。青年时代的磨难和体验直接决定10年、15年后他们的心态和价值观。一个人青年时期总被人看不起、压抑、仇富,等他40
岁突然成功了他幸福吗?会回报社会吗?他如何教育下一代?
■名词解释
蚁族:指“高校毕业生低收入聚居群体”。该群体高知、弱小、聚居。他们受过高等教育,平均月收入低于两千元,绝大多数没有“三险”和劳动合同;他们平
均年龄集中在22—29岁之间,九成属于“80后”一代;他们主要聚居于城乡结合部或近郊农村,形成独特的“聚居村”。
调查,在北京的边缘
■一篇报道的启发
在这本叫做《蚁族》的“大学毕业生聚居村实录”出版之前,“蚁族”这个名词基本上属于动物学的概念。一位29岁的年轻学者带领他的团队经过两年的社会
调查后,第一次将这个昆虫的名字冠于一个年轻群体的头上。他们高知、低收入、聚居在一起生活,像蚂蚁一样不被关注,也像蚂蚁一样全力以赴、永不言弃、不可
轻视。
为“蚁族”著书立传源自一场好奇的探访。
2007年夏天,在北大做博士后研究的廉思读到《中国新闻周刊》里的一篇纪实报道,名为《向下的青春——“高知”贫民村调查》。报道中的主人公李竟一
年前毕业于中国农业大学,因为考研和就业双重失败,不得不暂住于海淀区一个叫唐家岭的村子继续挣扎着追求梦想。而这个村子里,和他有着相同境遇的高校毕业
生不在少数。
“令人担忧的现状、年轻脆弱的心灵以及无处寄托的青春和梦想。”廉思这样形容他解读到的李竟。作为地地道道的北京人,也作为“80后”,他没有想到自
己身边还生活着这样的同龄人。与此同时,博士后研究“社会稳定”的他又敏锐地感觉到这不仅是一个简单的“贫民村”的问题。
■这也是北京
站在唐家岭的街道上,廉思真有点不敢相信自己的眼睛——这也是北京?拥挤狭窄的小路充斥着垃圾尘土,各种名目的小店凌乱肮脏,电线杆、墙壁上到处贴满
了租房的小广告:180元起,有宽带……欢迎入住。
“看不出任何首都的气息,典型的城乡结合部。可一般的城乡结合部又不可能有这么多年轻人,而且都是学生打扮。你再看他们租住的房子,可以没有浴室没有
单独的厕所,但一定有宽带能上网。”
廉思了解到,这些走出校园不久的毕业生基本上都是拿着一千多元的工资,租着每月三百元左右的床位,到工作单位要坐两个小时以上的公交车。唐家岭本村居
民有三千人左右,其余近四五万人都属于这个聚居群体。
回到家廉思将“聚居村”输入搜索引擎,结果显示全是“少数民族聚居村”;查阅了国内外的一些相关资料也一无所获,此时的廉思意识到,唐家岭的年轻人们
已经形成了一个全新的生态群体。
“大家都关心成功的人,关心精英,从大学毕业两三年到四五年的这群人到底是什么状态,没有人问过他们过得怎么样。”
从唐家岭回来后,这些同龄人生活的场景时常在廉思眼前闪现,让他久久不能释怀,他决心要深入研究这个群体。
■政府支持的调查
廉思开始着手组织社会调查。正当他埋头设计问卷、确定调研地点的时候,北京市有关方面委托他就北京市大学毕业生“聚居村”问题进行专项调查。有了政府
的支持,研究工作顺利开展起来。
2008年春节,廉思带领他从人大招募来的研究生入村调查。恰逢全国遭遇50年不遇的雪灾,北京天寒地冻。在唐家岭的出租屋内,经常是问卷还没做完,
调研员的笔已经被冻得写不出字来。由于年龄相仿,村里的年轻人对廉思的调研小组没有任何抵触,有的不仅自己接受调查,还推荐身边的老乡和朋友。经过一个星
期的调研,这个群体的面貌逐渐在廉思眼前清晰起来。
在后来的调研报告里廉思这样描述他们:他们人数众多,大多聚居于城乡结合部或近郊农村,已经形成了一个个自然村落。他们有的毕业于名牌高校,更多的来
自地方院校和民办高校;有的完全处于失业状态,更多的从事保险推销、广告营销、电子器材销售等低收入工作。他们生活条件差,缺乏社会保障,挫折感、焦虑感
等心理问题较为严重。他们与外界的交往主要依靠互联网并以此宣泄情绪。
“热情、开朗、迷茫、彷徨。”这就是“聚居村”村民留给廉思的初次印象。调研结束后,他写成了四万多字的研究报告提交市委且获得了肯定,但廉思感到自
己的使命并没有完成。“我更关心的是他们的梦破了以后怎么样,他们会怎么看待这个社会。他们的怨恨可能给社会带来灾难。”
■“蚁族”一词的诞生
经过进一步的资料查阅和实地考察,廉思发现国外没有出现大学毕业生聚居现象,而国内除了北京之外,上海、广州、武汉、西安等大城市都有“聚居村”存
在,若要深入了解他们必须组织全国范围的社会调查,才能得出更有意义的结论。
由于第二次调查将在深度和广度上远远超过第一次,廉思决定成立课题组,招募不同领域的研究人员参与。他对前来应征的人说的很直接:“跟我干肯定没钱也
没名,凭的就是社会责任感和研究兴趣。”
2008年8月8日,借着这个举国欢庆的日子,汇集了政治学、心理学、社会学、统计学、经济学等学科的15人课题组正式成立了,廉思担任组长,研究题
目是《潜在危机:中国“大学毕业生低收入聚居群体”与社会稳定问题研究》。
在人文社科领域,社会调查是最花钱的。偏偏这一年廉思申报的课题没有获得批准,调研纯属个人行为,经费成了大难题。人大社会学系的一位教授告诉他:你要
把这个项目做下来,仅仅北京地区的调研没有15万绝不可能!做一份问卷的成本最少要200元,包括人工费、礼品费、交通费、误餐费等等;北京地区至少要
500份以上的样本量才有意义,还不包括后期研究需要支付的录音整理费、数据录入费……
箭在弦上,不得不发。拿着恩师资助的3万元启动资金,廉思和课题组成员们立即投入到环环相衔的工作流程中。很快3万元花光了,家人又支持了4万元,最
终课题组仅花费7万多元,完成了唐家岭、小月河、马连洼等七个“聚居村”的563份调查问卷的样本量。
当时课题组一位成员看了一本名叫《蚁呓》的书,讲蚂蚁的生活状态,很多话和他们调查的人群非常相像,比如“我很卑微但我不卑贱”、“弱小的强者”等
等,于是他们决定用“蚁族”这个名词替代“大学毕业生低收入聚居群体”。
廉思没料到,“蚁族”这个名词在网络上引起了极大的共鸣。网上很多人发帖“我是蚁族我报到”,还有网友写下:“只要一个人青春过奋斗过就不会不为蚁族
的故事感动,因为我们每个人心中都有一个蚁族。”
◆采访手记
蚁族热
廉思说话很快,随着“蚁族”热度的上升,他已成为各类媒体竞相拜访的对象。他似乎想用最短的时间表述最多的记忆、感慨和思考,当然是关于“蚁族”的。
“我希望更多的人能关注蚁族,而不是我廉思。”
《蚁族》出版后,很多80后的父母给他发邮件、打电话、网上留言。家长们告诉廉思是《蚁族》让他们知道了远在外地的孩子到底过着什么样的生活。“有个
家长说,怪不得儿子坚持不让他去住处看一眼;有个妈妈给我留言,她看了两天一直在哭,作为一个母亲,她感觉自己是那样的无力。外地一个父辈的朋友,看了当
地报纸对蚁族的报道,打电话来问我:你帮我判断判断,我的孩子到底是不是蚁族?”
聚焦难免带来一些尴尬。廉思随电视台去唐家岭拍摄,有蚁族接受采访时说,不知道是该感谢廉思还是该责怪廉思,因为他们看见报纸报道,唐家岭有兴建白领
公寓的计划。“如果‘白宫’(蚁族口中的白领公寓)建起来了,他们负担不起房租的话,就不得不往更远的地方搬。”这名蚁族不认识廉思,也不知道他就站在旁
边。
课题组受邀去人大、北大讲座,一些天之骄子反问廉思:蚁族跟我们有关系吗?我们有必要了解他们吗?那里面有多少北大、人大的毕业生?
“很多名牌大学毕业生自诩为‘社会精英’。什么是精英?精英应该负有关注社会、关怀弱势群体的责任感。你享受的权利越多,你承担的责任也就越大。真正
的精英应当是‘心为平民,行为精英’”。
其实有些蚁族聚居村离北大人大并不远,然而它们之间却竖立着一堵隐形、坚硬的墙。要打破这些墙,让蚁族的青春奋斗不再默默无语,廉思的路还只是刚刚启
程。不久,全国范围的调研即将展开,上海团队已经从同济、复旦、上海交大招募了四五十人,廉思等核心成员马上开赴当地。
“每个城市的聚居村形态都不尽相同。上海是群租房,在中低档小区里,一套三室一厅的房子能打出20个隔间住20个人。广州则是城中村,紧邻高档住宅的
旁边。”
无论他们处于城市的哪一个角落,他们都在发出自己的轻吟与呼喊,你会不会去聆听?
生活扑面而来,梦想流离失所
■蚁族展示了真实的80后:迷茫、彷徨,但有梦想,有责任,在坚持
蚁族是“80后”的群体,以22-29岁的大学毕业生为主。1999年大学第一批扩招生入学,2003年第一批扩招生毕业,融入滚滚红尘。因为就业难
或就业差,他们向自己的师兄师姐询问有没有便宜的地方可以落脚。刚刚走出校园,他们渴望安全感,寻求群体认同。由于高校和大量的科技类公司集中在北京的北
部,为了节省生活成本、把握机会,他们在城市的边缘慢慢积淀下来。
“2003年蚁族形成聚居,两年后有了一定规模,等2007年我第一次去调查的时候规模已经很大了。这是高等教育扩招、劳动力市场转型等因素伴随的产
品,正好让‘80后’赶上了。”
网上曾有一个流传很广的帖子,是“80后”描述自己的尴尬境遇:当我们上小学的时候读大学不要钱,当我们读大学的时候上小学又不要钱了。当我们不炒股
的时候傻子都能赚钱,当我们进股市的时候发现我们才是傻子。
“前不着村后不着店的,就是这状态!”廉思说社会对“80后”的定义一直偏于贬义,“最自私的一代”、“最没责任心的一代”、“垮掉的一代”,其实作
为改革开放后出生的第一代人,他们经历着国家的巨大变革,身上表现出来的价值观、行为方式与生活意识都折射出中国社会特定转型时期的变化。“80后”究竟
是一代什么人?廉思觉得“蚁族”展示了“80后”的真实面貌,“他们迷茫、彷徨,但有梦想、在坚持,而且承载了很多责任。”
一个来自北京农村的女孩告诉调研员,她希望自己的辛苦奋斗能让父母有富足的晚年,能让自己的孩子将来过上更好的生活。承载着如此责任的蚁族绝非少数。
为廉思作“聚居村民序”的邓锟在唐家岭住了两年,两年里他做过销售、干过技术、考过研、进过传销,也曾创过业。他对父母隐瞒真实情况,总是报喜不报忧。
“日子过得再苦他都没有哭过。但是有天早上起来,同屋问他昨天晚上怎么哭那么大声?邓锟完全没有印象,看看枕头是湿的,才知道自己在梦里嚎啕。”廉思
感到心被揪得难受,蚁族是咬着牙苦撑啊!他们中的很多人都背负着整个家族的希望来到大城市打拼,中华民族的传统在他们身上是有体现的。“他们是最真实的
‘80后’。”
■蚁族基本上属于“穷二代”群体,只能靠自己,对成功的渴望特别强烈
2009年春节,很多蚁族因为没钱或没票回家,只能在聚居村里过年。大年三十的下午,廉思带着年货到了唐家岭,他和十几个“蚁族”买菜、买水果,热闹
地准备年夜饭。
“我们做了一大桌的菜,挤在一个小房间里,还挺有过年的样子。”喝着酒、嗑着瓜子,当电视机里的春晚载歌载舞时,小屋的气氛却渐渐变了。“我就记得当
时有几个男孩子先后到厕所去抹眼泪了。”
什么是真正的奋斗?从初始接触的怜悯、同情到最终的佩服、尊重,廉思看到蚁族们确实在奋斗。“三年一辆车五年一套房”是很多蚁族的奋斗目标,梦想对于
他们来说尤其重要。
“你问小月河的人最崇拜谁,他们肯定说王宝强。其实王宝强不是蚁族,没受过高等教育。但他在小月河住过,而且成功了,他写的自传小月河的人都看。他们
对成功的渴望特别强烈,这就是支撑他们坚持下去的动力。
调查显示,蚁族50%以上来自农村,20%以上来自县级市,来自省会和直辖市的仅占7%,大部分家庭的年收入不超过5万,这说明蚁族基本上属于“穷二
代”群体。这个群体只能靠自己。
不久前,廉思带一家电视台再度回访唐家岭,遇到一个就职于金融公司的北大毕业生。“他一个月挣5000还是不敢花。穷二代买房首付就交不起,要攒很多
年。城里房租1000块,唐家岭只要300块。这就是现实。”
蚁族告诉廉思“没有比生活更现实的生活”,“生活扑面而来,梦想流离失所。”这些高度凝练的词语全来自他们的亲身感受。
“其实‘三年一辆车五年一套房’这个梦对很多北京人来说也不敢想,但我们不去戳破这个梦,否则七八个人住一屋,七八十人用一个厕所,没有梦怎么坚持?
他们的路是他们自己选的,我们没有资格也没有权力告诉他们应该怎么做。有人会劝他们为什么不回老家?面对城乡巨大的差别,这种劝说太苍白了。”
有人境况好转搬离了聚居村,有人最终放弃梦想回到了自己的家乡。这是摆在蚁族脚下的两条路,通往任何一个方向都是要经过一番彷徨与挣扎的。
■蚁族在调查中强烈质疑了他们所受的高等教育,对这个群体,社会和政府应该有所作为
面对蚁族的调查,课题组成员时时刻刻都能感受到强烈的冲击力,因为蚁族距离他们自己太近了。一个调研员在访谈中偶然遇到了学校的师兄——两年前曾经是
学生会里非常活跃的人物——双方尴尬得说不出话来。
走出“聚居村”时,每个调研员都禁不住在心里问自己:几年后我会不会成为他们?还有一个调研员告诉廉思,当他错过了最后一辆返城的公交车时,他感觉错
过了这辆车仿佛错过了整个世界。大多数蚁族的梦能否实现谁都不敢确定。
因为好奇,廉思走近了蚁族,在调研中跟蚁族一起吃饭、聊天、喝酒,但总感觉那里并不属于自己。“我尽量地从蚁族的角度去看待问题,但很可能我尽全力都
做不到。蚁族是真实地生活在那里,而我们只是去体验过后又回来过自己的生活,我们永远是旁观者。”
作为一个学者,廉思感到有时自己是无力的。他能为这些平凡而又坚韧的年轻人做些什么?同情、无谓的劝解都是没有意义的。
“在我们的调查卷里有一个问题,问蚁族觉得高等教育给他们带来了什么?选项有知识技能的提高、文化水平的提高,还有自身素质、道德修养、人际交往等
等,可他们只选了最后一项‘一张文凭’。当问到高等教育缺失什么的时候,他们把以上几项全选上了。大学生们走上社会才知道自己真正需要什么,这些是高等教
育应该反思的东西。”蚁族的身上可能存在着欠缺,但未必是他们个人原因造成的。
虽然廉思认为蚁族内心的力量远比自己要强得多,但他们真实的生活境遇的确令人担忧,他们应该得到社会的倾听与关注。
“对这个群体,社会和政府是可以有所作为的。比如短期内帮他们整治环境和治安,让他们生活好一点,还可以安装一些避孕套机等等。中期来说落实一些民主
权利,让他们参与投票。设立一些文体设施,进行职业培训。长远的一些问题则需要逐步立法解决,比如廉租房制度,目前没有北京户口是享受不到的。还有高等教
育扩招问题,用不用扩招、扩招多少;民办教育的规模问题,蚁族中37%来自民办大学,好多是被骗来的,这些都需要经过慎重讨论最后出台措施。”
廉思并不掩饰他的忧虑,“关心蚁族就是关心我们国家的未来。青年时代的磨难和体验直接决定10年15年后他们的心态和价值观。一个人青年时期总被人看
不起、压抑、仇富,等他40岁突然成功了他幸福吗?会回报社会吗?他如何教育下一代?这才是值得思考的。”
posted @
2010-02-13 00:30 d66380022|
编辑 收藏
昨天把表单定义的映射文件做完了,今天依然是相当重要的,做的是单向表单实例映射,首先表单实例映射文件。
难点1是map的配置:
<map
name="propertyMap"
table="itcast_formInstance_propertyMap">
<key
column="formInstanceId"></key>
<map-key
type="string"
column="name"></map-key>
<element
type="serializable"
column="value"></element>
</map>
为什么要实现serializable,所有的数据都是以二进制形式存在,所有的对象理论上都可以序列化,但是有些对象序列
化后会产生比如逻辑等等问题。在这里我们希望服务器重启后,仍然保存有我想要的对象,也就是可以把原来的对象拿出来!就要实现序列化 ,同学的序列化解释:
我们有时候将一个java对象变成字节流的形式传出去或者从一个字节流中恢复成一个java对象,例如,要将java对象存储到硬盘或者传送给网络上
的其他计算机,这个过程我们可以自己写代码去把一个java对象变成某个格式的字节流再传
输,但是,jre本身就提供了这种支持,我们可以调用OutputStream的writeObject方法来做,如果要让java帮我们做,要传输的对象必须实现serializable接口,这样,javac编译时就会特殊处理。
2是定义FormDefinitionActionForm。由于表单字段可以增加,如图:
我们用两个数组存放
private String
propertyNameList = {};
private Class[] propertyValueTypeList
= {};
3.那我们就在FormDefinitionAction中
可以这样处理:
//
actionForm
--> formDefinition
//
1,
copy properties
BeanUtils.copyProperties(formDefinition,
actionForm);
//
2,
fieldDefinitionList
for
(int
i = 0; i < actionForm.getPropertyNameList().length; i++) {
String
name = actionForm.getPropertyNameList()[i];
if
(name != null && name.trim().length() > 0) { // 有效的字段说明
Class
valueType = actionForm.getPropertyValueTypeList()[i];
formDefinition.getFieldDefinitionList().put(name,
valueType);
}
}
//
Save
formDefinitionService.save(formDefinition);
return
mapping.findForward("toList");)
小难点3.要把不同的表单定义名称显示到页面
用Sql语句:select distinct
pd.name ProcessDefinition的全类名pd
小难点4.页面设计
难点5.审批信息内容:谁 在 什么时间
对哪个表单 做了什么样的审批
难点6.整个实体类图及关联
最重要的还是下图的关系:要理解好
总之,今天下午听的晕乎晕乎的,趁过年还得好好复习一下!
posted @
2010-02-09 00:12 d66380022|
编辑 收藏
OA项目之审批流转
今天是OA项目的最后一个模块,其业务流程是员工提交申请-à部门经理-à ,这期间要经过的人不一样,有的要经过一个审批就OK了,而有的得经过3个以上的人审批才行。实现审批流转有4个要求:
1.方便的定义/x修改 与 管理
流程定义
2. 方便的定义/x修改 与 管理
表单模版
3.执行审批流转
4.方便的查询所有的 表
单实例 (数据)记录(查询流转过的表单)
业务流程如同前天已画的图:
员工提交申请,后面的环节就会按照我们定义
好的流程走了
所有的表单都要分页
今天做审批管理,它包含审批流程管理和表单
模版管理
1.设计实体,
2.创建一个Action ,也和前面的一样CRUD,只是在列表时加了个分页,多添
加了个查看流程文件(processdefinition.xml)
中,查看流程图片
3.分页设计:因为所有页面都要用,所以写成公共的,但超链接不一样
如图:
分页主要代码:
// 用户指定
private int pageSize;
private
int currentPage;
//
查询数据库
private
int recordCount;
private
List recordList;//当前页的所有pd
//
计算
private
int totalPage;
private
int startPageIndex;
private
int endPageIndex;
/**
* 计算指定页中第一条记录的索引
*/
public static int
clacFirstResult(int pageNum, int pageSize) {
return
(pageNum
- 1) * pageSize;
}
public
PageView(int
pageSize, int currentPage, int recordCount, List recordList) {
this.pageSize
=
pageSize;
this.currentPage
=
currentPage;
this.recordCount = recordCount;
this.recordList
=
recordList;
//
计算
totalPage,
startPageIndex, endPageIndex;
totalPage
=
(recordCount + pageSize - 1) / pageSize;
startPageIndex
=
1;
endPageIndex
=
totalPage;
if
(totalPage
> 10) {
//
正常显示当前页附近的共10个页码,当前页属于前半部分
startPageIndex
= currentPage - 4;
endPageIndex
= currentPage + 5;
//
(前面不足4个)显示前10个页码
if
(startPageIndex < 1) {
startPageIndex
= 1;
endPageIndex
= 10;
}
//
(后面不足5个)显示后10个页码
else
if (endPageIndex > totalPage) {
endPageIndex
= totalPage;
startPageIndex
= totalPage - 10 + 1; // 显示时包含开始与结
束的边界
}
}
}
之后测试分页
4.解决session问题:
由于在action中用到了session和jbpmContext,必须用一个session,才能保证是同一事务,在这里用jbpmContext得到session
5.Hibernate关于set list map的映射文件
以为例
class Person{
private
Set<String>
addressSet; // 收货地址
private
List<String>
addressList;
private
Map<String,
String> phoneNumberMap; // 电话号
集合,如:家庭 -- 010-12345678
}
<set name="addressSet"
table="itcast_addressSet">
<key
column="personId"/>
<element
type="string"
column="address"/>
</set>
<list name="addressList"
table="itcast_addressList">
<key
column="peronId"/>
<list-index
column="idx">
<element
type="string"
column="address">
</list>
表单流转
支持各种审批流程:JBPM
支持各种表单定义:表单中要填写的字段的数
量不同,类型也不一样,ActionForm当然不能用,按照上面的业务需求实现编码。
明天继续!
posted @
2010-02-07 23:46 d66380022|
编辑 收藏
趁今天休息,把昨天不会的知识总结一下,这几天小汤给我们带项目,给大家的感觉就是老师水平很高,我们还得苦修几年才行啊,小汤经验挺丰富的,以至于我们
遇到问题时,他一问这个对象可以有吗?下面万籁无声时,小汤一般就说“这个可以有”,好了,还是总结知识点吧:
1.HIbernate创建查询,首先拿到session,再
List list = session .createQuery(//
" FROM Department d WHERE d.parentId = ?")//
.setParameter(0,值)//
.list();
之后测试,一般对于CRUD操作,都要单元测试。
注意:
用//格式固定格式,Hibernate源码就是这样固定格式的
2.用到的标签(不熟练的)举例:
<html:link
action="/dept?method=editUI&id=${department.id}">修改<
/html:link>
<html:link
action="/dept?method=del&id=${department.id}&parentId=${parent.id}"
onclick="return window.confirm('您确定要删除这条记录吗?')">删除</html:link>
3.外键可以为空
4.游离:数据库中有,但没有和session关联,Hibernate根据id判定是否是游离状态,如果你id有值 ,则不是游离。
我在网上查了一下什么是游离对象?
游离对象的特征。游离对象具有以下特征:
(1) 不再位于Session的缓存中,也可以说,游离对象不被Session关联。
(2) 游离对象是由持久化对象转变过来的,因此在数据库中可能还存在与它对应的记录(前提条件是没有其他程序删除了这条记录)。
游离对象与临时对象的相同之处在于,两者都不被Session关联,因此Hibernate不会保证它们的属性变化与数据库保持同步。游离对象与临时对象
的区别在于:前者是由持久化对象转变过来的,因此可能在数据库中还存在对应的记录,而后者在数据库中没有对应的记录。
Session的以下方法使持久化对象转变为游离对象:
(1)
当调用Session的close()方法时,Session的缓存被清空,缓存中的所有持久化对象都变为游离对象。如果在应用程序中没有引用变量引用这
些游离对象,它们就会结束生命周期。
(2)Session的evict()方法能够从缓存中删除一个持久化对象,使它变为游离状态。当Session的缓存中保存了大量的持久化对象,会消耗
许多内存空间,为了提高性能,可以考虑调用evict()方法,从缓存中删除一些持久化对象。但是多数情况下不推荐使用evict()方法,而应该通过查
询语言,或者显式的导航来控制对象图的深度。
感觉这段话说的挺好的,就copy下来
5.注册时间转换器
转换器为便于在项目中易于维护,放在一个Servlet中,然后将Servlet配置在web.xml中
时间转换器:
Java代码
package cn.itcast;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.beanutils.Converter;
public class UtilDateConverter implements Converter {
private static SimpleDateFormat format = new
SimpleDateFormat("yyyy-MM-dd");
public Object convert(Class type, Object value) {
if (value == null) {
return value;
}
if (value instanceof Date) {
return value;
}
if (value instanceof String) {
try {
return format.parse((String) value);
} catch (ParseException ignore) {
}
}
return null;
}
}
Servlet类:
Java代码
package cn.itcast;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import org.apache.commons.beanutils.ConvertUtils;
public class InitConvert extends HttpServlet {
@Override
public void init() throws ServletException {
//注册转换器
ConvertUtils.register(new UtilDateConverter(), Date.class);
}
}
web.xml配置:
<servlet>
<servlet-name>InitConvert </servlet-name>
<servlet-class>cn.itacst.InitConvert </servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
6. ActionForward 动态传参问题:
ActionForward af = mapping.findForward(“toList”);
return new ActionForward(af.getPath+"&parentId="+af,af.getRedirect);
好了,今天就写到此吧,明天还要上课,睡了!
posted @
2010-02-07 00:25 d66380022|
编辑 收藏
今天继
续OA
工作流,今天完成部门添加工作,创建子
部门,员工管理等操作
1.部门管理
部门的CRUD操作和完善
列
表:
顶层部门或显示指定部门的子部门
1. 添
加子门和添加同级部门是同一个添加
1.取出所有的最顶层部门,使用递归,遍历所有部门,
名称前面加上空格。
2.当前要处理的部门的名称比上一级部门多一个空格。
效果:
A1
A2
B2
B1
B
B3
之后存到作用域中,这个递归要放到Action中进行。
posted @
2010-02-06 00:23 d66380022|
编辑 收藏
OA工作流第二天
再有几天过年了,心情好。今年过节不回家,明年挣钱了再回,其实车票也很不好买的,以至于车票是近
几天的焦点。。。今天是OA项目的第二天,汤兄带我们做了岗位管理模块,我们是从对象到表进行设计,这就是所谓的正向工程。
整体设计步骤:
一、当然是根据需求设计实体,实现功能:
1.了解需求
2.设计实体(设计数据库表) 对象-->表
3.分析功能的流程
1.整体。2.具体(部分)
二、编码实现,单元测试
1.准备编码:创建Action,与Service接口、实现类(空)。
完成Action中的方法声明与返回值。()
2.完成Action的方法,确定出所用的Service方法,在Service接口中声明他,并写好注释。
1.获取参数
2.调用业务方法
3.返回一个显示
3.完成Service的方法实现,实现要求的功能。确定出Dao中的方法,在Dao接口中声明他,并写好注释。
4.完成Dao的方法的实现。
(为某些Service与Dao写单测试)
三、页面显示层显示效果
1.写页面(Jsp,把静态页面改为动态页面)。
2.写配置
3.测试运行
具体设计
步骤:1.设计实体,有部门员工岗位账号四个实体。
实体之间的关系,实体中的属性。
如下图:
一个关系,就是一个外键
2.接着就是设计映射文件:
多对一:<many-to-one
name class column=”外键”/>
一对多:<set
name=”bean中的set属性名”>
<key column=”外键”/>
<one-to-many class/>
</set>
一对一:1.主键关联
关键表:<one-to-one
name=” 与之关联的在本类中的属性名”/>
附属表:
<one-to-one
name=” 与之关联的在本类中的属性名”
constrained=”true”/>
<id name="id">
<generator
class="foreign">
<param
name="property">与之关联的在本类中的属性</param>
</generator>
</id>
2.外键关联
关键表:<many-to-one
name=” 与之关联的在本类中的属性名” column=”” class=”” unique=”true”/>
附属表:
<one-to-one
name=” 与之关联的在本类中的属性名” class=”” property-ref=” 对方类中关于本类的属性名”/>
多对多:<set
name table="关系表">
<key
column="本表的id(比如roleId)"></key>
<many-to-many
class="与之关联的类名"
column="与之形成关系的id(比如employeeId)"></many-to-many>
</set>
以Employee.hbm.xml为例,只写
关联关系的
<!--
跟department的多对一 -->
<many-to-one
name="department"
class="Department"
column="departmentId"></many-to-one>
<!--
跟roles的多对多 -->
<set
name="roles"
table="itcast_employee_role">
<key
column="employeeId"></key>
<many-to-many
class="Role" column="roleId"></many-to-many>
</set>
<!--
跟user的一对一 -->
<one-to-one
name="user"></one-to-one>
其他的也是如此写。
如果还不明白,请与我联系,我给你源码。本
人qq:510570367
3.业务流
程
用struts控制流转,jsp显示,完成CRUD操作。剩下的就是代码的编写了。。。
注意:
1.在开发中一定要使用自定义标签,可以很
好的处理回显问题:回显对应的formBean中对应的字段
2.在
写关键的代码时,一定要测试。
今天就Ok了,明天继续!
posted @
2010-02-04 20:12 d66380022|
编辑 收藏
今天在班上上自习,有几点得备份一下,老忘记:1.是读取Properties文件的方法;2.是Eclipse快捷键的单词补全;3.是一点生活感触
1.读取Properties文件的方法
Properties props = new Properties();
InputStream is =
当前类.getClass().getResourceAsStream("/文件所在路径");//注:"/"表示根路径(classes)
props.load(is);
在需要使用属性文件的时候,直接 props.getProperty("
属性文件中的name");再强转一下就搞定了。。.
2.这是转老师的,尽管我以前也常用单词补全的快捷键,我是“Alt+c”,但我从未总结过,这次拿老师的晒晒
Eclipse的快捷键设置或修改方法:
1,打开快捷键设置窗口。有两种方法:
a) Window -> Preferences, General -> Keys.
b) 连按两次'Ctrl+Shift+L'。
2,找到要修改快捷键的功能。在右侧窗口的"type filter text"文本框里输入查
询的字符串,匹配结果会在下方列出。有两种查询方式:
a) 输入功能名,如"Content Assist"(不含引号).
b) 输入绑定的快捷键名,如"alt+/"(不含引号).
提示:如果没有查到相应的功能,选中列表下方
的"Include unbound commands"试试,这个表示把未绑定快捷键的功能也列出来。
3,绑定新的快捷键。选中要设置快捷键的功能,在下
方的"Binding"中就会显示当前绑定的快捷键。点击"Binding"后的文本框,让其得到焦点,用"Backspace"
(退格键)删除现在正在绑定的快捷键,然后直接按快
捷键即可(如要修改为
"alt+/",是在按住"alt"键的同时按"/"键,而不是输入字符串
"alt+/")。
--------------------------------------------------
需要修改的快捷键:
我们习惯使用自动补全的功能叫做"Content
Assist",他的默认快捷键是"Ctrl+space",和输入法有冲突,所以不能使用。一般习惯把他改为'Alt+/',但"Alt+/"和功
能"word completion"(单词自动补全)的快捷键重复,所以还要把"word completion"的快捷键改掉,一般改为'Alt+C
3.一些生活感触
我们今天上午到附近转了一会儿,我看到了这有一胡同里的房子顶全是石棉瓦盖的,真让我对北京失望极了,走出胡同,确切说是走过公路,发现公路两边是截然不
同的两片天空,那边全是很豪华的小区。。。差距也忒大了...
努力,向前看!
posted @
2010-02-03 22:12 d66380022|
编辑 收藏
OA
工作流(
一)
笔记
今天开始项目之旅,做的第一个项目是OA,OA是OFFICE AUTOMATION的缩写,是利用技术提高办公的效率,从而实现办公自动化。汤兄给我们对OA整体做了介绍,还介绍了需求,OA在整体上实现起来是一样的,只是根据企业的需求,业务不同,实现不同而已。当然OA项目分了很多模块,没时间做太多模块,我们只做核心的模块。第一天主要是搭建环境和基础功能的实
现。
下
面总结一下一天所学知识
该系统的使用者是员工(使用者)和管理员(管理系统)
1.组织机构管理(部门、岗位、员工)
2.审批流转
1审批管理
2执行审批流转
3表单查询
3.根据实际,使用两层:
1表示层(view)
2业务逻辑层(Service
+ DAO)
4.所使用的框架和技术
Struts 1.3.8, Jstl
1.1, Hibernate 3.2.3, Jbpm
3.2.2(工作流),
Junit4 ,jQuery
5. 搭建环境
1.
添加Struts 1.3.8的jar包与配置文件
2.
添加Jbpm的jar包,同时也会添加Hibernate的jar包。再添加相应的配置文件(jbpm.cfg.xml、log4j.properties与hibernate.cfg.xml)。
3.
添加JDBC驱动的jar包
4.
创建的数据库。修改Hibernate.cfg.xml中的数据库连接信息,并创建数据库表。
5.
添加Junit4的jar包
6.
解决Struts中的commons-BeanUtils.jar与Hibernate中的commons-Collections.jar的冲突问题。
DAO层设计
对一些dao,有公共的
方法,可以写一个BaseDao
,让UserDao,RoleDao继承BaseDao
Service层
设计
在Service层 直接操作数据库
解决提交的表单内容的中文乱码
所有的页面都将使用utf-8编码,所以提交的表单内容也是utf-8编码。
在过滤器中设置request的编码为utf-8:
最后解决:统一业务操作中的Dao操作要使用统一session
统一的管理session的打开关闭与事务的开始提交
总之,今天学到的东西挺多的,受益匪浅啊!也有些感觉以前的知识已有些淡忘,还是得复习复习了。。。
posted @
2010-02-02 21:23 d66380022|
编辑 收藏
今天是jBPM的第二天,内容不多,定义不少,主要讲了流程变量,节点和事件等知识,全是新的知识,刚学肯定生疏,久了就没问题了,编程嘛,多敲代码,多
调试,才是王道。
1. 流程变量
通过org.jbpm.context.exe.ContextInstance来操
作变量。
2.变量的生命周期
变量的访问和赋值是在某一个token上进行的,缺省时,是基于root
Token。每个Token(执行路线)有它自己的一套流程变量。变量的作用域和所属的Token的生命周期一致,不同的Token上的同名变量互不影
响。
3.变量值要求
变量名的类型为java.lang.String,支持的变量值类型如下(文档10.1节)。(
如
果变量值是classes that are persistable with
hibernate,则POJO的id应为long型或String型。
saveOrUpdate( po );
savePoIdAndPoClassAsVariable()
session.get(
class, id )
节点
1.
流程图中的各种节点的作用及用法
为什么需要多种节点类型?
需要有不同类型(作用)的节点,才能设计出复杂的流程图。
Jbpm有一套预先定义好的节点类型。如果不够用,也可以使用自定义节点进行扩展,以完成不同的流程的需要。
不同的节点类型代表不同的行
为。
每个流程都必须要有开始节点和结束节点。
2.预定义节点
start-state,开始节点:标识流
程开始、
end-state,结束节点:标识流程结束、
task-node,任务节点:可以放0个或多个任务、
decision,
决策节点:路径选择,只使用一个流转(叉路口)、
fork/join,分支节点/合并节点:可以分为多个并行执行的分支、
state,状
态节点:等待。
每个节点都对应一个类(Jbpm的持久化类),都是org.jbpm.graph.def.Node的子类。节点
都有名字、流转(end-state除外)。
event事件
事
件。
1, 有几种事件,分别在什么时候触发
2, 怎么指定当事件触发时做什么事(Action)
1, 节点的事件
a)
进入节点(node-enter)。(开始节点没有)
b) 离开节点(node-leave)。(结束节点没有)
2,
流转的事件
a) 只有一个:使用流转(take a transition)
3, 任务的事件
a)
创建任务(task-create)
b) 分配任务(task-assign)
c)
开始任务(task-start)à TaskInstance.start()
d) 结束任务(task-end)à
TaskInstance.end()
每个事件有一个动作(action)清单。当jBPM引擎产生一个事件,动作(action)清单就会被
执行. 不同的节点支持的事件类型不同,是由event元素所在的节点的类型决定的,例如transition只有一个事件。
可以在event元
素用可以指定一个动作,当指定的事件发生时,这个动作被执行。
可以给同一个事件指定多个动作,当这个事件触发的时候,这些动作执行的顺序
和定义先后顺序是一致的。
不同元素支持不同的事件类型:
一般的节点都具有的事件:node-enter,进入节点、
node-leave,离开节点;
start-state只有node-leave;
end-state只有node-enter;
transition
只有一个执行转换的事件(taking a transition)。因为只有一个事件,所以配置时不用写event元素,而直接配置Action。
task
有task-create,任务创建、task-assign,任务分配、task-start,任务开始、task-end,任务结束。
关
于哪些元素支持哪些事件,可以通过文档的18.4节中的xml文件的写法中获得。
如果配置的事件类型不存在,不会报错,也不会执行。
注
意:在事件中定义的动作(Action)不应该(不能)影响流程的执行。即不要在事件的动作中给token发信号,否则会抛异常:token is
locked。(在Node中配置的Action可以给Token发信号。)
事件执行的顺序:
已触发事件:node-leave
已触发事件:transition
已
触发事件:node-enter
已触发事件:task-create
已触发事件:task-assign
已
触发事件:task-start
已触发事件:task-end
*************************
动态的创建不确定数量的任务实例 *********
会签。
实现任务分配给多个人,在流程定义中定义的相
应的任务,不指定参与者,也不知道指定为谁。需要做以下工作:
1,
阻止jBPM自动创建任务实例(设置task-node的create-tasks="false")
2,
在node-enter事件中定义一个动作指定用于创建TaskInstance的类。
类
CreateTaskInstancesAction要接管两个操作:创建与分配任务实例。
创建任务实例要调用方法:
TaskMgmtInstance.createTaskInstance(Task, ExecutionContext);
其中的
Task 是任务的定义,可以先得到当前的节点:
TaskNode taskNode = (TaskNode)
executionContext.getNode();
然后通过任务的名字得到任务的定义:
Task task =
taskNode.getTask("审批");
任务分配
个人任务:actor-id=”xxx”
查询组任务列表的方法为:
TaskMgmtSession.findPooledTaskInstances(String
actorId)
对于一个组任务,如果他的actorId为null,组中所
有的用户都可以在组任务列表中看到这个任务。如果使用TaskInstance.setActorId(String)方法设置这个任务由指定的
acrorId来办理,这时pooledActors中的其他人就看不到这个任务了,就是说actorId会屏蔽pooledActors;
当这个用户因某些原因不能办理任务时,可以把这个任务再退回到组任务列表中,方法是调用TaskInstance.setActorId(null)设置
actorId为null,这时pooledActors中的所有人又都可以看到这个任务了。
不管使用哪种方式分配任务,参与者
(Actor-id,字符串类型)的计算(确定)都是由业务层负责解释的。
最后汤兄给我们推荐了一些好书,学习java必须准备三样: 心态,基础,睡觉。能学多少学多少。明天才是OA工作流项目的开始!加油。。。
posted @
2010-02-01 21:59 d66380022|
编辑 收藏
JBPM与OA
项目
哈
哈,今天终于要开始做项目了,心情特别好,在第一天中汤兄让我们先明白了什么是工作流,怎样很好的解决这一类问题等,接着来了个Helloworld,就入门了。每天都在学习,每天都有收获,感觉真好。还要再提一下,OA(办公自动化)主要技术之一就是工作流,好,还是仔细总结一下一天所学:
1. 工作流就是工
作流程的计算机化。
流程(OA),数量多,随时更改
网购:提交订单—>配货—>发货—>收货—>付款
当我们想增加、修改流程时,而不想编程则需要用到工作流引擎,由它负责判断下一步
做什么。下图是它的原理:
状态机 +if
else
2. 工作流要解决的主要问题是:为实现某个业务目
标,在多个参与者之间,利用计算机,按某种预定规则自
动传递文档、信息或者任务。
通俗的说,就是多个人在一起合作完成某件事情。
接下来是jBPM介绍
3.jBPM介绍
jBPM全称是Java
Business Process Management。是一种基于J2EE的轻量级工作流管理系统,jBPM是公开源
代码项目。
官方主页http://labs.jboss.com/
下载地址:http://labs.jboss.com/jbossjbpm
最重要的还是接下来的jBPM的使用
4.Jbpm的使用
server:提供的一个执行、测试工作流和平台(Web应用程序)。
流程图是一个有向图,由两部分组成:节点和流转。节点有各种各样形状(代表各种各
样的作用)。流转就是指单箭头,代表从一个节点到下一个节点。
此文件的约束就是 jPDL。
在jPDL中,不同
的节点,就用不同的标签。
1.xml文件名必须为:processdefinition.xml。
2.必须要在一个zip文件的根目
录中。
3.可以有一个名为processimage.jpg的文件,是流程图。
应用myEclipse设
计流程图步骤:
1.装jbpm-jpdl-3.2.2插件:
找到jbpm-jpdl-3.2.2下的designer路
径复制一下,注意路径中不能有中文
2.之后在桌面上myEclipse快
捷方式,点右键,查找目标,找到myEclipse安装目录,再其下的links目录下
加入a.link文件
(a可以随意写),内容为
path=粘贴
注意里路径变为双斜线,之后关闭myEclipse,再打开就OK了。
3.在myEclipse下新建介绍java工程,在src下,新建Process
Definition点下一步,为Process
name :起个名,比如HelloWorld
。。。。
4,启动服务器:server/start.bat
5,访问:http://localhost:8080/jbpm-console,登陆后,点Deploy,下图:
6.将zip文件部署
7.点Deploy
8.点start
9.点tokens
后点singal,后在其下点singal
10.点tasks,点start ,按部就班搞定
注意事项:
1.怎么从开始节点往下走?Tokens
à Signal(只点一次)
2.怎么没有properties窗口?Window
à Show
View à
Properties
3.怎么一点Signal,就结束了呢?没有在Task-Node中
定义任务吧。要说明任务名称与任务的执行者。
4.点击Process
Image,在图片上没有一个正在运
行的标志,而且在上方还有一个错误提示?把节点的名称改为英文,重新Deploy就可
以了。
Jboss Server所在的路径中不能有
中文或特殊
字符(如&,有的在文件夹jbpm&oa中,这样就不行),否则不能运行
Token的解释:流程实例通过Token的维护
当前正在执行的节点
入门程序:
HelloWorld
1, 设计流程定义à
打包为zip文件(流程
定义文档,说明par的格式要
求)
2, 部署流程定义à
把工作流交给工
作流管理系统保存起来。只需要执行一次,一般是管理员进行操作。
3, 执行流程à
多个操作:
a)
启动(创建)流程实例(Signal)
b)
获取任务列表(只是自已的任务实
例列表)
c)
办理任务
i.
开始任务
ii.
结束任务
今天就这么多了,明天再写!
posted @
2010-01-31 23:36 d66380022|
编辑 收藏
今天继续讲的是lucene
的分词器,汤兄先回顾了昨天的所学内容,很好。今天讲了lucene
的细节,比如分词器和高亮器,以及高级搜索等功能的实现框架Compass
,案例是传智的贴吧搜索功能的实现,用的当然也是lucene
。
全文检索(Lucene
)的深入
分词器:对文本资源进行切分,将文本按规则切
分为一个个可以进行索引的最小单位(关键词)。
某文档中的一段文本,经过分词后如下:
1
|
2
|
3
|
4
|
5
|
6
|
7
|
8
|
9
|
10
|
11
|
12
|
13
|
在
|
Internet
|
上
|
采集
|
信息
|
的
|
软件
|
被
|
叫做
|
爬虫
|
或
|
蜘蛛
|
。
|
建立索引和进行搜索时都要用到分词器。为了保证能正确的搜索到结果,在建立索引
与进行搜索时使用的分词器应是同一个。
全文检索不区分大小写
对于中文分词,通常有三种方式:单字分词、二分法分词、词典分词。
最好的分词器:词库分词
高亮器:
1.作用:
1.截取摘要(大小)
2.高亮关键字(前缀
后缀)
2.怎么用:
过滤器
Filter
RangeFilter,可以对搜索出来的结果进行过
滤。
排序
sort
Lucene的搜索结果默认按相关度排序的。所谓相关度,就是文档的得分。Lucene有一个评分机制,就是对检索结果按某种标准进行评估,然后按分值的高低来对结果进行排序。
查询对象
TermQuery
Term是查询的最小单位,第一个参数是属性,第
二个是要查询的内容,下面的代码的
整个意思就是在title中查询检索
Term term = new
Term(“title”,”检索”);
Query query = new
TermQuery(term);
关键词查询RangeQuery
范围查询WildcardQueryPhraseQuery
短语查询
BooleanQuery
public void
add(Query query, Occur occur)
Occur 用于表示布尔查询子句关系的类,包括:
Occur.MUST,Occur.MUST_NOT,Occur.SHOULD。
1,
MUST和MUST:取得连个查询子句的交集。
2,
MUST和MUST_NOT:包含MUST并且查询结果中不包含MUST_NOT的检索结果。
3,
SHOULD与SHOULD,表示“或”关系,最终检索结果为所有检索子句的并集。
Compass框架
Lucene +
Hibernate
Hibernate操作实现原理:
主配置文件 :hibernate.cfg.xml
1.连接信息
2.声明映射文件
3.其他配置
映射文件:.hbm.xml
对象
– 表
属性
– 列
同样,Compass实现原理如图:
posted @
2010-01-31 23:35 d66380022|
编辑 收藏
Lucene
今天由汤阳光老师(不如说是汤兄)给我们讲lucene,一见汤兄,太年轻了,真是这感觉真让我有些小惭愧,呵呵。。。还是学好技术是第一要务。
从
现在到年前都是汤兄给我们上课,今天和明天是搜索引擎,存储数据用的是Hibernate,全文检索的简化框架是Compass,Lucene讲1.5
天,Compass讲半天。总结一天所学的.全文检索是目前最流行的技术,由于用数据库搜索实现的匹配度,相关度排序和搜索速度太慢,而这些都非常致命。
下面详细回顾:
1.信息检索:找出与用户需求相关的信息
平时接触的信息有文:html,doc,pdf和 txt,
多媒体:音频,视频,图片...
全文检索: 1.只关注文本。比如我搜索:中国的首都在哪里?和我搜索中国 首都
北京是一样的,我们主要是研究出现了某些词的文本 2.不处理语义,只是词匹配
全文检索的作用:1.bbs,blog,news,商城的站内搜索,资源有限
Eclipse的帮助就是用Lucene做的
2.入门
运行原理/入门概念
Hello World
需求:就像百度的搜索框一样,输入内容,点击搜索,得出结果,并且要求时间非常短
后台:点搜索后,会去信息集合(索引库)里搜索,注:这个索引库是按照一定的结构存储,这个结构可以实现快速搜索
使用流程:1事先就不停再找,建立索引,2.搜索
索引库的结构:索引库是存到一些二进制文件,这些文件在同一个目录下 --à索引库目录
Document 一条数据
Field 数据中的一个字段
Field是组成Document的元素
实现:
步骤:1.建立索引
2.搜索
都用到的是分词器(analyzer),应使用同一种分词器
实现HelloWorld:添加jar包
lucene-core-2.4.0.jar(核心);
contrib/analyzers/lucene-analyzers-2.4.0.jar(分词器);
contrib/highlighter/lucene-highlighter-2.4.0.jar(高亮器);
1.建立Article.java,属性有id,title,content
2.HelloWorld.java.两个主要方法:
1.建立索引:
createIndex()
2.搜索
search()
进行搜索
public void search() throws Exception {
String
queryString = "document";
//
1,把要搜索的文本解析为 Query
String[]
fields = { "name", "content" };
QueryParser queryParser = new
MultiFieldQueryParser(fields, analyzer);
Query query
= queryParser.parse(queryString);
//
2,进行查询
IndexSearcher indexSearcher = new IndexSearcher(indexPath);
Filter
filter = null;
TopDocs
topDocs = indexSearcher.search(query, filter, 10000);
System.out.println("总共有【"+topDocs.totalHits+"】条匹配结果");
// 3,打印结果
for(ScoreDoc
scoreDoc : topDocs.scoreDocs){
int docSn = scoreDoc.doc; // 文档内部编号
Document doc = indexSearcher.doc(docSn); // 根据编号取出相应的文档
File2DocumentUtils.printDocumentInfo(doc; // 打印出文档信息
}
}
IndexWriter:操作索引库,增删改
主要方法介绍:
// 构造方法:如果索引库不存在,会自动创建。如果存在,就使用他
new IndexWriter(String/Directory indexPath, Analyzer a,
MaxFieldLength mfl)
// 构造方法:第三个参数指定是否创建一个新的索引库。
// 1,有索引库,create为true:会重新创建。2,没有索引库,create为false,会报错。
new IndexWriter(String/Directory indexPath, Analyzer a, boolean
create, MaxFieldLe
ngth mfl)
// 添加索引
addDocument( Document doc )
// 更新
updateDocument(Term term, Document doc)
// 删除
deleteDocument(Term term)
// 合并索引库
addIndexesNoOptimize(Directory[])
今天学了Lucene的入门,明天学习Lucene的高级知识,以及compass框架!
// 优化索引库
optimize()
IndexSearcher:操作索引库,查询
// 构造方法,索引库不存在,就报错
new IndexSearcher( String indexPath )
// 搜索
TopDocs search( Query query, Filter filer, int n )
// 搜索
TopDocs search( Query query, Filter filer, int n , Sort sort)
Document doc( int docSn )
Documet:Lucene所操作的对象
Field:组成Document的元素,代表一个属性。Store、Index
new Field( String name, String value, Store
store, Index index )
Directory:索引库(目录)
FSDirectory
:真实的目录