◎筱米加步枪◎.Blog

Happy coding

Spring中进行测试-Junit框架的扩展

利用Spring来进行测试。首先看看下面几个类。【参照网上的资料】

1.AbstractSpringContextTests 类是针对所有测试情景的类,一般不使用,而是使用他们的之类。

2.AbstractDependencyInjectionSpringContextTests 类继承了AbstractSpringContextTests是一个针对所有测试的超类,具体依赖于Spring上下文。可支持依赖注入

3.AbstractTransactionalSpringContextTests 类继承了AbstractDependencyInjectionSpringContextTests,继承该类的测试用例在spring管理的事务中进行,测试完后对数据库的记录不会造成任何影响。你对数据库进行一些操作后,它会自动把数据库回滚,这样就保证了你的测试对于环境没有任何影响。

测试用例需实现protected abstract String[] getConfigLocations()方法来获取上下文。

1.创建一个测试类的基类

/**
 * Spring测试的基类
 * 
 * @author ChenST
 *
 */
public abstract class BaseSpringTest extends AbstractDependencyInjectionSpringContextTests {
	
	/**
	 * 获取上下文spring context,该路径是在classpath下的路径
	 */
	public String[] getConfigLocations() {
		String[] configLocations = { "applicationContext.xml" };
		return configLocations;
	}
}

2.测试用例

/**
 * 测试用例,测试Dao的方法getUserInfo(String userCode)
 * 
 * @author ChenST
 *
 */
public class UsersDaoTest extends BaseSpringTest {
	
	/** 用户Dao,注入实现 */
	private UsersDAO userDao;
	
	public void setUserDao(UsersDAO userDao) {
		this.userDao = userDao;
	}

	/**
	 * 测试getUserInfo()方法,需要以test开头
	 */
	public void testGetUserInfo(){
		Users user=userDao.getUserInfo("004");
	    System.out.println(user.getDepartment().getDepName());
	}
}

可通过MyEclipse中的Outline透视图中进行单个方法的测试或者整个类的测试。

Bean属性拷贝出现java.lang.ExceptionInInitializerError可能原因

前些天,进行使用PropertyUtils工具进行Bean的属性拷贝,总出现:java.lang.ExceptionInInitializerError错误,明明字段啥的都一样啊。。许久才发现。原来我包引错了~~闷~

我引用的是 com.sun.org.apache.commons.beanutils.PropertyUtils 类。

正确的是引用 org.apache.commons.beanutils.PropertyUtils

备注并引以为戒。

.userlibraries文件技巧与用法

.userlibraries文件,顾名思义,就是用户库的意思。记载了所包含的用户库的信息。

如果我们工程很多,而且引用的包很多,而且很多工程都共用很多包,那不是很麻烦。?

使用.userlibraries文件可以帮助我们管理这些包,使用MyEclipse可以通过这个.userlibraries文件把相关的用户库给引用进来。无须导入很多包。

举个例子:

<?xml version="1.0" encoding="UTF-8"?>
<eclipse-userlibraries version="2">
<library name="struts" systemlibrary="false">
<archive path="E:/lib/esim65/lib/struts/commons-codec.jar"/>
<archive path="E:/lib/esim65/lib/struts/commons-collections.jar"/>
<archive path="E:/lib/esim65/lib/struts/commons-dbutils-1.1.jar"/>
<archive path="E:/lib/esim65/lib/struts/commons-digester.jar"/>
<archive path="E:/lib/esim65/lib/struts/commons-fileupload.jar"/>
<archive path="E:/lib/esim65/lib/struts/commons-httpclient.jar"/>
<archive path="E:/lib/esim65/lib/struts/commons-io-1.2.jar"/>
<archive path="E:/lib/esim65/lib/struts/commons-lang-2.0.jar"/>
<archive path="E:/lib/esim65/lib/struts/commons-net-1.4.1.jar"/>
<archive path="E:/lib/esim65/lib/struts/commons-validator.jar"/>
<archive path="E:/lib/esim65/lib/struts/struts.jar"/>
<archive path="E:/lib/esim65/lib/struts/Struts-Layout.jar"/>
<archive path="E:/lib/esim65/lib/struts/struts-legacy.jar"/>
</library>
</eclipse-userlibraries>

比如我们记录一个struts包,里面包含了struts中的包,每个工程用到strust的时候,我们可以直接导入这个文件来把strust库中的包引进来。

