通向架构师的道路(第二十天)万能框架spring(二)maven结合spring与ibatis

2015-01-15  来源:本站原创  分类:【23】、架构师  人气:11 

一、前言

上次讲了Struts结合Spring并使用Spring的JdbcTemplate来搭建工程框架后我们面临着jar库无法管理,工程发布不方便,jar包在工程内太占空间,jar包冲突,管理,甚至漏包都问题。于是我们在讲“万能框架spring(二)”前,传授了一篇番外篇,即讲利用maven来管理我们的jar库。

从今天开始我们将结合“万能框架spring(一)”与番外篇maven来更进一步丰富我们的ssx框架,那么今天讲的是使用iBatis3结合SS来构建我们的ssi框架,我们把这个框架命名为beta吧。

二、SSI框架

通向架构师的道路(第二十天)万能框架spring(二)maven结合spring与ibatis

还记得我们在第十八天中讲到的我们的框架的架构图吗?上面这张是我们今天的架构图,除了Struts,Spring层,我们需要变换的是DAO层即把原来的SQL这部分换成iBatis,我们在次使用的是iBatis版本3。

由于我们在第十八天中已经说了这样的一个框架的好处其中就有:

层中相关技术的替换不影响到其它层面

所以对于我们来说我们需要改动的代码只有datasource.xmldao层的2个接口两个类,那我们就一起来看看这个基于全注解的SSi框架是怎么样搭起来的吧。

三、搭建SSI框架

3.1建立工程

我们还是使用maven来建立我们的工程

通向架构师的道路(第二十天)万能框架spring(二)maven结合spring与ibatis

建完后照着翻外篇《第十九天》中的“四、如何让Maven构建的工程在eclipse里跑起来”对工程进行设置。

通向架构师的道路(第二十天)万能框架spring(二)maven结合spring与ibatis

通向架构师的道路(第二十天)万能框架spring(二)maven结合spring与ibatis

通向架构师的道路(第二十天)万能框架spring(二)maven结合spring与ibatis

3.2 增加iBatis3的jar相关包

打开pom.xml

第一步

找到“slf4j”,将它在pom中的描述改成如下内容:


<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-api</artifactId>

<version>1.5.10</version>

</dependency>

第二步

增加两个jar包


<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-log4j12</artifactId>

<version>1.5.10</version>

</dependency>

<dependency>

<groupId>org.apache.ibatis</groupId>

<artifactId>ibatis-core</artifactId>

<version>3.0</version>

</dependency>

3.3 开始配置ibatis与spring结合

打开/src/main/resources/spring/datasource下的datasource.xml,增加如下几行


<bean id="iBatisSessionFactory" class="org.sky.ssi.ibatis.IBatis3SQLSessionFactoryBean" scope="singleton">

<property name="configLocation" value="sqlmap.xml"></property>

<property name="dataSource" ref="dataSource"></property>

</bean>

<bean id="iBatisDAOSupport" class="org.sky.ssi.ibatis.IBatisDAOSupport">

</bean>

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<property name="dataSource" ref="dataSource" />

</bean>

此处,我们需要4个类,它们是:

org.sky.ssi.ibatis.IBatis3SQLSessionFactoryBean类


package org.sky.ssi.ibatis;

import java.io.IOException;

import java.io.Reader;

import javax.sql.DataSource;

import org.apache.ibatis.builder.xml.XMLConfigBuilder;

import org.apache.ibatis.io.Resources;

import org.apache.ibatis.mapping.Environment;

import org.apache.ibatis.session.Configuration;

import org.apache.ibatis.session.SqlSessionFactory;

import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory;

import org.springframework.beans.factory.FactoryBean;

import org.springframework.beans.factory.InitializingBean;

import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;

/**

*

* IBatis3SQLSessionFactoryBean is responsible for integrating iBatis 3 <p>

* with spring 3. Since all environment configurations have been moved to <p>

* spring, this class takes the responsibility to get environment information<p>

* from spring configuration to generate SqlSessionFactory.

* @author lifetragedy

*

*/

