Spring揭秘-第13章 统一的数据访问异常层次体系

Spring揭秘-第13章 统一的数据访问异常层次体系 DAO可以分离数据哭的访问和存储,屏蔽各种数据访问方式的差异性,下面以访问顾客信息为例,使用DAO模式 首先定义一个数据访问对象接口,如下 public interrface ICustomerDao{ Customer findCustomerByPK(String customerId); void updateCustomerStatus(Customer customer);   之后,所有的数据访问都通过该接口进行,不论底层存储机制如何改变,DAO的实现因此会扩展,但客户端代码不需要调整 客户端要用的时候这样使用即可。 publicclassCustomerService { privateICustomerDao customerDao; publicvoid disableCustomerCampain(String customerId) { Customer customer=getCustomerDao().findCustomerByPK(customerId); customer.setCampainStatus(CampainStatus.DISABLE); getCustomerDao().updateCustomerStatus(customer); } publicICustomerDao getCustomerDao() { return customerDao; } publicvoid setCustomerDao(ICustomerDao customerDao) { this.customerDao=customerDao; }   我们只要针对不同的数据存储方式实现不同的Dao类即可。 我们开始实现具体的访问数据了。 publicCustomer findCustomerByPK(String customerId) { Connection con=null; try{ con=getDataSource().getConnection(); Customer cust=..; return cust; } catch(SQLException e){ //这里咋办,直接抛出还是直接处理? } finally{ releaseConnection(con); } } privatevoid releaseConnection(Connection con){ }   SQLException 是checked exception,如果在DAO的实现类里直接处理掉,那么客户端怎么知道发生了问题, 于是,只能处理,那么客户端的签名就要改了 <span class="typ">Customer</span><span class="pln"> findCustomerByPK</span><span class="pun">(</span><span class="typ">String</span><span class="pln"> customerId</span><span class="pun">)</span><span class="kwd">throws</span><span class="typ">SQLExcepiton</span><span class="pun">;</span> ICustomerDao也要改了,可是这样的话 如果数据在其他方式存储,那么其他类型的异常捕获就要继续添加到方法签名。由于数据访问机制的不同,导致这个接口签名不断在变化。 那怎么办呢?DAO如此美好的远景。 直接抛出,的话,因此,可以根据发生的异常信息封装成不同的unchecked exception,然后抛出,这样方法签名不用改。因为unchecked不需要编译器检查。 要开始写了?Spring的数据访问异常层次体系已经给我们做完了 该体系下面所有的异常类型均以DataAccessException为统领,然后划分成不同的子类型 ![](/images/3ab324530a8c3d0b0216d3f7549ebbfa6b7869f4.jpg) 这些类是啥搜索一下,或者根据名字猜一下,之后我们就可以

2014-07-13 · 1 min · bystander

Spring揭秘-第四章BeanFactory笔记

之前说了,IoC容器就是一个IoC Service Provider,但是容器是个啥意思?![](/images/d4d1615a6c1a06895088631c37e3fca7692f0b8a.png) 可以看到IoC容器提供了更多的内容, Spring的IoC容器又分成两种, 1.BeanFactory 。基础类型IoC容器,提供完整的IoC服务支持。如果没有特殊指定,默认采用延 迟初始化策略(lazy-load)。只有当客户端对象需要访问容器中的某个受管对象的时候,才对 该受管对象进行初始化以及依赖注入操作。所以,相对来说,容器启动初期速度较快,所需 要的资源有限。对于资源有限,并且功能要求不是很严格的场景,BeanFactory是比较合适的 IoC容器选择。 2.ApplicationContext。ApplicationContext在BeanFactory的基础上构建,是相对比较高 级的容器实现,除了拥有BeanFactory的所有支持,ApplicationContext还提供了其他高级特性,比如事件发布、国际化信息支持等,这些会在后面详述。ApplicationContext所管理 的对象,在该类型容器启动之后,默认全部初始化并绑定完成。所以,相对于BeanFactory来 说,ApplicationContext要求更多的系统资源,同时,因为在启动时就完成所有初始化,容 器启动时间较之BeanFactory也会长一些。在那些系统资源充足,并且要求更多功能的场景中, ApplicationContext类型的容器是比较合适的选择。 通过 图4-2,我们可以对BeanFactory和ApplicationContext之间的关系有一个更清晰的认识。 ![](/images/f531ea3e11bb391453eb5f763283398c938634b2.png) Bean工长,就是生成Bean的嘛,每个业务对象被看成Javabean,我们与工厂打交道就简单得多,我们只要告诉他我要什么对象,至于怎么组装,那是他的事情。 工厂提供了一些对外的接口,比如获取Bean,渠道Bean的状态等等。 以xml为例 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="djNewsProvider" class="..FXNewsProvider"> <constructor-arg index="0"> <ref bean="djNewsListener"/> </constructor-arg> <constructor-arg index="1"> <ref bean="djNewsPersister"/> </constructor-arg> </bean> <bean id="djNewsListener" class="..impl.DowJonesNewsListener"> </bean> <bean id="djNewsPersister" class="..impl.DowJonesNewsPersister"> </bean> </beans> 然后 public static void main(String[] args) { DefaultListableBeanFactory beanRegistry = new DefaultListableBeanFactory(); BeanFactory container = (BeanFactory)bindViaXMLFile(beanRegistry); FXNewsProvider newsProvider = (FXNewsProvider)container.getBean("djNewsProvider"); newsProvider.getAndPersistNews(); } public static BeanFactory bindViaXMLFile(BeanDefinitionRegistry registry) { XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(registry); reader.loadBeanDefinitions("classpath:../news-config.xml"); return (BeanFactory)registry; // 或者直接 //return new XmlBeanFactory(new ClassPathResource("../news-config.xml")); } 人生好像就美好

2014-07-13 · 1 min · bystander

Spring揭秘-第三章IoC Service Provider读书笔记

我们虽然已经通过IoC声明了相应的依赖,但是最终总要有个啥东西将这些依赖对象绑定在一起,这里而IoC Service Provider, 来啦,表示一种绑定的实现方式,可以使一段代码,也可以是一组相关的泪,甚至是框架或容器。 比如前一篇提到的 IFXNewsListener newsListener = new DowJonesNewsListener(); IFXNewsPersister newsPersister = new DowJonesNewsPersister(); FXNewsProvider newsProvider = new FXNewsProvider(newsListener,newsPersister); newsProvider.getAndPersistNews();   就是一个容器,只不过太简单了,不适用于更多的场景, IoC容器就是Spring提供依赖注入服务的Provider IoC Service Provider 是干嘛? 1.业务对象的构建管理,剥离客户端对象的构建的依赖逻辑,比如A引用B,那么A是B的客户端对象,容器需要理清这种关系。 2.业务对象之间的依赖绑定,通过1的实现, 识别各个对象的依赖关系,然后将这些对象依赖的对象注入绑定,用的时候就有了。 那你要问了,这怎么管理对象间的依赖关系呢 IoC Service Provider怎么就能完全领会代码的意图呢?他怎么记住这么多的依赖关系等等,他要这么做 1.元数据方式 2.通过描述性较强的xml来记录对应信息 3.通过编写代码的方式注册这些信息 3.直接编码方式, 明确了依赖关系 IoContainer container = ...; container.register(FXNewsProvider.class,new FXNewsProvider()); container.register(IFXNewsListener.class,new DowJonesNewsListener()); ... FXNewsProvider newsProvider = (FXNewsProvider)container.get(FXNewsProvider.class); newProvider.getAndPersistNews();   2.配置文件方式 最常见的还是xml方式, <bean id="newsProvider" class="..FXNewsProvider"> <property name="newsListener"> <ref bean="djNewsListener"/> </property> <property name="newPersistener"> <ref bean="djNewsPersister"/> </property> </bean> <bean id="djNewsListener" class="..impl.DowJonesNewsListener"> </bean> <bean id="djNewsPersister" class="..impl.DowJonesNewsPersister"> </bean> 然后我们要用的时候 container.readConfigurationFiles(...); FXNewsProvider newsProvider = (FXNewsProvider)container.getBean("newsProvider"); newsProvider.getAndPersistNews(); 容器读取配置文件,然后取到其中的两个类,注入进来。 1.元数据方式 代表实现Java Guide,基于java注解,在类中直接使用元数据信息来标注 各个对象之间的依赖关系。然后框架根据信息组装之后交给客户端对象使用 这种方式重写我们的例子就是 public class FXNewsProvider { private IFXNewsListener newsListener; private IFXNewsPersister newPersistener; @Inject public FXNewsProvider(IFXNewsListener listener,IFXNewsPersister persister) { this.newsListener = listener; this.newPersistener = persister; } ... } 通过 @Inject,我们指明需要IoC Service Provider通过构造方法注入方 余下的部分由Guide提供的Module完成,我们继承一下。 public class NewsBindingModule extends AbstractModule { @Override protected void configure() { bind(IFXNewsListener.class) .to(DowJonesNewsListener.class).in(Scopes.SINGLETON); bind(IFXNewsPersister.class).to(DowJonesNewsPersister.class).in(Scopes.SINGLETON); } } 最后,要用的时候,直接来拿吧。 Injector injector = Guice.createInjector(new NewsBindingModule()); FXNewsProvider newsProvider = injector.getInstance(FXNewsProvider.class); newsProvider.getAndPersistNews();  

2014-07-13 · 1 min · bystander

《Spring揭秘》读书笔记-第二章IoC的基本概念

理念就是让别人为你服务,中文名控制反转,也叫依赖注入DI public class FXNewsProvider { private IFXNewsListener newsListener; private IFXNewsPersister newPersistener; public void getAndPersistNews() { String[] newsIds = newsListener.getAvailableNewsIds(); if(ArrayUtils.isEmpty(newsIds)) { return; } for(String newsId : newsIds) { FXNewsBean newsBean = newsListener.getNewsByPK(newsId); newPersistener.persistNews(newsBean); newsListener.postProcessIfNecessary(newsId); } } } 假设这个类用来处理新闻, IFXNewsListener 用来获取新闻, IFXNewsPersister 用来把获取的新闻持久化 当我们需要获取不同的新闻源,比如道琼斯的新闻时,我们会写一个 DowJonesNewsListener 类和 DowJonesNewsPersister 类,然后实例化 public FXNewsProvider() { newsListener = new DowJonesNewsListener(); newPersistener = new DowJonesNewsPersister(); } 如果我们依赖于某个类或服务,最简单而有效的方式就是直接 在类的构造函数中新建相应的依赖类。 注意看, ,我们都是自己主动地去获 取依赖的对象! 可是回头想想,我们自己每次用到什么依赖对象都要主动地去获取,这是否真的必要?我们最终 所要做的,其实就是直接调用依赖对象所提供的某项服务而已 能不能我们用的时候自动送过来呢? 。现在是用什么,让别人直接送过来就成。所以,简单点儿说, IoC 的理念就是, 让别人为你服务!在图 2-1 中,也就是让 IoC Service Provider 来为你服务! ...

2014-07-01 · 2 min · bystander

《Spring揭秘》读书笔记-第一章Spring框架的由来

1.框架的由来 倡导J2EE轻量级应用解决方案 框架总结结构 整个Spring架构建立在Core核心模块上,是基础,该模块中,有一个IoC容器的实现,用来以依赖注入的方式管理对象之间的依赖关系。Core中还有一些气筒工具类,比如IO工具类 从图中看到,AOP模块,提供了轻便二强大的AOP框架,一AOP的形式增强POJO的能力,弥补OOP/OOSD的不足,采用Proxy模式,与IoC容器相结合 继续向上看,在Core和AOP之上,提供了完毕的数据访问和事务管理的抽象,其中,对JDBC API的最佳实践简化了API的使用,还未ORM产品提供了统一的支持, 为了简化Java EE的服务,比如JNDI,JMS等等,Spring还提供了这些的集成服务, 最后就是Web模块,提供了一套自己的Web MVC框架,上层模块依赖于下层模块,水平之间的模块彼此基本可以认为独立。 Spring不仅仅是容器,更是开发任何Java应用的框架, Spring 框架之上衍生的产品包括不限于Spring Web Flow,Spring Web Services,Spring Security,Spring Integration,Spring Rich Client 等等等等

2014-06-30 · 1 min · bystander

burpsuite抓包https

最近工作需要,需要burpsuite抓下https的包 burpsuite抓包https的时候,如果是https协议,火狐会不信任证书 这个时候点击我已充分了解可能的风险,然后添加例外,弹出图中的对话框 点击查看,进入证书管理企业免,选择图中的PortSwigger CA根证书,选择导出,保存一下这个证书 然后打开火狐的选项,进入高级->证书->查看证书->证书机构->导入,选择刚才的证书 ,最后,记住选中信任此CA证书标识的网站,ok 现在再抓包,可以看到https也抓到了。

2014-06-29 · 1 min · bystander

8583报文相关

以下是我在学习的时候发现的好的资料,都是非常有帮助的。 如果你想知道原理,看完下面这篇就会了 [藏]轻松掌握ISO8583报文协议原理 看了原理之后还想知道怎么来的。手工联系一下 谈谈8583报文的使用及测试 这篇文章不错 看完了想写代码了,可以看看这篇文章,基本上不能直接拿来用,但是可以参考实现 ISO8583报文工具类(组装和解析报文) 看完之后这里还有一些补充 ISO-8583协议的简要说明 最后,http://www.jpos.org/这个库基本可以用来做这个事情。 Jimmy写了一个例子非常好,iso-8583-tutorial-build-and-parse-iso-message-using-jpos-library,至于银联的那个规范搜一下。

2014-06-27 · 1 min · bystander

构建数据库连接的配置方法

以前我在写数据库连接的时候,都是在文件里写死的,或者一个简单地配置文件,只有一个数据库连接嘛,但是最近写一个测试工具的时候,需要很多数据库,而且有些还有分库规则,于是查找资料,完善了两个类,和xml的定义规则,分享出来。仅供参考,有任何指教请回复。不胜感谢 首先xml的配置格式定义如下 <?xml version="1.0" encoding="UTF-8"?> <config> <db-info> <id>oracle-test</id> <driver-name>oracle.jdbc.driver.OracleDriver</driver-name> <url>jdbc:oracle:thin:@127.0.0.1:1521:test</url> <user-name>admin</user-name> <password>admin</password> </db-info> <db-info> <id>mysql-test</id> <driver-name>com.mysql.jdbc.Driver</driver-name> <url>jdbc:mysql://127.0.0.1:3306</url> <user-name>root</user-name> <password>root</password> </db-info> </config> 然后我们有XmlConfigReader类,用来读取这个配置文件,并且返回对应的jdbcConfig对象。 这个对象就是一个model类,对应xml的属性 然后我们的DBUtil类会调用XmlConfigReader,通用的一般是传个 <id>mysql-test</id> 值,然后XmlConfigReader来读取返回,对象,然后在DBUtil里用这个对象得知来构造连接,我添加了一个简单的方法 public static Connection getConnection(String dbId,String dbName) throws ClassNotFoundException { Connection conn = null; try { //新建jdbc配置类。 XmlConfigReader xcr=new XmlConfigReader(); JdbcConfig jdbcconfig = xcr.getConnection(dbId,dbName); Class.forName(jdbcconfig.getDriverName()); //取得连接对象。 conn = DriverManager.getConnection(jdbcconfig.getUrl(), jdbcconfig.getUserName(), jdbcconfig.getPassword()); } catch (ClassNotFoundException e) { // 抛出 exception e.printStackTrace(); }catch(SQLException e) { e.printStackTrace(); } return conn; } 就是多传一个数据库名 然后XmlConfigReader哩对应有这个方法 //分库分表使用 public JdbcConfig getConnection(String dbId,String dbName) { SAXReader reader = new SAXReader(); // 拿到当前线程。 InputStream in = Thread.currentThread().getContextClassLoader() .getResourceAsStream("sys-config.xml"); try { Document doc = reader.read(in); Element rootElt = doc.getRootElement(); // 获取根节点 Iterator<?> iter = rootElt.elementIterator("db-info"); while (iter.hasNext()) { Element recordEle = (Element) iter.next(); String title: = recordEle.elementTextTrim("id"); if (title.equalsIgnoreCase(dbId)) { jdbcconfig.setDriverName(recordEle .elementTextTrim("driver-name")); jdbcconfig.setUrl(recordEle.elementTextTrim("url")+"/"+dbName); jdbcconfig.setUserName(recordEle .elementTextTrim("user-name")); jdbcconfig.setPassword(recordEle .elementTextTrim("password")); } } } catch (DocumentException e) { // 打印错误 e.printStackTrace(); } return jdbcconfig; } ...

2014-04-26 · 1 min · bystander

Google输入法和Java不兼容

一直发现自己写的Swing界面无法关闭,症状是点击了界面的关闭按钮后程序会卡住,然后点击无响应最后就挂掉了。 最开始以为是自己的资源没释放,但是没理由呀,应该在关闭的时候会自动释放,而且改了代码也没用。 今天再执行另一个Swing的时候,eclipse报错了 # # A fatal error has been detected by the Java Runtime Environment: # # EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x6d986cc3, pid=700, tid=2280 # # JRE version: Java(TM) SE Runtime Environment (7.0_45-b18) (build 1.7.0_45-b18) # Java VM: Java HotSpot(TM) Client VM (24.45-b08 mixed mode, sharing windows-x86 ) # Problematic frame: # C [GOOGLEPINYIN2.IME+0x96cc3] # # Failed to write core dump. Minidumps are not enabled by default on client versions of Windows 看问题说是Google拼音输入法冲突,导致访问禁止,在PChunder里卸载掉javaw的Google拼音模块,javaw马上就关闭了,于是修改系统的默认输入法为其他输入法问题解决。 我了个去,纠结了我好长时间。我说为啥公司电脑和我的电脑都会关不了呢…

2014-03-29 · 1 min · bystander

linux编写定时任务

linux中定时任务用来执行一些周期性的自动化的任务,比如有些人可能用来定期备份,也可能是定期检查一下特殊文件的签名,如果不一致,就报警,检测入侵。 cron是linux下的定时执行工具 这个工具的几个命令是这样的 /sbin/service crond start //启动服务 /sbin/service crond stop //关闭服务 /sbin/service crond restart //重启服务 /sbin/service crond reload //重新载入配置 注意,这几个服务都是要以root权限才能运行的,很多时候,只要我们可能只是一个低权限的用户,那么我们要执行一些定时任务的时候,可以这样做 直接通过这个命令来编辑,无需root用户 crontab 首先添加定时任务 crontab -e 打开之后按如下的格式编写 */1 * * * * ls >> /tmp/ls.txt 从左到右一次表示 分钟 一小时的第几分 0-59 小时 一天的第几小时 0-23 日期 一个月的的第几天 1-31 月份 一年的第几个月 1-12 周几 一周的第几天 0-6 /1表示每一天 /2表示每两天,直接*的话就表示每天/每小时这样 写完之后,wq保存退出 然后 crontab -l //列出当前的所有调度任务 可以看到自己的定时任务了,然后就不要做什么操作了,操作系统定时会读取配置的,编辑完成之后,我们的定时任务过一会就会生效了。 有时候,可能还要把结果信息和一些错误信息也写入 30 5 * * * ls >>/result/test 2>&1 注:2>&1 表示执行结果及错误信息。 这里就是说明天的5点50执行一次ls命令,并把结果追加到文件 如果我想每天5点30和17点30都执行一次呢,使用逗号隔开就行了 30 5,17 * * * ls >>/result/test 2>&1 如果是某个时间段呢 30 5-17 * * * ls >>/result/test 2>&1 这样5-17点钟的每个30分到会执行 如果是一些特殊的时间点,那么有更简单的方法,比如每月0点或者每天0点执行一次 @monthly ls >>/result/test 2>&1 @daily ls >>/result/test 2>&1 使用如上的关键字

2014-03-29 · 1 min · bystander