以上library节点的name属性就是存放这些包的文件夹名,archive节点的path属性是存放包的物理路径。

很幸运的MyEclipse可以帮我们生成这个文件。

右键工程>>【Build Path】>>【Configure Build Path】>>选择【Libraries】>>【Add Libraries】>>【User Libraries】>>【next】>>【User Libraries】>>【Export】>>选中要导出的库,和指定对应的文件即可。

如图,

 

要使用这个文件的时候,【Import】>>选中指定的文件即可。如图:

完毕~~

Cannot find ActionMappings or ActionFormBeans collection错误

今天,将一个工程改成EJB时候,使用Struts的Action访问,出现Cannot find ActionMappings or ActionFormBeans collection错误。

百度之~~得:可能少了Struts的包,于是将Struts的包再重新导入一次,解决问题。

网上说,这类问题可能还可能有如下问题所导致:备忘下~~

①Web.xml未初始化问题
少了一个<load-on-startup>0</load-on-startup>
这样开始是没有加载这个类,就没有初始化struts-config.xml,所以找不到actionmappings actionformbeans collection。
②struts-config.xml问题
③jar包不全或版本不对
也有可能导致这个问题,从stuts例子里面拷过来就好了。struts1.x自带共10个jar包。
④编译问题
有可能Action和Formbean没有编译,也会有这个问题,检查一下有没有对应的class文件就好。class路径不对可能也会导致这个问题。
⑤版本问题
用的servlet容器和struts版本不对或这两个版本协调有问题。

远程连接Oracle10g数据库

百度之~在问问上搜到的答案并解决。

要进行远程连接Oracle数据库,首先需要对远程连接进行设置。具体做法如下:

【开始】>>【所有程序】>>【Oracle-OraDb10g_home1】>>【配置和移植工具】>>【Net Configuration Assistant】

选择【本地Net服务名配置】>>【添加】之后根据要连接的远程 数据库的IP 服务名 即可。之后就可以用PLSQL Developer进行登陆了。

具体操作可见下图:

1.选择Net Configuration Assistant

2.配置服务名

3.配置主机名

4.PLSQL Developer登录

迭代器模式--回答历史性问题

记得以前春哥问我:为什么迭代器都能够遍历多种数据结构,是怎么实现的呢。?

今天有空,看了迭代器模式,研究了几个小时的JDK~~总结如下:

先来看看一个例子:

List<String> list=new ArrayList<String>();
		list.add("a");
		list.add("b");
		list.add("c");
		Iterator<String> iter=list.iterator();
		while(iter.hasNext()){
			System.out.println(iter.next());
		}
		
		//遍历Vector
		List<String> vec=new Vector<String>();
		vec.add("d");
		vec.add("e");
		vec.add("f");
		Iterator<String> iterv=vec.iterator();
		while(iterv.hasNext()){
			System.out.println(iterv.next());
		}

为什么一个方法能够遍历不同集合呢。?

看下它们的关系图就可以知道原理了,而且使用的是迭代器模式。

纯粹是纪念下午的研究结果~~

状态模式

定义摘自《head first》中:

状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。

对于使用者来说看起来好像是能够修改自己的类,实际上是委托状态对象来改变相关操作。

状态模式类图如下(截图于《head first》):

对于状态模式,我自己举了例子:描述一个人经过外界时间的影响,心情状态会有不同的变化。

例如:一个人捡到钱了,当然是很高兴,钱丢了当然就不高兴也就是悲伤了,当丢的钱又捡回来了,于是就从悲伤变成高兴了。

看下面状态图:

使用状态模式实现,代码如下:

1.状态接口

/**
 * 状态接口
 * 
 * @author ChenST
 *
 * @create 2010-3-25
 */
public abstract class State {
	
	/** 状态名 */
	private String name;
	
	/**
	 * 捡到钱了
	 */
	public abstract void pickMoney();
	
	/**
	 * 丢钱了
	 */
	public abstract void loseMoney();
	
	/**
	 * 钱捡回来了
	 */
	public abstract void backMoney();

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

2.正常状态

/**
 * 正常状态
 * 
 * @author Administrator
 *
 * @create 2010-3-25
 */
public class NormalState extends State {

	/** 该状态所发生的实体 */
	private Person person;
	
	public NormalState(Person person) {
		this.person=person;
		this.setName("正常");
	}
	
	public void loseMoney() {
		//丢钱了,很悲伤,状态转变
		System.out.println("钱丢啦!");
		person.setCurrent(person.getSad());
	}

