2007-03-15

数据持久化Hibernate的标准数据库连接池配置

以TOMCAT+MySql为例,Hibernate有两种连接数据库的方式:
1、Hibernate自行管理的数据库连接池
2、Hibernate使用当前容器配置的连接池
Hibernate+TOMCAT配置数据库连接池标准过程。
准备工作:
1、www.Hibernate.org下载最新的Hibernate,建议3.0
版。
2、安装了MYSQL,并且将MYSQL驱动复制到TOMCAT中的common\lib下。
3、在TOMCAT中建立一个新的WEB应用(这还不会的话就不要学
了)。
4、将Hibernate下的类库--LIB文件夹下的所有JAR复制到
WEB应用WEB-INF/lib下。
5、在WEB应用WEB-INF/classes目录下建立hibernate.cfg.xml文
件,内容如下:
<?xml version='1.0' encoding='GBK'?>
<!DOCTYPE hibernate-configuration
PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
实际上这一步建立的是个尚未有任何配置的XML文件。
一、Hibernate自行管理的数据库连接池
顾名思义,Hibernate框架包含了自己的管理数据库连接的方法,
这一切只需要配置hibernate.cfg.xml文件即可。
完整的hibernate.cfg.xml:
<?xml version='1.0' encoding='GBK'?>
<!DOCTYPE hibernate-configuration
PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
<!--Hibernate self-manager connection pool-->
<hibernate-configuration>
<session-factory>
<property name="show_sql">true</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/nihongo?useUnicode=true</property>
<property name="connection.username">root</property>
<property name="connection.password">kevin</property>
<mapping resource="cat/Cat.hbm.xml"/>
</session-factory>
</hibernate-configuration>
以上各属性值请依照自己的情况修改即可。

二、Hibernate使用当前容器配置的连接池
容器(如TOMCAT)建立连接池,并配置JNDI,Hibernate通过调用JNDI来
使用容器的连接池。
这中方式稍微有点复杂,需要配置三个XML文件:
1、%TOMCAT_HOME%/conf/server.xml
在server.xml中,</host>这之前加入如下WEB应用上下文配置:
<Context path="/quickstart" docBase="quickstart" debug="0" >
<Resource name="jdbc/MySql5" auth="Container"
type="javax.sql.DataSource" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/nihongo?useUnicode=true"
username="root" password="kevin" maxActive="100" maxIdle="10"
maxWait="-1"/></Context>
2、完整的hibernate.cfg.xml:
<?xml version='1.0' encoding='GBK'?>
<!DOCTYPE hibernate-configuration
PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
<!--Hibernate use JNDI to access container's connection pool-->
<hibernate-configuration>
<session-factory>
<property name="connection.datasource">java:comp/env/jdbc/MySql5</property>
<property name="show_sql">true</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<mapping resource="cat/Cat.hbm.xml"/>
</session-factory>
</hibernate-configuration>
3、WEB应用的web.xml文件:
在web.xml的</web-app>之前加入如下配置:
<!--Hibernate use container's connection pool-->
<resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/MySql5</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
以上,2种配置Hibernate连接数据库的方式,具体差异本人尚不完全明确。
朋友们可自行编写测试代码测试。具体的Hibernate应用API等请直接查阅
其中文文档。

2007-03-13

Struts+Spring+Hibernate练习

工具:
Eclipse3.1、MyEclipse4.03、Tomcat5.5.9、Properties Editor插件、MySql4.1.13

新建工程:名称为 login

创建Struts框架

创建 index.jsp,增加一链接指向 login.jsp

按下Ctrl + N,创建 login.jsp、LoginAction,使用MyEclipse的向导就可以了,记得选对正确的版本

在ActionForm配置页中选择类型为动态Form,并继承于DynaValidatorForm,新增两个属性:username、password,在创建jsp文件打上钩,将路径改为/login.jsp,然后下一步,改LoginAction的Input source改为/login.jsp,点击完成

按下Ctrl + N 创建一个forwards,记得选对正确的版本
name 输入 indexGo
路径选择 /index.jsp

配置validator
先添加Struts插件,使用向导
Plugin class : org.apache.struts.validator.ValidatorPlugIn
Property : pathnames
Value : /WEB-INF/validator-rules.xml,/WEB-INF/validation.xml
这里需要两个xml文件
现在创建“validation.xml” 文件

在这里说明一点,我使用MyEclipse创建的Struts框架中缺少了validator-rules.xml文件,需要动拷贝到WEB-INF目录中
此文件可以到http://struts.apache.org/下载

文件内容如下:
<form-validation>
<formset>
<form name="loginForm">
<field property="username" depends="required">
<arg0 key="prompt.username" />
</field>
<field property="password" depends="required">
<arg0 key="prompt.password" />
</field>
</form>
</formset>
</form-validation>

编辑资源文件“ApplicationResources.properties”
增加以下内容

prompt.username=User Name
prompt.password=User Password
errors.required={0} is required.

再创建中文件资源文件“ApplicationResources_zh_CN.properties”
增加以下内容
prompt.username=用户名称
prompt.password=登录密码
errors.required={0} 必需填写!

修改struts-config.xml文件
在以下位置增加绿色字体部份
<action-mappings >
<action
attribute="loginForm"
input="/login.jsp"
name="loginForm"
path="/login"
scope="request"
validate="true"
type="com.test.struts.action.LoginAction" />
</action-mappings>

这里说明提交的数据必需经过验证,而验证则是通过validator框架进行的。

修改LoginAction.java文件的execute方法,内容如下
public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) {
DynaValidatorForm loginForm = (DynaValidatorForm) form;
String username=loginForm.getString("username");
String password=loginForm.getString("password");
if(username.equals("test")||password.equals("test")){
return mapping.findForward("indexGo");
}else{
return mapping.getInputForward();
}
}

现在再修改一下login.jsp
增加以下绿色字体部份
<%@ page language="java" contentType="text/html; charset=UTF-8" %>

其中charset=UTF-8 是使用UTF-8的字符编码,这也是为了支持国际化而使用的。

好了,现在可以启动Tomcat进行测试了
http://localhost/login/ 这里说明一下,我的Tomcat已经装端口号改为80了,所以就不必使用http://localhost:8080/login/这样的方法了。

如果不输入任何数据而直接提交表单的话就可以看到效果了。

好了,如果没有什么问题的话就继续往下看吧,如果有问题的话就得往上看了^_^

现在创建Spring框架了,在这里我将Spring所有的包全部加载进去,因为我还不知道具体用到哪些类,全部加进去方便点

单选框选第二个,这样的话所有的类库和标签等都将拷贝到项目中去,这样方便以后的布署
下一步后是创建配置文件,将文件放到“WebRoot/WEB-INF”目录下,文件名称为“applicationContext.xml”


配置struts-config.xml文件,添加(spring)的插件

<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation" value="/WEB-INF/applicationContext.xml" />
</plug-in>


修改LoginAction配置

原:
<action
attribute="loginForm"
input="/login.jsp"
name="loginForm"
path="/login"
scope="request"
validate="true"
type="com.test.struts.action.LoginAction" />

</action-mappings>

改为:
<action
attribute="loginForm"
input="/login.jsp"
name="loginForm"
path="/login"
scope="request"
validate="true"
type="org.springframework.web.struts.DelegatingActionProxy" />
</action-mappings>


绿色字体部份为修改内容
这里将使用spring的代理器来对Action进行控制

当提交到/login.do是将控制权交给了spring,然后由spring来决定是否转回到struts的Action

现在来配置spring

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<bean name="/login" class="com.test.struts.action.LoginAction" singleton="false"></bean>
</beans>

绿色字体是关于转交控制权的配置内容

属性singleton="false",指明了Action 的实例获取方式为每次重新创建。解决了Struts中令人诟病的线程安全问题(Struts中,由一个Action实例处理所有的请求,这就导致了类公用资源在并发请求中的线程同步问题。)(摘自spring开发指南)

这时如果你要进行测试也是可以的,不过为了省点时间就不进行测试了。

建立数据库在 这里我使用的是mysql4.1.13

CREATE TABLE `user` (
`ID` int(11) NOT NULL auto_increment,
`USERNAME` varchar(50) NOT NULL default '',
`PASSWORD` varchar(50) NOT NULL default '',
PRIMARY KEY (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

添加记录 insert into user (USERNAME,PASSWORD) values ('test','test')

创建Hibernate框架
在配置界面中配置数据库的连接部份,重要的是点击链接将jdbc拷贝到lib目录中
使用MyEclipse的数据Database Explorer工具创建User.hmb.xml、AbstractUser.java、User.java映射文件
创建完成后可以将自动生成的hibernate.cfg.xml删除

创建UserDAO.java、UserDAOImp.java
UserDAO.java
public interface UserDAO {
public abstract boolean isValidUser(String username, String password);
}

UserDAOImp.java
import java.util.List;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import com.test.Hibernate.SessionFactory;
public class UserDAOImp extends HibernateDaoSupport implements UserDAO {
private SessionFactory sessionFactory;
private static String hql = "from User u where u.username=? ";
public boolean isValidUser(String username, String password) {
List userList = this.getHibernateTemplate().find(hql, username);
if (userList.size() > 0) {
return true;
}
return false;
}
}

修改LoginAction.java文件,使用userDao的方法来进行用户验证
package com.test.struts.action;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.validator.DynaValidatorForm;

import com.test.UserDAO;

public class LoginAction extends Action {

private UserDAO userDAO;

public UserDAO getUserDAO() {
return userDAO;
}

public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}

public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
DynaValidatorForm loginForm = (DynaValidatorForm) form;
// TODO Auto-generated method stub
String username = (String) loginForm.get("username");
String password = (String) loginForm.get("password");
loginForm.set("password", null);
if (userDAO.isValidUser(username,password)) {
return mapping.findForward("indexGo");
} else {
return mapping.getInputForward();
}
}
}
绿色字体为修改部份

现在剩下最后的spring配置了
<?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="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost/test</value>
</property>
<property name="username">
<value>root</value>
</property>
<property name="password">
<value>root</value>
</property>
</bean>

<!-- 配置sessionFactory, 注意这里引入的包的不同 -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref local="dataSource" />
</property>
<property name="mappingResources">
<list>
<value>com/test/Hibernate/User.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>

<bean id="userDAO" class="com.test.UserDAOImp">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>

<bean id="userDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<property name="target">
<ref local="userDAO" />
</property>
<property name="transactionAttributes">
<props>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="is*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>

<bean name="/login" class="com.test.struts.action.LoginAction" singleton="false">
<property name="userDAO">
<ref bean="userDAOProxy" />
</property>
</bean>
</beans>

现在可以进行测试了!

在编写代码有配置内容时一定要注意 hibernate 和 hibernate3 ,这两个包的名字就只差一个字,千万不要有错,否则找错误可是很难的。

Eclipse下配置spring应用

一. 关于Spring的环境配置问题。
需要的包(除了基本java web开发环境(如jdk,tomcat )之外的):spring-framework,jakarta-struts(后面有关于spring与struts结合的部分要用到).
二. 关于Spring的基本配置文件(我个人感觉,学习开发框架时,在明白了它的设计思想之后,配置文件设置是一个关键,等成功搭建起这个框架之后,在里面编程相信都难不到大家的)

在建立单纯的spring项目时,web.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<!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>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/application.xml</param-value>
</init-param>
上面加框的一段是用来指定spring配置文件的(可以为任意名,如上),也可以不写,不写时spring的配置文件默认名为: “<servlet-name>”名-servlet.xml。(如此处的<servlet-name>的值为“spring”,则配置文件名为:springt-servlet.xml)
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>


这时候spring配置文件(这里假定为spring-servlet.xml)如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<!-- - Application context definition for "springapp" DispatcherServlet. -->
<beans>
<bean id="LoginAction" class="com.ln.spring.LoginAction">
在bean中配置有属性(包括bean格式的属性)时,bean对应的java文件内必须要定义一个与property的name名字一样的属性值,并且需要有这个属性值的getter和setter方法。
<property name="msg">
<value>Hello World</value>
</property>
<property name="data">
<ref bean="data1" />
当一个bean中有格式为bean的属性时,用“<ref bean="bean-name" />”来指定,在指定”bean-name”后还要在下面用”<bean></bean>”来指定这个bean格式的属性的值,此时”<bean></bean>”中的”id”必须与前面指定的”bean-name”一致。
</property>
</bean>
<bean id="data1" class="com.ln.spring.MyAction">
<property name="message">
<value>liang</value>
</property>
</bean>
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/login.do">LoginAction</prop>
</props>
</property>
</bean>
</beans>

而在建立spring+struts项目时,web.xml文件按照struts项目的规格建立,在此不在多说,而在此时struts-config.xml如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
<form-beans>
<form-bean name="loginForm" type="com.ln.struts.LoginForm" />
</form-beans>
<action-mappings>
<action path="/login"
type="org.springframework.web.struts.DelegatingActionProxy"
name="loginForm">
<forward name="success" path="/main.jsp" />
<forward name="failure" path="/loginfail.jsp" />
</action>
</action-mappings>
<plug-in
className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation"
value="/WEB-INF/spring-servlet.xml" />
</plug-in>
</struts-config>
在这个配置文件中,由于使用spring来管理struts的action所以有两个地方要注意:
1. Action的”type”指向spring里定义的用来处理action的类,而不是自己写的action.
2.增加了一个”<plug-in></plug-in>“来指定spring配置文件。


此时spring-servlet.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 name="/login" class="com.ln.struts.LoginAction"
singleton="false">
此处的bean与struts-config.xml中的action相对应,name与struts-config.xml中action的path一致
<property name="msg">
<value>Hello World</value>
</property>
</bean>
</beans>

三. 应该注意的小问题:
1. 要把开发中所需要用到的包,tld文件相应地放在WEB-INF里的lib,tlds文件夹中。
2. 在需要使用到struts,spring,jstl等的标签时,一定要在web.xml中
用下面
<taglib>
<taglib-uri>http://java.sun.com/jstl/core</taglib-uri>
<taglib-location>/WEB-INF/c.tld</taglib-location>
</taglib>
这样的标签先进行声明。

2007-03-09

BIOS控制:从底层保障计算机系统安全[转贴]

纵观市场上的安全产品,从网络防火墙到各种网络加密、个人数字签证以及早期硬盘锁,均未能对 个人计算机本身进行实质性的保护。这些安全机制大都基于这样一种原理:利用一个软件,输入一个特定的密码,经过验证后即可获得合法身份,从而实现各种操 作,如购物、收发公文、浏览甚至修改机密数据。众所周知,这种基于纯密码的机制是很脆弱的,所以,许多关键行业和部门都采用了软、硬结合的方式,如设立各 种Smart卡认证机制。在银行工作的职工,每人都有一张代表自己电子身份的IC卡,每天上班,必须先刷卡才能进入银行的业务系统。这种机制的安全性大大 提高了,但对于个人或普通企业用计算机,这种机制成本太高。本文从BIOS工作原理出发,提出一种安全性高、全新的计算机安全保护机制。

一、原理

BIOS是计算机架构中最为底层的软件。在PC一加电时,首先执行的就是它,它负责 对计算机进行自检和初始化,在检查PC各部件都正常后再由它引导操作系统,如DOS、Windows等。如果一台PC没有BIOS,即无法开机,成了废铁 一堆。而且BIOS一般是不可以相互替代的,只有同一个厂家同一型号的主板,其BIOS才可以互换。本机制的基本原理就是将PC中的BIOS从主机中抽 出,存到一个带加密的外部设备中,如USB钥匙盘等,没有该盘就不能开启计算机;又由于外部设备是加密的,即使有含BIOS的USB钥匙盘,但不知道密码 也不能开机,从而实现计算机的保护。这种带加密的钥匙盘由于各自密码或加密算法不同,也避免了使用同型号BIOS进行开机的可能。

二、实现

