DWR 入門與應用(一)

Java 開發人員與網頁設計人員的橋樑 DWR…呃!我懶得寫簡介了…直接來看看可以做什麼吧!…

請先到 http://getahead.ltd.uk/dwr/ 下載 dwr.jar,放到WEB-INF/lib下…

負責處理客戶端請求,並呼叫Java物件的是DWRServlet,DWR其實也有些Model 2的味道,只是View的這一層比較弱,因為放到客戶端的JavaScript應用程式中…

在web.xml中加入DWRServlet…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" 
xmlns="http://java.sun.com/xml/ns/j2ee" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation=
"http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  <display-name>
  ajaxDWR</display-name>
  <servlet>
    <servlet-name>dwr-invoker</servlet-name>
    <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
    <init-param>
      <description>
      </description>
      <param-name>debug</param-name>
      <param-value>true</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>dwr-invoker</servlet-name>
    <url-pattern>/dwr/*</url-pattern>
  </servlet-mapping>
</web-app>

接下來寫個簡單的Hello吧!

1
2
3
4
5
6
7
package onlyfun.caterpillar;
 
public class Hello {
  public String hello(String name) {
      return "哈囉!" + name + "!您的第一個DWR!";
    }
}

客戶端要呼叫這個Java物件,傳給它參數,而後傳回一個字串,客戶端再顯示這個字串,神奇?其實是要告訴DWRServlet這件事,這需要一個dwr.xml:

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN"
 "http://www.getahead.ltd.uk/dwr/dwr10.dtd">
 
<dwr>
  <allow>
    <create creator="new" javascript="Hello">
      <param name="class" value="onlyfun.caterpillar.Hello" />
    </create>
  </allow>
</dwr>

creator設定為new,表示使用Hello的無參數建構子來生成物件,javascript設定為Hello,表示客戶端JavaScript程式可以使用Hello來呼叫對應的onlyfun.caterpillar.Hello物件。

來寫個客戶端的網頁,當中有一個輸入欄位…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=BIG5">
  <title>第一個DWR程式</title>
  <script type='text/javascript' src='dwr/interface/Hello.js'></script>
  <script type='text/javascript' src='dwr/engine.js'></script>
  <script type='text/javascript' src='dwr/util.js'></script>
  <script type='text/javascript' src='hello.js'></script>
</head>
<body>
 
<input id="user" type="text" />
<input type='button' value='哈囉' onclick='hello();' /> 
 
<div id="result"></div>
 
</body>
</html>

dwr/interface/Hello.js是由DWRServlet根據dwr.xml中的設定生成的,engine.js負責客戶端伺服端溝通,util.js是一些好用的JavaScript程式,可以讓您少寫很多JavaScript。

hello.js是我們自訂的函式,按下按鈕後,會呼叫當中的hello()函式:

1
2
3
4
5
6
7
8
function hello() {
    var user = $('user').value;
    Hello.hello(user, callback);
}
 
function callback(msg) {
   DWRUtil.setValue('result', msg);
}

${‘user’}取得輸入欄位的DOM物件,value取得當中的欄位值,而後呼叫Hello.hello(),並將value當作參數傳送… 結果是呼叫Server端的Hello Java物件,當結果傳回後,會呼叫JavaScript的callback函式,DWRUtil的setValue()方法會將傳回的msg設定給指定 id的DOM,結果就是…啥!AJAX的功能在哪…就這個而言就是發出非同步請求,而回應不用Refresh頁面啦!

好啦!這個無聊的Hello DWR可以做啥!…XD

已經可以讓您做個簡單的文字提示功能了…像這個…
http://caterpillar.onlyfun.net/Gossip/index.html

把滑鼠指到書的照片上,會顯示提示文字,這些提示文字本身不是存在網頁上的,而是在Server端,當滑鼠指到書上時,會用Request object去抓,然後顯示在框框中…

當然!我的網站只支援PHP,所以那不是DWR完成的功能,而且我是直接用Request object跟DOM去慢慢刻的…對初學者來說已經有些麻煩了…XD

不過!用DWR就可以很簡單完成這個功能…

先寫個Java類別吧!會抓properties檔案中的文字訊息,例如…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package onlyfun.caterpillar;
 
import java.util.ResourceBundle;
 
public class Book {
  private ResourceBundle resource;
  
  public Book() {
    resource = ResourceBundle.getBundle("book"); 
  }
        
  public String getDescription(String key) {
    return resource.getString(key);
  }
}

從程式中就知道,它會去抓book_zh_TW.properties的資料,這不是重點啦!只是Java的一個功能,我們要看的是DWR,不過先把book_zh_TW.properties準備好…

1
2
3
java=Java 學習筆記的介紹 … BlaBla...
spring=Spring 技術手冊的介紹…BlaBla...
ajax=Ajax in action 中文版的介紹…

唔!裏頭是中文字,自己用native2ascii轉換吧…這也不是重點…我們是要看DWR怎麼做到文字提示功能…

一樣的…要開放這個Book物件,在dwr.xml中…

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN" 
"http://www.getahead.ltd.uk/dwr/dwr10.dtd">
 
<dwr>
  <allow>
  <create creator="new" javascript="Book" scope="application">
            <param name="class" value="onlyfun.caterpillar.Book"/>
        </create>  
  </allow>
</dwr>

scope設定為application,表示這個Book物件在整個應用程式階段都活著。

然後,客戶端寫個網頁…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=BIG5">
  <script type='text/javascript' src='dwr/interface/Book.js'></script>
  <script type='text/javascript' src='dwr/engine.js'></script>
  <script type='text/javascript' src='dwr/util.js'></script>
  <script type='text/javascript' src='book.js'></script>
<title>個人著/譯作</title>
</head>
<body>
 
      <div id="ajax" onmouseover="getBookData(this);"
 onmouseout="clearData();"><a
 href="http://www.gotop.com.tw/waweb2004/home/home.aspx?pg=HM010X&bn=AXP011800"><small><img
 style="border: 0px solid ; width: 80px; height: 110px; float: left;"
 alt="Ajax in action 中文版" title="Ajax in action 中文版"
 src="images/ajax_in_action_c.jpg" hspace="10" vspace="2"></small></a></div>
 
      <div id="spring" onmouseover="getBookData(this);"
 onmouseout="clearData();"><a
 href="http://www.gotop.com.tw/waweb2004/home/home.aspx?pg=HM010X&bn=ACL021000"><small><img
 style="border: 0px solid ; width: 80px; height: 110px; float: left;"
 alt="Spring 技術手冊" title="Spring 技術手冊"
 src="images/SpringTech_S.jpg" hspace="10" vspace="2"></small></a></div>
 
      <div id="java" onmouseover="getBookData(this);"
 onmouseout="clearData();"><a
 href="http://www.gotop.com.tw/waweb2004/home/home.aspx?pg=HM010X&bn=ACL020931"><small><img
 style="border: 0px solid ; width: 80px; height: 110px; float: left;"
 alt="Java 學習筆記" title="Java 學習筆記"
 src="images/JavaGossip_Cover_Small.jpg" hspace="10"
 vspace="2"></small></a></div>
 
    <br/><br/><br/><br/><br/><br/>
 
    <div id="info"></div>
 
</body>
</html>

重點在於onmouseover跟onmouseout,滑鼠移入與移出時會呼叫的函式,還有最下面的info,抓回來的書籍介紹會放到當中…

book.js如下,簡單的很…

1
2
3
4
5
6
7
8
9
10
11
function getBookData(ele) {
  Book.getDescription(ele.id, setBookData);
}
 
function setBookData(description) {
  DWRUtil.setValue('info', description);
}
 
function clearData() {
  DWRUtil.setValue('info', '');
}

程式很簡單,我懶得解釋了…XD

看一下畫面好了…這是滑鼠移到 Ajax in action中文版 上的介紹畫面…

 

的区别与作用

<context-param>的作用:
web.xml的配置中<context-param>配置作用
1. 启动一个WEB项目的时候,容器(如:Tomcat)会去读它的配置文件web.xml.读两个节点: <listener></listener> 和 <context-param></context-param>
2.紧接着,容器创建一个ServletContext(上下文),这个WEB项目所有部分都将共享这个上下文.
3.容器将<context-param></context-param>转化为键值对,并交给ServletContext.
4.容器创建<listener></listener>中的类实例,即创建监听.
5.在监听中会有contextInitialized(ServletContextEvent args)初始化方法,在这个方法中获得ServletContext = ServletContextEvent.getServletContext();
context-param的值 = ServletContext.getInitParameter(“context-param的键”);
6.得到这个context-param的值之后,你就可以做一些操作了.注意,这个时候你的WEB项目还没有完全启动完成.这个动作会比所有的Servlet都要早.
换句话说,这个时候,你对<context-param>中的键值做的操作,将在你的WEB项目完全启动之前被执行.
7.举例.你可能想在项目启动之前就打开数据库.
那么这里就可以在<context-param>中设置数据库的连接方式,在监听类中初始化数据库的连接.
8.这个监听是自己写的一个类,除了初始化方法,它还有销毁方法.用于关闭应用前释放资源.比如说数据库连接的关闭.
如:
<!– 加载spring的配置文件 –>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml,/WEB-INF/action-servlet.xml,/WEB-
INF/jason-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
又如: —>自定义context-param,且自定义listener来获取这些信息
<context-param>
<param-name>urlrewrite</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>cluster</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>servletmapping</param-name>
<param-value>*.bbscs</param-value>
</context-param>
<context-param>
<param-name>poststoragemode</param-name>
<param-value>1</param-value>
</context-param>
<listener>
<listener-class>com.laoer.bbscs.web.servlet.SysListener</listener-class>
</listener>
public class SysListener extends HttpServlet implements ServletContextListener {
private static final Log logger = LogFactory.getLog(SysListener.class);
public void contextDestroyed(ServletContextEvent sce) {
//用于在容器关闭时,操作
}
//用于在容器开启时,操作
public void contextInitialized(ServletContextEvent sce) {
String rootpath = sce.getServletContext().getRealPath(“/”);
System.out.println(“————-rootPath:”+rootpath);
if (rootpath != null) {
rootpath = rootpath.replaceAll(“\\\\“, “/”);
} else {
rootpath = “/”;
}
if (!rootpath.endsWith(“/”)) {
rootpath = rootpath + “/”;
}
Constant.ROOTPATH = rootpath;
logger.info(“Application Run Path:” + rootpath);
String urlrewrtie = sce.getServletContext().getInitParameter(“urlrewrite”);
boolean burlrewrtie = false;
if (urlrewrtie != null) {
burlrewrtie = Boolean.parseBoolean(urlrewrtie);
}
Constant.USE_URL_REWRITE = burlrewrtie;
logger.info(“Use Urlrewrite:” + burlrewrtie);
其它略之….
}
}
/*最终输出
————-rootPath:D:\tomcat_bbs\webapps\BBSCS_8_0_3\
2009-06-09 21:51:46,526 [com.laoer.bbscs.web.servlet.SysListener]-[INFO]
Application Run Path:D:/tomcat_bbs/webapps/BBSCS_8_0_3/
2009-06-09 21:51:46,526 [com.laoer.bbscs.web.servlet.SysListener]-[INFO]
Use Urlrewrite:true
2009-06-09 21:51:46,526 [com.laoer.bbscs.web.servlet.SysListener]-[INFO]
Use Cluster:false
2009-06-09 21:51:46,526 [com.laoer.bbscs.web.servlet.SysListener]-[INFO]
SERVLET MAPPING:*.bbscs
2009-06-09 21:51:46,573 [com.laoer.bbscs.web.servlet.SysListener]-[INFO]
Post Storage Mode:1
*/
context-param和init-param区别
web.xml里面可以定义两种参数:
(1)application范围内的参数,存放在servletcontext中,在web.xml中配置如下:
<context-param>
<param-name>context/param</param-name>
<param-value>avalible during application</param-value>
</context-param>
(2)servlet范围内的参数,只能在servlet的init()方法中取得,在web.xml中配置如下:
<servlet>
<servlet-name>MainServlet</servlet-name>
<servlet-class>com.wes.controller.MainServlet</servlet-class>
<init-param>
<param-name>param1</param-name>
<param-value>avalible in servlet init()</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
在servlet中可以通过代码分别取用:
package com.wes.controller;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
public class MainServlet extends HttpServlet …{
public MainServlet() …{
super();
}
public void init() throws ServletException …{
System.out.println(“下面的两个参数param1是在servlet中存放的”);
System.out.println(this.getInitParameter(“param1″));
System.out.println(“下面的参数是存放在servletcontext中的”);
System.out.println(getServletContext().getInitParameter(“context/param”));
}
}
第一种参数在servlet里面可以通过getServletContext().getInitParameter(“context/param”)得到
第二种参数只能在servlet的init()方法中通过this.getInitParameter(“param1″)取得.

与的区别与作用

<context-param>的作用:
web.xml的配置中<context-param>配置作用
1. 启动一个WEB项目的时候,容器(如:Tomcat)会去读它的配置文件web.xml.读两个节点: <listener></listener> 和 <context-param></context-param>
2.紧接着,容器创建一个ServletContext(上下文),这个WEB项目所有部分都将共享这个上下文.
3.容器将<context-param></context-param>转化为键值对,并交给ServletContext.
4.容器创建<listener></listener>中的类实例,即创建监听.
5.在监听中会有contextInitialized(ServletContextEvent args)初始化方法,在这个方法中获得ServletContext = ServletContextEvent.getServletContext();
context-param的值 = ServletContext.getInitParameter(“context-param的键”);
6.得到这个context-param的值之后,你就可以做一些操作了.注意,这个时候你的WEB项目还没有完全启动完成.这个动作会比所有的Servlet都要早.
换句话说,这个时候,你对<context-param>中的键值做的操作,将在你的WEB项目完全启动之前被执行.
7.举例.你可能想在项目启动之前就打开数据库.
那么这里就可以在<context-param>中设置数据库的连接方式,在监听类中初始化数据库的连接.
8.这个监听是自己写的一个类,除了初始化方法,它还有销毁方法.用于关闭应用前释放资源.比如说数据库连接的关闭.
如:
<!– 加载spring的配置文件 –>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml,/WEB-INF/action-servlet.xml,/WEB-
INF/jason-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
又如: —>自定义context-param,且自定义listener来获取这些信息
<context-param>
<param-name>urlrewrite</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>cluster</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>servletmapping</param-name>
<param-value>*.bbscs</param-value>
</context-param>
<context-param>
<param-name>poststoragemode</param-name>
<param-value>1</param-value>
</context-param>
<listener>
<listener-class>com.laoer.bbscs.web.servlet.SysListener</listener-class>
</listener>
public class SysListener extends HttpServlet implements ServletContextListener {
private static final Log logger = LogFactory.getLog(SysListener.class);
public void contextDestroyed(ServletContextEvent sce) {
//用于在容器关闭时,操作
}
//用于在容器开启时,操作
public void contextInitialized(ServletContextEvent sce) {
String rootpath = sce.getServletContext().getRealPath(“/”);
System.out.println(“————-rootPath:”+rootpath);
if (rootpath != null) {
rootpath = rootpath.replaceAll(“\\“, “/”);
} else {
rootpath = “/”;
}
if (!rootpath.endsWith(“/”)) {
rootpath = rootpath + “/”;
}
Constant.ROOTPATH = rootpath;
logger.info(“Application Run Path:” + rootpath);
String urlrewrtie = sce.getServletContext().getInitParameter(“urlrewrite”);
boolean burlrewrtie = false;
if (urlrewrtie != null) {
burlrewrtie = Boolean.parseBoolean(urlrewrtie);
}
Constant.USE_URL_REWRITE = burlrewrtie;
logger.info(“Use Urlrewrite:” + burlrewrtie);
其它略之….
}
}
/*最终输出
————-rootPath:D:tomcat_bbswebappsBBSCS_8_0_3
2009-06-09 21:51:46,526 [com.laoer.bbscs.web.servlet.SysListener]-[INFO]
Application Run Path:D:/tomcat_bbs/webapps/BBSCS_8_0_3/
2009-06-09 21:51:46,526 [com.laoer.bbscs.web.servlet.SysListener]-[INFO]
Use Urlrewrite:true
2009-06-09 21:51:46,526 [com.laoer.bbscs.web.servlet.SysListener]-[INFO]
Use Cluster:false
2009-06-09 21:51:46,526 [com.laoer.bbscs.web.servlet.SysListener]-[INFO]
SERVLET MAPPING:*.bbscs
2009-06-09 21:51:46,573 [com.laoer.bbscs.web.servlet.SysListener]-[INFO]
Post Storage Mode:1
*/
context-param和init-param区别
web.xml里面可以定义两种参数:
(1)application范围内的参数,存放在servletcontext中,在web.xml中配置如下:
<context-param>
<param-name>context/param</param-name>
<param-value>avalible during application</param-value>
</context-param>
(2)servlet范围内的参数,只能在servlet的init()方法中取得,在web.xml中配置如下:
<servlet>
<servlet-name>MainServlet</servlet-name>
<servlet-class>com.wes.controller.MainServlet</servlet-class>
<init-param>
<param-name>param1</param-name>
<param-value>avalible in servlet init()</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
在servlet中可以通过代码分别取用:
package com.wes.controller;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
public class MainServlet extends HttpServlet …{
public MainServlet() …{
super();
}
public void init() throws ServletException …{
System.out.println(“下面的两个参数param1是在servlet中存放的”);
System.out.println(this.getInitParameter(“param1″));
System.out.println(“下面的参数是存放在servletcontext中的”);
System.out.println(getServletContext().getInitParameter(“context/param”));
}
}
第一种参数在servlet里面可以通过getServletContext().getInitParameter(“context/param”)得到
第二种参数只能在servlet的init()方法中通过this.getInitParameter(“param1″)取得.

