|
2012年2月11日
#
Physical to Virtual Machine by VMware vCenter ConverterJanuary 13, 2010 By Dinesh If you are trying to convert physical tovirtual machine and to be used in VMware workstation or Sun VirtualBox, then continue reading this article. VMware vCenter converter is being used to convert physical to virtual (P2V) to VMware ESX server. But you can use this converter to create VMDK and VMX files locally. When you want to convert physical tovirtual machine and use locally in VMware workstation or Sun VirtualBox, this method will help you lot. 
Follow the steps to create VMX and VMDK files by converting physical to virtual (P2V) in VMware vCenter Converter. 1) Download VMware vCenter Convert for Physical to Virtual (it’s completely free- registration required) 2) Complete the installation. 3) Open the converter, select ‘This local machine’. You can select remote computer also. You must have administrator privileges on remote computer to achieve this. 
Click on View Source details to make sure converter is reading your physical computer resources correctly. 4) Click next. In destination type select VMware workstation and choose your VMware product version where you will be running this virtual machine. 
Type a name for new virtual machine. If you will be connecting this physical machine and new virtual machine by networking, better to give separate name. Select the location for virtual machine. Make sure the location is having enough of disk space. It depends on your physical computer disk sizes and what disks you select to convert. 5) Click Next, this screen brings some more advanced option. Click on ‘Data to copy’ to choose the physical partitions to be included in conversion. Obviously, you can’t remove system or boot partitions from the list which will cause virtual machine booting problems. Target disks size in virtual machine is editable in this screen. 
6) Other options such as processors, disk types, memory size, network type and even running windows services also can be changed. Similar options are available when you convert by VMware workstation converter which is mentioned here. 7) Click Next and check the summery list as per your selection. Press Finish to start Physical to Virtual machine conversion by VMware vCenter Converter. Let the conversion complete. Status can be viewed as below. 
8) Unfortunately I didn’t allow completing due to space problem. But I did the same live physical to virtual conversation by VMware workstation converter, and opened virtual machine successfully.Read here for more information. 9) Once conversation is over, open the virtual machine in VMware workstation or VMware player. That’s it. Enjoy. Recommended Posts
| Is it possible to convert a Physical Ubuntu Install (Intel based PC with Ubuntu 10.10) to a virtual box disk, so that I can use that same environment on a separate pc or can keep it virtual for testing? Something similar to "Disk2VHD" which converts a physical Windows 2K3 and above box into a VHD or VMware image. Will be grateful for your assistance ! Kind Regards | feedback |
| Yes, however it will most likely take a very long time. I haven't actually tried the steps below, but they should work. First, you need to make an image of your entire partition. You need to know the partition path of the Ubuntu partition, for example /dev/sda1 would be the first partition on the first attached hard drive. sudo dd if=PART_PATH of=OUTPUT_PATH/ubuntu.bin
note that you should do the above command from a liveCD with the partition you are trying to copy unmounted -- i.e. you need to have another hard drive or something to copy all the data to. You can shut the liveCD down and boot back into Ubuntu to perform the last step: Convert the binary into a vbox drive: VBoxManage convertdd PATH_TO_ubuntu.bin ubuntu.vdi --format VDI
you can then use the resulting ubuntu.vdi as a Virtualbox drive. Just make sure you have plenty of time and hard drive space for this operation. A little tip: commandline tasks can be suspended by hitting The operation will go to sleep, and you can use you computer again. When you are interested in resuming the process, type fg in the terminal, and the operation will resume. Quite handy for long operations like this. |
P2V is a large subject to cover, as I cannot cover every scenario, so I am going to briefly cover a P2V conversion of an physical Ubuntu server I have kicking around. Many companies are trying to reduce there footprint and convert many physical machines into virtual ones, web servers, SMTP server are ideal candidates. The conversion is a two step process, the actual conversion and the cleanup process after you have created the VM. There are a number of 3rd party P2V converters including free ones but I will be using VMware own vCenter Converter to perform this task. Vware vCenter converter is a windows based application, that installs onto the vCenter management server, it fully supports both windows and linux conversions but you may want to check VMwareown website for all the available supported OS's. There are two versions of the converter available - Starter - is agent based and is free
- Enterprise - can be either be agent or can boot from a cd
VMware vCenter converter is not a silver bullet, you may have to work with the converted VM to get it working properly, also if the server originally had problems those problems may be replicated in the VM environment. The more complex the physical server (could be a domain control, cluster server, etc), the more you may have problems converting it and getting it to work, here is where you need to look at the VMware forums or search the internet for answers. Installing vCenter Converter Installing the vCenter converter is like a normal application installation, on the vCenter server start the installation by putting in the vCenter 4.1 cd, and then selecting vCenter Converter 
During the installation process, you will be asked about the vCenter management server details 
Once the installation has finished select the plugins -> manage-plugins from the top bar of the vCenter window, then select download and install plugin 
That's it, you are now ready to convert physical servers P2V Once you have the P2V plugin installed we can now import a physical server, I have a old HP D510 desktop PC with Ubuntu 32-bit OS running on it (yep old pc and old OS), lets convert this physical machine into a virtual machine. First select the ESXi server that you wish to import the new virtual machine into, in my case I have selected vmware01, right-click and select "import machine" 
Now enter the details of the running physical server, I selected "view source details", just to make sure the connection is working and we have access to the physical server 
All looks good, it see's my physical server as a Ubuntu 8.04 32-bit server 
The next screen, gives us details on where the VM will be placed, I changed the datastore to a shared storage area (filer2_ds1), you can change the name of the VM if you wish 
The screen allows us to configure the VM's hardware 
I notice that the network was in correct, so selected edit and changed the network from private to public and can add additional NIC's if you wish 
The "data to copy" screen allows us to select what volumes/filesystems we wish to copy across, there may be a case that you do not some volumes/filesystems copied and thus speed up the importing process. 
With very little effort we are at the summary screen ready to import our physical server 
It took about 5 minutes to import this server, the time it takes all depends on how much data you need to import, you can monitor the progress from the "recent tasks" window in the vCenter man screen 
And here we have it, a fully imported physical server, I double checked the hardware settings and it done a pretty good job as I did not have to change anything 