BIOS储存在计算机主机板的一种IC芯片(通常是FLASH)中,它有两个主要的 组成部分,即BootBlock段和主体BIOS。BootBlock段是不压缩的且存放于固定的地址空间,它是计算机开机时首先执行的部分。它主要负责 对计算机硬件做最基本、最简单的初始化,而后解压缩主体BIOS的其他模块,并一一执行,其流程如图1所示。由于BootBlock的这一特点,无需将 BootBlock段抽出至外部设备中,反而要利用它的初始化能力以启动与外部设备如USB盘的通信。但必须对BootBlock段加以修改,以实现对 USB钥匙盘的解密、主体BIOS的读入过程,即在检查BIOS校验和之前,从键盘读取用户的密码,并将该密码通过一定的运算方法加密,并发往USB接 口,在USB钥匙盘收到该密码后,允许内存的BIOS数据可读。

这样经过修改后,原主机板中存储BIOS的FLASH只存储修改过的 BootBlock段代码,不再有主体BIOS。同时不再采用FLASH芯片,直接使用一次性写入的PROM,避免其他软件或病毒对该区域代码的修改。对 于具体的加密算法和密码认证机制,不同的制造商可以选择不同的方式,如可以将主机板上具有惟一性的参数加入算法中,以实现一个主机板只有一套USB钥匙盘 相对应,等等。

USB钥匙盘的实现,和市面上通常所说的软件狗,其原理是一样的,只是这里说的 USB钥匙盘的储存容量要求相对大一些,至少要256KB以上。当然也可以不使用USB钥匙盘,而利用一些IC封装的CPU卡或SIM卡,做成LPT或 COM接口的设备,如北京握奇公司就提供串行的SIM IC,只需要稍加点简单的电路就可以实现与COM口的通信。其原理和USB钥匙盘一样,只是使用的通信接口不同而已。

三、扩展

前面所说的机制已经可以实现计算机安全保护了,但为了增加实用性,还需要做一些简单的扩展,以提高破译的代价。

扩展一是使用IDE的安全特性。现代计算机BIOS都已经支持IDE加密(AMI和 AWARD BIOS都有此功能),在实际使用过程中可结合该功能。该功能是对IDE硬盘进行加密,在BIOS开机阶段要求输入正确的密码,否则该硬盘不可以使用。在 没有通过密码验证的情况下,BIOS根本不能正确识别硬盘的设备类型,OS更不知道该硬盘的存在,也就无法使用或破坏硬盘中原有的数据。

扩展二是修改系统BIOS,在BIOS中将硬盘参数,如分区表等备份到USB钥匙 盘。做过BIOS开发的工程师知道,系统开机时首先执行的是BIOS,系统关机时最后执行的也是BIOS(意外断电除外,无论是操作系统关机还是按 Power Button关机,都有对应的SMI处理程序)。利用BIOS的这个特性,在每次开机时,BIOS负责从USB钥匙盘中读取硬盘参数并恢复到硬盘中,在关 机前,BIOS将硬盘参数备份到USB钥匙盘,同时破坏掉硬盘中该区域的数据。这样,即使将该硬盘安装到别的系统中,没有对应的钥匙盘也不能使用。

这样就从底层保障计算机安全,从而实现禁止非法使用。

原文链接

2007-03-08

举例说明jni调用c/c++接口