Spring基本配置

1.         配置AOP

<!– 切面表达式匹配服务层的所有操作方法 –>
    <aop:aspectj-autoproxy />
    <aop:config>

       <aop:pointcut id=”serviceMethods” expression=”execution(* com.eway.test.TestService.*(..))”/>

       <aop:advisor advice-ref=”txadvice” pointcut-ref=”serviceMethods”/>

    </aop:config>

切入范围:execution(* com.eway.test.TestService.*(..))

<aop:advisor> 指定事务方法(通知)

<aop:pointcut>方法(通知)源于特定的类或者方法

2.         配置事务通知

<!– 通知事务 –>

    <tx:advice id=”txadvice” transaction-manager=”TxManager”>

       <tx:attributes>

           <!–需要用到的事务方法 –> 

           <!– Set query transaction timeout –>
            <tx:method name=”get*” propagation=”REQUIRED” timeout=”60″ read-only=”true” />
            <tx:method name=”has*” propagation=”REQUIRED” timeout=”60″ read-only=”true” />
            <tx:method name=”query*” propagation=”REQUIRED” timeout=”60″ read-only=”true” />
            <tx:method name=”search*” propagation=”REQUIRED” timeout=”60″ read-only=”true” />
            <!– Set update transaction timeout: 2 min –>
            <tx:method name=”*” propagation=”REQUIRED” timeout=”120″ rollback-for=”ItemExistsException” />

       </tx:attributes>

    </tx:advice>

3.         配置事务

<!– 配置事务 –>

    <bean id=”TxManager”>

    <property name=”dataSource” ref=”DataSource”></property>

    </bean>

4.         配置数据源:省略

Spring事务和EJB事务相比

l         Spring声明式事务在任何环境下都可以使用,只需要修改配置文件,它就可以和JDBC,JDO,Hibernate或和其他的事务机制一起使用,而EJB的CMT(声明式事务管理)是绑定在JTA上

l         Sprin提供了回滚规则,而EJB没有

l         Sprin允许通过AOP(切面)定制事务,可以随意添加任何事务通知,而EJB除了通过setRollbackOnly(),就没有办法影响容器管理事务了

l         EJB事务可以跨越远程,而Sprin不提供

对Spring事务总结:关于spring的事务配置由三个部分组成,分别是:DataSource(数据源),TransactionManager(事务管理器),代理机制。无论哪种事务配置方式,一般变化的是代理机制这部分。

对Spring的理解

    Spring是一个轻量级的控制反转(IOC)和面向切面编程的框架

        IOC: 将类的主动权移交给接口,通过容器实例化对象(容器通过反射机制创建对象)

        AOP:在修改源代码的情况下给系统加一个新的功能或者技术(例如:一个登录程序,现在想记录登录日记,在不修改源代码的基础上,使用AOP写一个方法(称为通知)可以实现)

同时Spring提供支持事务,校验等等,使开发人员更容易编写更干净,更容易管理,更方便测试的代码。

String int 转换?

1 如何将字串 String 转换成整数 int?

A. 有两个方法:

1). int i = Integer.parseInt([String]); 或
i = Integer.parseInt([String],[int radix]);

2). int i = Integer.valueOf(my_str).intValue();

注: 字串转成 Double, Float, Long 的方法大同小异.

2 如何将整数 int 转换成字串 String ?

A. 有叁种方法:

1.) String s = String.valueOf(i);

2.) String s = Integer.toString(i);

3.) String s = “” + i;

注: Double, Float, Long 转成字串的方法大同小异.

Date和String的转换

 import java.text.DateFormat; 
 import java.text.SimpleDateFormat; 
 import java.text.ParseException; 
 import java.util.Calendar; 
 import java.util.Date; 
 
 
 DateFormat format = new SimpleDateFormat("yyyy-MM-dd");         
             Date date = null;    
            String str = null;                  
                       
            // String转Date    
            str = "2007-9-26";          
            try {    
                date = format.parse(str);  // Wed sep 26 00:00:00 CST 2007    
            } catch (ParseException e) {    
                e.printStackTrace();    
            }    
                        
            date = java.sql.Date.valueOf(str);  // 只保留日期部分,返回的是java.sql.Date  2007-9-26    
                        
            // Date转String    
            date = new Date();   // Wed sep 26 18 17:14:01 CST 2007       
            str = format.format(date);  // 2007-9-26    
                        
            format = DateFormat.getDateInstance(DateFormat.SHORT);    
            str = format.format(date);  // 07-9-26    
                        
            format = DateFormat.getDateInstance(DateFormat.MEDIUM);    
            str = format.format(date);  // 2007-9-26   
                        
            format = DateFormat.getDateInstance(DateFormat.FULL);    
            str = format.format(date);  // 2007年9月26日 星期三   

Spring事务管理(个人理解)

就给个实例,记录下。慢慢理解,有写的不好的地方需要提高。先理解思想就好~

bean.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
	<!-- 启动注解 -->
	<context:annotation-config/>
	
	<!-- 定义数据源 -->
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
		<property name="driverClassName" value="org.gjt.mm.mysql.Driver"/>
	    <property name="url" value="jdbc:mysql://localhost:3306/weboutlook?useUnicode=true&amp;characterEncoding=UTF-8"/>
	    <property name="username" value="root"/>
	    <property name="password" value=""/>
	    <!-- 连接池启动时的初始值 -->
		<property name="initialSize" value="1"/>
		<!-- 连接池的最大值 -->
		<property name="maxActive" value="500"/>
		<!-- 最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 -->
		<property name="maxIdle" value="2"/>
		<!--  最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 -->
		<property name="minIdle" value="1"/>
	</bean>
	
	<!-- 配置sessionFactory -->
	<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<property name="dataSource" ref="dataSource"/>
		<property name="mappingResources">
			<list>
				<value>cn/kinca/weboutlook/beans/User.hbm.xml</value>
				<value>cn/kinca/weboutlook/beans/Email.hbm.xml</value>
				<value>cn/kinca/weboutlook/beans/ReceivedEmail.hbm.xml</value>
				<value>cn/kinca/weboutlook/beans/SentEmail.hbm.xml</value>
		    </list>
		</property>
		<property name="hibernateProperties">
			<value>
		        hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
		        hibernate.hbm2ddl.auto=update
		        hibernate.show_sql=true
		        hibernate.format_sql=false
		        hibernate.cache.use_second_level_cache=true
       	        hibernate.cache.use_query_cache=false
        	    hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider
			</value>
		</property>
	</bean>
	<!-- 配置事务管理 操作数据库时要不全成功要不全失败-->
	<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory"/>
	</bean>
	<!-- 配置事务传播特性,这里使用注解方式 -->
	<tx:annotation-driven transaction-manager="txManager"/>
	
	<!-- 交由Spring管理的Action类 -->
	<bean id="userService" class="cn.kinca.weboutlook.serviceimpl.UserServiceImpl"/>
	<bean id="emailService" class="cn.kinca.weboutlook.serviceimpl.EmailServiceImpl"/>
	<!-- cn.itcast.web.PersonAction类中的personService由spring通过注解注入上面personService的值,如果不通过注解需要加properties -->
	<bean id="userAction" class="cn.kinca.weboutlook.web.UserAction"/>
	<bean id="emailAction" class="cn.kinca.weboutlook.web.EmailAction"/>
</beans>

ServerImpl.java

@Transactional
public class EmailServiceImpl implements EmailService {
	@Resource private SessionFactory sessionFactory;
	public void emailadd(Email email) {
		sessionFactory.getCurrentSession().persist(email);
	}
	
	@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
	public Set<Email> emailload() {
		User user = (User) sessionFactory.getCurrentSession().get(User.class, (Integer)ActionContext.getContext().getSession().get("userid"));
		//这里有个懒加载的问题。使用openSessionInView好像不起作用,不的什么原因
		System.out.println(user.getEmails());
		return user.getEmails();
	}
	