When I started the VM, all I had to do was edit the /etc/network/interfaces file and change the NIC to eth3 and up the interface and away we go, as you can see below 
Ok not all P2V conversions will go as smoothly as this one did but you get the idea on what is involved and what you need to prepare before hand when performing a P2V conversion. There is also a Cold-Clone boot CD which allows you reboot the physical server from the CD and clone the physical server while it is offline.
向Ubuntu里添加雅黑字体,貌似已经成为了中文用户的一项必要功课。 即使你像我一样喜欢使用英文的系统,还是需要在浏览网页,编辑文档,收发邮件等过程中用到中文字体。 如果你Google或者参考 Ubuntu Wiki 就很容易找到向 Ubuntu 里添加字体的方法。 一直以来我也是这么做的,但是最近我发现 Ubuntu 10.04 以后有了更简单的方法。 你只需要三步便可完成: 1. 从Windows的机器上复制雅黑字体文件。以Win7为例,在 %windir%\fonts 下面找到雅黑字体,默认有两个文件(字体) 2. 复制到Ubuntu的机器上,双击字体文件选择 Install Font (安装字体),或者在右键列表里选择安装 3. 现在字体已经可以使用了,你直接在你想要设置的程序里修改就可以了 另外设置Firefox的中文字体有一个小技巧。 你不应该去设置默认字体,这样会更改英文的字体。 你应该去高级里设置中文Chinese的字体以及其他Other的字体。 Other对应于Unicode。 这样可以保持英文字体不变,中文字体改为雅黑。
aria2是我今天新学到的一个命令行的下载工具,虽然还没研究透,但是他绝对比wget更好. aria2 是 Linux 下一个不错的高速下载工具。由于它具有分段下载引擎,所以支持从多个地址或者从一 个地址的多个连接来下载同一个文件。这样自然就大大加快了文件的下载速 度。aria2 也具有断点续传功能,这使你随时能够恢复已经中断的文件下载。除了支持一般的 http(s) 和 ftp 协议外,aria2 还支持 BitTorrent 协议。这意味着,你也可以使用 aria2 来下载 torrent 文件。 安装 aria2 aria2 目前已被包含到许多 Linux 发行版中,因此你可以通过所用的系统直接加以安装。例如,在 Debian/Ubuntu 中,你可以在终端执行如下指令来安装 aria2: sudo apt-get install aria2 aria2 的使用方法 aria2 是命令行程序,使用非常简单。 - 一般使用使用 aria2 下载文件,只需在命令后附加地址即可。比如我们下载ubuntu如:
aria2c http://www.mirror.tw/pub/ubuntu/releases/jaunty/ubuntu-9.04-desktop-i386.iso - 分段下载利用 aria2 的分段下载功能可以加快文件的下载速度,对于下载大文件时特别有用。为了使用 aria2 的分段下载功能,你需要在命令中指定 s 选项。如:
aria2c -s 2 http://www.mirror.tw/pub/ubuntu/releases/jaunty/ubuntu-9.04-desktop-i386.iso 这将使用 2 个连接来下载该文件。s 后面的参数值介于 1~5 之间,你可以根据实际情况选择。 - 断点续传在命令中使用 c 选项可以断点续传文件。如:
aria2c -c http://www.mirror.tw/pub/ubuntu/releases/jaunty/ubuntu-9.04-desktop-i386.iso - 下载 torrent 文件你也可以使用 aria2 下载 BitTorrent 文件。如:
aria2c -o gutsy.torrent http://cdimage.ubuntu.com/daily-live/current/gutsy-desktop-i386.iso.torrent
关于 aria2 的更多用法,可以通过 man aria2c 查阅。
Home > virtualization > How To Convert VMWare Image (.vmdk) to VirtualBox Image (.vdi) How To Convert VMWare Image (.vmdk) to VirtualBox Image (.vdi)If you're new here, you may want to subscribe to my RSS feed. Thanks for visiting! I’ve found more and more people are switching to Virtualbox these days and I keep running into the same question. ”How can I convert my VMware images to Virtualbox images?” Well, breath easy because it is possible and not very difficult! There are two methods that I am aware of that will allow you to use your VMware images on Virtualbox. The first method I’ll outline uses the graphical Virtualbox interface and the second uses the command line. Each method should be equally as stable, it simple depends on your preference. Method 1 Start Virtualbox Inside the Virtualbox Menu click: File > Virtual Media Manager Click on the “Add” button. Locate and select the VMware .vmdk file you’d like to convert. Click Open. Verify your disk image has been added to the list of images and that the virtual and actual sizes appear accurate. Click OK Create a new virtual machine profile, selecting your imported image for the storage. Boot your new virtual machine.
Method 2 To use the second method we’ll need an addition command-line tool called qemu. sudo aptitude install qemu
You’ll new be able to convert a .vmdk (VMware image) to a .bin format, which can then be converted to a Virtualbox native .vdi format. qemu-img convert /path/to/original.vmdk converted.bin
You’ll then need to use the VBoxManage utility that comes with Virtualbox to convert the .bin to a native .vdi format: VBoxManage convertdd converted.bin converted.vdi
You can now create your new Virtualbox machine profile, using this new .vdi file as your disk image. Two methods for converting VMware images to Virtualbox images. Are there any other methods that you can suggest, or have you had better experience with one or the other? Let us know!
VMware vCenter Converter StandaloneAutomate and simplify physical to virtual machine conversions as well as conversions between virtual machine formats with Converter Standalone. Features & BenefitsVMware vCenter Converter Standalone can be run on a wide variety of hardware and supports most commonly used versions of Microsoft Windows and Linux operating systems. Quickly and reliably convert local and remote physical machines into virtual machines without any disruption or downtime. Complete multiple conversions simultaneously with a centralized management console and an intuitive conversion wizard. DOWNLOAD INCLUDES- VMware vCenter Converter Standalone
Learn more about VMware vCenter Converter Standalone Evaluate VMware vSphere
VBoxManage modifyhd xpvm.vdi --resize 20000 du -sh vmxp.vdi ref:
http://stackoverflow.com/questions/1486077/java-good-way-to-encapsulate-integer-parseint# java.toString() ,(String),valueOf (2009-11-14 23:56:43)在java项目的实际开发和应用中,常常需要用到将对象转为String这一基本功能。本文将对常用的转换方法进行一个总结。常用的方法有Object#toString(),(String)要转换的对象,String.valueOf(Object)等。下面对这些方法一一进行分析。 方法1:采用 Object#toString()方法请看下面的例子: Object object = getObject(); System.out.println(object.toString()); 在这种使用方法中,因为java.lang.Object类里已有public方法.toString(),所以对任何严格意义上的java对象都可以调用此方法。但在使用时要注意,必须保证object不是null值,否则将抛出NullPointerException异常。采用这种方法时,通常派生类会覆盖Object里的toString()方法。 方法2:采用类型转换(String)object方法这是标准的类型转换,将object转成String类型的值。使用这种方法时,需要注意的是类型必须能转成String类型。因此最好用instanceof做个类型检查,以判断是否可以转换。否则容易抛出CalssCastException异常。此外,需特别小心的是因定义为Object 类型的对象在转成String时语法检查并不会报错,这将可能导致潜在的错误存在。这时要格外小心。如: Object obj = new Integer(100); String strVal = (String)obj; 在运行时将会出错,因为将Integer类型强制转换为String类型,无法通过。但是, Integer obj = new Integer(100); String strVal = (String)obj; 如是格式代码,将会报语法错误。 此外,因null值可以强制转换为任何java类类型,(String)null也是合法的。 方法3:采用String.valueOf(Object) String.valueOf(Object)的基础是Object#toString()。但它与Object#toString()又有所不同。在前面方法1的分析中提到,使用后者时需保证不为null。但采用第三种方法时,将不用担心object是否为null值这一问题。为了便于说明问题,我们来分析一下相关的源代码。Jdk里String# valueOf(Object)源码如下:
public static String valueOf(Object obj) { return (obj == null) ? "null" : obj.toString(); } 从上面的源码可以很清晰的看出null值不用担心的理由。但是,这也恰恰给了我们隐患。我们应当注意到,当object为null时,String.valueOf(object)的值是字符串”null”,而不是null!!!在使用过程中切记要注意。试想一下,如果我们用 if(String.valueOf(object)==null){System.out.println(“传入的值是null!”);}这样的语句将可能会发生什么问题。再想一下,向控制台输出时,在视觉上如下语句在执行的结果上有什么不同: System.out.println(String.valueOf(null)); System.out.println(null); 我们看到的输出将是一模一样的东西:null,但它们意义相同吗? 以上是对object对象转换为String的一些总结。 | Convert a String to an int, returning zero if the conversion fails. | | /** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * * * @author John Keyes (john at integralsource.com) * @version $Revision: 680644 $, $Date: 2008-07-29 01:13:48 -0700 (Tue, 29 Jul 2008) $ */ public class Main { //-------------------------------------------------------------------- /** * <p>Convert a <code>String</code> to an <code>int</code>, returning * <code>zero</code> if the conversion fails.</p> * * @param str the string to convert * @return the int represented by the string, or <code>zero</code> if * conversion fails */ public static int stringToInt(String str) { return stringToInt(str, 0); } /** * <p>Convert a <code>String</code> to an <code>int</code>, returning a * default value if the conversion fails.</p> * * @param str the string to convert * @param defaultValue the default value * @return the int represented by the string, or the default if conversion fails */ public static int stringToInt(String str, int defaultValue) { try { return Integer.parseInt(str); } catch (NumberFormatException nfe) { return defaultValue; } } }
|
http://www.java2s.com/Code/Java/Data-Type/ConvertaStringtoanintreturningzeroiftheconversionfails.htm |
2012年2月10日
#
声明:ITeye资讯文章的版权属于ITeye网站所有,严禁任何网站转载本文,否则必将追究法律责任!DBeaver 1.5 正式版发布了! DBeaver 是一个通用的数据库管理工具和 SQL 客户端,支持 MySQL、PostgreSQL、Oracle、DB2、MSSQL、Sybase、Mimer、HSQLDB、Derby以及其他兼容 JDBC 的数据库。DBeaver 提供一个图形界面用来查看数据库结构、执行SQL查询和脚本、浏览和导出数据、处理BLOB/CLOB 数据以及修改数据库结构等。 该版本的新特性包括: - 新增WMI(Windows管理规范,这是一项核心的Windows管理技术)浏览器
- 重新设计了系统架构,以支持非关系型数据库
- 改进了ERD插件
- 修复了Oracle插件附件,提升了性能
- 修复了大量的bug
摘要: 您还未登录 !登录注册论坛首页→Java企业应用论坛→Mybatis3.0查询,保存,更新,删除数据。全部HibernateSpringStrutsiBATIS企业应用LuceneSOAJava综合设计模式TomcatOOJBoss最成熟稳定甘特图控件,支持Java和.Net浏览 337 次主题:Mybatis3.0查询,保存,更新,删除数据。精华帖 (0) :: 良好帖 (0) :: 新手帖 (... 阅读全文
这次的项目中,一个同事遇到了一个奇怪的问题。背景是这样的,项目中使用了struts2+spring,在前端有一个功能实现是使用JQuery的 ajax请求访问一个struts2的action,要求返回的是view是json。其中项目加入了如下本问题相关的jar包:struts2- core-2.1.8.1.jar,struts2-json-plugin-2.2.1.jar,json-lib-2.4-jdk15.jar。具体 的代码与配置都没有问题,即使用了标准的相关写法,因为不涉及到这个问题的讨论,所以就不贴代码了。因为当时帮他调试的时候没有记录具体的异常,我在网上 找到了相关的问题贴,转载如下: http://hi.baidu.com/%BF%AA%CB%B3/blog/item/c06cbf451d530b8cb3b7dc4c.html 异常形式: Class org.apache.struts2.json.JSONWriter can not access a member of * 或是 Class com.googlecode.jsonplugin.JSONWriter can not access a member of class* 第一种是struct2.1.8与json结合时的异常,第二种是struct2.1.6与json结合的异常。 具体: Class org.apache.struts2.json.JSONWriter can not access a member of class oracle.jdbc.driver.BaseResultSet with modifiers "public" 解释: 不能把程序中的某种数据结构串行化成json格式。 原因: struts2的action里面的数据转换成json数据时,会将提供了get方法的属性都串行化输出JSON到客户端。有的时候,很多属性并不能串行 化成json数据,比如这里的oracle.jdbc.driver.BaseResultSet。这时还进行强行转换就会出现这样的异常。 解决方法: 在不能串行化到json的属性相应的get方法前加一条json标记@JSON(serialize=false)。告诉json不需要转化这个属性。或者根本不写这个get方法。 后记: 对于不需要在前台输出的json数据,也可以用同样的方法进行处理,从而减少服务器和客户端间交互的信息量。 可在需要在前台输出的属性的get方法前加上@JSON(name="status")标识,从而为该属性起了一个别名,在前台就可以通过status作为属性名来读取其值。 由此可见是因为序列化问题造成的,反思我们项目中的问题,原因是因为在action中注入service时使用的是接口(网上的另一种说法是在 action中的接口不能给予get方法,但是那只是描述了现象,如果上文所述正确的话那从本质上说明了原因),而且提供了get方法,接口不能被串行 化。去掉get方法后,异常消失。先在此记录下,有空了看下相关的源代码,拿源码说事更有说服力....
感觉现在的JAVA框架越来越多,纷繁复杂。想彻底研究一种框架,了解下其中的一些通用的东西,于是选择了struts2。 看了很多struts2的文档,发现很多都是在讲struts2与JSP使用很多标签库,我不喜欢用那么多的标签,于是研究了下如何使用velocity与 struts2整合。 主要有四个步骤: 1,添加pom依赖 (这里我采用 maven管理依赖,相当方便) - <dependency>
- <groupId>org.apache.velocity</groupId>
- <artifactId>velocity</artifactId>
- <version>1.6</version>
- <scope>compile</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.velocity</groupId>
- <artifactId>velocity-tools</artifactId>
- <version>1.3</version>
- <scope>compile</scope>
- </dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.6</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-tools</artifactId>
<version>1.3</version>
<scope>compile</scope>
</dependency> 2,修改web.xml - <!DOCTYPE web-app PUBLIC
- "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
- "http://java.sun.com/dtd/web-app_2_3.dtd" >
-
- <web-app>
- <display-name>Archetype Created Web Application</display-name>
-
- <filter>
- <filter-name>struts2</filter-name>
- <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>struts2</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
-
- <servlet>
- <servlet-name>velocity</servlet-name>
- <servlet-class>org.apache.velocity.tools.view.servlet.VelocityViewServlet</servlet-class>
- </servlet>
-
-
- <servlet-mapping>
- <servlet-name>velocity</servlet-name>
- <url-pattern>*.vm</url-pattern>
- </servlet-mapping>
-
- <welcome-file-list>
- <welcome-file>index.vm<welcome-file>
- </welcome-file-list>
- </web-app>
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>velocity</servlet-name>
<servlet-class>org.apache.velocity.tools.view.servlet.VelocityViewServlet</servlet-class>
</servlet>
<!-- Map *.vm files to Velocity -->
<servlet-mapping>
<servlet-name>velocity</servlet-name>
<url-pattern>*.vm</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.vm<welcome-file>
</welcome-file-list>
</web-app>
3,增加/WEB-INF/velocity.properties 这里根据需要加velocity参数,我暂时啥参数也不加,整个空文件,用默认的总可以吧,需要的时候再加好了。 4,增加/EB-INF/toolbox.xml - <?xml version="1.0"?>
-
- <toolbox>
- <tool>
- <key>link</key>
- <scope>request</scope>
- <class>org.apache.velocity.tools.struts.StrutsLinkTool</class>
- </tool>
- <tool>
- <key>msg</key>
- <scope>request</scope>
- <class>org.apache.velocity.tools.struts.MessageTool</class>
- </tool>
- <tool>
- <key>errors</key>
- <scope>request</scope>
- <class>org.apache.velocity.tools.struts.ErrorsTool</class>
- </tool>
- <tool>
- <key>form</key>
- <scope>request</scope>
- <class>org.apache.velocity.tools.struts.FormTool</class>
- </tool>
- <tool>
- <key>tiles</key>
- <scope>request</scope>
- <class>org.apache.velocity.tools.struts.TilesTool</class>
- </tool>
- <tool>
- <key>validator</key>
- <scope>request</scope>
- <class>org.apache.velocity.tools.struts.ValidatorTool</class>
- </tool>
- </toolbox>
<?xml version="1.0"?>
<toolbox>
<tool>
<key>link</key>
<scope>request</scope>
<class>org.apache.velocity.tools.struts.StrutsLinkTool</class>
</tool>
<tool>
<key>msg</key>
<scope>request</scope>
<class>org.apache.velocity.tools.struts.MessageTool</class>
</tool>
<tool>
<key>errors</key>
<scope>request</scope>
<class>org.apache.velocity.tools.struts.ErrorsTool</class>
</tool>
<tool>
<key>form</key>
<scope>request</scope>
<class>org.apache.velocity.tools.struts.FormTool</class>
</tool>
<tool>
<key>tiles</key>
<scope>request</scope>
<class>org.apache.velocity.tools.struts.TilesTool</class>
</tool>
<tool>
<key>validator</key>
<scope>request</scope>
<class>org.apache.velocity.tools.struts.ValidatorTool</class>
</tool>
</toolbox>
好,到此为止整合完毕。 最后添上一个helloworld.vm - velocity的helloWorld
- #foreach( $header in $request.HeaderNames )
- <b>$header:</b> $request.getHeader($header)<br>
- #end
velocity的helloWorld
#foreach( $header in $request.HeaderNames )
<b>$header:</b> $request.getHeader($header)<br>
#end 试一下吧,会打出浏览器的一些请求的head出来。原来不是helloworld,呵呵。但是还是小有成就感,至少出来点东西了吗。 ====================邪恶的分割线================== 接下来我们来真正的helloWorld。 1,建立index.vm - <html>
- <body>
- <form action="HelloWorld">
- <input type="text" name="userName"/>
- <input type="submit" value="提交" />
- </form>
- </body>
- </html>
<html>
<body>
<form action="HelloWorld">
<input type="text" name="userName"/>
<input type="submit" value="提交" />
</form>
</body>
</html>
2,修改struts.xml 加上如下配置 - <package name="default" extends="struts-default">
- <action name="HelloWorld" class="com.yajun.helloworld.HelloWorld">
- <result name="SUCCESS">/success.vm</result>
- </action>
- </package>
<package name="default" extends="struts-default">
<action name="HelloWorld" class="com.yajun.helloworld.HelloWorld">
<result name="SUCCESS">/success.vm</result>
</action>
</package> 3,如上面的配置所示,还需要加入 com.yajun.helloworld.HelloWorld 这个类: - package com.yajun.helloworld;
-
- public class HelloWorld {
-
- private String message;
- private String userName;
-
- public HelloWorld(){
- }
-
- public String execute() {
- setMessage("Hello " + getUserName());
- return "SUCCESS";
- }
-
- public String getMessage() {
- return message;
- }
-
- public void setMessage(String message) {
- this.message = message;
- }
-
- public String getUserName() {
- return userName;
- }
-
- public void setUserName(String userName) {
- this.userName = userName;
- }
-
- }
package com.yajun.helloworld;
public class HelloWorld {
private String message;
private String userName;
public HelloWorld(){
}
public String execute() {
setMessage("Hello " + getUserName());
return "SUCCESS";
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
和success.vm - <html>
- <head>
- <title>Hello World</title>
- </head>
- <body>
- <h1>$message</h1>
- </body>
- </html>
<html>
<head>
<title>Hello World</title>
</head>
<body>
<h1>$message</h1>
</body>
</html> 完成了,运行吧。哈哈。 感觉比标签清爽许多,而且velocity可以直接从 struts2 的 valueStack中 取得像要的值,还是挺不错的。 但是,有突然发现,中文显示有问题呀。于是想到了velocity.properties那个文件还需要配置个东西: input.encoding = GBK output.encoding = GBK 这下一个HelloWorld应该OK了。
网上找了好多关于Mybatis3 generator 自动化工具的教程 都说的很是含糊, 好吧 cmd什么的我实在不懂得敲。。。 详细的用法我已经在附件demo里体现了 。 这里需要注明的是 附件里的demo也是在网上找的demo基础上改的~ 添加了关于sqlserver 分页 插件 Mybatis generator的使用主要是 generatorConfig.xml配置文件的使用 - <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE generatorConfiguration
- PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
- "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
-
- <generatorConfiguration>
- <properties resource="util/generatorConfig.properties" />
- <!-- classPathEntry:数据库的JDBC驱动,换成你自己的驱动位置 -->
-
- <classPathEntry location="${classPath}" />
- <context id="MBG" targetRuntime="MyBatis3"
- defaultModelType="conditional">
- <plugin type="plugin.SelectByPagePlugin" />
- <!-- 此处是将Example改名为Criteria 当然 想改成什么都行~
- <plugin type="org.mybatis.generator.plugins.RenameExampleClassPlugin">
- <property name="searchString" value="Example$" />
- <property name="replaceString" value="Criteria" />
- </plugin>
- -->
- <plugin
- type="org.mybatis.generator.plugins.EqualsHashCodePlugin" />
- <plugin
- type="org.mybatis.generator.plugins.MapperConfigPlugin">
- <property name="fileName" value="GeneratedMapperConfig.xml" />
- <property name="targetPackage"
- value="com.cy.mybatis.mbg.util" />
- <property name="targetProject" value="${targetProject}" />
- </plugin>
- <commentGenerator>
- <!-- 去除自动生成的注释 -->
- <property name="suppressAllComments" value="true" />
- </commentGenerator>
- <jdbcConnection driverClass="${driverClass}"
- connectionURL="${connectionURL}" userId="${userId}"
- password="${password}">
- </jdbcConnection>
- <javaTypeResolver>
- <property name="forceBigDecimals" value="false" />
- </javaTypeResolver>
- <!-- targetProject:自动生成代码的位置 -->
- <javaModelGenerator targetPackage="${modelPackage}"
- targetProject="${targetProject}">
- <property name="enableSubPackages" value="true" />
- </javaModelGenerator>
-
- <sqlMapGenerator targetPackage="${sqlMapperPackage}"
- targetProject="${targetProject}">
- <property name="enableSubPackages" value="true" />
- </sqlMapGenerator>
-
- <javaClientGenerator type="XMLMAPPER"
- targetPackage="${daoMapperPackage}"
- targetProject="${targetProject}">
- <property name="enableSubPackages" value="true" />
- </javaClientGenerator>
- <!-- tableName:用于自动生成代码的数据库表;domainObjectName:对应于数据库表的javaBean类名 -->
- <!--
- <table tableName="visitor_info" domainObjectName="Visitor" enableCountByExample="false" enableUpdateByExample="false"
- enableDeleteByExample="false" enableSelectByExample="false"
- selectByExampleQueryId="false">
-
- </table>
- -->
- <table tableName="weather_info" domainObjectName="Weather">
- </table>
- </context>
- </generatorConfiguration>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<properties resource="util/generatorConfig.properties" />
<!-- classPathEntry:数据库的JDBC驱动,换成你自己的驱动位置 -->
<classPathEntry location="${classPath}" />
<context id="MBG" targetRuntime="MyBatis3"
defaultModelType="conditional">
<plugin type="plugin.SelectByPagePlugin" />
<!-- 此处是将Example改名为Criteria 当然 想改成什么都行~
<plugin type="org.mybatis.generator.plugins.RenameExampleClassPlugin">
<property name="searchString" value="Example$" />
<property name="replaceString" value="Criteria" />
</plugin>
-->
<plugin
type="org.mybatis.generator.plugins.EqualsHashCodePlugin" />
<plugin
type="org.mybatis.generator.plugins.MapperConfigPlugin">
<property name="fileName" value="GeneratedMapperConfig.xml" />
<property name="targetPackage"
value="com.cy.mybatis.mbg.util" />
<property name="targetProject" value="${targetProject}" />
</plugin>
<commentGenerator>
<!-- 去除自动生成的注释 -->
<property name="suppressAllComments" value="true" />
</commentGenerator>
<jdbcConnection driverClass="${driverClass}"
connectionURL="${connectionURL}" userId="${userId}"
password="${password}">
</jdbcConnection>
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- targetProject:自动生成代码的位置 -->
<javaModelGenerator targetPackage="${modelPackage}"
targetProject="${targetProject}">
<property name="enableSubPackages" value="true" />
</javaModelGenerator>
<sqlMapGenerator targetPackage="${sqlMapperPackage}"
targetProject="${targetProject}">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator>
<javaClientGenerator type="XMLMAPPER"
targetPackage="${daoMapperPackage}"
targetProject="${targetProject}">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<!-- tableName:用于自动生成代码的数据库表;domainObjectName:对应于数据库表的javaBean类名 -->
<!--
<table tableName="visitor_info" domainObjectName="Visitor" enableCountByExample="false" enableUpdateByExample="false"
enableDeleteByExample="false" enableSelectByExample="false"
selectByExampleQueryId="false">
</table>
-->
<table tableName="weather_info" domainObjectName="Weather">
</table>
</context>
</generatorConfiguration> 其中的properties元素里引用了一个generatorConfig.properties配置文件是为了方便移植的时候,只需修改resource的路径值和generatorConfig.properties里的值即进行生成操作 配置文件配好了之后, 进行生成代码, 既可以使用命令的方式, 也可以自已写一个带main的类来运行, 附件里提供了一个带main的运行类 MyBatisGeneratorTool.java 。 由于在使用Mybatis generator 工具时 默认会生成example类 如果你不喜欢也可以在generatorConfig.xml中设置不自动生成。 当然test包里也提供了一个简单的包含Example类的测试用例。 sqlserver的分页插件 在<plugin type="plugin.SelectByPagePlugin" /> 中配置~ 如果不需要取掉此行再执行就是了 为了调试方便 配置了log4j 在控制台输出sql 如果不需要删掉即可~
分类: Road to Java 2010-08-11 23:34 1129人阅读 收藏 举报 iBatis 3中新增了SelectBuilder/SqlBuilder两个工具类,用于利用类函数的方式动态生成SQL 语句,减少拼接SQL语句时候大量的显式字符串操作,减少字符串操作可能出现的错误,提高程序的易读性。 在iBatis 3的用户指南中,列举出了若干个实例,如下是个最简单的例子,生成一个静态的SQL语句: - import static org.mybatis.jdbc.SelectBuilder.*;
-
- public String selectBlogsSql() {
- BEGIN();
- SELECT("*");
- FROM("BLOG");
- return SQL();
- }
下面几个例子生成动态的SQL语句 - private String selectPersonLike(Person p){
- BEGIN();
- SELECT("P.ID, P.USERNAME, P.PASSWORD, P.FIRST_NAME, P.LAST_NAME");
- FROM("PERSON P");
- if (p.id != null) {
- WHERE("P.ID like #{id}");
- } if (
- p.firstName != null) {
- WHERE("P.FIRST_NAME like #{firstName}");
- } if (
- p.lastName != null) {
- WHERE("P.LAST_NAME like #{lastName}");
- } ORDER_BY("P.LAST_NAME");
- return SQL();
- }
-
-
- public String deletePersonSql() {
- BEGIN();
- DELETE_FROM("PERSON");
- WHERE("ID = ${id}");
- return SQL();
- }
- public String insertPersonSql() {
- BEGIN();
- INSERT_INTO("PERSON");
- VALUES("ID, FIRST_NAME", "${id}, ${firstName}");
- VALUES("LAST_NAME", "${lastName}");
- return SQL();
- }
- public String updatePersonSql() {
- BEGIN();
- UPDATE("PERSON");
- SET("FIRST_NAME = ${firstName}");
- WHERE("ID = ${id}");
- return SQL();
- }
通过上面的实例,我们已经可以生成SQL语句了,但是如何使用这些SQL,用户指南中并没有提及。当然,对于简单的例子,如例1中生成的静态 SQL,我们完全可以以纯粹的JDBC的方式来执行。但例子2中几个方法,则必须首先将里面的变量替换掉,才能执行,因此,利用iBatis中自带的类进 行变量替换则应该是最好的办法(当然我们可以用Velocity等模板工具来做这件事情,但在iBatis环境下,不是最佳的方案)。 iBatis3的一个缺陷就是相关的开发文档太少,要想做这件事情就必须啃源码了。 首先通过观察,找到了SelectBuilder/SqlBuilder同一个package下的SqlRunner类,该类封装了针对数据库操作 的select,insert, update和delete的等方法,很显然这是一个SQL执行类,select默认的返回类型为Map。 下一步,需要寻找能替换关键字变量的相关类了,得感谢ibatis 3.0 Dynamic Sql 设计解 ...这篇文章,对Dynamic Sql相关类和类关系有了了解,才找到最终的解决方案,如下: - private Connection conn=null;
- private SqlRunner sqlRunner;
-
- {
-
- try {
- conn = sessionFactory.getConfiguration().getEnvironment().getDataSource().getConnection();
- sqlRunner=new SqlRunner(conn);
- } catch (SQLException e) {
- logger.error(e);
- }
-
- }
-
- public void deletPerson(Map keysMap) {
- BEGIN();
- DELETE_FROM("PERSON");
- WHERE("ID = #{id}");
-
-
- TextSqlNode node =new TextSqlNode(SQL());
- DynamicSqlSource s=new DynamicSqlSource(sessionFactory.getConfiguration(),
- node);
-
- BoundSql sql = s.getBoundSql(keysMap);
- logger.debug(sql.getSql());
-
-
- try {
- sqlRunner.delete(sql.getSql(),keysMap.get("id"));
- conn.commit();
- } catch (Exception e) {
- conn.rollback();
- throw e;
- }
- }
使用起来很简单: - try {
- Map params= new HashMap();
- params.put("id","1");
- deletePerson();
-
- } catch (Exception e) {
-
- e.printStackTrace();
- }
如上,使用map是为了支持任意多个参数,同时利用SelectBuilder/SqlBuilder强大的SQL构建能力,我们完全可以封装一些 很通用的数据库操作功能,比如通用删除功能,只需将上面的方法进行修改,将表名和包含主键变量的Map传入就可以实现了,而不需要再去XML文件写 SQL。
Project Information Members Featured Downloads | 1、已完成的功能: 1、使用jetty应用容器 2、内存数据库hsqldb 3、异常处理 4、struts2集成jsonResult 5、单元测试基类的封装 6、spring声明式事务处理 7、DAO基类实现基本的CRUD功能,其他的DAO类继承BaseDao 8、分页组件封装 9、maven项目管理 10、静态文件分离解决,比如静态文件放在CDN上 11、gbk编码时ajax乱码的解决 计划的功能: 1.maven插件生成框架(使用freemarker实现),支持设置代码的编码,目前所有文件的编码为gb18030。 2、更新列表--2011.11.04 1、修复jetty与hsqldb例子代码工程的jetty启动报错异常。 3、新功能--代码生成器--2011.11.22 基于主干开发了代码生成器。 1、在代码生成器codeGenerator项目根目录下运行: mvn clean compile mvn install -Dmaven.test.skip=true; 将插件安装到本地。 2、在frame(为主干项目)项目的pom.xml中写入
<plugin> <groupId>com.ldl.code</groupId> <artifactId>code-maven-plugin</artifactId> <version>1.0.1</version> </plugin> 3、运行插件: 插件共有四个参数: 1)templateDirectory:模板文件夹的位置,默认在“用户帐号根目录/codeTemplate”(模板文件在codeGenerator项目的template目录下)。 2)pdmFile:powerdesinger文件的位置,默认为“用户帐号根目录/code.pdm”。 3)outputDirectory:生成的代码的输出文件夹(尽量为frame工程的根目录,这样生成的代码就不用再拷到frame里了)。 4)module:模块名称,有些项目都是分模块开发的(可以为null,则为不分模块)。 在frame项目下运行(文件夹的位置根据自己的实际位置改写): mvn code:generate -DtemplateDirectory=d:/code -DoutputDirectory=d:/frame -DpdmFile=d:/code.pdm 4、如果outputDirectory文件夹不是指定在frame工程下,则把生成的代码拷贝到frame工程里。然后在frame工程struts.xml文件中加入<include file="struts-xx.xml"></include>,这个数量看生成的struts-xx.xml文件数量。 5、代码生成器的实现原理: 1)、使用dom4j解析pdm文件生成javabean。 2)、使用freemarker作为模板。 3)、目前只支持mysql的数据类型到java数据类型的转换。 |
今日公司新项目计划采用MyBatis与Spring3,网上搜索一圈,发现了MyBatis提供了一个支持Spring3容器的jar包,于是取下用之,大概的写了一个小例子,供大家参考,不足之处,还望指出。 web.xml - <servlet>
- <servlet-name>Dispatcher</servlet-name>
- <servlet-class>
- org.springframework.web.servlet.DispatcherServlet
- </servlet-class>
- <init-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>
- classpath:spring_config/applicationContext-mvc.xml
- </param-value>
- </init-param>
- </servlet>
- <servlet-mapping>
- <servlet-name>Dispatcher</servlet-name>
- <url-pattern>*.do</url-pattern>
- </servlet-mapping>
<servlet>
<servlet-name>Dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:spring_config/applicationContext-mvc.xml
</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Dispatcher</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
Spring配置 - <!--
- 使用SqlSessionFactoryBean工厂产生SqlSessionFactory对象,
- 方便后期注入Dao
- -->
- <bean id="sqlSessionFactory"
- class="org.mybatis.spring.SqlSessionFactoryBean">
- <property name="dataSource" ref="dataSource" />
- <property name="configLocation"
- value="classpath:mybatis_config/Configuration.xml">
- </property>
- </bean>
-
- <!-- 会自动将basePackage中配置的包路径下的所有带有@Mapper标注的Dao层的接口生成代理,替代原来我们的Dao实现。-->
- <bean
- class="org.mybatis.spring.annotation.MapperScannerPostProcessor">
- <property name="sqlSessionFactoryBeanName"
- value="sqlSessionFactory" />
- <property name="basePackage" value="com.demo.dao" />
- </bean>
-
- <bean name="transactionManager"
- class="org.springframework.jdbc.
- datasource.DataSourceTransactionManager">
- <property name="dataSource" ref="dataSource"></property>
- </bean>
-
- <!--Spring AOP 2.0 的方式配置事务,这个就不用多解释了吧!-->
- <tx:advice id="txAdvice" transaction-manager="transactionManager">
- <tx:attributes>
- <tx:method name="delete*"
- propagation="REQUIRED" read-only="false"
- rollback-for="java.lang.Exception"
- no-rollback-for="java.lang.RuntimeException"/>
- <tx:method name="find*"
- propagation="SUPPORTS"/>
- </tx:attributes>
- </tx:advice>
-
- <aop:config>
- <aop:pointcut id="pc"
- expression="execution(* *.*.*(..))" />
- <aop:advisor pointcut-ref="pc" advice-ref="txAdvice" />
- </aop:config>
<!--
使用SqlSessionFactoryBean工厂产生SqlSessionFactory对象,
方便后期注入Dao
-->
<bean id="sqlSessionFactory"
class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation"
value="classpath:mybatis_config/Configuration.xml">
</property>
</bean>
<!-- 会自动将basePackage中配置的包路径下的所有带有@Mapper标注的Dao层的接口生成代理,替代原来我们的Dao实现。-->
<bean
class="org.mybatis.spring.annotation.MapperScannerPostProcessor">
<property name="sqlSessionFactoryBeanName"
value="sqlSessionFactory" />
<property name="basePackage" value="com.demo.dao" />
</bean>
<bean name="transactionManager"
class="org.springframework.jdbc.
datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--Spring AOP 2.0 的方式配置事务,这个就不用多解释了吧!-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="delete*"
propagation="REQUIRED" read-only="false"
rollback-for="java.lang.Exception"
no-rollback-for="java.lang.RuntimeException"/>
<tx:method name="find*"
propagation="SUPPORTS"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="pc"
expression="execution(* *.*.*(..))" />
<aop:advisor pointcut-ref="pc" advice-ref="txAdvice" />
</aop:config>
最后看一下我的Dao的接口的写法 -
-
-
-
-
-
-
-
- @Mapper("userDao")
- public interface UserDao {
- public void insertUser(User user);
- public void updateUser(User user);
- public void deleteUser(Long uid);
-
-
-
- public List<User> getAllUser(Map<String,Object> likeCondition);
- public User getUser(Long uid);
- }
/**
* 这里的@Mapper就是上面所讲的Mapper扫描器中所需要的配置,会自动生成代理对象。
* 注意,接口中的方法名称要和对应的MyBatis映射文件中的语句的id值一样,因为生成的
* 动态代理,会根据这个匹配相应的Sql语句执行。另外就是方法的参数和返回值也需要注
* 意。接口中的方法如何定义,对应的MyBatis映射文件就应该进行相应的定义。
* 最后,标注中的userDao是用来作为Spring的Bean的id(或name)进行使用的,方便我
* 们在Service层进行注入使用。
*/
@Mapper("userDao")
public interface UserDao {
public void insertUser(User user);
public void updateUser(User user);
public void deleteUser(Long uid);
/**
* 进行模糊查询
*/
public List<User> getAllUser(Map<String,Object> likeCondition);
public User getUser(Long uid);
}
至此,使用MyBatis-Spring包的基本配置就结束了。 有什么表述不清的地方还望大家指出,如有需要更多信息,请留言,谢谢! 更新:上传相关工程附件,具体演示使用方法。。。。。。。。。 12年1月30日上传DEMO示例,附件中的bigdt.rar 一级相关jar包,附件中的other.zip和spring_iBATIS.zip 分享到: 
- Last Published: 17 January 2012
- |
- Version: 1.1.0-SNAPSHOT
Sample CodeJPetStore 6 is a full web application built on top of MyBatis 3, Spring 3 and Stripes. It is available for downloading in the downloads section of MyBatis project site. In this section we will walk through this sample to understand how is it built and learn how to run it. PurposeThis new JPetStore comes with the same idea in mind than for its predecessors: keep it simple. The main purpose behind JPetStore 6 is to demonstrate that a full web application can be built with just a few classes, and what is more important, with no advanced coding skills. You just need to know plain Java and SQL. The 6th version of JPetStore is the smallest one in the family. It uses just 24 java classes while keeping a good design and program structure. As we will see a bit later, you will not find JDBC code, object creation, binding code or transaction handling code. What is more impressive is that you will not even find any call to the MyBatis API. Although this sounds magical, you will see that the combination of MyBatis mappers and dependency injection lets you build applications with no dependency on MyBatis. Program StructureJPetStore 6 follows the typical maven project structure /jpetstore <-- Maven pom.xml goes here.
/src
/main/
/java <-- Java code goes here.
/org/
/mybatis
/jpetstore
/domain <-- Business domain objects go here.
/persistence <-- Mapper interfaces go here.
/service <-- Application logic goes here.
/web
/actions <-- Presentation logic (actions) goes here.
/resources <-- Non java files go here.
/org
/mybatis
/jpetstore
/persistence <-- Mapper XML files go here.
/database
/webapp
/css
/images
/WEB-INF <-- web.xml and applicationContext.xml go here.
/jsp <-- JSP files go here.
Configuration filesConfiguration files are read during application startup. Their purpose is to configure the three frameworks composing the application: Stripes, Spring and MyBatis. We will just need to configure two files: web.xml and applicationContext.xml. web.xmlFirst of all we need to start Stripes, so we follow the Stripes manual to do so. The manual says that we should set up a dispatcher servlet and a filter. So let's go. <filter>
<display-name>Stripes Filter</display-name>
<filter-name>StripesFilter</filter-name>
<filter-class>net.sourceforge.stripes.controller.StripesFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>StripesFilter</filter-name>
<servlet-name>StripesDispatcher</servlet-name>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<servlet>
<servlet-name>StripesDispatcher</servlet-name>
<servlet-class>net.sourceforge.stripes.controller.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>StripesDispatcher</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping> Stripes is able to search for ActionBean classes, for that purpose we must set up the base package it should search in. <filter-class>net.sourceforge.stripes.controller.StripesFilter</filter-class>
<init-param>
<param-name>ActionResolver.Packages</param-name>
<param-value>org.mybatis.jpetstore.web</param-value>
</init-param>
</filter> We are done with Stripes. Let's move on to the Spring side. According to Spring's reference manual we should add a Context listener to start up Spring. So let's add it: <listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener> By default Spring will use /WEB-INF/applicationContext.xml if we don't specify a different file. The default is fine for us. Now we have to let Stripes know that it will be running with Spring. This way we will be able to inject Spring beans directly into Stripes ActionBeans. For that purpose, following once again the Stripes manual, we set up an interceptor as follows below: <filter-class>net.sourceforge.stripes.controller.StripesFilter</filter-class>
...
<init-param>
<param-name>Interceptor.Classes</param-name>
<param-value>
net.sourceforge.stripes.integration.spring.SpringInterceptor
</param-value>
</init-param>
</filter>We are done with web.xml. As you may have notice, we have not set up any MyBatis 3 configuration yet. That configuration goes into the Spring's applicationContext.xml that we will see in the following section. applicationContext.xmlAs you already know applicationContext.xml is the Spring's configuration file. Spring is a dependency injection framework and it has to know which beans it must create and how to bind them together and that is what applicationContext.xml file is for. Let's have a deeper look into it. The first and easiest thing we have to do is let Spring know where are our service beans. We will let Spring search them in our classpath so we just need to provide it the base package to search in: <context:component-scan base-package="org.mybatis.jpetstore.service" /> NOTE Spring's component scan feature is not able to find MyBatis mappers. A mapper is not a plain bean and Spring would not know how to instantiate it. We will need a MapperScannerConfigurer for that, as we will see soon. We will also need a DataSource and a TransactionManager. Given that this is a demo application we will use a test Spring DataSource that will create an HSQL in-memory database and load our database scripts into it and the standard Spring's DataSourceTransactionManager to handle transactions. <jdbc:embedded-database id="dataSource">
<jdbc:script location="classpath:database/jpetstore-hsqldb-schema.sql"/>
<jdbc:script location="classpath:database/jpetstore-hsqldb-dataload.sql"/>
</jdbc:embedded-database>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>So far, all we have done is standard Stripes and Spring configuration and now it is time to move on to the MyBatis part. As you have learned in this manual to set up MyBatis with Spring you need at least two things: an SqlSessionFactoryBean and a mapper class. So let's go hands on. First define a SqlSessionFactoryBean: <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
</bean>And now we need to setup our mappers. For that purpose we will use the MapperScannerConfigurer that works similar to Spring standard component scan. It will search our classpath for mapper classes and register them to MyBatis. Similar to Spring's component scan we must configure the base package to search in. <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="org.mybatis.jpetstore.persistence" />
</bean>To save some writing when building our mapper xml files we would want to be able to use short aliases for beans. The SqlSessionFactoryBean has the capability to search for beans and register their short names as aliases if we setup the typeAliasPackage property like the following <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="typeAliasesPackage" value="org.mybatis.jpetstore.domain" />
</bean>Our application is now fully configured and ready to run. But before running it lets have a tour through the code to see how it looks like. Code tourJPetStore 6 is a typical MVC application with three layers: presentation, logic and data access. PresentationThe presentation layer is composed by JSP files and Stripes ActionBeans. JSPs just use plain HTML, JSTL tags and Stripes tags so there is nothing especial about them for the sake of this sample. Stripes ActionBeans are like Struts actions or Spring MVC controllers so there is nothing especial with them either. Given that we have integrated Stripes with Spring, we can inject our services into our ActionsBeans so you can just use them without caring about its creation or lookup. Have a look at CatalogActionBean: @SessionScope
public class CatalogActionBean extends AbstractActionBean {
...
@SpringBean
private transient CatalogService catalogService;
...
public ForwardResolution viewCategory() {
if (categoryId != null) {
productList = catalogService.getProductListByCategory(categoryId);
category = catalogService.getCategory(categoryId);
}
return new ForwardResolution(VIEW_CATEGORY);
}
...Note the @SpringBean annotation, that is an Stripes annotation that tells Stripes to look for that bean in Spring and inject it into this ActionBean. LogicApplication logic is composed by plain Java beans that act as services and plain Java beans that act as domain objects. This layer is in charge of filling domain objects with database data and updating database data with the content of the domain objects. For this purpose this layer must be transactional, that is, it must be able to perform atomic database updates. Let's have a look at OrderService code to see how all this is achieved: @Service
public class OrderService {
@Autowired
private ItemMapper itemMapper;
@Autowired
private OrderMapper orderMapper;
@Autowired
private LineItemMapper lineItemMapper;
@Transactional
public void insertOrder(Order order) {
order.setOrderId(getNextId("ordernum"));
for (int i = 0; i < order.getLineItems().size(); i++) {
LineItem lineItem = (LineItem) order.getLineItems().get(i);
String itemId = lineItem.getItemId();
Integer increment = new Integer(lineItem.getQuantity());
Map<String, Object> param = new HashMap<String, Object>(2);
param.put("itemId", itemId);
param.put("increment", increment);
itemMapper.updateInventoryQuantity(param);
}
orderMapper.insertOrder(order);
orderMapper.insertOrderStatus(order);
for (int i = 0; i < order.getLineItems().size(); i++) {
LineItem lineItem = (LineItem) order.getLineItems().get(i);
lineItem.setOrderId(order.getOrderId());
lineItemMapper.insertLineItem(lineItem);
}
}The first thing you will notice is that there is no JDBC code in the service, nor it is any MyBatis code in it. You may think that we used the DAO pattern and database access code is in the database layer, but as we will see later, the database layer is built with MyBatis mappers, that are plain java interfaces, and that is why you will not find any call to MyBatis API in the whole application. It is just not needed. The second thing you may have noticed is that there are no commits or rollbacks. That is because it uses the declarative transaction demarcation feature of Spring that is fully supported by MyBatis-Spring. The Spring's @Transactional annotation indicates that this method is transactional, that means that all updateInventoryQuantity, insertOrder and insertLineItem mapper calls must succeed or none. PersistenceThe persistence layer is composed of MyBatis mappers. Mappers are just plain Java interfaces and mapper XML files containing the SQL statements. There is no custom Java code in this layer. When the getOrder method is called on the OrderMapper interface, MyBatis will execute the getOrder SQL statement in OrderMapper.xml file and will populate the Order domain bean with retrieved data. public interface OrderMapper {
List<Order> getOrdersByUsername(String username);
Order getOrder(int orderId);
void insertOrder(Order order);
void insertOrderStatus(Order order);
}<mapper namespace="org.mybatis.jpetstore.persistence.OrderMapper">
<cache />
<select id="getOrder" resultType="Order" parameterType="int">
select
BILLADDR1 AS billAddress1,
BILLADDR2 AS billAddress2,
BILLCITY,
BILLCOUNTRY,
BILLSTATE,
BILLTOFIRSTNAME,
BILLTOLASTNAME,
BILLZIP,
SHIPADDR1 AS shipAddress1,
SHIPADDR2 AS shipAddress2,
SHIPCITY,
SHIPCOUNTRY,
SHIPSTATE,
SHIPTOFIRSTNAME,
SHIPTOLASTNAME,
SHIPZIP,
CARDTYPE,
COURIER,
CREDITCARD,
EXPRDATE AS expiryDate,
LOCALE,
ORDERDATE,
ORDERS.ORDERID,
TOTALPRICE,
USERID AS username,
STATUS
FROM ORDERS, ORDERSTATUS
WHERE ORDERS.ORDERID = #{value}
AND ORDERS.ORDERID = ORDERSTATUS.ORDERID
</select>
...
</mapper>NOTE You can easily add caching to your queries by adding a <cache /> element to your mapper xml file. Or, if you prefer, Spring lets you cache at a higher level, caching the whole call to a mapper or service method. Running JPetStoreYou may ask. Does all this work? Yes it does! Let's run it. Let's assume you have a clean computer. These are the steps you should follow to have the sample running on Tomcat 7 with NetBeans 7: - Download and install NetBeans 7.x JEE version with Tomcat 7
- In NetBeans select Team/Subversion/Checkout
- Enter "http://mybatis.googlecode.com/svn" as repository URL
- Enter "sub-projects/jpetstore-6/trunk" as remote repository folder
- Enter your projects folder name, in my case "/home/eduardo/NetBeansProjects/jpetstore6"
- NetBeans will prompt "A new project was found do you want to open it". Press ok
- A new project named "JPetStore Demo 6" will be shown in NetBeans projects tab
- Right click on jpetstore project and select "Run"
- Select Tomcat 7 Server
- JPetStore home page should be shown!!
These are the steps to run it in Eclipse. The process is a bit longer because Eclipse does not provide built-in SVN and maven support and does not provide an option to install Tomcat. - Download and install a JDK 6 or later
- Download and upzip Eclipse
- Download and unzip Tomcat 7
- Run Eclipse
- In eclipse, go to Help/Eclipse Marketplace
- Install m2e plugin (maven)
- Install m2e-wtp plugin (maven for wtp)
- Install subclipse plugin (subversion)
- Go to SVN tab
- In SVN add a new repository "http://mybatis.googlecode.com/svn"
- In SVN go to "sub-projects/jpetstore-6/trunk"
- Mouse right click and select "Check out", name the project as "jpetstore"
- Go to Java EE tab
- Right click on jpetstore project and select "Configure/Convert to Maven Project"
- Right click on jpetstore project and select "run on server"
- Select Tomcat 7 Server and set your installation directory
- JPetStore home page should be shown!!
Now you are ready to play with it, experiment with your own changes or whatever you want. And remember that if you find a bug or something that is missing or can be improved (for example the missing tests!), change it, create a diff patch file and fill an issue with it in the tracker. Thanks in advance!!! NOTE JPetStore 6 should run in any Servlet 2.5 y JSP 2.1 compliant Java server. Netbeans or Eclipse are not needed either, you can run the sample from your favorite IDE or the command line.
|