public class IBatis3SQLSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean{

private String configLocation;

private DataSource dataSource;

private SqlSessionFactory sqlSessionFactory;

private boolean useTransactionAwareDataSource = true;

private String environmentId = "development";

public String getConfigLocation() {

return configLocation;

}

public void setConfigLocation(String configLocation) {

this.configLocation = configLocation;

}

public DataSource getDataSource() {

return dataSource;

}

public void setDataSource(DataSource dataSource) {

this.dataSource = dataSource;

}

public SqlSessionFactory getSqlSessionFactory() {

return sqlSessionFactory;

}

public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {

this.sqlSessionFactory = sqlSessionFactory;

}

public boolean isUseTransactionAwareDataSource() {

return useTransactionAwareDataSource;

}

public void setUseTransactionAwareDataSource(

boolean useTransactionAwareDataSource) {

this.useTransactionAwareDataSource = useTransactionAwareDataSource;

}

public String getEnvironmentId() {

return environmentId;

}

public void setEnvironmentId(String environmentId) {

this.environmentId = environmentId;

}

public SqlSessionFactory getObject() throws Exception {

return this.sqlSessionFactory;

}

public Class<SqlSessionFactory> getObjectType() {

return SqlSessionFactory.class;

}

public boolean isSingleton() {

return true;

}

public void afterPropertiesSet() throws Exception {

this.sqlSessionFactory = this.buildSqlSessionFactory(configLocation);

}

protected SqlSessionFactory buildSqlSessionFactory(String configLocation)

throws IOException {

if (configLocation == null) {

throw new IllegalArgumentException(

"configLocation entry is required");

}

DataSource dataSourceToUse = this.dataSource;

if (this.useTransactionAwareDataSource

&& !(this.dataSource instanceof TransactionAwareDataSourceProxy)) {

dataSourceToUse = new TransactionAwareDataSourceProxy(

this.dataSource);

}

Environment environment = new Environment(environmentId,

new IBatisTransactionFactory(dataSourceToUse), dataSourceToUse);

Reader reader = Resources.getResourceAsReader(configLocation);

XMLConfigBuilder parser = new XMLConfigBuilder(reader, null, null);

Configuration config = parser.parse();

config.setEnvironment(environment);

return new DefaultSqlSessionFactory(config);

}

}

org.sky.ssi.ibatis.IBatisDAOSupport


package org.sky.ssi.ibatis;

import javax.annotation.Resource;

import org.apache.ibatis.session.SqlSession;

import org.apache.ibatis.session.SqlSessionFactory;

import org.apache.log4j.Logger;

/**

* Base class for all DAO class. The subclass extends this class to get

* <p>

* DAO implementation proxy.

*

* @author lifetragedy

*

* @param <T>

*/

public class IBatisDAOSupport<T> {

protected Logger log = Logger.getLogger(this.getClass());

@Resource

private SqlSessionFactory ibatisSessionFactory;

private T mapper;

public SqlSessionFactory getSessionFactory() {

return ibatisSessionFactory;

}

protected SqlSession getSqlSession() {

return ibatisSessionFactory.openSession();

}

public T getMapper(Class<T> clazz) {

mapper = getSqlSession().getMapper(clazz);

return mapper;

}

public T getMapper(Class<T> clazz, SqlSession session) {

mapper = session.getMapper(clazz);

return mapper;

}

/**

* close SqlSession

*/

protected void closeSqlSession(SqlSession sqlSession) throws Exception {

try {

if (sqlSession != null) {

sqlSession.close();

sqlSession = null;

}

} catch (Exception e) {

}

}

}

org.sky.ssi.ibatis.IBatisTransaction


package org.sky.ssi.ibatis;

import java.sql.Connection;

import java.sql.SQLException;

import javax.sql.DataSource;

import org.apache.ibatis.transaction.Transaction;

import org.springframework.jdbc.datasource.DataSourceUtils;