	public void pickMoney() {
		System.out.println("捡到钱了!");
		person.setCurrent(person.getHappy());
	}

	public void backMoney() {
		//无状态改变
	}
}

3.高兴状态

/**
 * 高兴的状态
 * 
 * @author ChenST
 *
 * @create 2010-3-25
 */
public class HappyState extends State {

	/** 该状态所发生的实体 */
	private Person person;
	
	public HappyState(Person person) {
		this.person=person;
		this.setName("高兴");
	}
	
	public void backMoney() {
		//无任何状态改变
	}

	public void loseMoney() {
		//无任何状态改变
	}

	public void pickMoney() {
		//无任何状态改变
	}
}

4.悲伤状态

/**
 * 悲伤状态
 * 
 * @author ChenST
 *
 * @create 2010-3-25
 */
public class SadState extends State {

	/** 该状态所发生的实体 */
	private Person person;
	
	public SadState(Person person) {
		this.person=person;
		this.setName("悲伤");
	}
	
	public void backMoney() {
		//丢失的钱失而复得,很高兴
		System.out.println("捡回来了,原来丢在这儿了");
		person.setCurrent(person.getHappy());
	}

	public void loseMoney() {
		//无状态改变
	}

	public void pickMoney() {
		//无状态改变
	}
}

5.人类,状态存在的实体

/**
 * 一个人的类
 * 
 * @author ChenST
 *
 * @create 2010-3-25
 */
public class Person extends State{

	/** 高兴的状态 */
	private State happy;
	
	/** 悲伤的状态 */
	private State sad;
	
	/** 正常的状态 */
	private State normal;
	
	/** 当前的状态 */
	private State current;
	
	public Person(){
		this.happy=new HappyState(this);
		this.sad=new SadState(this);
		this.normal=new NormalState(this);
		//当前状态为正常状态
		this.current=this.normal;
	}
	
	/**
	 * 显示打印当前状态
	 */
	public void showCurrentState(){
		System.out.println(current.getName());
	}
	
	/**
	 * 重新设置状态,回复默认状态
	 */
	public void resetState(){
		this.current=this.normal;
	}
	
	//
	//委托给状态对象去执行操作
	//
	public void backMoney() {
		current.backMoney();
	}

	public void loseMoney() {
		current.loseMoney();
	}

	public void pickMoney() {
		current.pickMoney();
	}

	public State getCurrent() {
		return current;
	}

	public void setCurrent(State current) {
		this.current = current;
	}

	public State getHappy() {
		return happy;
	}

	public void setHappy(State happy) {
		this.happy = happy;
	}

	public State getNormal() {
		return normal;
	}

	public void setNormal(State normal) {
		this.normal = normal;
	}

	public State getSad() {
		return sad;
	}

	public void setSad(State sad) {
		this.sad = sad;
	}
}

6.测试类

/**
 * 测试类
 * 
 * @author ChenST
 *
 * @create 2010-3-25
 */
public class Test {
	
	public static void main(String[] args) {
		//今天詹姆斯出去买东西
		Person james=new Person();
		james.pickMoney();		 //今天运气好,捡到钱了
		james.showCurrentState();//查看下詹姆斯的心情
		james.resetState();		 //于是不买东西了回家了.(恢复默认状态)
		james.showCurrentState();//查看下詹姆斯的心情
		
		//第二天詹姆斯又出去买东西
		james.loseMoney();		 //今天运气不好,丢钱了
		james.showCurrentState();//查看下詹姆斯的心情
		james.backMoney();		 //今天运气还不算很差,钱捡回来了。
		james.showCurrentState();//查看下詹姆斯的心情
	}
}

7.运行结果

捡到钱了!
高兴
正常
钱丢啦!
悲伤
捡回来了,原来丢在这儿了
高兴

OK~~完毕~可以看到,如果对状态的增加或者修改,或者对行为的增加或修改,都可以很好的扩展和维护。只要在人的类里面增加相应的状态和方法即可改变,而不需要改变整体结构,用增加类来代替if 的条件判断。

外观模式

今天,做完了公司的课题,无聊之余总结下之前的【外观模式】,看了这个模式的具体内容,很早以前就有用这样的思想了,只是不知道它叫外观模式。外观模式:实际上是提供一个经常使用的接口,这个接口他执行了许多子系统中的许多操作,使得用户不需要了解子系统中的具体操作,只需使用接口。这种例子是很常见的。

例如:我们知道用户、角色、权限三者关系,在早期,还没有角色的概念,只有用户和权限的概念,是直接讲权限赋予用户,但是后来为了方便管理,才引入角色的概念,把权限赋予角色,再把角色赋予用户。而角色就是我们外观模式中说的经常使用的接口,权限就是子系统,用户就是客户。

看下面的两个等价图:

1.有角色参与:

2.无角色参与:

可以看到,使用外观模式使的客户使用更方便,不需要了解子系统的过程,整个层次也更清晰。

无聊的实现了下这个代码:贴个纪念~~

1.权限类

/**
 * 权限类
 * 
 * @author ChenST
 *
 * @create 2010-3-24
 */
public class Right {
	