	@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
	public boolean checkUId(List<String> uIds,String uId){
		//遍历list内容,与uid比较
		System.out.println("-------------");
        for(String cUId:uIds){
        	System.out.println(cUId);
        	if(cUId.equals(uId))return false;
        }
		return true;
	}
	//从邮件服务器读取邮件并保存到系统数据库,并读取总的邮件条数
	public int loadReceivedEmail(int emailid) throws Exception {
		/**
		 * 注意UID与MessageID并非一个东西,
		 * UID是邮箱用来标识你这个账户的每一封邮件的东西,
		 * 而MessageID是发送邮件的时候生成的唯一ID,
		 * 也有可能发送没有你的接收邮箱自己生成,或者是javamail生成的,
		 * 总是取messageid需要下载邮件的头,这样有联网操作会很慢的,所以我们只需要存储下来uid就好了,
		 * 记得保存的时候按照邮箱存储,因为不同的邮箱uid会重复的,
		 * 至于规律最好别去参考有增的就有减的,所以还是安心的遍历吧,反正很快
		 */
		//Set<ReceivedEmail> receivedEmails=new HashSet();
		List<String> uIds=new ArrayList();
		List<ReceivedEmail> receivedEmails=new ArrayList();
		//配置邮件服务器连接信息
		Email email=(Email)sessionFactory.getCurrentSession().get(Email.class, emailid);
		Properties props = System.getProperties();   
        props.put("mail.smtp.host", email.getSmtp());   
        props.put("mail.smtp.auth", "true");   
        Session session = Session.getDefaultInstance(props, null);   
        URLName urln = new URLName("pop3", email.getPop3(), 110, null,   
                email.getEmail(), email.getPassword());   
        Store store = session.getStore(urln);   
        store.connect();   
        Folder folder = store.getFolder("INBOX");   
        folder.open(Folder.READ_ONLY);   
        Message message[] = folder.getMessages();   
        POP3Folder inbox = (POP3Folder) folder;
       // System.out.println("Messages's length: " + message.length);   
        EmailReceive pmm = null;   
        
        //从数据库中读取该邮箱对应的所有邮件的uid放入list集合中
        Criteria cr=sessionFactory.getCurrentSession().createCriteria(ReceivedEmail.class);
        cr.add(Restrictions.eq("belongemail.id", emailid));
        receivedEmails=cr.list();
        for(ReceivedEmail re:receivedEmails){
        	uIds.add(re.getUid());
        }
        //首先判断该邮件uid是否存在,如不存在则下载该邮件,否则不处理
        for (int i = 0; i < message.length; i++) {  
	        if(checkUId(uIds,inbox.getUID(message[i]))){
	        	try { 
	        		//下载邮件并放入/mail/用户名/receivedemails文件下
	        		String userPath=(String) ActionContext.getContext().getSession().get("username");
	        		String realpath=ServletActionContext.getServletContext().getRealPath("/mail/"+userPath+"/receivedemails");
	        		File emailFilePath=new File(new File(realpath),new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date())+".eml");
	        		if(!emailFilePath.getParentFile().exists())emailFilePath.getParentFile().mkdirs();
	        		OutputStream ips = new FileOutputStream(emailFilePath.getPath());
	        		message[i].writeTo(ips);
	        		ips.close();
		            pmm = new EmailReceive((MimeMessage) message[i]);  
		            ReceivedEmail receivedEmail=new ReceivedEmail();
		            receivedEmail.setUid(inbox.getUID(message[i]));
		            receivedEmail.setSender(pmm.getFrom());
		            receivedEmail.setToAddress(pmm.getMailAddress("to"));
		            receivedEmail.setCcAddress(pmm.getMailAddress("cc"));
		            receivedEmail.setBccAddress(pmm.getMailAddress("bcc"));
		            receivedEmail.setSubject(pmm.getSubject());
		            receivedEmail.setSendtime(pmm.getSentDate());
		            pmm.getMailContent((Part) message[i]);
		            receivedEmail.setContent(pmm.getBodyText());
		            
		            receivedEmail.setBelongemail(email);
	    
		            sessionFactory.getCurrentSession().persist(receivedEmail);
		            
		            //receivedEmails.add(receivedEmail);
		            /*String rmsg=null;
		            System.out.println("Message " + i + " subject: " + pmm.getSubject());   --
		            System.out.println("Message " + i + " sentdate: "+ pmm.getSentDate());   --
		            System.out.println("Message " + i + " replysign: "+ pmm.getReplySign());   
		            System.out.println("Message " + i + " hasRead: " + pmm.isNew());   
		            System.out.println("Message " + i + "  containAttachment: "+ pmm.isContainAttach((Part) message[i]));   
		            System.out.println("Message " + i + " form: " + pmm.getFrom());   --
		            System.out.println("Message " + i + " to: "+ pmm.getMailAddress("to"));  -- 
		            System.out.println("Message " + i + " cc: "+ pmm.getMailAddress("cc"));   --
		            System.out.println("Message " + i + " bcc: "+ pmm.getMailAddress("bcc"));   --
		            pmm.setDateFormat("yy年MM月dd日 HH:mm");   
		            System.out.println("Message " + i + " sentdate: "+ pmm.getSentDate());   
		            System.out.println("Message " + i + " Message-ID: "+ pmm.getMessageId());   
		            // 获得邮件内容===============   
		            pmm.getMailContent((Part) message[i]);   
		            System.out.println("Message " + i + " bodycontent: \r\n"   
		                    + pmm.getBodyText());   
		            pmm.setAttachPath("c:\\aaaa\\");    
		            pmm.saveAttachMent((Part) message[i]);  
		             
		            rmsg="Message " + i + " subject: " + pmm.getSubject()
		            	+"\r\nMessage " + i + " sentdate: "+ pmm.getSentDate()
		            	+"\r\nMessage " + i + " replysign: "+ pmm.getReplySign()
		            	+"\r\nMessage " + i + " hasRead: " + pmm.isNew()
		            	+"\r\nMessage " + i + "  containAttachment: "+ pmm.isContainAttach((Part) message[i])
		            	+"\r\nMessage " + i + " form: " + pmm.getFrom()
		            	+"\r\nMessage " + i + " to: "+ pmm.getMailAddress("to")
		            	+"\r\nMessage " + i + " cc: "+ pmm.getMailAddress("cc")
		            	+"\r\nMessage " + i + " bcc: "+ pmm.getMailAddress("bcc");
		            pmm.setDateFormat("yy年MM月dd日 HH:mm");
		            rmsg = rmsg + "\r\nMessage " + i + " sentdate: "+ pmm.getSentDate()
		            	+"\r\nMessage " + i + " Message-ID: "+ pmm.getMessageId();
		            // 获得邮件内容===============   
		            pmm.getMailContent((Part) message[i]);   
		            rmsg = rmsg +"\r\nMessage " + i + " bodycontent: \r\n"   
		                    + pmm.getBodyText();   
		            pmm.setAttachPath("c:\\aaaa\\");    
		            pmm.saveAttachMent((Part) message[i]); 
		            OutputStream rms = new FileOutputStream("resource\\demo3.log",true);
		            rms.write(rmsg.getBytes());
		    		rms.close();
		    		*/
	        	} catch (Exception ex) {
	    			ex.printStackTrace();
	    		}
	        }
        }
        return ((Long)sessionFactory.getCurrentSession().createQuery("select count(*) from ReceivedEmail where belongemail.id=:emailid").setInteger("emailid", emailid).iterate().next()).intValue();  
       //System.out.println("receivedEmails.size()"+receivedEmails.size());
       //return receivedEmails;
	}

	//从数据库把邮件导入到set集合中并且在center页面显示,由于有分页,所以不考虑在loadReceivedEmail()方法中吧邮件放入set集合
	/* (non-Javadoc)
	 * @see cn.kinca.weboutlook.service.EmailService#showReceivedEmail(int, int)
	 */
	@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
	public List<ReceivedEmail> showReceivedEmail(int emailid,int page){
		List<ReceivedEmail> receivedEmails=new ArrayList();
		Criteria cr=sessionFactory.getCurrentSession().createCriteria(ReceivedEmail.class);
		cr.add(Restrictions.eq("belongemail.id", emailid));
		cr.setFirstResult((page-1)*20);
		cr.setMaxResults(20);
		receivedEmails= cr.list();
		return receivedEmails;
	}
	
	//从email表读取发信email的pop3,smtp等信息
	@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
	public Email loadEmailData(int emailid){
		return (Email) sessionFactory.getCurrentSession().get(Email.class, emailid);	
	}

	//保存发送的邮件到数据库
	public void saveSentEmail(SentEmail sentEmail) {
		sessionFactory.getCurrentSession().persist(sentEmail);	
	}
}