public class IBatisTransaction implements Transaction{

private DataSource dataSource;

private Connection connection;

public IBatisTransaction(DataSource dataSource, Connection con, boolean autoCommit){

this.dataSource = dataSource;

this.connection = con;

}

public Connection getConnection(){

return connection;

}

public void commit()

throws SQLException{ }

public void rollback()

throws SQLException{ }

public void close()

throws SQLException{

if(dataSource != null && connection != null){

DataSourceUtils.releaseConnection(connection, dataSource);

}

}

}

org.sky.ssi.ibatis.IBatisTransactionFactory


package org.sky.ssi.ibatis;

import java.sql.Connection;

import java.util.Properties;

import javax.sql.DataSource;

import org.apache.ibatis.transaction.Transaction;

import org.apache.ibatis.transaction.TransactionFactory;

public class IBatisTransactionFactory implements TransactionFactory{

private DataSource dataSource;

public IBatisTransactionFactory(DataSource dataSource){

this.dataSource = dataSource;

}

public void setProperties(Properties properties){ }

public Transaction newTransaction(Connection connection, boolean flag){

return new IBatisTransaction(dataSource,connection,flag);

}

}

此三个类的作用就是在datasource.xml文件中描述的,把spring与datasource.xml中的datasource和transaction连接起来,此处尤其是“IBatis3SQLSessionFactoryBean”的写法,它通过spring中的“注入”特性,把iBatis的配置注入进spring并委托spring的context来管理iBatis(此属网上没有的资料,全部为本人在历年工程中的经验总结,并且已经在至少3个项目中进行了集成使用与相关测试)。

建立iBatis配置文件

我们先在/src/main/resources目录下建立一个叫sqlmap.xml的文件,内容如下:


<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE configuration PUBLIC "-//ibatis.apache.org//DTD Config 3.0//EN" "http://ibatis.apache.org/dtd/ibatis-3-config.dtd">

<configuration>

<mappers>

<mapper resource="ibatis/index.xml" />

<mapper resource="ibatis/login.xml" />

</mappers>

</configuration>

然后我们在/src/main/resources 目录下建立index.xml与login.xml这2个xml文件。

通向架构师的道路(第二十天)万能框架spring(二)maven结合spring与ibatis

看到这儿,有人会问了:为什么不把这两个xml文件也建立在spring目录下?

原因很简单:

在datasource.xml文件内我们已经通过


<bean id="iBatisSessionFactory" class="org.sky.ssi.ibatis.IBatis3SQLSessionFactoryBean" scope="singleton">

<property name="configLocation" value="sqlmap.xml"></property>

<property name="dataSource" ref="dataSource"></property>

</bean>

这样的方式把iBatis委托给了spring,iBatis的核心就是这个sqlmap.xml文件了,而在这个sqlmap.xml文件已经引用了login.xml与index.xml文件了。

而我们的web.xml文件里有这么一句:


<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>/WEB-INF/classes/spring/**/*.xml</param-value>

</context-param>

因此如果我们再把ibatis/index.xml与ibatis/login.xml再建立到src/main/resources/spring目录下,spring于是会在容器启动时试图加载这两个xml文件,然后一看这两个xml文件不是什么spring的bean,直接抛错,对吧?

其们等一会再来看login.xml文件与index.xml文件,我们先来搞懂iBatis调用原理.

3.4 iBatis调用原理

1)iBatis就是一个dao层,它又被称为sqlmapping,它的sql是书写在一个.xml文件内的,在该xml文件内会将相关的sql绑定到相关的dao类的方法。

2)在调用结束时我们需要在finally块中关闭相关的sql调用。

我们来看一个例子。

login.xml文件


<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE mapper

PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN"

"http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">

<mapper namespace="org.sky.ssi.dao.LoginDAO">

<select id="validLogin" resultType="int" parameterType="java.util.Map">

<![CDATA[

SELECT count(1) from t_login where login_id= #{loginId} and login_pwd=#{loginPwd}

]]>

</select>

</mapper>

该DAO指向了一个接口org.sky.ssi.dao.LoginDAO,该dao接受一个sql,并且接受一个Map类型的参数。

那么我们来看该DAO

LoginDao.java


package org.sky.ssi.dao;

import java.util.Map;

public interface LoginDAO {

public int validLogin(Map<String, Object> paraMap) throws Exception;

}

