`
tianhandigeng
  • 浏览: 368897 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

项目开发全纪录(三)

阅读更多

 

21、GET和POST的区别
      首先要讲一点get和post都是浏览器与服务器交互的一种方式.但是对于get来说它不仅仅按常规的理解那样只有取的过程,它也有向服务器发送信息的过程,它之所以也能传送数据,只是用来告诉服务器,你到底需要什么样的数据。
所有的人都知道如下的区别:
Post传输数据时,不需要在URL中显示出来,而Get方法要在URL中显示。
Post传输的数据量大,可以达到2M,而Get方法由于受到URL长度的限制,只能传递大约1024字节
Post顾名思义,就是为了将数据传送到服务器端,Get就是为了从服务器取得数据,而Get之所以也能传送数据,只是用来设计告诉服务器,你到底需要什么样的数据。Post的信息作为Http请求的内容,而Get是在Http头部传输的。
具体描述:
    HTTP 定义了与服务器交互的不同方法,最基本的方法是 GET 和 POST。事实上 GET 适用于多数请求,而保留 POST 仅用于更新站点。根据 HTTP 规范,GET 用于信息获取,而且应该是 安全的和 幂等的。所谓安全的意味着该操作用于获取信息而非修改信息。换句话说,GET 请求一般不应产生副作用。幂等的意味着对同一 URL 的多个请求应该返回同样的结果。完整的定义并不像看起来那样严格。从根本上讲,其目标是当用户打开一个链接时,她可以确信从自身的角度来看没有改变资源。比如,新闻站点的头版不断更新。虽然第二次请求会返回不同的一批新闻,该操作仍然被认为是安全的和幂等的,因为它总是返回当前的新闻。反之亦然。POST 请求就不那么轻松了。POST 表示可能改变服务器上的资源的请求。仍然以新闻站点为例,读者对文章的注解应该通过 POST 请求实现,因为在注解提交之后站点已经不同了(比方说文章下面出现一条注解);
 
在FORM提交的时候,如果不指定Method,则默认为GET请求,Form中提交的数据将会附加在url之后,以?分开与url分开。字母数字字符原样发送,但空格转换为“+“号,其它符号转换为%XX,其中XX为该符号以16进制表示的ASCII(或ISO Latin-1)值。GET请求请提交的数据放置在HTTP请求协议头中,而POST提交的数据则放在实体数据中;

GET方式提交的数据最多只能有1024字节,而POST则没有此限制。

 

22、同步和异步
     同步这里的“同”并不是“一起”的意思,而是“协同”的意思。
     同步就是协同步调,按预定的先后次序进行运行。如:你说完,我再说。
“同”字从字面上容易理解为一起动作,其实不是,“同”字是指协同、协助、互相配合。
如进程、线程同步,可理解为进程或线程A和B一块配合,A执行到一定程度时要依靠B的某个结果,于是停下来,示意B运行;B依言执行,再将结果给A;A在继续操作。
     同步就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回,同时其他线程也不能调用这个方法。按照这个定义,其实绝大多数函数都是同步调用。但是一般而言,我们在说同步、异步的时候,特指那些需要其他部件协作或者需要一定时间完成的任务。最常见的例子就是SendMessage。该函数发送一个消息给某个窗口,在对方处理完消息之前,这个函数不返回。当对方处理完毕之后,该函数才把消息处理函数所返回的LRESULT值返回给调用者。
    在多线程编程里面,一些敏感数据不允许被多个线程同时访问,此时就使用同步访问技术,保证数据在任何时刻,最多一个线程访问,以保证数据的完整性。
   
异步的概念和同步相对,当一个异步过程调用发出后,调用者不能立刻得到结果,实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者。
实例:叫人吃饭
比如说你正在忙一件事件,你朋友来叫你去吃饭,现在来看看同步和异步对于这个事情是怎么处理的。
同步:你朋友来你的办公室通知你,但是你的工作还没完成,所以你的朋友就会一直等你,等你做完以后才一起去吃饭。
异步:你朋友来你的办公室通知你,你说好,你想去吧,我待会就来。你朋友得到你的口头答应以后,就离开你的办公室去找餐厅点菜去了,你忙完工作后,就去餐厅找你朋友,一起吃饭。
看看下面的图:

同步:

23、如何使用Ant
这里只讲一下简单的应用,具体请参考相关的文档:
第一步:从http://ant.apache.org 下载 apache-ant-1.7.0-bin.zip,解压到你自己的目录,我的:E:\apache-ant-1.7.0

第二步:配置 JAVA_HOME 和 ANT_HOME
配置完成后,打开dos窗口,输入 ant 回车,如果提示:
Buildfile: build.xml does not exist!
Build failed

则说明配置完成

第三步:创建自己的工程
我的工程:test
目录结构:
D:\work\code\test_core\src
D:\work\code\test_core\lib


第四步:编写build.xml

 

 

24、单元测试和集成测试
单元测试:单元测试是开发者编写的一小段代码,用于检验目标代码的一个很小的、很明确的功能是否正确。
集成测试:集成测试是在功能模块开发完成后,为验证功能模块之间匹配调用的正确性而进行的测试。
在单元测试时,往往需要通过模拟对象屏蔽外在模块的依赖,而集成测试恰恰是要验证模块
之间集成后的正确性。

1、Junit+EasyMock进行单元测试

导入需要的jar包:


 下面是一个简单的测试例子
UserDao接口:

public interface UserDao {
   public int getMatchCount(String userName,String password);
}

 UserService接口:

public interface UserService {
   boolean hasMatchUser(String userName,String password);
}

 UserService接口的实现UserServiceImpl:

public class UserServiceImpl implements UserService {
    private UserDao userDao;
	public boolean hasMatchUser(String userName, String password) {
		// TODO Auto-generated method stub
		int matchCount=userDao.getMatchCount(userName, password);
		return matchCount>0;
	}
	public UserDao getUserDao() {
		return userDao;
	}
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}
}

 UserServiceImpl要用到userDao组件的实现,但是现在的情况是userDao的实现并没有写好,或者是userDao的实现是由另外的人员编写,这时候要测试自己写的这个UserServiceImpl实现类是否正确,就要用到上面讲的那个EasyMock测试框架了,我们这里是和Junit框架结合使用的.下面是测试类:
UserServiceImplTest:

public class UserServiceImplTest extends TestCase {
     private UserServiceImpl userService;
     @Override
     protected void setUp() throws Exception{
    	 userService=new UserServiceImpl();
    	 super.setUp();
     }
     
     public void testHasMatchUser(){
    	 UserDao userDao=EasyMock.createMock(UserDao.class);
    	 userService.setUserDao(userDao);
    	 
    	 EasyMock.expect(userDao.getMatchCount("tom","654321")).andReturn(0);
    	 EasyMock.expect(userDao.getMatchCount("tom","123456")).andReturn(1);
    	 
    	 EasyMock.replay(userDao);
    	 
    	 assertEquals(userService.hasMatchUser("tom","654321"),false);
    	 assertEquals(userService.hasMatchUser("tom","123456"),true);
    	 
    	 EasyMock.verify(userDao);
     }
}

 2、集成测试(Spring提供的模拟类)
   Spring在org.springframework.mock包中为一些依赖于容器的接口提供了模拟类,这样用户可以在不启动容器的情况下执行单元测试,提供单元测试的运行效率。
   我们在实际的使用过程中,对于不想启动Spring容器,又想做集成测试,那么我们就可以继承AbstractDependencyInjectionSpringContextTests类,这个类所添加的主要功能是其属性能被Spring容器中的Bean自动装配,用户无须手工通过ApplicationContext#getBean()从容器中获取目标Bean自行装配。
看下面例子:

package email;

import org.springframework.test.AbstractDependencyInjectionSpringContextTests;

/**
 * @project_name jms
 * @file_name Login.java
 * @author tianhandigeng
 * @version Oct 12, 2010 10:22:17 PM
 * @declaration
 */
public class Login extends AbstractDependencyInjectionSpringContextTests{

	// 设置邮件发送者
	private UserMessageProducer userMessageProducer;

	// 设置注册人员的信息
	private PersonInfo personInfo = new PersonInfo();

	public UserMessageProducer getUserMessageProducer() {
		return userMessageProducer;
	}

	public void setUserMessageProducer(UserMessageProducer userMessageProducer) {
		this.userMessageProducer = userMessageProducer;
	}
	
	@Override
	protected String[] getConfigLocations(){
		return new String[]{"classpath:applicationContext.xml"};
	}

	// 注册后发送邮件
	public void testSetEmail() {
		personInfo.setUserName("胡学汪");
		personInfo.setPassword("14981498");
		personInfo.setEmail("tianhandigeng@sohu.com");
		
		this.getUserMessageProducer().sendUserLoginInformationMail(personInfo);
	}
}
 

【根据描述,userMessageProducer属性就不需要我们手动的从容器拿出Bean】

 

25、JMS(ActiveMQ)和Spring整合发送邮件
1、在使用ActiveMQ5.4.1的时候,关闭broker重新启动的时候,出现异常java.io.EOFException:Chunk stream does
   not exist at page on broker start
暂时的解决办法:
   在activemq.xml中<broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" ataDirectory="${activemq.base}/data" destroyApplicationContextOnStop="true" schedulerSupport="false">
   加上红色的配置。

2、现在来讲ActiveMQ与Spring的整合
   在这里我们以注册后发送邮件这个例子来讲两者的整合
第一步:导入jar包


 上面有些jar并不是一定需要的,有的是进行测试用的

第二步:这里本来配置文件是一点一点写的,在这里我就全给出了:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:amq="http://activemq.apache.org/schema/core"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://activemq.apache.org/schema/core
        http://activemq.apache.org/schema/core/activemq-core-5.3.2.xsd">

	<!--定义内嵌的ActiveMQ Broker,使用消息存储机制,服务器重启后,消息不会丢失 -->
	<amq:broker useJmx="false" persistent="true">
		<amq:persistenceAdapter>
			<amq:amqPersistenceAdapter directory="e:/zuwoba" />
		</amq:persistenceAdapter>
		<!-- The transport connectors ActiveMQ will listen to ... -->
		<amq:transportConnectors>
			<amq:transportConnector uri="tcp://localhost:61616" />
		</amq:transportConnectors>
	</amq:broker>
	<!-- 配置JMS Connection Factory,用到缓存功能 -->
	<bean id="jmsFactory"
		class="org.apache.activemq.pool.PooledConnectionFactory">
		<property name="connectionFactory">
			<bean
				class="org.apache.activemq.ActiveMQConnectionFactory">
				<property name="brokerURL" value="tcp://localhost:61616" />
			</bean>
		</property>
	</bean>
	<!-- 配置消息发送目的地 -->
	<bean id="queueDestination"
		class="org.apache.activemq.command.ActiveMQQueue">
		<constructor-arg value="MY.queue" />
	</bean>
	<!-- 配置Spring中消息发送的JMS Template -->
	<bean id="producerJmsTemplate"
		class="org.springframework.jms.core.JmsTemplate">
		<property name="connectionFactory">
			<bean
				class="org.springframework.jms.connection.SingleConnectionFactory">
				<property name="targetConnectionFactory"
					ref="jmsFactory" />
			</bean>
		</property>
		<!-- 配置发送地址 -->
		<property name="defaultDestination" ref="queueDestination" />
		<!-- 增加一个信息转换器 -->
		<property name="messageConverter" ref="userMessageConverter" />
	</bean>
	<!-- 配置消息转换器 -->
	<bean id="userMessageConverter"
		class="com.zuwoba.util.mail.UserMessageConverter">
	</bean>
	<!-- 配置消息发送者 -->
	<bean id="userMessageProducer"
		class="com.zuwoba.util.mail.UserMessageProducer">
		<property name="jmsTemplate" ref="producerJmsTemplate" />
	</bean>
	<!-- 配置消息接收者 -->
	<bean id="userMessageConsumer"
		class="com.zuwoba.util.mail.UserMessageConsumer">
		<property name="mailService" ref="mailService" />
	</bean>
	<!-- 配置Mail Service -->
	<bean id="mailService"
		class="com.zuwoba.service.impl.MailServiceImpl">
		<property name="sender" ref="sender" />
		<property name="freeMarkerConfigurer" ref="freeMarkerConfigurer"/>
	</bean>
	<!-- 配置邮件模板 -->
	<bean id="freeMarkerConfigurer"
	    class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
	    <property name="templateLoaderPath" value="classpath:mailTemplate"/>
	    <property name="freemarkerSettings">
	         <props>
	             <prop key="template_update_delay">1800</prop>
	             <prop key="default_encoding">gbk</prop>
	             <prop key="locale">zh_CN</prop>
	         </props>
	    </property>
	</bean>
	<!-- 配置邮件发送者 -->
	<bean id="sender"
		class="org.springframework.mail.javamail.JavaMailSenderImpl">
		<property name="host" value="smtp.sina.com" />
		<property name="username" value="tianhandigeng" />
		<property name="password" value="14981498" />
		<property name="javaMailProperties">
			<props>
				<prop key="mail.smtp.auth">true</prop>
			</props>
		</property>
	</bean>
	<!-- 配置messageListener,用它来接收消息-->
	<!-- 定义queue的侦听器 -->
	<bean id="messageListener"
		class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
		<constructor-arg ref="userMessageConsumer" />
		<property name="defaultListenerMethod" value="handleMessage" />
		<property name="messageConverter" ref="userMessageConverter" />
	</bean>
	<!-- 定义queue的侦听容器 -->
	<bean id="listenerContainer"
		class="org.springframework.jms.listener.DefaultMessageListenerContainer">
		<property name="concurrentConsumers" value="20" />
		<property name="connectionFactory" ref="jmsFactory" />
		<property name="destination" ref="queueDestination" />
		<property name="messageListener" ref="messageListener" />
	</bean>
</beans>

 第三步:我们现在写当用户点击注册以后,发送消息给ActiveMQ的类,也就是消息发送者:
UserMessageProducer.java

package email;

import javax.jms.Queue;

import org.springframework.jms.core.JmsTemplate;

/**
 * @project_name jms
 * @file_name UserMessageProducer.java
 * @author tianhandigeng
 * @version Oct 12, 2010 8:41:59 PM
 * @declaration
 */
public class UserMessageProducer {
	private JmsTemplate jmsTemplate;
	// 如果"目的地"属性放于jmsTemplate中,则不用添加此属性
	private Queue defaultDestination;

	public void sendUserLoginInformationMail(PersonInfo personInfo) {
		/**
		 * 若"目的地"属性放于jmsTemplate中,则用此方式
		 * getJmsTemplate().convertAndSend(personInfo);
		 */
         getJmsTemplate().convertAndSend(this.defaultDestination,personInfo);
	}

	public JmsTemplate getJmsTemplate() {
		return jmsTemplate;
	}

	public void setJmsTemplate(JmsTemplate jmsTemplate) {
		this.jmsTemplate = jmsTemplate;
	}

	public Queue getDefaultDestination() {
		return defaultDestination;
	}

	public void setDefaultDestination(Queue defaultDestination) {
		this.defaultDestination = defaultDestination;
	}

}

 第四步:因为我们传给ActiveMQ的是对象,所以要有一个消息转换类,将对象转换为ActiveMQ所能理解的message,同时当从ActiveMQ取出message时这个转换类也会将message转换为对象。
UserMessageConverter.java

package email;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.ObjectMessage;
import javax.jms.Session;

import org.apache.activemq.command.ActiveMQObjectMessage;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.Logger;
import org.springframework.jms.support.converter.MessageConversionException;
import org.springframework.jms.support.converter.MessageConverter;

/** 
 * @project_name   jms
 * @file_name     UserMessageConverter.java
 * @author        tianhandigeng
 * @version       Oct 12, 2010 4:52:50 PM 
 * @declaration   
 */
public class UserMessageConverter implements MessageConverter {
    private static transient Log logger=LogFactory.getLog(UserMessageConverter.class);
	public Object fromMessage(Message message) throws JMSException,
			MessageConversionException {
		if(logger.isDebugEnabled()){
			logger.debug("Receive JMS message:"+message);
		}
		if(message instanceof ObjectMessage){
			ObjectMessage oMsg=(ObjectMessage)message;
			if(oMsg instanceof ActiveMQObjectMessage){
				ActiveMQObjectMessage aMsg=(ActiveMQObjectMessage)oMsg;
				try{
					PersonInfo personInfo=(PersonInfo)aMsg.getObject();
					return personInfo;
				}catch(Exception e){
					logger.error("Message:["+message+"]is not a instance of personInfo.");
					throw new JMSException("Message:["+message+"]is not a instance of personInfo.");
				}
			}else{
				logger.error("Message:["+message+"]is not"+"a instance of ActiveMQObjectMessage[personInfo].");
			    throw new JMSException("Message:["+message+"] is not"+"a instance of ActiveMQObjectMessage[personInfo].");
			}
		}else{
			logger.error("Message:["+message+"] is not a instance of ObjectMessage.");
			throw new JMSException("Message:["+message+"] is not a instance of ObjectMessage.");
		}
	}

	public Message toMessage(Object obj, Session session) throws JMSException,
			MessageConversionException {
		if(logger.isDebugEnabled()){
			logger.debug("Convert User Object to JMS message:"+obj);
		}
		if(obj instanceof PersonInfo){
			ActiveMQObjectMessage msg=(ActiveMQObjectMessage)session.createObjectMessage();
			msg.setObject((PersonInfo)obj);
			return msg;
		}else{
			logger.error("Object:["+obj+"] is not a instance of PersonInfo.");
			throw new JMSException("Object:["+obj+"] is not a instance of PersonInfo.");
		}
	}

}

 第五步:从ActiveMQ中取出消息
UserMessageConsumer.java

package email;

import javax.jms.JMSException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.mail.MailSender;

/**
 * @project_name jms
 * @file_name UserMessageConsumer.java
 * @author tianhandigeng
 * @version Oct 12, 2010 9:08:23 PM
 * @declaration
 */
public class UserMessageConsumer {
	private static transient Log logger = LogFactory
			.getLog(UserMessageConsumer.class);
	private MailService mailService;

	public void handleMessage(PersonInfo personInfo) throws JMSException {
		if (logger.isDebugEnabled()) {
			logger.debug("Receive a User object from ActiveMQ:"
					+ personInfo.toString());
		}
		mailService.sendSimpleMail(personInfo);
	}

	public static Log getLogger() {
		return logger;
	}

	public static void setLogger(Log logger) {
		UserMessageConsumer.logger = logger;
	}

	public MailService getMailService() {
		return mailService;
	}

	public void setMailService(MailService mailService) {
		this.mailService = mailService;
	}
}

 第六步:书写发送消息的业务类
MailService.java

package email;

import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;

/**
 * @project_name jms
 * @file_name MailService.java
 * @author tianhandigeng
 * @version Oct 16, 2010 3:10:26 PM
 * @declaration
 */
public class MailService {
	private JavaMailSender sender;

	public JavaMailSender getSender() {
		return sender;
	}

	public void setSender(JavaMailSender sender) {
		this.sender = sender;
	}
	
	//发送邮件
	public void sendSimpleMail(PersonInfo personInfo){
		System.out.println("到这了");
		SimpleMailMessage msg=new SimpleMailMessage();
		msg.setFrom("tianhandigeng@sina.com");
		msg.setTo((String)personInfo.getEmail());
		msg.setSubject("注册成功");
		msg.setText("恭喜,您在组我吧网已经注册成功,你的用户名是:"+(String)personInfo.getUserName());
		sender.send(msg);
		System.out.println("成功发送邮件");
	}

}

 第六步:测试

package email;

import org.springframework.test.AbstractDependencyInjectionSpringContextTests;

/**
 * @project_name jms
 * @file_name Login.java
 * @author tianhandigeng
 * @version Oct 12, 2010 10:22:17 PM
 * @declaration
 */
public class Login extends AbstractDependencyInjectionSpringContextTests{

	// 设置邮件发送者
	private UserMessageProducer userMessageProducer;

	// 设置注册人员的信息
	private PersonInfo personInfo = new PersonInfo();

	public UserMessageProducer getUserMessageProducer() {
		return userMessageProducer;
	}

	public void setUserMessageProducer(UserMessageProducer userMessageProducer) {
		this.userMessageProducer = userMessageProducer;
	}
	
	@Override
	protected String[] getConfigLocations(){
		return new String[]{"classpath:applicationContext.xml"};
	}

	// 注册后发送邮件
	public void testSetEmail() {
		personInfo.setUserName("胡学汪");
		personInfo.setPassword("14981498");
		personInfo.setEmail("tianhandigeng@sohu.com");
		
		this.getUserMessageProducer().sendUserLoginInformationMail(personInfo);
	}
}

 

26、如何查看某端口的使用情况
    有时候在开发过程中要看具体的端口被哪个进程占用,网上大都是说用“netstat”命令,但是在实际使用过程中并不够使用,在这里从网上找到了一个解决的办法:
在Windows命令窗口下执行:
netstat –aon|findstr “80”
TCP   127.0.0.1:80   0.0.0.0:0  LISTENING  2448
看到了吗,端口被进程号为2448的进程占用,继续执行下面命令
tasklist|findstr “2448”
thread.exe      2016 Console   0   16,064K
很清楚吧,thread占用了你的端口,Kill it
如果第二步查不到,那就开任务管理器,看哪个进程是2448,然后杀之即可。

如果需要查看其他端口,把80改掉即可

 

27、public/protected/private/unsigned


28、Struts 2 整合SiteMesh的步骤
第一步:添加Struts 2的jar包
第二部:添加SiteMesh  jar包和Struts 2 SiteMesh插件jar包,所需的jar包如下


 第三步:定义装饰器页面,一般在头部要加上这样

<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator"%>

 下面是常用的SiteMesh的三个标签

<decorator:title/>
	<decorator:head/>
	<decorator:body/>

 29、URI和URL
   这两个单词一直都没去弄到底有什么不同,以前总是觉得很模糊,现在来看看具体有什么不同:
URI : Uniform Resourse Identitier
URL: Uniform Resource Locations
字面去解释都是表示”统一资源定位符”的意思.但是看看后面的这两个单词,又可以看出两者有什么不同,URI强调的是”身份”,URL强调的是”位置”.
URI更为注重资源而不太注重位置,URI对于定位Internet上的资源是更为通用的架构.
URI有两种形式:一种是URL,另一种是URN
URL表示的是某台特定主机上的一个资源的具体路径,是一个精确地、固定的位置。
URN(uniform resource name)指的是某一块特定内容的唯一的名字,和资源所在的位置无关,是location-independent的,允许资源从一个地方移到另一个地方。
URN仍然是实验性的,还没有被广泛的采用.URN需要一个基础架构来支持解决资源定位问题。
所以说,现在URI基本上都是URL。

 

30、Struts 2 Action接收参数的3中方式
    用Action属性接收参数
    用DomainModel接收参数
    用ModelDriven接收参数

在实际的开发中,一般都是用第一种,其次是第二种,第三种用得少,我觉得第一种自己用得习惯所以就用采用了第一种。

 

 

 

------未完待续-------

 

 

 

 

 

 

 

1
3
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics