1 通讯协议
关于协议,关于网络编程,这方面的基础基本没有。第一次写相对底层一点这一块代码,是做android上的数据和文件上传和登陆机制,没有用httpclient,貌似现在这个也支持文件上传和cookie机制的。传输层的协议我简单理解就是一个交互信息的规范,目前产品研发需要做自定义协议的实现,主要就是xml和java命令对象的转换需要,在终端和服务器通过约定的xml转换成命令对象执行操作,用了Digester和betwixt。转换器类的参考了ConvetUtils的设计。
2 单元测试
主要采用了spring-test中的一些封装的类,然后也使用另外的mock框架
1 @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false)
2 public abstract class SpringTxTestCase
extends AbstractTransactionalJUnit4SpringContextTests {
3
4 protected DataSource dataSource;
5
6 @Autowired
7 public void setDataSource(DataSource dataSource) {
8 super.setDataSource(dataSource);
9 this.dataSource = dataSource;
10 }
11
12
13 }
14
defaultRollback
:是否回滚事务
子类需要定义applicationContext文件的位置, 如:
@ContextConfiguration(locations = { "/applicationContext-test.xml" })
mock的一点小应用 (mockito下载
http://www.oschina.net/p/mockito)
public class OMALiteServiceServletTest extends DmBaseTest {
private OMALiteServiceServlet servlet;
private HttpServletRequest req;
private MockHttpServletResponse resp;
@Before
public void setUp() throws Exception {
servlet = new OMALiteServiceServlet() {
@Override
public ServletContext getServletContext() {
return new MockServletContext();
}
};
req = mock(HttpServletRequest.class);
when(req.getRemoteHost()).thenReturn("222.222.222.222");
when(req.getRemotePort()).thenReturn(8888);
resp = new MockHttpServletResponse();
servlet.init();
}
/**
* 客户端发送了非法报文
*/
@Test
// @Repeat(100)
public void test01() throws Exception {
when(req.getParameter("message")).thenReturn("<status1></status>");
servlet.service(req, resp);
}
/**
* 客户端第一次发送的不是replace
*/
@Test
public void test02() throws Exception {
when(req.getParameter("message")).thenReturn("<final/>");
servlet.service(req, resp);
}
/**
* 客户端第一次发送replace,然后发送final
*/
@Test
public void test03() throws Exception {
when(req.getParameter("message")).thenReturn("<replace></replace>").thenReturn("<final/>");
servlet.service(req, resp);
servlet.service(req, resp);
}
/**
* 客户端第一次发送replace,然后发送alert
*/
@Test
public void test04() throws Exception {
when(req.getParameter("message")).thenReturn("<replace></replace>").thenReturn("<alert></alert>");
servlet.service(req, resp);
servlet.service(req, resp);
}
/**
* 客户端返回result命令中item和服务器发送的Get命令的item不一致
*/
@Test
public void test05() throws Exception {
final Get get = mock(Get.class);
List list = mock(List.class);
when(list.size()).thenReturn(2);
when(get.getItems()).thenReturn(list);
servlet = new OMALiteServiceServlet() {
@Override
public ServletContext getServletContext() {
MockServletContext sc = new MockServletContext();
OMALiteSession session = mock(OMALiteSession.class);
when(session.getAttribute("first")).thenReturn(false);
when(session.getAttribute("lastCommand")).thenReturn(get);
when(session.getAttribute("visitTime")).thenReturn(System.currentTimeMillis());
sc.setAttribute(OMALiteStatus.BASE_SESSION_KEY + "222.222.222.222:8888", session);
return sc;
}
};
servlet.init();
when(req.getParameter("message"))
.thenReturn(
"<result><item><path>path1</path><value>value1</value><type>type1</type></item><item><path>path2</path><value>value2</value></item><type>type2</type></result>");
servlet.service(req, resp);
}
/**
* ip和port相同才为一个session
*/
@Test
public void test06() throws Exception {
when(req.getParameter("message")).thenReturn("<replace></replace>");
servlet.service(req, resp);
when(req.getParameter("message")).thenReturn("<replace></replace>");
when(req.getRemoteHost()).thenReturn("111.222.222.222"); //更改ip和port模拟另一个用户访问
when(req.getRemotePort()).thenReturn(8877);
servlet.service(req, resp);
when(req.getRemoteHost()).thenReturn("222.222.222.222"); //切换到第一个用户
when(req.getRemotePort()).thenReturn(8888);
when(req.getParameter("message")).thenReturn("<alert></alert>");
servlet.service(req, resp);
}
}
三 JMS
java消息服务。可用于不同服务器之间的消息传递。
以前对这一块的基本没接触过,目前了解一些远程监控都是基于jms消息服务的,还有一些分布式缓存的东西比如Ehcache
JMS 服务器http://activemq.apache.org/
四 异常处理。
异常处理是一个一直很重视但是并没有怎么处理好且没仔细体会的话题了。
如果我们用struts2我们知道可以在将所有异常抛给它,然后在配置文件中配置异常对于的视图。另外spring也有相关的机制。
这一次的编码没有用任何框架,用的servlet编写控制,并分了dao和service层。这里浅谈一下自己在编码中异常处理的一些心得。
1 重视异常。
写一些测试代码的时候我们总是习惯catch 异常然后直接打印异常堆栈e.printStackTrace()。但是这在生产环境中是一个很不好的习惯。
我们必须严格禁止System.out.println() 和e.printStackTrace()。 出现了异常我们需要两方面的处理,一是对于开发人员日后追踪bug做日志记录,另一方面是对客户的反馈。
2如何对待异常
当我们catch到异常之后,有2种对待的方式。
a 吞掉异常。在一些对我们整个系统业务并不重要的异常我们可以吃掉,如果需要可以加入一些warn级别的日志。
比如SpringJdbcTemp 中的queryForMap方法,当数据库记录为空的时候会抛出一个
EmptyResultDataAccessException ,这个异常其实对于我们并不重要,当没有数据我们返回一个空map不就ok了,所以我们可以catch这个异常然后new 一个HashMap就行。
1 SimpleJdbcTemplate simpleJdbcTemplate = null;2 String sql = null;
3 Map map;
4 try {
5 map = simpleJdbcTemplate.queryForMap(sql);
6 } catch (EmptyResultDataAccessException e1) {
7 map = Maps.newHashMap();
8 }
b 向上抛出异常
当目前获取的异常在本层并不想作处理的时候,我们可以包装成一个新的异常统一到上层做处理。
1 try {
2 return loader.newDigester().parse(new ByteArrayInputStream(lowerLabelMessage.getBytes()));
3 } catch (Exception e) {
4 throw new OMALiteAnalyticException("server message is Illegal,the message is " + message, e);
5 }
c处理异常
下面的代码
try {
sendOMALite = receiveOMALite.getCommand().doReceiveHandle(req);
} catch (OMALiteClientException e) {
resp.sendErrorStatus(COMMAND_FAILED,
getCommandNameOfOMALite((OMALite) currentSession.getAttribute("lastOMALite")),
receiveOMALite.getPkgId());
logger.error(e.getMessage(), e);
return;
} catch (OMALiteServerException e) {
resp.sendFinal(receiveOMALite.getPkgId());
logger.error(e.getMessage(), e);
} catch (OMALiteException e) {
resp.sendErrorStatus(COMMAND_FAILED,
getCommandNameOfOMALite((OMALite) currentSession.getAttribute("lastOMALite")),
receiveOMALite.getPkgId());
logger.error("UnKnow Exception", e);
return;
}
这段代码在servlet之中,dao和service的代码基本都采用a,b两条做的处理,都包装成自定义异常到顶层处理 。注意,一定要做log记录,resp.sendxx是发生此类异常需要反馈给客户的东西,而logger.error则是记录给我们开发人员作bug追踪的。
3
posted on 2012-01-03 00:38
周磊 阅读(449)
评论(0) 编辑 收藏