ClassLoader如何加载class

jvm里有多个类加载,每个类加载可以负责加载特定位置的类,例如,
bootstrap加载负责加载jre/lib/rt.jar中的类, 我们平时用的jdk中的类都位于rt.jar中。
extclassloader负责加载jar/lib/ext/*.jar中的类,
appclassloader负责classpath指定的目录或jar中的类。
除了bootstrap之外,其他的类加载器本身也都是java类,它们的父类是ClassLoader。

Java 默认修饰符

1.       类(class

可见性修饰符: public—在所有类中可见,在其他包中可以用import导入。

             缺省—就是没有修饰符,在同一个包中的类中可见,在其他包中不能用import导入。

              修饰符:final—终态类,表示该类不能被继承

                            abstract抽象类,不能新建对象

2.       变量(variable

Java中变量有两种,方法变量和字段变量

方法变量只能用一个修饰符:final—表示常量,不能修改

下面是字段变量的修饰符

        可见性修饰符:public在任何类中可见

                             protected       在子类中或同一个包中可见

                             private—只在本类中可见,子类中也不可见

                             缺省—在同一个包中可见,子类不在一个包中,子类中也不可见  

        修饰符:static—静态变量,被类的所有实例共享

                      final—常量,定义后不能修改

*transient告诉编译器,在类对象序列化的时候,此变量不需要持久保存

*volatile—指出可能有多个线程修改此变量,要求编译器优化以保证对此变量的修改能够被正确的处理

这两带*的不是很常用,但也是Java的修饰符,我也不是很清楚

3.方法(method)

   可见性修饰符:public在任何类中可见

                             protected—在子类中或同一个包中可见

                             private—只在本类中可见,子类中也不可见

                                   缺省—在同一个包中可见,子类不在一个包中,子类中也不可见

   修饰符: static—静态方法,并不需要创建类的实例就可以访问静态方法

                      final—常方法,所有子类不能覆盖该方法,但可以重载

                      abstract—抽象方法,在抽象类中没有实现的方法

                      native—本地方法,参见Java Native Interface(JNI)

synchronized 在多线程中,synchronized方法调用时,其他所有方法不能调用该方法

3.       接口(interface

         可见性修饰符:public—所有类中可见

                       缺省—同一个包中可见

         接口中的变量总是需要定义为public static final 接口名称,但可以不包含这些修饰符,编译器默认就是这样  

     

         接口中的方法只能使用publicabstract修饰符     

JAVA线程创建各个方法

*******************************************
第一种方法
*******************************************
new Thread(){
public void run(){
//操作代码

}.start()
—————–等价于——————–
public class extendthread extends thread {
public void run() {
//操作代码
}
public static void main(string[] args) {
extendthread t = new extendthread();
t.start();
}
}

*******************************************
第二种方法
*******************************************
new Thread(new Runable(){
public void run(){
//操作代码

}).start()
—————–等价于——————–
public class implementrunnable implements runnable {
public void run() {
//操作代码
}
public static void main(string[] args) {
implementrunnable runnable = new implementrunnable();
thread t = new thread(runnable);
t.start();
}
}