	/** 【添加】的权限 */
	public final static String ADD_RIGHT="【添加】";
	
	/** 【删除】的权限 */
	public final static String DELETE_RIGHT="【删除】";
	
	/** 【更新】的权限 */
	public final static String UPDATE_RIGHT="【更新】";
	
	/** 【查看】的权限 */
	public final static String SEE_RIGHT="【查看】";
}

2.角色抽象类

/**
 * 角色抽象类
 * 
 * @author ChenST
 *
 * @create 2010-3-24
 */
public abstract class Role {
	
	/** 角色拥有的权限*/
	private Set<String> rights;
	
	public Role(){
		this.rights=new HashSet<String>();
		//赋权操作
		this.addRight();
	}
	
	/**
	 * 添加权限
	 */
	public abstract void addRight();

	public Set<String> getRights() {
		return rights;
	}
}

3.管理员角色

/**
 * 超级管理员角色
 * 
 * @author ChenST
 *
 * @create 2010-3-24
 */
public class Admin extends Role{
	
	/*
	 * 添加全部的权限
	 * (non-Javadoc)
	 * @see facade.Role#addRight()
	 */
	@Override
	public void addRight() {
		this.getRights().add(Right.ADD_RIGHT);
		this.getRights().add(Right.DELETE_RIGHT);
		this.getRights().add(Right.SEE_RIGHT);
		this.getRights().add(Right.UPDATE_RIGHT);
	}
}

4.会员用户

/**
 * 会员用户
 * 
 * @author ChenST
 *
 * @create 2010-3-24
 */
public class Vip extends Role {

	/*
	 * 会员用户拥有【添加】权限
	 * (non-Javadoc)
	 * @see facade.Role#addRight()
	 */
	@Override
	public void addRight() {
		this.getRights().add(Right.ADD_RIGHT);
	}
}

5.普通用户角色

/**
 * 普通用户角色
 * 
 * @author ChenST
 *
 * @create 2010-3-24
 */
public class CommonUser extends Role{

	/*
	 * 普通用户只拥有【查看】的权限
	 * (non-Javadoc)
	 * @see facade.Role#addRight()
	 */
	@Override
	public void addRight() {
		this.getRights().add(Right.SEE_RIGHT);
	}
}

5.用户类

/**
 * 用户
 * 
 * @author ChenST
 *
 * @create 2010-3-24
 */
public  class User {
	
	/** 用户姓名 */
	private String name;
	
	/** 用户所拥有的角色 */
	private Set<Role> roles;
	
	public User(String name){
		this.name=name;
		roles=new HashSet<Role>();
	}
	
	/**
	 * 添加权限
	 * @param role
	 */
	public void addRole(Role role){
		this.roles.add(role);
	}
	
	/**
	 * 查看用户所拥有的权限
	 */
	public void lookRight(){
		System.out.println(this.name+"权限有:"+this.getRights());
	}

	/**
	 * 获取用户所拥有的权限
	 * @return
	 */
	public Set<String> getRights() {
		Set<String> rights=new HashSet<String>();
		for (Role role : roles) {
			for (String right: role.getRights()) {
				rights.add(right);
			}
		}
		return rights;
	}
}

6.测试类

/**
 * 测试类
 * 
 * @author ChenST
 *
 * @create 2010-3-24
 */
public class Test {