首先在eclipse中建立一个java工程StatisticJNIProject,设置好必要的参数(主要是输出目录,好找到你编译后的class文件位置:-)),在根目录(一般是src目录,注意是根目录,也就是程序中没有package,原因后边再说)下建立SITStatistic.java文件(当然,文件名可以随便取了)。文件内容如下:
/*
* Created on 2006-8-22
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class SITStatistic {
static {
System.loadLibrary("Tjni");
}
public native void doStatistic();
public static void main(String[] args) {
SITStatistic hh = new SITStatistic();
hh.doStatistic();
//System.getProperties();
//System.out.println(System.getProperties());
}
}
接下来编译工程,会得到SITStatistic.class文件(如果不用开发环境也可以直接用javac命令便宜文件SITStatistic.java,反正目标是生成SITStatistic.class文件)。
启动命令行(开始->运行 cmd.exe),将当前目录转到SITStatistic.class所在目录,执行javah SITStatistic 命令(注意,不是javah SITStatistic.class,没有扩展名),系统将在当前目录下生成SITStatistic.h文件。这个文件正是c++需要实现的头文件。
到此,这个简单的例子的java部分已经全部实现完成了。我们接下来转到c++部分。
首先在%JAVA_HOME%/include文件夹及其子文件夹下找到jni.h,jawt_md.h,jni_md.h三个文件,将他们拷贝到 Visual Studio安装目录\VC\include 目录下(其他的开发环境只要能保证编译是能找到这写头文件即可)。

建立vc的工程 new->project 点Visual C++下的Win32,选择Win32 Project。填写项目名称TJni,点OK。在Application Settings中设置Application Type 为DLL,Application options 为Empty project,点OK,工程就算建好了。说了一堆,其实就是建一个基本的动态链接库工程。然后把我们之前生成的SITStatistic.h文件加入到Tjni工程中,在工程中建立一个.cpp文件来实现SITStatistic.h中的方法,具体代码如下:
#define _Included_SITStatistic
#include
#ifdef __cplusplus

extern "C" {

#endif

/*

* Class: SITStatistic

* Method: doStatistic

* Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;

*/

JNIEXPORT void JNICALL Java_SITStatistic_doStatistic
(JNIEnv *, jobject)

{
cout<< "Hello World!";
return;

}

#ifdef __cplusplus

}

#endif

#endif


生成工程,会得到TJni.dll文件。把该文件考到SITStatistic.class文件所在的文件夹,执行SITStatistic.class文件,有可能你就成功了.

JNI调用c/c++接口方案


编写JNI代码的大致流程如右图所示:

1. 首先编写需要JNI功能的Java类源文件。其中,需要JNI实现的方法应当用native关键字声明。在该类中,用System. loadLibrary()方法加载需要的动态链接库。关键代码如下:
//Compute.java
……
public class Compute {
public native double comp (double [] params);
……
static {
// 调用动态链接库
System. loadLibrary(“mathlib”);
}
……
}
2. 将该类源文件用Java类编译器编译成二进制字节码文件。由于采用了native关键字声明,编译器会忽视没有代码体的JNI方法部分。
3. 利用javah -jni *.class 生成相关JNI方法的头文件。我们可以手工生成该文件,但是由于Java虚拟机是根据一定的命名规范完成对JNI方法的调用,所以手工编写头文件需要特别小心。
上述文件产生的头文件部分代码如下:
//Compute. h
……
extern “C” {
JNIEXPORT jdouble JNICALL Java_Compute_comp (JNIEnv *, jobject, jdoubleArray);
}
……
可以看出,JNI函数名称分为三部分:首先是Java关键字,供Java虚拟机识别;然后是调用者类名称(全限定的类名,其中用下划线代替名称分隔符);最后是对应的方法名称,各段名称之间用下划线分割。
JNI 函数的参数也由三部分组成: 首先是JNIEnv *,是一个指向JNI运行环境的指针;第二个参数随本地方法是静态还是非静态而有所不同——非静态本地方法的第二个参数是对对象的引用,而静态本地方法的 第二个参数是对其 Java 类的引用; 其余的参数对应通常 Java 方法的参数,参数类型需要根据一定规则进行映射。
4. 根据头文件编写相应方法的实现代码。由于篇幅所限,具体的实现部分在此不再赘述。在编码过程中,需要注意变量的长度问题,例如Java的整型变量长度为32位,而C语言为16位,所以要仔细核对变量类型映射表,防止在传值过程中出现问题。
5. 利用C/C++编译器将JNI实现代码编译成动态链接库。调用者类中需要显式调用该链接库。
在Win32环境下,可以利用Visual C ++或其他能产生DLL文件的C/C++编译器将实现代码编译成动态链接库。
经过上述处理,就基本上完成了一个包含本地化方法的Java类的开发。

2007-02-28

热烈庆祝安全服务器项目组博客正式开通!!!

在项目组全体同仁的积极努力下,安全服务器项目组博客于2007年2月28日正式上线,希望组内人员积极发表文章,并期待大家积极发表评论。