LoginImpl.java


package org.sky.ssi.dao.impl;

import java.util.Map;

import org.apache.ibatis.session.SqlSession;

import org.sky.ssi.dao.LoginDAO;

import org.sky.ssi.ibatis.IBatisDAOSupport;

import org.springframework.stereotype.Repository;

@Repository

public class LoginDAOImpl extends IBatisDAOSupport<LoginDAO> implements LoginDAO {

public int validLogin(Map<String, Object> paraMap) throws Exception {

SqlSession session = this.getSqlSession();

try {

return this.getMapper(LoginDAO.class, session).validLogin(paraMap);

} catch (Exception e) {

log.error(e.getMessage(), e);

throw new Exception(e);

} finally {

this.closeSqlSession(session);

}

}

}

很简单吧,一切逻辑都在xml文件内。

一定记得不要忘了在finally块中关闭相关的sql调用啊,要不然将来工程出了OOM的错误不要怪我啊.

3.5 index模块

Index.xml文件


<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE mapper

PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN"

"http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">

<mapper namespace="org.sky.ssi.dao.StudentDAO">

<select id="getAllStudent" resultType="org.sky.ssi.dbo.StudentDBO">

<![CDATA[

SELECT student_no studentNo, student_name studentName from t_student

]]>

</select>

<update id="addStudent" parameterType="java.util.Map">