	public static void main(String[] args) {
		//创建用户james和green
		User james=new User("james");
		User green=new User("green");
		User joe=new User("joe");
		//创建三个角色 超级管理员,普通管理员,普通用户
		Role admin=new Admin();
		Role vip=new Vip();
		Role commonUser=new CommonUser();
		//给james赋予角色,赋予管理员和普通用户
		james.addRole(admin);
		james.addRole(commonUser);
		//给green赋予角色,赋予管理员
		green.addRole(admin);
		//给joe赋予角色,赋予管理员和会员
		joe.addRole(vip);
		joe.addRole(admin);
		//查看拥有的权限
		james.lookRight();
		green.lookRight();
		joe.lookRight();
	}
}

运行结果:

james权限有:[【删除】, 【更新】, 【查看】, 【添加】]
green权限有:[【删除】, 【更新】, 【查看】, 【添加】]
joe权限有:[【删除】, 【更新】, 【查看】, 【添加】]

可以看到,对于角色很好扩展和维护,对于权限的分配也可以很好维护,例如,会员用户要添加一个新的权限,那么则只要修改会员用户的权限,而不需要把相关的用户全部修改。OK~~

IE中网页字体变小的解决方案

前些天就遇到这类问题(网页字体变得很小)了,我知道可以用鼠标滚轴来调节,但是调节的总是没有原先默认的好。今日百度了下,得解决方案:

打开【运行】输入【regedit】进入注册表。

【HKEY_CURRENT_USER】>>【Software】 >>【Microsoft】 >> 【Internet Explorer】 >> 【International】 >> 【Scripts】 >> 【26/3】下的IEFontSize文件,

修改它的值为02,00,00,00即可(02为默认值,00为最小字号,01为较小字号,03较大字号,04为最大字号)

适配器模式

适配器模式:顾名思义,就是由一个中间介质,实现一种接口到另外一种接口的转化。两种接口都不用改变其中任何一个接口的结构。

适配器模式成为【类适配器】和【对象适配器】,这里用java实现,因此只讨论【对象适配器】,结构看下图:

 

举个例子,今天插在笔记本的鼠标坏了,叫小妹去买个鼠标,可是买回来才发现,她居然买了个PS2接口的鼠标,可是我笔记本是USB接口的呀,这要怎么用啊。?

如果再买个USB的鼠标,那么这个就浪费了,很明显我是不想换鼠标。更不想把笔记本给换成台式的吧~,于是这个时候我们就想到了用转换器,即实现USB到PS2的转换,代码实现如下:

1.USB接口

/**
 * USB接口
 * 
 * @author ChenST
 * 
 * @create 2010-3-23
 */
public interface USB {
	
	/** 产品描述 */
	public void describe();
}

2.PS2接口

/**
 * PS2接口【鼠标圆孔接口】
 * 
 * @author ChenST
 * 
 * @create 2010-3-23
 */
public interface PS2 {
	
	/** 产品描述 */
	public void describe();
}

3.鼠标类

/**
 * 鼠标类,实现了PS2接口,即【圆孔的鼠标】
 * 
 * @author ChenST
 * 
 * @create 2010-3-23
 */
public class Mouse implements PS2 {

	public void describe() {
		System.out.println("用的是PS2接口");
	}
}

4.适配器(USB和PS2的转换器)

/**
 * 接口适配器,拥有USB接口
 * 
 * @author ChenST
 * 
 * @create 2010-3-23
 */
public class Adapter implements USB{

	/** PS2接口 */
	private PS2 ps2;
	
	public Adapter(PS2 ps2) {
		this.ps2=ps2;
	}
	
	public void describe() {
		ps2.describe();
	}
}

5.测试类

/**
 * 测试类
 * 买了一个圆孔鼠标想要插笔记本上,却发现笔记本上没有圆孔,
 * 只有USB接口,这个鼠标好贵啊,再买个圆孔鼠标经济上是不可行的,
 * 更不能扔了笔记本而换台式的电脑把。于是想到使用USB和PS2转化器
 * 将转化器插在笔记本电脑上,于是笔记本USB接口就变成了PS2接口了,
 * 此时鼠标就可以接入了。
 * 
 * @author ChenST
 * 
 * @create 2010-3-23
 */
public class Test {

	public static void main(String[] args) {
		//圆孔鼠标
		PS2 mouse=new Mouse();
		//适配器,把他变成鼠标要用的接口
		Adapter adapter=new Adapter(mouse);
		//现在查看下原来是USB的接口的适配器用的是什么接口
		adapter.describe();
	}
}

运行结果:

用的是PS2接口

从结果可以看出,适配器已经实现了从USB接口到PS2接口的转换了~~OK~又学习了一个新模式