2010年3月7日
巴巴运动网的权限模块总结
因为巴巴运动网的权限设计模块对我来说,可以实现,打算好好整理一下思路,面试时说不定还能起点作用,看了两遍,自己总结下:
权限定义/权限组(角色)模块
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|
编辑 收藏