insert into t_student(student_no, student_name)values(seq_student_no.nextval,#{stdName})

</update>

<update id="delStudent" parameterType="java.util.Map">

delete from t_student where student_no=#{stdNo}

</update>

</mapper>

它指向了StudentDAO这个接口

StudentDAO.java


package org.sky.ssi.dao;

import org.sky.ssi.dbo.StudentDBO;

import org.sky.ssi.student.form.*;

import java.util.*;

public interface StudentDAO {

public List<StudentDBO> getAllStudent() throws Exception;

public void addStudent(Map<String, Object> paraMap) throws Exception;

public void delStudent(Map<String, Object> paraMap) throws Exception;

}

StudentDAOImpl.java


package org.sky.ssi.dao.impl;

import java.util.List;

import java.util.Map;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

import org.apache.ibatis.session.SqlSession;

import org.sky.ssi.dao.StudentDAO;

import org.sky.ssi.ibatis.IBatisDAOSupport;

import org.sky.ssi.dbo.StudentDBO;

import org.springframework.stereotype.Repository;

@Repository

public class StudentDAOImpl extends IBatisDAOSupport<StudentDAO> implements StudentDAO {

@Override

public List<StudentDBO> getAllStudent() throws Exception {

SqlSession session = this.getSqlSession();

try {

return this.getMapper(StudentDAO.class, session).getAllStudent();

} catch (Exception e) {

throw new Exception(e);

} finally {

this.closeSqlSession(session);

}

}

public void addStudent(Map<String, Object> paraMap) throws Exception {

SqlSession session = this.getSqlSession();

try {

this.getMapper(StudentDAO.class, session).addStudent(paraMap);

} catch (Exception e) {

throw new Exception(e);

} finally {

this.closeSqlSession(session);

}

}

public void delStudent(Map<String, Object> paraMap) throws Exception {

SqlSession session = this.getSqlSession();

try {

this.getMapper(StudentDAO.class, session).delStudent(paraMap);

} catch (Exception e) {

throw new Exception(e);

} finally {

this.closeSqlSession(session);

}

}

}

3.6 Service接口微微有些改变

为了演示给大家看 iBatis接受多个参数的例子因此我们把原来的如:login(String loginId, String loginPwd)这样的方法改成了public int validLogin(Map<String, Object> paraMap) throws Exception;这样的结构,请大家注意。

四、beta工程中的增加功能

4.1 增加了一个filter

在我们的web.xml文件中


<filter>

<filter-name>LoginFilter</filter-name>

<filter-class>org.sky.ssi.filter.LoginFilter</filter-class>

<init-param>

<param-name>exclude</param-name>

<param-value>/jsp/login/login.jsp,

/login.do

</param-value>

</init-param>

</filter>

<filter-mapping>

<filter-name>LoginFilter</filter-name>

<url-pattern>*.jsp</url-pattern>

</filter-mapping>

<filter-mapping>

<filter-name>LoginFilter</filter-name>

<url-pattern>/servlet/*</url-pattern>

</filter-mapping>

<filter-mapping>

<filter-name>LoginFilter</filter-name>

<url-pattern>*.do</url-pattern>

</filter-mapping>

有了这个filter我们就不用在我们的web工程中每一个action、每 个jsp里进行“用户是否登录”的判断了,它会自动根据配置除去“exclude”中的相关web resource,全部走这个“是否登录”的判断。

注意此处这个exclude是笔者自己写的,为什么要exclude?

如果你不exclude,试想一个用户在login.jsp中填入相关的登录信息后点一下login按钮跳转到了login.do,而这两个web resource由于没有被“排除”出“需要登录校验”,因此每次你一调用login.jsp, login.do这个filter就都会强制要求你再跳转到login.jsp,那么我们一个用户从login.jsp登录完后再跳回login.jsp再跳回,再跳回,如此重复,进入死循环。

4.2 增加了一个自动记录异常的日志功能

在我们的applicationContext.xml文件中


<bean

id="methodLoggerAdvisor"

class="org.sky.ssi.util.LoggerAdvice" >

</bean>

<aop:config>

<aop:aspect

id="originalBeanAspect"

ref="methodLoggerAdvisor" >

<aop:pointcut

id="loggerPointCut"

expression="execution(* org.sky.ssi.service.impl.*.*(..))" />

<aop:around

method="aroundAdvice"

pointcut-ref="loggerPointCut" />

</aop:aspect>

</aop:config>

这样,我们的dao层、service层、有错就只管往外throw,框架一方面在接到相关的exception会进行数据库事务的自动回滚外,还会自动把service层抛出的exception记录在log文件中。

五、测试我们的工程

确认我们的StudentServiceImpl中删除学生的delStudent方法内容如下:


public void delStudent(String[] stdNo) throws Exception {

for (String s : stdNo) {

Map<String, Object> paraMap = new HashMap<String, Object>();

paraMap.put("stdNo", s);

studentDAO.delStudent(paraMap);

throw new Exception("force system to throw a exception");

}

}

我们把beta工程添加入我们在eclipse中配好的j2eeserver中去并启动起来。

通向架构师的道路(第二十天)万能框架spring(二)maven结合spring与ibatis

在IE中输入:http://localhost:8080/beta/index.do。 系统直接跳到login界面

通向架构师的道路(第二十天)万能框架spring(二)maven结合spring与ibatis

我们输入相关的用户名写密码。

通向架构师的道路(第二十天)万能框架spring(二)maven结合spring与ibatis

我们选中“13号学生高乐高”与“9号学生”,点“deletestudent”按钮。

通向架构师的道路(第二十天)万能框架spring(二)maven结合spring与ibatis

后台抛错了,查看数据库内的数据

通向架构师的道路(第二十天)万能框架spring(二)maven结合spring与ibatis

数据还在,说明我们的iBatis的事务已经在spring中启作用了.

再次更改StudentServiceImpl.java类中的delStudent方法,把“throw new Exception("force system to throw a exception");”注释掉,再来运行

通向架构师的道路(第二十天)万能框架spring(二)maven结合spring与ibatis

我们再次选 中9号和13号学生,点deletestudent按钮,删除成功,这个够13的人终于被删了,呵呵。

相关文章
  • 通向架构师的道路(第二十天)万能框架spring(二)maven结合spring与ibatis 2015-01-15

    一.前言 上次讲了Struts结合Spring并使用Spring的JdbcTemplate来搭建工程框架后我们面临着jar库无法管理,工程发布不方便,jar包在工程内太占空间,jar包冲突,管理,甚至漏包都问题.于是我们在讲"万能框架spring(二)"前,传授了一篇番外篇,即讲利用maven来管理我们的jar库. 从今天开始我们将结合"万能框架spring(一)"与番外篇maven来更进一步丰富我们的ssx框架,那么今天讲的是使用iBatis3结合SS来构建我们的

  • 通向架构师的道路(第十八天)万能框架Spring(一)(转) 2013-03-14

    一.前言 前一阵列刚换了个新的工作环境,然后自己的baby也刚出生,一直没有时间去做工作以后的其它事了,担搁了一段日子. 今天儿子满一周了,我内人她家帮着照顾着,总算我可以喘口气休息一下,因此决定将这个系列的博文继续下去,同时也将此篇献给我刚出生一周的儿子和幸苦了10个月的爱人. 二.基本概念 Spring,作为一个流行框架它给我们在日常工程中的框架搭建提供了太多的便利了,它就像一个骨架一样,你可以在上面自己去塑出肌肤与血肉并赋于它灵魂. 从今天开始我们将要连续几天基于Spring的基础上来讲软

  • 通向架构师的道路(第十八天)万能框架Spring(一) 2015-01-15

    一.前言 前一阵列刚换了个新的工作环境,然后自己的baby也刚出生,一直没有时间去做工作以后的其它事了,担搁了一段日子. 今天儿子满一周了,我内人她家帮着照顾着,总算我可以喘口气休息一下,因此决定将这个系列的博文继续下去,同时也将此篇献给我刚出生一周的儿子和幸苦了10个月的爱人. 二.基本概念 Spring,作为一个流行框架它给我们在日常工程中的框架搭建提供了太多的便利了,它就像一个骨架一样,你可以在上面自己去塑出肌肤与血肉并赋于它灵魂. 从今天开始我们将要连续几天基于Spring的基础上来讲软

  • 通向架构师的道路(第二十二天)万能框架spring(四)使用struts2 2015-01-15

    一.前言 SSH有了,现在我们要把我们的struts层从原来的1.3替换成struts2.x,引入了struts2.0后我们会发觉我们的代码和框架的变化还是不小的 二.Struts2的好处 1)在struts2的方法里,一切变量是线程安全的,而原有的struts1不是的; 2)在struts2中如果你声明了如下这样的代码: privater String studentName=""; public void setStudentName(String studentName){ th

  • 通向架构师的道路(第二十一天)万能框架spring(三)之SSH 2015-01-15

    一.前言 我们有了Spring+JdbcTemplate和Spring+iBatis并结合maven的基础,搭建一个SSX这样的框架现在就和玩一样的简单了,今天我们将搭建一个使用Struts1.3,Srping3, Hibernate3的SSH1的开发框架,大家跟着我一步步走,会发觉在程序跑通后自己再动手搭建一遍这个框架,只需要30分钟. 二.SSH框架 仔细看这个框架,稍微有点不一样了. 1) Spring3是通过一个hibernate template来和hibernate的dao层结合起来

  • 通向架构师的道路(第二十七天)IBM网格计算与企业批处理任务架构 2015-01-16

    一.批处理 我们在一些项目中如:银行.保险.零商业门店系统中的对帐.结帐.核算.日结等操作中经常会碰到一些"批处理"作业. 这些批处理经常会涉及到一些大数据处理,同时处理一批增.删.改.查等SQL,往往涉及到好几张表,这边取点数据那边写点数据,运行一些存储过程等. 批处理往往耗时.耗资源,往往还会用到多线程去设计程序代码,有时处理不好还会碰到内存泄漏.溢出.不够.CPU占用高达99%,服务器被严重堵塞等现象. 笔者曾经经历过一个批处理的3次优化,该批处理笔者按照数据库连接池的原理实现了

  • 通向架构师的道路(第二十三天)maven与ant的奇妙整合 2015-01-15

    一.前言 我们在<万能框架spring>前四天中都用到了maven,接下去要讲述在SSX这样的架构下我们的"单元测试"是怎么进行的,但是在此之前我们再来深入入解一下maven,因为我们的单元测试需要用到的是junit+ant+junitreport这样的组合.而......由于我们已经使用了maven,那么我们如何可以延续经典的junit+ant这样的单元测试的组合呢?其答案就是把maven和ant再进行组合一下. 二.用Maven任务在Ant中使用Maven依赖 Mave

  • 通向架构师的道路(第二十六天)漫谈架构与设计文档的写作技巧 2015-01-16

    前言: 这篇是一篇番外篇,没有太多代码与逻辑,完全是一种"软"技巧,但是它对于你如何成为一名合构的架构设计人员很重要. 在此要澄清一点,架构师本身也是"程序员",不是光动嘴皮子的家伙们,如果你不是一名程序虽出身那你根本谈不上也不可能成为一名架构师. 那么架构师还有哪些是作为一名程序员来说不具备的呢? 其中有一项能力就叫做"文档写作能力". 一.Soft Skill与Hard Skill 作为一名架构师除了是一名资深的程序员外,它还必须具有相应的S

  • 通向架构师的道路(第十九天)使用maven构建Spring工程 (转) 2013-03-16

    一.前言 上次大家拿了我上传的工程后,有些人自己通过spring3,struts1.3,hibernate3的download的包自行去装配jar包 到工程的WEB-INF\lib目录下.有些是通过我上传的alpha_lib包把里面的jar文件一股脑的copy到了工程的WEB-INF\lib目 录下去. 有时经常还会发生少包了,ClassNotFound这样的错误,或者是一些因为缺包还引起的各种莫名奇妙的错误,呵呵,是不是够折腾的啊? 尝过苦头了,才知道幸苦!那么我们有没有一种更好的方式,比如说

  • 通向架构师的道路(第一天)之Apache整合Tomcat 2015-01-13

    一.先从J2EE工程的通用架构说起 这是一个通用的Web即B/S工程的架构,它由: ü Web Server ü App Server ü DB Server 三大部分组成,其中: ² Web Server 置于企业防火墙外,这个防火墙,大家可以认为是一个CISCO路由器,然后在CISCO路由器上开放了两个端口为:80和443. 80端口:用于正常的http访问 443端口:用于https访问,即如果你在ie里打入https://xxx.xxx.xx这样的地址,默认 走的是443这个端口. We

  • 通向架构师的道路(第二天)之apache tomcat https应用 2015-01-13

    一.总结前一天的学习 在前一天的学习中我们知道.了解并掌握了Web Server结合App Server是怎么样的一种架构,并且亲手通过Apache的Http Server与Tomcat6进行了整合的实验. 这样的架构的好处在于: ü 减轻App Server端的压力,用Web Server来分压,即Web Server只负责处理静态HTML内容,而App Server专职负责处理Java请求,这对系统的performance是一个极大的提升. ü 安全,Web Server端没有任何Java源

  • 通向架构师的道路(第三天)之apache性能调优 2015-01-13

    一.总结前一天的学习 在前两天的学习中我们知道.了解并掌握了Web Server结合App Server实现单向Https的这样的一个架构.这个架构是一个非常基础的J2ee工程上线布署时的一种架构.在前两天的教程中,还讲述了Http服务器.App Server的最基本安全配置(包括单向https的实现), 它只是避免了用户可以通过浏览器侵入我们的Web访问器或者能够通过Web浏览器来查询我们的Web目录结构及其目录内的文件与相关内容,这种入侵我们把它称为: Directory traversal

  • 通向架构师的道路(第四天)之Tomcat性能调优-让小猫飞奔 2015-01-13

    一.总结前一天的学习 从"第三天"的性能测试一节中,我们得知了决定性能测试的几个重要指标,它们是: ü 吞吐量 ü Responsetime ü Cpuload ü MemoryUsage 我们也在第三天的学习中对Apache做过了一定的优化,使其最优化上述4大核心指标的读数,那么我们的Apache调优了,我们的Tomcat也作些相应的调整,当完成今的课程后,到时你的"小猫"到时真的会"飞"起来的,所以请用心看完,这篇文章一方面用来向那位曾写过&

  • 通向架构师的道路(第五天)之tomcat集群-群猫乱舞 2015-01-13

    一.为何要集群 单台App Server再强劲,也有其瓶劲,先来看一下下面这个真实的场景. 当时这个工程是这样的,tomcat这一段被称为web zone,里面用spring+ws,还装了一个jboss的规则引擎Guvnor5.x,全部是ws没有service layer也没有dao layer. 然后App Zone这边是weblogic,传输用的是spring rmi,然后App Zone这块全部是service layer, dao layer和数据库打交道. 用户这边用的是.net,以w

  • 通向架构师的道路(第八天)之weblogic与apache的整合与调优 2015-01-13

    一.BEAWeblogic的历史 BEA WebLogic是用于开发.集成.部署和管理大型分布式Web应用. 网络应用和数据库应 用的Java应用服务器.将Java的动态功能和Java Enterprise标准的安全性引入大型网络应用的 开发.集成.部署和管理之中. BEA WebLogic Server拥有处理关键Web应用系统问题所需的性能 .可扩展性和高可用性. 与BEA WebLogic Commerce ServerTM配合使用, BEA WebLogicServer可为部署适应性个性

  • 通向架构师的道路(第十九天)使用maven构建Spring工程 2015-01-15

    一.前言 上次大家拿了我上传的工程后,有些人自己通过spring3,struts1.3,hibernate3的download的包自行去装配jar包到工程的WEB-INF\lib目录下.有些是通过我上传的alpha_lib包把里面的jar文件一股脑的copy到了工程的WEB-INF\lib目录下去. 有时经常还会发生少包了,ClassNotFound这样的错误,或者是一些因为缺包还引起的各种莫名奇妙的错误,呵呵,是不是够折腾的啊? 尝过苦头了,才知道幸苦!那么我们有没有一种更好的方式,比如说:

  • 通向架构师的道路(第二十五天)SSH的单元测试与dbunit的整合 2015-01-15

    一.前言 在二十三天中我们介绍了使用maven来下载工程的依赖库文件,用ant来进行war包的建立.今天我们在这个基础上将使用junit+dbunit来进行带有单元测试报告的框架的架构. 目标: 每次打包之前自动进行单元测试并生成单元测试报告 生成要布署的打包文件即war包 单元测试的代码不能够被打在正式的要布署的war包内,单元测试仅用于unit test用 使用模拟数据对dao层进行测试,使得dao方法的测试结果可被预料 二.Junit+Ant生成的单元测试报告 上面是一份junit生成的测

  • 通向架构师的道路(第六天)之漫谈基于数据库的权限系统的设计 2015-01-13

    一.权限系统 这一天将讲述一个基本的基于数据库的权限管理系统的设计,在这一天的课程的最后将讲述"左右值无限分类实现算法"如何来优化"系统菜单"的结构而告终.今天的内容和前几天的基础框架是一样的它们都属于基础知识,在这些基础知识上还可以扩展出无数的变种与进化设计. 二.先来看客户的一个需求 2.1 用户实际需求 1. 所有的用户.角色可动态配置 2. 所有的系统菜单的权限要求具体到"增,删,改.查.打印.导出"这样的小权限的设计 3. 所有的权限基

  • 通向架构师的道路(第七天)之漫谈使用ThreadLocal改进你的层次的划分 2015-01-13

    一.什么是ThreadLocal 早在JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路.使用这个工具类可以很简洁地编写出优美的多线程程序. ThreadLocal很容易让人望文生义,想当然地认为是一个"本地线程".其实,ThreadLocal并不是一个Thread,而是Thread的局部变量,也许把它命名为ThreadLocalVariable更容易让人理解一些. 当使用ThreadLocal维护

  • 通向架构师的道路(第九天)之weblogic的集群与配置 2015-01-14

    一.Weblogic的集群 还记得我们在第五天教程中讲到的关于Tomcat的集群吗? 两个tomcat做node即tomcat1, tomcat2,使用Apache HttpServer做请求派发. 现在看看WebLogic的集群吧,其实也差不多. 区别在于: ² Tomcat的集群的实现为两个物理上不同的tomcat,分别就是两个node,没有总控端,没有任何控制台可言(只有通过比较简陋的http://localhost:8080/manager/html,或者是http://localhos