2012年11月8日
摘要: 1财务制度题库 单选题 1.下列各会计要素,( )不是反映财务状况的会计要素。 A.资产 B.负债 C.收入  ...
阅读全文
var ssshsj = new Date( $("#ssshsj").val().replace(/-/g,"/"));
对于Ibatis操作Date/Time/DateTime,总结如下:
将pojo的属性类型设置为java.sql.Date(或java.sql.Time, java.sql.Timestamp),此时会严格遵循这三种类型的语义。但此方法因存在前文中提到的性能问题,在JDK1.6以前的JDK版本中能少使用就少使用。
如果你想在pojo中使用java.util.Date, 则要注意:
完整的日期时间,要确保jdbcType为空,或为DATE,TIME以外的值
只需要时间,要指定jdbcType=”TIME”
只需要日期,要指定jdbcType=”DATE”
final OutputStream out = new FileOutputStream("D:/EDI/EDi.zip"); //实例文件输出流
ArchiveOutputStream os = new ArchiveStreamFactory().createArchiveOutputStream(ArchiveStreamFactory.ZIP, out);
//实例化存档输出流,工厂方法创建zip的存档输出流
// File f1 = new File(file.getPath());
os.putArchiveEntry(new ZipArchiveEntry(file.getName())); //生成存档文件名
IOUtils.copy(new FileInputStream(file), os); //添加拷贝存档文件
os.closeArchiveEntry();
os.close();
//*************************
try {
File input = new File("D:/EDI/EDi.zip");//获得下载文件路径
contentType="application/octet-stream";
docStream = new FileInputStream(input);//获得输入流名称
contentDisposition =URLEncoder.encode(input.getName() ,"UTF-8");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "download";
WEBWORK的文件下载机制。使用起来还是比较简单的。下面是用法说明:
首先在一个ACTION中,如果判断有权限进行文件下载。
则:
1、读出该下载文件,并生成一个流。 文件名应当从请求的request中读出,或从用户的表中取出。
public String downLoadFile(String fileName){
try {
File input = new File("e:/engilish literature.doc");
docStream = new FileInputStream(input);
contentDisposition = "test.txt";
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "download";
}
2、将输出导向到一个特殊的RESULT中去。叫做Steam Result。
<action name="register" class="com.job2easy.web.user.RegisterAction">
<result name="success" type="dispatcher">
<param name="location">/home/register-result.jsp</param>
</result>
<result name="input">
<param name="location">/home/register.jsp</param>
</result>
<result name="download" type="stream">
<param name="contentType">application/x-msdownload</param>
<param name="inputName">docStream</param>
<param name="bufferSize">1024</param>
<param name="contentDisposition">attachment;filename="${contentDisposition}"</param>
</result>
<interceptor-ref name="params"/>
</action>
3、这中间有几个参数需要配置:
contentType设成 application/x-msdownload 就可以。这样浏览器会保证弹出一个下载文件的对话框。
inputName 这个比较重要,这个名字是输入流的名称, 以后要steam result的实现类中为根据OGNL的表达式去查找的。
contentDisposition 这个是下载之后,保存在用户端的文件名称。${contentDisposition} 看一下代码。如果写成上述的方式,就有机会在ACTION中设置文件名。
4、另外一个参数:contentLength就是下载文件的大小,webwork的stream result似乎实现有问题,不能根据文件的大小动态进行设置,只能写死。
这个参数的意义是告诉浏览下载的文件有多大,以便浏览器正确的显示进度条。如果这个功能很重要的话,可以重新写一个RESULT来实现。
http://blog.csdn.net/jackfrued/article/details/44921941
数据列出来如下:
ID NAME COUR SCORE
--- ------- ---- -----
1 name_1 语文 33
1 name_1 数学 63
1 name_1 英语 71
1 name_1 历史 68
1 name_1 化学 94
2 name_2 语文 85
2 name_2 数学 4
2 name_2 英语 98
2 name_2 历史 9
2 name_2 化学 12
3 name_3 语文 49
3 name_3 数学 96
3 name_3 英语 30
3 name_3 历史 60
3 name_3 化学 2
要实现的行转列的效果如下(或者类似的结果):
ID NAME SCORES
--- ------- --------------------
1 name_1 33,63,71,94,68
2 name_2 85,4,98,12,9
3 name_3 49,2,60,96,30
通过case表达式
select id,name,sum(case when course='语文' then score end) "语文",
sum(case when course='数学' then score end) "数学",
sum(case when course='英语' then score end) "英语",
sum(case when course='历史' then score end) "历史",
sum(case when course='化学' then score end) "化学"
from HANG2LIE
group by id,name;
union有去重功能:
结构如下:
ID NAME Chinese Math English History Chemistry
--- ------- ---------- ---------- ---------- ---------- ----------
2 name_2 85 4 98 9 12
1 name_1 33 63 71 68 94
3 name_3 49 96 30 60 2
我们要实现如下的查询效果:列转行
ID NAME COUR SCORE
--- -------- ---- -----
2 name_2 语文 85
1 name_1 语文 33
3 name_3 语文 49
2 name_2 数学 4
1 name_1 数学 63
3 name_3 数学 96
2 name_2 英语 98
1 name_1 英语 71
3 name_3 英语 30
2 name_2 历史 9
1 name_1 历史 68
3 name_3 历史 60
2 name_2 化学 12
1 name_1 化学 94
3 name_3 化学 2
1、集合查询
实现的SQL语句:
select id,name,'语文' course,chinese score from lie2hang
union
select id,name,'数学' course,math score from lie2hang
union
select id,name,'英语' course,english score from lie2hang
union
select id,name,'历史' course,history score from lie2hang
union
select id,name,'化学' course,chemistry score from lie2hang;
select * from (select A.*, rownum rn from T_CD_LOC A where rownum > 20) where rn <41 错
select * from (select t.* ,rownum rn from T_CD_LOC t where rownum<=40) where rn>=20 对
firstIndex=0
pageNumber
pageSize=20
select * from (select A.*,rownum rn from T_CD_LOC a where rownum < ((firstIndex+pageNumber+1)*pageSize) where rn >((firstIndex+pageNumber)*pageSize)
js被缓存了,加控制版本 <script src="../lib_js/paymentplan.js?v=1"></script>
摘要: EhCache 分布式缓存/缓存集群开发环境:System:WindowsJavaEE Server:tomcat5.0.2.8、tomcat6JavaSDK: jdk6+IDE:eclipse、MyEclipse 6.6 开发依赖库:JDK6、 JavaEE5、ehcache-core-2.5.2.jarEmail:hoojo_@126.comBlog:http://blog.csdn...
阅读全文
3、JConsole监控
JMX(Java Management Extensions)是一个为应用程序植入管理功能的框架。JMX是一套标准的代理和服务,实际上,用户可以在任何Java应用程序中使用这些代理和服务实现管理。可以利用JDK的JConsole来访问Tomcat JMX接口实施监控,具体步骤如下:
1)首先,打开Tomcat5的bin目录中的catalina.bat文件,添加:
JAVA_OPTS="-Xms512m -Xmx512m -Xmn256m -XX:PermSize=64m -XX:MaxPermSize=64m -Djava.rmi.server.hostname=192.168.222.132 -Dcom.sun.management.jmxremote.port=1090 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false"
-Dcom.sun.management.jmxremote:代表开启JMX的管理功能
2)重启tomcat,并查看监控端口(上面配置的1090)是否已启动
3)打开jdk的bin目录(如C:\Program Files\Java\jdk1.7.0_17\bin)下的JConsole,并输入iP和监控端口进行连接
监控结果:
http://www.itzhai.com/hibernate-one-to-many-association-mapping-configuration-and-the-cascade-delete-problem.html首先举一个简单的一对多双向关联的配置:
一的一端:QuestionType类
package com.exam.entity;
import java.util.Set;
public class QuestionType {
private String typeName;
private char typeUniqueness;
private Set quesion;
public String getTypeName() {
return typeName;
}
public void setTypeName(String typeName) {
this.typeName = typeName;
}
public char getTypeUniqueness() {
return typeUniqueness;
}
public void setTypeUniqueness(char typeUniqueness) {
this.typeUniqueness = typeUniqueness;
}
public Set getQuesion() {
return quesion;
}
public void setQuesion(Set quesion) {
this.quesion = quesion;
}
}
配置文件:
<hibernate-mapping package="com.exam.entity">
<class name="QuestionType" table="exam_question_type">
<id name="typeName" column="type_name"></id>
<property name="typeUniqueness" column="type_uniqueness"/>
<set name="quesion" inverse="true" cascade="delete">
<key column="question_type_name"/>
<one-to-many class="Question"/>
</set>
</class>
</hibernate-mapping>
多的一端:Question类
package com.exam.entity;
import java.util.Date;
public class Question {
private int questionNo;
private QuestionType questionType;
private String questionsTitle;
public int getQuestionNo() {
return questionNo;
}
public void setQuestionNo(int questionNo) {
this.questionNo = questionNo;
}
public QuestionType getQuestionType() {
return questionType;
}
public void setQuestionType(QuestionType questionType) {
this.questionType = questionType;
}
public String getQuestionsTitle() {
return questionsTitle;
}
public void setQuestionsTitle(String questionsTitle) {
this.questionsTitle = questionsTitle;
}
}
配置文件:
<hibernate-mapping package="com.exam.entity">
<class name="Question" table="exam_question">
<id name="questionNo" column="question_no" >
<generator class="increment" />
</id>
<many-to-one name="questionType" column="question_type_name"/>
<property name="questionsTitle" column="questions_title" length="200" />
</class>
</hibernate-mapping>
首先说明一下一些常用的属性:
<many-to-one>元素包含以下属性:
name:设定映射的持久化类的属性名
column:设定和持久化类的属性对应的表的外键
class:设定持久化类的属性的类型
cascade:设定是否级联
lazy:设定是否延迟加载
<set>元素包含以下属性:
name:设定映射的持久化类的属性名
cascade:设置是否级联
inverse:设定反向控制,如果为true则一的一端不维护外键
<key>:设定与所关联的持久化类对应的表的外键。
one-to-many:设定所关联的持久化类
如果要对一对多关联映射进行级联删除,可以按照上面的举例进行配置:
首先看到一的一端:
<set name="quesion" inverse="true" cascade="delete">
<key column="question_type_name"/>
<one-to-many class="Question"/>
</set>
这里设置inverse表示一的一端不维护外键,设置cascade=”delete”表示删除一的一端时对关联到得多的所有的对象也一起删除
再看到多的一端:
<many-to-one name="questionType" column="question_type_name"/>
这里的column表示外键的名,需要和一的一端设置的key标签里的column保持一致,表示维护同一个键值。
可以按照如下的代码执行删除操作:
session.beginTransaction();
QuestionType questionType = (QuestionType) session.load(QuestionType.class, "判断题");
session.delete(questionType);
session.getTransaction().commit();
这里使用load查上来的对象是持久状态的(Persistent),只有是Persistent状态的对象才可以使用session.delete()操作进行级联删除,由new创建的对象属于Transient状态,不能进行session.delete()操作。
需要先删子表,再删除主表,否则报错
好文章
http://www.itzhai.com/hibernate-one-to-many-association-mapping-configuration-and-the-cascade-delete-problem.html
http://blog.csdn.net/itcareerist/article/details/5896143
http://www.cnblogs.com/xdp-gacl/p/4261895.html
http://www.ibm.com/developerworks/cn/linux/l-cn-socketftp/
http://blog.csdn.net/sweetsnow24/article/details/7447110
http://jingyan.baidu.com/article/b7001fe1738d9a0e7282dda6.html
http://wenku.baidu.com/link?url=YjPcc8q-E9jnAEqsEJQZ7juMw8TICa0q9ppU3ICqEyQJBl4JGQynegQT03DQA0oyA-CxGAtDKJ_pvuvo3prfVeLEsxzC7VUWjWMsQVAxht_
问题1:XML是什么?
答:XML即可扩展标记语言(Extensible Markup language),你可以根据自己的需要扩展XML。XML中可以轻松定义
, 等自定义标签,而在HTML等其他标记语言中必须使用预定义的标签,比如,而不能使用用户定义的标签。使用DTD和XML Schema标准化XML结构。XML主要用于从一个系统到另一系统的数据传输,比如企业级应用的客户端与服务端。
问题2:DTD与XML Schema有什么区别?
答:DTD与XML Schema有以下区别:DTD不使用XML编写而XML Schema本身就是xml文件,这意味着XML解析器等已有的XML工具可以用来处理XML Schema。而且XML Schema 是设计于DTD之后的,它提供了更多的类型来映射xml文件不同的数据类型。DTD即文档类型描述(Document Type definition)是定义XML文件结构的传统方式。
问题3:XPath是什么?
答:XPath是用于从XML文档检索元素的XML技术。XML文档是结构化的,因此XPath可以从XML文件定位和检索元素、属性或值。从数据检索方面来说,XPath与SQL很相似,但是它有自己的语法和规则。
问题4:XSLT是什么?
答:XSLT也是常用的XML技术,用于将一个XML文件转换为另一种XML,HTML或者其他的格式。XSLT为转换XML文件详细定义了自己的语法,函数和操作符。通常由XSLT引擎完成转换,XSLT引擎读取XSLT语法编写的XML样式表或者XSL文件的指令。XSLT大量使用递归来执行转换。一个常见XSLT使用就是将XML文件中的数据作为HTML页面显示。XSLT也可以很方便地把一种XML文件转换为另一种XML文档。
问题5:什么是XML元素和属性
答:最好举个例子来解释。下面是简单的XML片断。
Xml代码
6758.T
2300
例子中id是元素的一个属性,其他元素都没有属性。
问题6:什么是格式良好的XML
答:这个问题经常在电话面试中出现。一个格式良好的XML意味着该XML文档语法上是正确的,比如它有一个根元素,所有的开放标签合适地闭合,属性值必须加引号等等。如果一个XML不是格式良好的,那么它可能不能被各种XML解析器正确地处理和解析。
问题7:XML命名空间是什么?它为什么很重要?
答:XML命名空间与Java的package类似,用来避免不同来源名称相同的标签发生冲突。XML命名空间在XML文档顶部使用xmlns属性定义,语法为xmlns:prefix=’URI’。prefix与XML文档中实际标签一起使用。下面例子为XML命名空间的使用。
Xml代码
837363223
问题8:DOM和SAX解析器有什么区别
答:这又是一道常见面试题,不仅出现在XML面试题中,在Java面试中也会问到。DOM和SAX解析器的主要区别在于它们解析XML文档的方式。使用DOM解析时,XML文档以树形结构的形式加载到内存中,而SAX是事件驱动的解析器。
问题9:XML CDATA是什么
答:这道题很简单也很重要,但很多编程人员对它的了解并不深。CDATA是指字符数据,它有特殊的指令被XML解析器解析。XML解析器解析XML文档中所有的文本,比如This is name of person,标签的值也会被解析,因为标签值也可能包含XML标签,比如First Name。CDATA部分不会被XML解析器解析。
问题10:Java的XML数据绑定是什么
答:Java的XML绑定指从XML文件中创建类和对象,使用Java编程语言修改XML文档。XML绑定的Java API,JAXB提供了绑定XML文档和Java对象的便利方式。另一个可选的XML绑定方法是使用开源库,比如XML Beans。Java中XML绑定的一个最大的优势就是利用Java编程能力创建和修改XML文档。
以上的XML面试问答题收集自很多编程人员,但它们对于使用XML技术的每个人都是有用的。由于XML具有平台独立的特性,XPath,XSLT,XQuery等XML技术越来越重要。尽管XML有冗余和文档体积大等缺点,但它在web服务以及带宽、速率作为次要考虑因素的系统间数据传输起很大作用,被广泛用于跨平台数据传输。
http://www.cnblogs.com/qanholas/p/3904833.html
SQL SERVER 理论上有32767个逻辑连接,SQL SERVER根据系统自行调配连接池。
首先 ,操作系统的用户数:即同时通过网络连接到这台电脑上面的用户限制,以5用户操作系统,搭建的文件服务器为例,去同时访问这个文件服务器的网络用户为5个。
下面说说SQL server,购买数据库有两种方式,1、根据用户数购买。2、根据cpu个数购买。
根据用户数购买,假如你购买了一个50用户的数据库,那么可以通过网络访问数据库的人数限制为50。
根据cpu个数购买的数据库访问人数不受限制,服务器上面有几颗cpu就要买几个授权的SQL server,但是如果你只买一个授权的话数据库也可以正常运行,但是微软认为你的数据库不合法。就如同盗版系统。
一个连接不等于一个用户,单独一个用户可以有超过一个的连接,单独一个连接可以有超过一个用户。
你可以运行里面输入perfmon,然后加入下面两个计数器进行对比
SQLServer: General Statistics — Logical Connections:与系统建立的逻辑连接数。SQLServer: General Statistics — User Connections:连接到系统的用户数。
打个比喻
sql server是你家的房子
用户数 是你家房子钥匙
连接数 是你家房子能进去的人
不是很恰当,但是基本能说明问题
一个房子有多少个钥匙是明确的,但是每个钥匙是可以让多个人进去
也就是说,sql server的用户是可以登陆sql server进行操作的,而连接数指的是使用某个用户名登陆的为了执行某个具体操作的一个连接。
通常一个SQL SERVER 查询器,一个ADOCONNECTION是一个连接。
在SQL Server里查看当前连接的在线用户数
use master
select loginame,count(0) from sysprocesses
group by loginame
order by count(0) desc
select nt_username,count(0) from sysprocesses
group by nt_username
order by count(0) desc
如果某个SQL Server用户名test连接比较多,查看它来自的主机名:
select hostname,count(0) from sysprocesses where loginame='test'
group by hostname
order by count(0) desc
如果某个SQL Server用户名test连接比较多,查看它最后一次操作的时间范围分组:
select convert(varchar,last_batch,111),count(0) from sysprocesses where loginame='test'
group by convert(varchar,last_batch,111)
order by count(0) desc
如果从主机(www)来的连接比较多,可以查看它的进程详细情况
select * from??sysprocesses where hostname='www'
如果www机器主要提供网页服务,可能是asp程序处理连接时出了问题, 生成杀这些进程的SQL语句:
select 'kill '+convert(varchar,spid) from sysprocesses where hostname='www'
如果这样的问题频繁出现,可以写一个存储过程sp_KillIdleSpids.sql,
写一个作业, 执行它, 来自动杀掉从主机(www)来但已经一天没有响应的用户连接.
?
?
?
--------------------------------
SQL Server的用户及权限?
?sysadmin 可以在 SQL Server 中执行任何活动?
serveradmin 可以设置服务器范围的配置选项 关闭服务器?
setupadmin 可以管理链接服务器和启动过程?
securityadmin 可以管理登录和 CREATE DATABASE 权限 还可以读取错误日志和更改密码?
processadmin 可以管理在 SQL Server 中运行的进程?
dbcreator 可以创建 更改和除去数据库?
diskadmin 可以管理磁盘文件?
bulkadmin 可以执行 BULK INSERT 语句? ......
最大连接数是指数据库能承受的最大并发访问数量
SQL Server的并发用户数或者license怎么理解? 华软论坛 2005-12-06 13:38:55 在 MS-SQL Server / 基础类 提问
盗版的有并发用户数的限制吗?正版好像有10用户,50用户的版本,如果用C/S架构的话,每个客户端连接算不算一个用户?
后来有段时间好像改到 只按CPU购买License了。现在又好像见到购买连接数的license.
讲了这么一堆,想告诉你的是,如果你只有10用户的License,其实也是没有限制的。这是微软的市场人员亲口告诉我的。 [华 软 网]
欢迎转载,但请保留出处,本文章转自[华软网] 原文链接:http://www.huarw.com/db/dbbbs/MSSQLServer/200512/735120.html
你指的是购买许可吧?
SQL 提供3种购买方式
1) Processor license. (按CPU购买)
要求为运行SQL Server 2000的操作系统上的每个CPU购买许可. 这种方式不需要购买客户端访问许可.
2) Server plus device CALs. (服务器许可加每设备客户端访问许可)
运行SQL Server 2000的服务器需要一个许可, 每个访问SQL Server 2000的设备需要一个客户端访问许可.
3) Server plus user CALs. (服务器许可加每用户客户端访问许可)
运行SQL Server 2000的服务器需要一个许可, 每个访问SQL Server 2000的用户需要一个客户端访问许可
2、每客户
每客户授权模式要求每个将访问 SQL Server 2000 服务器的设备都具有一个客户端访问许可证。对于客户端连接到不止一个服务器的网络,每客户模式通常更划算。
在编辑框中,选择要授权的设备数。
选择授权模式:
使用该对话框设置授权模式,以使客户端可以访问 Microsoft? SQL Server? 的该实例。SQL Server 2000 支持两种客户端访问授权模式,一个用于设备,另一个用于处理器。
设备可以是工作站、终端或运行连接到 SQL Server 实例的 SQL Server 应用程序的任何其它设备。
处理器指的是安装在运行 SQL Server 2000 实例的计算机上的中央处理器 (CPU)。一个计算机上可以安装多个处理器,从而需要多个处理器许可证。
一旦设置了授权模式便无法再更改。可以在安装 SQL Server 之后添加设备或处理器许可证,这使用 "控制面板 "中的 SQL Server 2000 授权安装实用工具来进行。
1、授权模式
当从 "控制面板 "访问该对话框时,安装过程中选择的模式在默认情况下为选中,同时显示以前选择的设备数或处理器数。
2、每客户
每客户授权模式要求每个将访问 SQL Server 2000 服务器的设备都具有一个客户端访问许可证。对于客户端连接到不止一个服务器的网络,每客户模式通常更划算。
在编辑框中,选择要授权的设备数。
3、处理器许可证
使用处理器许可,安装在运行 SQL Server 的计算机上的每个处理器都需要一个许可证。处理器许可证允许任意数目的设备访问服务器,无论它们是通过 Intranet 还是 Internet。
使用处理器许可,SQL Server 2000 可以利用每个安装的处理器,并支持不限数目的客户端设备。通过 Internet 提供对 SQL Server 数据库的访问的客户或拥有大量用户的客户通常选择处理器许可证。
在编辑框中选择要授权的处理器数。
SQL Server安装成功后,重起计算机后SQL Server自动启动服务。
10用户不是指的连接用户
在创建自定义控制台时,可以给控制台指派两种常用访问选项中的一种:作者模式或用户模式。依次有三个级别的用户模式,因此共有四种默认访问控制台的选项:
作者模式
用户模式-完全访问
用户模式-受限访问,多窗口
用户模式-受限访问,单窗口
你安装的是企业版,10个客户端是指你能够在别的机子上只能安装10个Sql客户端同它连接
http://i-lolo.iteye.com/blog/1611562
在进入网络通信之前,让我们来普及一点网络基础概念。如果你是有一定的计算机网络基础,请直接跳到第五点之后开始阅读。
第一、 什么是计算机网络?
书本上那些文绉绉的概念我们可以不去理,我告诉你,我们两台电脑连在一起就组成了一个计算机网络。其实我们的电脑甚至是全世界的电脑都是连着的,只要你的电脑连着网,你就在这个巨大的计算机网络里,你也许会问为什么我和他们是连着的啊?大家知道自己是怎么上的网?ADSL是吧,拨号上网。换个比方说吧,我们在公司我们的电脑通过网线,双绞线,然后是Hub(集线器),连接到胡哥的电脑,然后胡哥的机子通过拨号,ADSL,连到电信的网关那儿,然后中国电信通过海底光缆和美国电信网关连接,然后再像刚刚我们连接中国电信一样,逆推过去,连接到美国每一台联网的计算机。所以说只要你连着网,你就是和全世界的在线用户连着。这是一个巨大的计算机网络。非常巨大。
第二、 计算机网络的主要功能?
资源共享、信息传输与集中处理、均衡负荷与分布处理、综合信息服务(www/综合数字网络 ISDN)。这些个功能,不多说。这些你不平时都在用么?你的资源能够上传共享给其他人,有的人平时还很喜欢聊QQ,是吧,所以上面说的这四个也许还有更多的什么功能都是些冠冕堂皇的话,稍微看下就好。用了自然就晓得了。
第三、 什么是网络通信协议?
我来问你,为什么你说话身边的人能够听的懂,别人说的话你为什么也能够听懂,而为什么如果你去对一个外国人说话或者一个外国人来和你说话你们却互相听不懂呢?你会说废话嘛因为我说的是中文,是汉语,中国人说的都是汉语,而外国人说的是另一种语言,是外语。就是这样,网络通信协议就像我们的中文一样,她就是我们之间的共同语言,他规定了我们之间怎么说话,我先说什么你再说什么,你怎么说,而我应该怎么听。而网络通信得先规定约定一些俗成的网络通信协议,先说好,两台计算机之间什么收发信息,信息格式是什么,信息怎么发,怎么接收,而万一出错怎么办怎么处理。没有了这个协议,两台电脑就不知道互相之间怎么说话,就像你对一头大母猪说完爱你,而人家根本就不知道你在说什么。
在这儿和大家提一下网络协议的分层思想。学过计算机网络的同学都知道有两种基本的国际标准分层模型,一个是OSI参考模型,一个是TCP/IP参考模型。OSI参考模型,是国际标准化组织搞出来的开放互联传统模型,一共有七层:物理/数据链路/网络/传输/会话/表示/应用。学网络和硬件的一般都要熟悉这七层标准,至于这七层都是干嘛的,大家自己问度娘或者自己看关于网络的书去。(中南大学高阳教授主编了一本叫《计算机网络原理与实用技术》的书,里边很详尽的介绍了这个OSI参考模型,没记错的话应该是在第一章1.4.5里,是放在TCP/IP协议之后的……)这里就不多说了,因为对于咱们编程的软件人员来说,实际当中的应用,是分为四层,也就是TCP/IP参考模型。最底层物理+数据链路层/网络层/传输层/应用层。我们编的程序是位于应用层,所以说,我们一直是在和哪一层打交道?TCP/IP层。我们编写一个程序发送一些数据,发给传输层,TCP/IP层,在这一层对数据进行封装,按照先前约定的协议,然后走向下一层,通过网线,再走到物理数据链路层,这时候数据就变成了一连串的01010101,到达对面之后逆推上面的过程,进行解封,ok,信息发送完毕。这儿涉及到比较多的网络底层,目前我们不需要过多了解,因为我们要做的工作不需要了解牵扯到到这么底层的东西,如果你想深入了解或者今后你想做杀毒软件什么的,去读《TCP/IP详解》。
第四、 IP——(Internet Protocol网络之间互连的协议)?
你不用管其他的,你只需要知道IP这个东西给我们做出的最大贡献,就是给我们每一台电脑提供了一个独一无二的IP地址。你想我的机器要和你的机器交流说话,我得知道你的机器叫什么,你的机器得有一个独一无二的区别标识,否则的话我就不知道传的信息有没有传到你那儿,也不知道这信息到底传给谁。IP地址这东西我们都知道吧?像我的本机IP: 113.240.187.242 这是湖南省长沙市的IP。他是由四个字节组成的(也就是说每一个值不能超过255)。(这个是IPV4,能够组成将近四亿多地址,现在已经出来了IPV6,高档货,八个字节,地址数是IPV4的几何倍数)IPV4的IP地址按照其网络IP段和主机IP段占的字节数分ABC三类网。这个这里不说,大家自己去了解,好吧?拿高阳教授的那本书翻翻。顺带看看子网掩码啊网关啊什么的。自己去了解。在这儿我就累得给你敲了。
第五、 TCP协议和UDP协议?
好了,上一步里我们通过独一无二的IP地址找到了对方连在了一起。我们可以通话了,关于通话我们有两种方式:
第一、 TCP协议,什么叫TCP协议?Transmission Control Protocol 传输控制协议TCP是一种面向连接(连接导向)的、可靠的、基于字节流的运输层(Transport layer)通信协议。什么叫可靠的?打个比方,我们打电话,上一步通过IP找到对方就相当于拨号打通了你的电话,你拿起电话接了,我说一句“喂?”,如果你这边不回应,我就会杵这儿一直“喂”下去,是不?因为不知道你那边到底接到了听到了我的话没有,所以你这边一定要告诉我你听到了你收到了我刚刚的那句信息,我才会接着给你说下面的话给你发下面的数据。我每发一次信息我要你给我确认收到了,然后我再给你发接下来的东西,这个就叫可靠。在TCP/IP协议里边这叫“三次握手”机制。怎么握手,握手是怎么回事,问度娘,好吧?
第二、 UDP协议。User Datagram Protocol的简称, 中文名是用户数据报协议,是 OSI 参考模型中一种无连接的传输层协议。UDP这种方式相对于TCP来说更加简单。UDP说话就是,我给你说一句话,你听没听到我不管。就像发电报,“黄河黄河我是长江!”哐当一下就发出去了。不管黄河收到没有。两种方式一种安全可靠但是慢,一种简单快捷但是不可靠。根据不同的需求选择。像我们平时聊QQ开视频啊什么的,用的就是UDP,因为我们传输的这些个数据丢个一两个包什么的无所谓,顶多就是视频多了几个马赛克,是吧。那么平时我们玩的网络游戏,像CF啊魔兽世界啊,是哪一种呢?自己想,好吧?
第三、 中南-马志丹 http://java-mzd.javaeye.com 惊喜看得到!
基础普及完了,接下来我们来看看为什么要去做网络通信。这一段我就简单点说。在计算机刚出来那会儿 ,那时候的人们都觉得计算机这东西就是主要为计算而存在的就是一个计算工具,但是自从1983年起,TCP\IP协议的出现,让计算机从此转变为了人们的一个交流工具。自那以后,只要你有一台电脑,不管你是开网页看电影,还是上人人找朋友,不管你是登邮箱收发邮件,还是登QQ聊天,你的生活的方方面面都离不开那电脑屏幕后边的网络技术。换句话说,如果没有了网络通信技术,电脑以及大多数软件将会失去他们原有的生命力。就像一棵大树没有根。没有网络通信就没有如今繁荣的QQ世界,没有了网络通信,世界上那些个IT巨头诸如IBM诸如谷歌,将会如断线风筝落日残阳。我想说,如果你不懂网络通信技术,你就不是一个合格的程序员,如果你不精通网络通信技术,你就无法开发出一款真正优秀的营运软件!除非你想永远停留在枯燥的单机时代,你想让自己的技术永远留在表层。
现在,让我们来考虑如何实现。
在做实现之前,我想先让大家明白几个概念:
1) Socket
A. 两个Java应用程序可通过一个双向的网络通信连接实现数据交换,这个双向链路的一端称为一个Socket
B. Socket通常用来实现client-server连接
C. Java.net包中定义的两个类Socket和ServerSocket,分别用来实现双向连接的client和server端
D. 建立连接时所需要的寻址信息为远程计算机的IP地址和端口号(Port number)
上面我们提到了IP地址,那是每一台电脑独一无二的一个地址标识,是为了对方计算机能够找得到你给你发信息。建立连接我们很显然需要这个信息才能够完成。那么这个端口号又是用来干什么的呢?举个例子,假如说我电脑上现在上着人人和QQ,你的电脑上也是上着人人和QQ,如果我用QQ给你发一条消息他怎么知道就发到你的QQ上而不会在你的人人上呢?是吧?所以说光用IP地址是无法区分到不同的应用程序的。所以需要端口号来达到这个作用。端口号在计算机内部是用两个字节来表示,也就是说总共有65536个端口。在这儿需要注意下面两个点:
•1.1024之前的端口我们自己编的程序不要征用它,因为这些端口是给系统用的。比如说80端口,胡哥给咱们讲过的。干嘛的?负责处理HTTP上网访问网页等等的端口。还有就是21端口,FTP的,是吧?还有其他的一些著名端口,想知道问度娘去,好吧?在这里就不罗嗦了。
•2.TCP端口和UDP端口是分开的,比如说TCP有个8888端口,他和你的UDP8888端口是不一样的。
•3.上述每一类有65536个端口。也就是说我们的计算机能够运行131072个程序,只要你电脑吃得消。
既然要实现通信,那我们肯定要确定两个通信对象,一个是服务器对象server,一个是客户端对象client。我们需要知道,这两个对象是两个应用程序,他们的对话,是两个不同的程序之间的对话。你会说我只有两个对象也还没法实现他们之间的交互啊,不用急,我也知道他们两个不是神仙会心有灵犀。两个对象之间想要实现互相之间的信息交互,就必须要有一个通道。这个通道就像是一根管子,一头扎在服务器端,一头插在客户端。信息就在这根管子里来来往往。这根管子怎么插呢,插在哪儿呢?这个时候就需要用到刚刚提到的Socket了。
Socket的意思呢就是一个插座,服务器和客户端各有一个插座,安插在各自的一个端口上,管子插在这两个插座上,然后在他们这两个端口上接入数据流。Socket通常用来实现server-client连接。Java里面有一个包java.net,他下边有定义了两个类,Socket和ServerSocket,分别用来实现双向连接的server端和client端。
接下来我们来建立TCP服务器端和客户端。
服务器端:我们用的是ServerSocket,新建一个server插座,并且交给他一个端口号,这个插座他有一个非常方便的构造方法ServerSocket(int port),让他知道自己监听哪一个端口,然后新建一个socket对象,开机,并用.accept语句让他处在待机状态,等待接受client的接入。一旦有客户端接入就将它赋给新建的Socket对象,并且用.getInputStream以及.getOutputStream命令获得他的输入输出流。这个流,就是一根管子,信息都在这根管子里流通。这样说东西不怎么好说,那么我们就在这个流上面再包一层,将这个流封装成DataOutputStream(),DataInputStream。然后就可以利用输出流(这个是相对于服务器来说,这个输出流到了客户端就成了输入流了)来.write信息,利用输入流来.read()获取客户端发来的信息。Ok,接收完了,.close关闭输入输出流,以及关闭socket,关机。
客户端:写法和服务器端有点类似,新建一个插座,这儿需要留意的是,客户端需要用到的插座是Socket而不是ServerSocket,新建一个Socket牌插座,同样用他的Socket(String host,int port)构造方法方法给他一个IP地址和端口号,让它拨打区号以及具体电话号,这个和服务器端的IP地址以及端口号要一致,ok,这个时候server就相当于申请连接到服务器的某一个端口上了。两个程序就等于是连接上了。但是有些人就会问了啊,这只是客户端申请连接,人家服务器接不接受呢。好,前面我们的服务器不是提到了.accept么,这个方法就是用来接受客户端的,这个时候就是:你申请连接,我接受连接,接下来,照着上面服务器一样,客户端也获取到自己的输入输出流,封装,用输出流写出信息。咱们之间就可以互相通信了。还有一个问题啊,要是如果有另一个客户端接入了呢?简单,那就再.accept一下。如果有N多客户端接入,那就不断的.accept,不断循环它。这个问题大家都知道可以用while语句。
具体的敲法,请看我给大家附上的代码实现。下面给大家看下Socket通信模型。看着这个模型,再回头看看上面给大家唠叨的那些个点,我想大家都知道服务器和客户端该怎么去写怎么去实现通信了吧?
好了,这一段“三分钟让你看懂”到此就结束了,想来大家对网络通信也该有了一个相对清晰的认识。如果你还想了解学习更多的网络通信方面的知识,如果你还想知道如何去实现一些更多的通信功能,比如建立公共聊天室实现群聊,又比如建立一个以互联网为基础的以网络画板为主体的协助平台,又比如,你想做一个自己的软件来实现像QQ一样MSN一样或者像人人桌面一样的各种功能……请继续关注我们的随后更新。请记住,我们是ZCL,我们是一群简单快乐的牧码人!
后记:第一篇正儿八经的技术日志,4K多全手打,这样说起来应该蛮自豪的感觉。但是说实话还是觉得自己写的有些乱。自己只是把课堂上老师们讲的一些知识点,根据自己敲的代码以及做了的一些课堂笔记,罗列了出来。也查了一些在线资料和书籍,像度娘,像学校发的那本我都没怎么动过的《计算机网络原理和实用技术》。在前面花了好些篇幅来讲计算机网络基础知识,是因为我给自己定下的目标就是让任何一个人甚至你是没怎么学过接触过java或者计算机网络这一块,看了我的博客之后,都能够对网络通信有一个比较清晰的认识,而让接触过java的人知道怎么样初步的去实现两个软件或者说程序之间的通信,知道他们之间是怎么回事儿并且自己动手实现它。这确实是一个有点难度的过程。但是你如果把这个都搞定了,那么,你的java网络通信就基本可以说入了一个门了。我似乎听见了胡哥用他那一惯的口吻在我身后说,这种程度,要说入门还早的很呢!当然咯,就算我现在做到网络画图板做到网络文件传输,也感觉自己只是进了一个门,门后的世界无比之大,等待我们不断的去探索,去创新,去创造它。生命有限,学海无涯;人有老时,学无止境嘛。发现的问题蛮多。但获得的收获也不少。果然检验自己是否学会掌握一个东西的最好办法就是尝试着去教给别人。只有你能够很清晰的把事儿给别人说清楚了教会了,你才能说自己懂了。写完这篇博客,感觉自己对网络通信的理解又加深了一些,对其中的一些知识点的掌握也更加牢靠了一些。只言片语薄闻浅见,希望大家多多批评不吝赐教!
最后的最后:用胡哥的一句话来与君共勉吧!
标准即平庸,合格即废物。
(附)服务器端代码:
Java代码 收藏代码
package con120722;
import java.net.*;
import java.io.*;
public class Server
{
private ServerSocket ss;
private Socket socket;
private BufferedReader in;
private PrintWriter out;
public Server()
{
try
{
ss = new ServerSocket(10000);
while (true)
{
socket = ss.accept();
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(),true);
String line = in.readLine();
out.println("you input is :" + line);
out.close();
in.close();
socket.close();
}
}
catch (IOException e)
{}
}
public static void main(String[] args)
{
new Server();
}
}
客户端代码:
Java代码 收藏代码
package con120722;
Java代码 收藏代码
import java.io.*;
import java.net.*;
public class Client
{
Socket socket;
BufferedReader in;
PrintWriter out;
public Client()
{
try
{
socket = new Socket("localhost", 10000);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(),true);
BufferedReader line = new BufferedReader(new InputStreamReader(System.in));
out.println(line.readLine());
line.close();
out.close();
in.close();
socket.close();
}
catch (IOException e)
{}
}
public static void main(String[] args)
{
new Client();
}
}
http://www.cnblogs.com/mingforyou/archive/2012/03/03/2378143.html
http://www.educity.cn/wenda/450855.html
Eclipse崩溃,错误提示:
MyEclipse has detected that less than 5% of the 64MB of Perm
Gen (Non-heap memory) space remains. It is strongly recommended
that you exit and restart MyEclipse with new virtual machine memory
paramters to increase this memory. Failure to do so can result in
data loss. The recommended Eclipse memory parameters are:
eclipse.exe -vmargs -Xms128M -Xmx512M -XX:PermSize=64M -XX:MaxPermSize=128M
1.参数的含义
-vmargs -Xms128M -Xmx512M -XX:PermSize=64M -XX:MaxPermSize=128M
-vmargs 说明后面是VM的参数,所以后面的其实都是JVM的参数了
-Xms128m JVM初始分配的堆内存
-Xmx512m JVM最大允许分配的堆内存,按需分配
-XX:PermSize=64M JVM初始分配的非堆内存
-XX:MaxPermSize=128M JVM最大允许分配的非堆内存,按需分配
我们首先了解一下JVM内存管理的机制,然后再解释每个参数代表的含义。
1)堆(Heap)和非堆(Non-heap)内存
按照官方的说法:“Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配。堆是在 Java 虚拟机启动时创建的。”“在JVM中堆之外的内存称为非堆内存(Non-heap memory)”。
可以看出JVM主要管理两种类型的内存:堆和非堆。简单来说堆就是Java代码可及的内存,是留给开发人员使用的;非堆就是JVM留给自己用的,
所以方法区、JVM内部处理或优化所需的内存(如JIT编译后的代码缓存)、每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法的代码都在非堆内存中。
堆内存分配
JVM初始分配的堆内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的堆内存由-Xmx指定,默认是物理内存的1/4。默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;
空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。因此服务器一般设置-Xms、-Xmx 相等以避免在每次GC 后调整堆的大小。
说明:如果-Xmx 不指定或者指定偏小,应用可能会导致java.lang.OutOfMemory错误,此错误来自JVM,不是Throwable的,无法用try...catch捕捉。
非堆内存分配
JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。(还有一说:MaxPermSize缺省值和-server -client选项相关,
-server选项下默认MaxPermSize为64m,-client选项下默认MaxPermSize为32m。这个我没有实验。)
上面错误信息中的PermGen space的全称是Permanent Generation space,是指内存的永久保存区域。还没有弄明白PermGen space是属于非堆内存,还是就是非堆内存,但至少是属于了。
XX:MaxPermSize设置过小会导致java.lang.OutOfMemoryError: PermGen space 就是内存益出。
说说为什么会内存益出:
(1)这一部分内存用于存放Class和Meta的信息,Class在被 Load的时候被放入PermGen space区域,它和存放Instance的Heap区域不同。
(2)GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS 的话,就很可能出现PermGen space错误。
这种错误常见在web服务器对JSP进行pre compile的时候。
2)JVM内存限制(最大值)
首先JVM内存限制于实际的最大物理内存,假设物理内存无限大的话,JVM内存的最大值跟操作系统有很大的关系。简单的说就32位处理器虽然可控内存空间有4GB,但是具体的操作系统会给一个限制,
这个限制一般是2GB-3GB(一般来说Windows系统下为1.5G-2G,Linux系统下为2G-3G),而64bit以上的处理器就不会有限制了。
2. 为什么有的机器我将-Xmx和-XX:MaxPermSize都设置为512M之后Eclipse可以启动,而有些机器无法启动?
通过上面对JVM内存管理的介绍我们已经了解到JVM内存包含两种:堆内存和非堆内存,另外JVM最大内存首先取决于实际的物理内存和操作系统。所以说设置VM参数导致程序无法启动主要有以下几种原因:
1) 参数中-Xms的值大于-Xmx,或者-XX:PermSize的值大于-XX:MaxPermSize;
2) -Xmx的值和-XX:MaxPermSize的总和超过了JVM内存的最大限制,比如当前操作系统最大内存限制,或者实际的物理内存等等。说到实际物理内存这里需要说明一点的是,
如果你的内存是1024MB,但实际系统中用到的并不可能是1024MB,因为有一部分被硬件占用了。
3. 为何将上面的参数写入到eclipse.ini文件Eclipse没有执行对应的设置?
那为什么同样的参数在快捷方式或者命令行中有效而在eclipse.ini文件中是无效的呢?这是因为我们没有遵守eclipse.ini文件的设置规则:
参数形如“项 值”这种形式,中间有空格的需要换行书写,如果值中有空格的需要用双引号包括起来。比如我们使用-vm C:/Java/jre1.6.0/bin/javaw.exe参数设置虚拟机,
在eclipse.ini文件中要写成这样:
-vm
C:/Java/jre1.6.0/bin/javaw.exe
-vmargs
-Xms128M
-Xmx512M
-XX:PermSize=64M
-XX:MaxPermSize=128M
实际运行的结果可以通过Eclipse中“Help”-“About Eclipse SDK”窗口里面的“Configuration Details”按钮进行查看。
另外需要说明的是,Eclipse压缩包中自带的eclipse.ini文件内容是这样的:
-showsplash
org.eclipse.platform
--launcher.XXMaxPermSize
256m
-vmargs
-Xms40m
-Xmx256m
其中–launcher.XXMaxPermSize(注意最前面是两个连接线)跟-XX:MaxPermSize参数的含义基本是一样的,我觉得唯一的区别就是前者是eclipse.exe启动的时候设置的参数,
而后者是eclipse所使用的JVM中的参数。其实二者设置一个就可以了,所以这里可以把–launcher.XXMaxPermSize和下一行使用#注释掉。
4. 其他的启动参数。 如果你有一个双核的CPU,也许可以尝试这个参数:
-XX:+UseParallelGC
让GC可以更快的执行。(只是JDK 5里对GC新增加的参数)
补充:
如果你的WEB APP下都用了大量的第三方jar,其大小超过了服务器jvm默认的大小,那么就会产生内存益出问题了。
解决方法: 设置MaxPermSize大小
可以在myelipse里选中相应的服务器比如tomcat5,展开里面的JDK子项页面,来增加服务器启动的JVM参数设置:
-Xms128m
-Xmx256m
-XX:PermSize=128M
-XX:MaxNewSize=256m
-XX:MaxPermSize=256m
或者手动设置MaxPermSize大小,比如tomcat,
修改TOMCAT_HOME/bin/catalina.bat,在echo "Using CATALINA_BASE: $CATALINA_BASE"上面加入以下行:
JAVA_OPTS="-server -XX:PermSize=64M -XX:MaxPermSize=128m
建议:将相同的第三方jar文件移置到tomcat/shared/lib目录下,这样可以减少jar 文档重复占用内存
1.JVM内存管理的机制
内存空间划分为:Sun JDK在实现时遵照JVM规范,将内存空间划分为堆、JVM方法栈、方法区、本地方法栈、PC寄存器。
堆: 堆用于存储对象实例及数组值,可以认为Java中所有通过new创建的对象的内存都在此分配,Heap中对象所占用的内存由GC进行回收,在32位操作系统上最大为2GB,在64位操作系统上则没有限制,其大小可通过-Xms和-Xmx来控制,-Xms为JVM启动时申请的最小Heap内存,默认为物理内存的1/64但小于1GB;-Xmx为JVM可申请的最大Heap内存,默认为物理内存的1/4但小于1GB,默认当空余堆内存小于40%时,JVM会增大Heap到-Xmx指定的大小,可通过-XX:MinHeapFreeRatio=来指定这个比例;当空余堆内存大于70%时,JVM会减小Heap的大小到-Xms指定的大小,可通过-XX:MaxHeapFreeRatio=来指定这个比例,对于运行系统而言,为避免在运行时频繁调整Heap 的大小,通常将-Xms和-Xmx的值设成一样。
JVM方法栈: 为线程私有,其在内存分配上非常高效。当方法运行完毕时,其对应的栈帧所占用的内存也会自动释放。当JVM方法栈空间不足时,会抛出StackOverflowError的错误,在Sun JDK中可以通过-Xss来指定其大小。
方法区: 要加载的类的信息(名称、修饰符等)、类中的静态变量、类中定义为final类型的常量、类中的Field信息、类中的方法信息。方法区域也是全局共享的,在一定条件下它也会被GC,当方法区域要使用的内存超过其允许的大小时,会抛出OutOfMemory的错误信息。在Sun JDK中这块区域对应Permanet Generation,又称为持久代,默认最小值为16MB,最大值为64MB,可通过-XX:PermSize及-XX:MaxPermSize来指定最小值和最大值。
本地方法栈: 用于支持native方法的执行,存储了每个native方法调用的状态。在Sun JDK的实现中,和JVM方法栈是同一个。
PC寄存器: 占用的可能为CPU寄存器或操作系统内存。
2.Java堆和栈的区别
Java把内存划分成两种:一种是栈内存,一种是堆内存。
在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。
堆内存用来存放由new创建的对象和数组。在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或对象后,还可以在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,在栈中的这个特殊的变量就变成了数组或者对象的引用变量,以后就可以在程序中使用栈内存中的引用变量来访问堆中的数组或者对象,引用变量相当于为数组或者对象起的一个别名,或者代号。
引用变量是普通变量,定义时在栈中分配内存,引用变量在程序运行到作用域外释放。而数组&对象本身在堆中分配,即使程序运行到使用new产生数组和对象的语句所在地代码块之外,数组和对象本身占用的堆内存也不会被释放,数组和对象在没有引用变量指向它的时候,才变成垃圾,不能再被使用,但是仍然占着内存,在随后的一个不确定的时间被垃圾回收器释放掉。这个也是java比较占内存的主要原因。但是在写程序的时候,可以人为的控制。
3.Java内存泄露和内存溢出
内存泄漏:分配出去的内存回收不了
内存溢出:指系统内存不够用了
http://zhidao.baidu.com/link?url=gQ4IAoIl07v0sxITrvasf8LwMwmFELou2d-6w11tqNHsNNdxQvDTg5f-EMlS0HSrAOG0mqw0DoBocICbuSfTvK
第一对所有的代码包括页面中的java代码都进行一遍彻底的回顾检查,
1.对那些静态(static)的对象要特别留神,特别是类型为Map,List,Set的,静态的变量会一直驻存在内存中,生命周期比较长,不会被垃圾器回收。
2.对于代码,要审查是否生成了大量的冗余的对象,还有一些逻辑业务处理的类,
算法是否过于复杂,调整算法,对于代码认真审查,再仔细重构一遍代码,能提高代码质量,提高程序运行稳定性。
3.Java中的内存溢出大都是因为栈中的变量太多了。其实内存有的是。建议不用的尽量设成null以便回收,多用局部变量,少用成员变量。
1),变量所包含的对象体积较大,占用内存较多。
2),变量所包含的对象生命周期较长。
3),变量所包含的对象数据稳定。
4),该类的对象实例有对该变量所包含的对象的共享需求。
4.在我的程序中对静态变量的优化后,使程序占用内存量至少提升了5k-10k。所以也不容忽视。
第二还有就是String类相关的东西:
1.字符串累加的时候一定要用StringBuffer的append方法,不要使用+操作符连接两个字符串。差别很大。而且在循环或某些重复执行的动作中不要去创建String对象,因为String对象是要用StringBuffer对象来处理的,一个String对象应该是产生了 3个对象(大概是这样:))。
2.字符串length()方法来取得字符串长度的时候不要把length放到循环中,可以在循环外面对其取值。(包括vector的size方法)。特别是循环次数多的时候,尽量把length放到循环外面。
int size = xmlVector.size();
for (int i = 2; i < size; i++) {
...
}
3 .写代码的时候处理内存溢出
try{
//do sth
....
}catch (outofmemoryerror e){//可以用一个共通函数来执行.
system.out.print (“no memory! ”);
system.gc();
//do sth again
....
}
4.对于频繁申请内存和释放内存的操作,还是自己控制一下比较好,但是System.gc()的方法不一定适用,最好使用finallize强制执行或者写自己的finallize方法。 Java 中并不保证每次调用该方法就一定能够启动垃圾收集,它只不过会向JVM发出这样一个申请,到底是否真正执行垃圾收集,一切都是个未知数。
1.优化程序2.改进算法3.增加jvm内存分配
http://www.jb51.net/article/77470.htm
http://www.php100.com/html/program/jquery/2013/0905/6004.html
http://bhsc-happy.iteye.com/blog/678163
http://www.cnblogs.com/Javame/p/3881187.html
JMX
Java Management Extensions,Java管理扩展,初步看了些资料,以为是专门管理,监控jvm的一些信息的,特别是visual VM这个监控jvm的东西,还有一个添加JMX连接的时候(我自己想错了,那样的话应该叫jvm Management Extensions),其实他能使得基于java语言开发的程序能被管理,并且是可扩展的。
Jdk以前是通过JVMPI之类来监测Java程序运行中的jvm和系统的一系列情况,现在通过jmx就可以做到,这是通过java.lang.management 包来实现的,这个包是 JMX 在 JDK方面 的一个应用,并不是表示jmx就是一个监控jvm的东西。
我们可以用jmx来监控我们的系统,通过公布API的方式,但是,这里采用监控这个词,也是受了前面的例子的影响,实际上,个人觉得,就可以用jmx来开发我们的系统。
现在的jboss,hibernate,tomcat各种应用都号称实现了JMX规范,将可管理,可调用的MBean注册到MBeanServer中,通过一种类似“web服务”的方式公布出去,并且伴有一个名字,可以通过该名字找到该MBean。并且,这里的MBean是可以被管理的,说到这里又想到了OSGI。
JMX与Web Service
个人认为,我们实现JMX规范,将东西发布出去,和通过web Service的方式是很类似的,也是可以远程调用的,只是相对的web Service的方式更加SOA一些,不过JMX号称也要提供对非java客户端的支持,也就是跨语言了吧。。。
现在的JMX连接方式:
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9999/server"); JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
看了下源码,貌似还是通过RMI来实现的,不知道它要怎么实现非java客户端支持。
从这里,我觉得JMX可以实现的,我们也都可以通过web Service实现,只是看在它有个“M”上,以后如果有什么系统管理,监控方面的,可以考虑使用它,也许开发,个人觉得还是使用web service好一些。
说到这里,感觉OSGI与JMX也好像,在看到JMX能够对MBean进行管理的时候,我就觉得跟OSGI很像,OSGI管理的是Bundle,找了找资源,原来早就有人考虑过了:
http://teamojiao.iteye.com/blog/438334
顺便,在查资料的时候,发现一个东西,
if your question means, how to manage an OSGi runtime with JMX, you should have a look at MAEXO (http://code.google.com/p/maexo/). With MAEXO bundles up and running you will transparently get MBeans for a fair amount of services of the OSGi runtime as well as MBeans for your own services and bundles. Just have a look at the screencast.
摘一些话:仅做参考
<网友回复>
一个大系统中,各内部模块系统之间的基于接口方式的互相调用和治理,使用jmx是最佳方案.
带来的好处是
1.面向接口,远程调用对于开发人员是透明的,模块在调用jmx接口时,与调用本地方法几乎相同.
2.可视化的治理界面, 通过 Jconsole等jmx客户端,可以实时监控系统,并且可实时调用方法进行某些操作.
典型应用场景:
某聊天系统,一台服务器作为 在线用户列表服务器 A1, n台服务器为用户提供聊天业务处理 N1 ,N2,N3...,
一台服务器作为后台治理系统A2.
系统治理员现在进行下面这样一个操作,察看某用户是否在线,找到该用户,发现其在线,则将该用户加入黑名单,并踢下线.
对应的jmx接口可以由以下几个:
A1为A2提供查询在线用户jmx接口,加入黑名单接口,kickout接口,
A1为N1..等服务器提供以下接口: 注册业务服务器,添加在线用户.查找黑名单用户
N1...到N3为A1提供kickout接口.
因此在上面的踢下线操作,则由用户在A2的web界面发出,交由A1执行,A1记录黑名单之后,再找到用户所在业务服务器调用N1提供的接口让用户下线.
以上情形是在生产环境下的部署,而在开发工作,则可以将A1,A2,N...N3等功能合并在一个应用中调试. 由于使用的是jmx接口,在本地调试合并之后,可以直接调用应用内部接口方法.
这样借助jmx实现的应用模块的灵活组装与拆分,使得系统的可以根据负载需要,根据性能情况,灵活的拆分和整合部署分布式的应用.
替代方案,选择webservice,xmlrpc等,但是这些都需要手工编写或用工具生成大量的代码来辅助完成接口间的java对象序列化 。
经典jmx案例:
1.Jboss.使用jmx治理内部的各个service。
2. 基于java的开源网管软件 Hyperic HQ ,通过jmx与各被治理资源进行通讯和信息采集.
<网友回复>JMX是一个治理的框架。
当我们想使用JMX的时候,就要问,我们的系统当中有需要监控治理的资源或者对象吗?实事求是一点,我们不能为了想使用一个高端的技术,就歪曲系统的本来面目。
假如第一个问题是肯定的,接下来就是看这些资源是否有生命周期。
经典案例:jboss就是将所有可部署的组件作为资源来治理,这些组建都有其生命周期。这个理念甚至延伸到了其系统内部,将其内部的服务作为组件纳入到 JMX中来,成就了jboss基于jmx的微内核系统。
http://www.cnblogs.com/linzheng/archive/2011/01/23/1942328.html
http://www.ibm.com/developerworks/cn/linux/l-cn-socketftp/
一,网络编程中两个主要的问题
一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输。
在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可以唯一地确定Internet上的一台主机。
而TCP层则提供面向应用的可靠(tcp)的或非可靠(UDP)的数据传输机制,这是网络编程的主要对象,一般不需要关心IP层是如何处理数据的。
目前较为流行的网络编程模型是客户机/服务器(C/S)结构。即通信双方一方作为服务器等待客户提出请求并予以响应。客户则在需要服务时向服务器提 出申请。服务器一般作为守护进程始终运行,监听网络端口,一旦有客户请求,就会启动一个服务进程来响应该客户,同时自己继续监听服务端口,使后来的客户也 能及时得到服务。
二,两类传输协议:TCP;UDP
TCP是Tranfer Control Protocol的 简称,是一种面向连接的保证可靠传输的协议。通过TCP协议传输,得到的是一个顺序的无差错的数据流。发送方和接收方的成对的两个socket之间必须建 立连接,以便在TCP协议的基础上进行通信,当一个socket(通常都是server socket)等待建立连接时,另一个socket可以要求进行连接,一旦这两个socket连接起来,它们就可以进行双向数据传输,双方都可以进行发送 或接收操作。
UDP是User Datagram Protocol的简称,是一种无连接的协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,它在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。
比较:
UDP:1,每个数据报中都给出了完整的地址信息,因此无需要建立发送方和接收方的连接。
2,UDP传输数据时是有大小限制的,每个被传输的数据报必须限定在64KB之内。
3,UDP是一个不可靠的协议,发送方所发送的数据报并不一定以相同的次序到达接收方
TCP:1,面向连接的协议,在socket之间进行数据传输之前必然要建立连接,所以在TCP中需要连接
时间。
2,TCP传输数据大小限制,一旦连接建立起来,双方的socket就可以按统一的格式传输大的
数据。
3,TCP是一个可靠的协议,它确保接收方完全正确地获取发送方所发送的全部数据。
应用:
1,TCP在网络通信上有极强的生命力,例如远程连接(Telnet)和文件传输(FTP)都需要不定长度的数据被可靠地传输。但是可靠的传输是要付出代价的,对数据内容正确性的检验必然占用计算机的处理时间和网络的带宽,因此TCP传输的效率不如UDP高。
2,UDP操作简单,而且仅需要较少的监护,因此通常用于局域网高可靠性的分散系统中client/server应用程序。例如视频会议系统,并不要求音频视频数据绝对的正确,只要保证连贯性就可以了,这种情况下显然使用UDP会更合理一些。
三,基于Socket的java网络编程
1,什么是Socket
网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个Socket。Socket通常用来实现客户方和服务方的连接。Socket是TCP/IP协议的一个十分流行的编程界面,一个Socket由一个IP地址和一个端口号唯一确定。
但是,Socket所支持的协议种类也不光TCP/IP一种,因此两者之间是没有必然联系的。在Java环境下,Socket编程主要是指基于TCP/IP协议的网络编程。
2,Socket通讯的过程
Server端Listen(监听)某个端口是否有连接请求,Client端向Server 端发出Connect(连接)请求,Server端向Client端发回Accept(接受)消息。一个连接就建立起来了。Server端和Client 端都可以通过Send,Write等方法与对方通信。
对于一个功能齐全的Socket,都要包含以下基本结构,其工作过程包含以下四个基本的步骤:
(1) 创建Socket;
(2) 打开连接到Socket的输入/出流;
(3) 按照一定的协议对Socket进行读/写操作;
(4) 关闭Socket.(在实际应用中,并未使用到显示的close,虽然很多文章都推荐如此,不过在我的程序中,可能因为程序本身比较简单,要求不高,所以并未造成什么影响。)
3,创建Socket
创建Socket
java在包java.net中提供了两个类Socket和ServerSocket,分别用来表示双向连接的客户端和服务端。这是两个封装得非常好的类,使用很方便。其构造方法如下:
Socket(InetAddress address, int port);
Socket(InetAddress address, int port, boolean stream);
Socket(String host, int prot);
Socket(String host, int prot, boolean stream);
Socket(SocketImpl impl)
Socket(String host, int port, InetAddress localAddr, int localPort)
Socket(InetAddress address, int port, InetAddress localAddr, int localPort)
ServerSocket(int port);
ServerSocket(int port, int backlog);
ServerSocket(int port, int backlog, InetAddress bindAddr)
其中address、host和port分别是双向连接中另一方的IP地址、主机名和端 口号,stream指明socket是流socket还是数据报socket,localPort表示本地主机的端口号,localAddr和 bindAddr是本地机器的地址(ServerSocket的主机地址),impl是socket的父类,既可以用来创建serverSocket又可 以用来创建Socket。count则表示服务端所能支持的最大连接数。例如:学习视频网 http://www.xxspw.com
Socket client = new Socket("127.0.01.", 80);
ServerSocket server = new ServerSocket(80);
注意,在选择端口时,必须小心。每一个端口提供一种特定的服务,只有给出正确的端口,才 能获得相应的服务。0~1023的端口号为系统所保留,例如http服务的端口号为80,telnet服务的端口号为21,ftp服务的端口号为23, 所以我们在选择端口号时,最好选择一个大于1023的数以防止发生冲突。
在创建socket时如果发生错误,将产生IOException,在程序中必须对之作出处理。所以在创建Socket或ServerSocket是必须捕获或抛出例外。
4,简单的Client/Server程序
1. 客户端程序
import java.io.*;
import java.net.*;
public class TalkClient {
public static void main(String args[]) {
try{
Socket socket=new Socket("127.0.0.1",4700);
//向本机的4700端口发出客户请求
BufferedReader sin=new BufferedReader(new InputStreamReader(System.in));
//由系统标准输入设备构造BufferedReader对象
PrintWriter os=new PrintWriter(socket.getOutputStream());
//由Socket对象得到输出流,并构造PrintWriter对象
BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream()));
//由Socket对象得到输入流,并构造相应的BufferedReader对象
String readline;
readline=sin.readLine(); //从系统标准输入读入一字符串
while(!readline.equals("bye")){
//若从标准输入读入的字符串为 "bye"则停止循环
os.println(readline);
//将从系统标准输入读入的字符串输出到Server
os.flush();
//刷新输出流,使Server马上收到该字符串
System.out.println("Client:"+readline);
//在系统标准输出上打印读入的字符串
System.out.println("Server:"+is.readLine());
//从Server读入一字符串,并打印到标准输出上
readline=sin.readLine(); //从系统标准输入读入一字符串
} //继续循环
os.close(); //关闭Socket输出流
is.close(); //关闭Socket输入流
socket.close(); //关闭Socket
}catch(Exception e) {
System.out.println("Error"+e); //出错,则打印出错信息
}
}
}
2. 服务器端程序
import java.io.*;
import java.net.*;
import java.applet.Applet;
public class TalkServer{
public static void main(String args[]) {
try{
ServerSocket server=null;
try{
server=new ServerSocket(4700);
//创建一个ServerSocket在端口4700监听客户请求
}catch(Exception e) {
System.out.println("can not listen to:"+e);
//出错,打印出错信息
}
Socket socket=null;
try{
socket=server.accept();
//使用accept()阻塞等待客户请求,有客户
//请求到来则产生一个Socket对象,并继续执行
}catch(Exception e) {
System.out.println("Error."+e);
//出错,打印出错信息
}
String line;
BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream()));
//由Socket对象得到输入流,并构造相应的BufferedReader对象
PrintWriter os=newPrintWriter(socket.getOutputStream());
//由Socket对象得到输出流,并构造PrintWriter对象
BufferedReader sin=new BufferedReader(new InputStreamReader(System.in));
//由系统标准输入设备构造BufferedReader对象
System.out.println("Client:"+is.readLine());
//在标准输出上打印从客户端读入的字符串
line=sin.readLine();
//从标准输入读入一字符串
while(!line.equals("bye")){
//如果该字符串为 "bye",则停止循环
os.println(line);
//向客户端输出该字符串
os.flush();
//刷新输出流,使Client马上收到该字符串
System.out.println("Server:"+line);
//在系统标准输出上打印读入的字符串
System.out.println("Client:"+is.readLine());
//从Client读入一字符串,并打印到标准输出上
line=sin.readLine();
//从系统标准输入读入一字符串
} //继续循环
os.close(); //关闭Socket输出流
is.close(); //关闭Socket输入流
socket.close(); //关闭Socket
server.close(); //关闭ServerSocket
}catch(Exception e){
System.out.println("Error:"+e);
//出错,打印出错信息
}
}
}
5,支持多客户的client/server程序
前面的Client/Server程序只能实现Server和一个客户的对话。在实际应用 中,往往是在服务器上运行一个永久的程序,它可以接收来自其他多个客户端的请求,提供相应的服务。为了实现在服务器方给多个客户提供服务的功能,需要对上 面的程序进行改造,利用多线程实现多客户机制。服务器总是在指定的端口上监听是否有客户请求,一旦监听到客户请求,服务器就会启动一个专门的服务线程来响 应该客户的请求,而服务器本身在启动完线程之后马上又进入监听状态,等待下一个客户的到来。
1. java_home C:\jdk1.6.0_30
2. Path ;%java_home%\bin
3. classpath .;%java_home%\lib\dt.jar;%java_home%\lib\tools.jar
http://www.cnblogs.com/sunada2005/p/3577799.html
http://greemranqq.iteye.com/blog/1774258
http://www.cnblogs.com/-lpf/p/4317281.html
我在项目开发过程中,经常要改动JAVA/JSP 文件,但是又不想从新启动服务器(服务器从新启动花时间),想直接获得(debug)结果.有两种方式热部署 和热加载:
1.热加载:在server.xml -> context 属性中 设置 reloadable="true"
Java代码
- <Context docBase="xxx" path="/xxx" reloadable="true"/>
2. 热部署:在server.xml -> context 属性中 设置 autoDeploy="true"
Java代码
- <Context docBase="xxx" path="/xxx" autoDeploy="true"/>
3.区别:
热加载:服务器会监听 class 文件改变,局部进行加载,不清空session ,不释放内存。开发中用的多,但是要考虑内存溢出的情况。
热部署: 整个项目从新部署,包括你从新打上.war 文件。 会清空session ,释放内存。项目打包的时候用的多。
也可以通过Eclipse上设置实现上述配置文件的修改
Eclipse的工程名右键: properties->Tomcat->General->Make this context as reloadable(reloadable="true")不要选中 Eclipse的工程名右键:Tomcat project->Update Context Definition
注意:source 属性有些版本不支持,容易出错,去掉就行
二。
不重启Tomcat有两种方式:热部署、热加载
热部署:容器状况在运行时重新部署整个项目。这类环境下一般整个内存会清空,重新加载,这类方式
有可能会造成sessin丢失等环境。tomcat 6确实可以热部署了,而且对话也没丢.
热加载:最好是在调试过程中使用,免患上整个项目加载,Debug标准样式支持热加载。容器状况在运行时重
新加载转变编译后的类。在这类环境下内存不会清空,sessin不会丢失,但容易造成内存溢出,或者找不到方
法。一般转变类的布局和模型就会有异常,在已经有的变量和方法中转变是不会出问题的(Eclipse、
MyEclipse8、JBuilder、IntelliJ IDEA…)。
常用的一定第二种:热加载了,设置如下!
在tomcat的conf中的server.xml中的host设置中添加<Context path="/test"
docBase="D:/develop/test"
debug="0" privileged="true" reloadable="true"/>
reloadable="true" !最重要
它内里有很多属性,意义如下:
1>path:指定拜候该web应用的URL进口;
2>docBase:指定web应用的文件路径,可以给定绝对路径,也可以给定相对于<Host>的appBase属性【默认
指向tomcat的webapps】的相对于径;要是Web应用是个war文件,则指定war文件的路径。
3>className:指定使成为事实Context组件的Java类的名字,这个Java类必须使成为事实org.apache.catalina.Context
接口,该属性的默认值为org.apache.catalina.StandardContext。
4>reloadable:要是这个属性设置为true,Tomcat服务器在运行状况下会监视在WEB-INF/classess和WEB-
INF/lib目次下的class文件的改动,以及监视web应用的WEB-INF/web.xml文件的改动。要是检测到的class
文件或者web.xml文件被更新,服务器会自动加载Web应用。该属性的默认值为false.在web应用的开发和调
试阶段,把reloadable设为true,可以方便对web应用的调试。在web应用正式发布阶段,把reloadable设为
false,可以减低tomcat的运行负荷,提高Tomcat的运行性能。
5>cachingAllowed:要是为true,标示允许启用静态资源的缓存。使用缓存能提高拜候静态资源的效率。
tomcat把那一些时常被客户端拜候的静态资源(如:HTML文档、图片文件和声响文件等)放在缓存中,当客户再
次拜候有关静态资源时,Tomcat只需直接从缓存中读取相关数据,无须反复读取文件系统中的文件。该属
性的默认值为true.
6>cacheMaxSize:设定静态资源的缓存的最大容量,以K为单元。要是,要是该属性为100,表示100K,默认
为10240(即10M)。
7>workDir:指定web应用的工作目次。Tomcat在运行时会把与这个web应用相关的临应试文章件放在此目次下。
8>uppackWar:要是此项设为true,表示将把web应用的war文件睁开为开放目次布局后再运行。要是设为
false,则直接运行war文件。该属性的默认值为true。
同志们,使用tomcat6.0的注意了啊。当你使用我的方法设置tomcat后,你的myeclipse报如下错误时,不要惊慌,这是正确的,且听我解释。
console报错:
警告: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property ' debug' to '0' did not find a matching property. 这是由于你使用的是tomcat6.0,由于它路程经过过程其他途径对debug="0"这个属性进行了使成为事实,所以这搭不能再有此属性。你只要将它去掉,就能够没事了启动了。 也就是说去掉debug="0“,万事OK,呵呵。
(转)
-------------------------------------------------------------
针对需要重新启动tomcat的服务,重新启动方式为:
安装版:tomcat/bin/shotdown.bat 关闭tomcat服务
tomcat/bin/startup.bat 开启tomcat服务
或者-->我的电脑-->管理-->服务和应用程序/服务-->找到Apache Tomcat重启
http://blog.sina.com.cn/s/blog_3c9872d00102w00y.html
Apache与Tomcat整合应用是一个老话题,不算新技能,但对非运维人员在配置过程中或许也会遇到一些问题。这里只是把自己多回配置的过程做一个摘录,供自己翻阅并望对过路的人有用。
Apache是当下在Windows、Unix、Linux 等操作系统中最流行的Web服务器软件之一,其反应速度快、运行效率高,不仅支持HTML等静态页面,在加载插件后也可支持 PHP 页面等。Tomcat是Apache软件基金协会与Sun公司联合开发的Web服务器,除支持HTML静态页面外,还是JSP、Servlet等JAVA WEB应用的服务器。在相同运行环境下,Tomcat对静态页面的反应速度没有Apache灵敏,整合 Apache与Tomcat能使系统运行于一个良好环境下,实现JAVA的动态与静态页面分离,不仅让系统更安全,同时也可提高系统效率。
一、JAVA应用基础架构
通用的JAVA应用架构如下,包括WEB Server、APP Server和DB Server三个部分:
1、WEB Server
WEB Server置于企业防火墙外,这个防火墙也可以认为是一个CISCO路由器,在CISCO路由器上开放两个端口为:80和443,其中:
80端口:用于正常的http访问
443端口:用于https访问,即如果你在ie里打入https://xxx.xxx.xx这样的地址,默认走的是443这个端口
WebServer专门用于解析HTML、JS(JavaScript)、CSS、JPG/GIF等图片格式文件、TXT、VBSCRIPT、PHP等“静态”网页内容。
2、APP Server
APP Server置于企业防火墙内,它和Web Server之间的连接必须且一定为内部IP连接。App Server用于解析我们的任何需要Java编译器才能解析的“动态”网页,其实App Server本身也能解析任何静态网页的。在应用中我们这样来想一下:我们让负责专门解析静态网页的Web Server来解析html等内容,而让App Server专门用于解析任何需要Java编译器才能解析的东西,让它们各司其职。这样作的好处:
1)为App Server“减压”,同时也提高了性能;
2)不用再把8080这个端口暴露在internet上,也很安全,毕竟我们的App Server上是有我们的代码的,就算是编译过的代码也容易被“反编译”,这是很不安全的;
3)为将来进一步的“集群扩展”打好了基础。
3、DB Server
比方说我们用MySQL,它需要通过3306与App Server进行连接,那么这个1521我们称为数据库连接端口,如果把它暴露在Internet上就比较危险,就算密码很复杂,但 对于高明的黑客来说,要攻破你的口令也只是时间上的问题而己。因此我们把我们的DB Server也和App Server一样,置于内网的防火墙,任何的DB连接与管理只能通过内网来访问。
二、系统安装与配置
系统安装包括MySQL的安装,WEB Server即Apache的安装,App Server即Tomcat的安装。关于这三个系统安装网上相关的文档很多,此处略去。以下主要摘录需要重点配置的内容。
1、Apache的配置
做技术的人应该都会Apache的基础配置,如果不会确实需要学一学。
Apache的配置主要集中在httpd.conf文件中,它位于Apache的安装目录下,比如我的是在“C:\webserver\apache\apache22\conf”目录下。用Ultraedit或Notepad++编辑器打开文件,通常需要修改的内容包括ServerName、DocumentRoot、VirtualHost内容等。此处我修改的内容包括:
1)DocumentRoot原目录为C:/webserver/apache/apache22/htdocs,修改为D:/WWW/apache/htdocs,将网站发布路径与Apache安装路径分开;
2)找到如下红色标示内容:
Options FollowSymLinks
AllowOverride None
Order deny,allow
deny from all
把这个”deny from all”改成”allow fromall’。
Options FollowSymLinks
AllowOverride None
Order deny,allow
allow from all
以免访问Apache根目录下的文件时出现以下错误提示:
3)再找到下面这样的行
Options FollowSymLinks indexes
把它注掉改成下面这样
#Options FollowSymLinks indexes
Options None
以免在访问Apache目录时出现直接列表显示子目录或目录下文件的不安全情况,如下图样子:
以上配置修改完成后重启Apache服务,保证要能正常运行。
三、Apache与Tomcat的整合配置
Apache(Web Server)负责处理HTML静态内容,Tomcat(App Server)负责处理动态内容;原理图如下:
上述架构的原理是: 在Apache中装载一个模块,这个模块叫mod_jk; Apache通过80端口负责解析任何静态web内容; 任何不能解析的内容,用表达式告诉mod_jk,让mod_jk派发给相关的App Server去解释。
因此,首先把 mod_jk-1.2.31-httpd-2.2.3(可从网上搜索下载该模块,如http://download.csdn.net/detail/shangkaikuo/4494837)拷贝到 "/Apache2.2/modules" 目录下。接下来:
1、添加workers.properties文件
在 “/Tomcat 8.0/conf ” 文件夹下(也可以是其它目录下)增加 workers.properties 文件,输入以下内容。(将其中相应目录替换成自己本地tomcat或jre安装目录)
#让mod_jk模块认识Tomcat
workers.tomcat_home=d:/webserver/tomcat/tomcat8
#让mod_jk模块认识JRE
workers.java_home=C:/java/jdk1.8.0_45/jre
#指定文件路径分割符
ps=/
##
#工作端口,此端口应该与server.xml中Connector元素的AJP/1.3协议所使用的端口相匹配
worker.list=AJP13
worker.AJP13.port=8009
#Tomcat服务器的地址
worker.AJP13.host=localhost
#类型
worker.AJP13.type=ajp13
#负载平衡因数
worker.AJP13.lbfactor=1
**注意:worker.list=AJP13中,AJP13为自定义名称,但此名称必须与下文所述的 “/Apache 2.2/conf/httpd.conf ” 文件中,JkMount指令对应的名称相匹配。
2、httpd.conf文件中添加配置内容
加入workers.properties文件后,可修改 “/Apache 2.2/conf/httpd.conf ” 文件,加入以下配置,注意JkMount指令中的变量必须与worker.list所配置的名称相同。
# 此处mod_jk-1.2.31-httpd-2.2.3文件为你下载的文件
LoadModule jk_module modules/mod_jk-1.2.31-httpd-2.2.3.so
# 指定tomcat监听配置文件地址
JkWorkersFile "C:/webserver/tomcat/tomcat8/conf/workers.properties"
#JkWorkersFile "C:/webserver/apache/apache22/conf/workers.properties"
# 指定日志存放位置
JkLogFile "C:/webserver/tomcat/tomcat8/logs/mod_jk2.log"
JkLogLevel info
-virtualhost *-
ServerName localhost
DocumentRoot "C:/webserver/tomcat/tomcat8/webapps"
DirectoryIndex index.html index.htm index.jsp index.action
ErrorLog logs/shsc-error_log.txt
CustomLog logs/shsc-access_log.txt common
JkMount /*WEB-INF AJP13
JkMount /*j_spring_security_check AJP13
JkMount /*.action AJP13
JkMount /servlet/* AJP13
JkMount /*.jsp AJP13
JkMount /*.do AJP13
JkMount /*.action AJP13
-/virtualhost-
上述配置中的红色内容是为了告诉Apache哪些交给Tomcat去处理,其它的都交由Apache自身去处理。
其中绿色的两句比较关键,分别告诉:Apache载入一个额外的插件,用于连接tomcat; 连接时的配置参数描述位于Tomcat安装目录的/conf目录下的一个叫workers.properties文件中,mod_jk一般使用ajp13协议连接,使用的是tomcat的8009端口。
完成以上配置后,重启 Apache、Tomcat。此时Apache、Tomcat的默认目录为 "C:/Program Files/Apache Software Foundation/Tomcat 7.0/webapps ”,Apache使用默认的80端口、Tomcat端口改成1080或其它非8080默认端口(修改是为了安全,也可以不用修改)。在Tomcat默认目录下添加test目录,在该目录下加入index.jsp页面,然后通过http://localhost/test/index.jsp试试是否可以正常访问,如页面可正常访问,证明整合配置已经成功。
至此,似乎整个配置工作已经完成,但是如果你想试着把静态的HTML页面放到Apache的htdocs发布目录下,把JSP等动态内容放到Tomcat的webapps目录下(该目录下不存放*.html文件),然后通过http://localhost/index.html想访问Apache目录下的内容,你会发现404之类的不能访问的错误。如何解决,这里暂时卖个关子.......如果你能看出问题,能容易解决掉,就诚挚为你点个赞!
http://www.jfox.info/guan-yu-Tomcat-he-Tomcat-de-mian-shi-wen-ti
http://www.jfox.info/guan-yu-Tomcat-he-Tomcat-de-mian-shi-wen-ti
关于Tomcat和Tomcat的面试问题
一、Tomcat的缺省是多少,怎么修改
Tomcat的缺省端口号是8080.
修改Tomcat端口号:
1.找到Tomcat目录下的conf文件夹
2.进入conf文件夹里面找到server.xml文件
3.打开server.xml文件
4.在server.xml文件里面找到下列信息
maxThreads=”150″ minSpareThreads=”25″ maxSpareThreads=”75″
enableLookups=”false” redirectPort=”8443″ acceptCount=”100″
connectionTimeout=”20000″ disableUploadTimeout=”true” />
5.把port=”8080″改成port=”8888″,并且保存
6.启动Tomcat,并且在IE浏览器里面的地址栏输入http://127.0.0.1:8888/
7、tomcat默认采用的BIO模型,在几百并发下性能会有很严重的下降。tomcat自带还有NIO的模型,另外也可以调用APR的库来实现操作系统级别控制。
NIO模型是内置的,调用很方便,只需要将上面配置文件中protocol修改成 org.apache.coyote.http11.Http11NioProtocol,重启即可生效。如下面的参数配置,默认的是HTTP/1.1。
<Connector port=”8080″
protocol=”org.apache.coyote.http11.Http11NioProtocol”
connectionTimeout=”20000″
redirectPort=”8443″
maxThreads=”500″
minSpareThreads=”20″
acceptCount=”100″
disableUploadTimeout=”true”
enableLookups=”false”
URIEncoding=”UTF-8″ />
二、tomcat 如何优化?
1、优化连接配置.这里以tomcat7的参数配置为例,需要修改conf/server.xml文件,修改连接数,关闭客户端dns查询。
参数解释:
URIEncoding=”UTF-8″ :使得tomcat可以解析含有中文名的文件的url,真方便,不像apache里还有搞个mod_encoding,还要手工编译
maxSpareThreads : 如果空闲状态的线程数多于设置的数目,则将这些线程中止,减少这个池中的线程总数。
minSpareThreads : 最小备用线程数,tomcat启动时的初始化的线程数。
enableLookups : 这个功效和Apache中的HostnameLookups一样,设为关闭。
connectionTimeout : connectionTimeout为网络连接超时时间毫秒数。
maxThreads : maxThreads Tomcat使用线程来处理接收的每个请求。这个值表示Tomcat可创建的最大的线程数,即最大并发数。
acceptCount : acceptCount是当线程数达到maxThreads后,后续请求会被放入一个等待队列,这个acceptCount是这个队列的大小,如果这个队列也满了,就直接refuse connection
maxProcessors与minProcessors : 在 Java中线程是程序运行时的路径,是在一个程序中与其它控制线程无关的、能够独立运行的代码段。它们共享相同的地址空间。多线程帮助程序员写出CPU最 大利用率的高效程序,使空闲时间保持最低,从而接受更多的请求。
通常Windows是1000个左右,Linux是2000个左右。
useURIValidationHack:
我们来看一下tomcat中的一段源码:
【security】
if (connector.getUseURIValidationHack()) {
String uri = validate(request.getRequestURI());
if (uri == null) {
res.setStatus(400);
res.setMessage(“Invalid URI”);
throw new IOException(“Invalid URI”);
} else {
req.requestURI().setString(uri);
// Redoing the URI decoding
req.decodedURI().duplicate(req.requestURI());
req.getURLDecoder().convert(req.decodedURI(), true);
可以看到如果把useURIValidationHack设成”false”,可以减少它对一些url的不必要的检查从而减省开销。
enableLookups=”false” : 为了消除DNS查询对性能的影响我们可以关闭DNS查询,方式是修改server.xml文件中的enableLookups参数值。
disableUploadTimeout :类似于Apache中的keeyalive一样
给Tomcat配置gzip压缩(HTTP压缩)功能
compression=”on” compressionMinSize=”2048″
compressableMimeType=”text/html,text/xml,text/javascript,text/css,text/plain”
HTTP 压缩可以大大提高浏览网站的速度,它的原理是,在客户端请求网页后,从服务器端将网页文件压缩,再下载到客户端,由客户端的浏览器负责解压缩并浏览。相对于普通的浏览过程HTML,CSS,Javascript , Text ,它可以节省40%左右的流量。更为重要的是,它可以对动态生成的,包括CGI、PHP , JSP , ASP , Servlet,SHTML等输出的网页也能进行压缩,压缩效率惊人。
1)compression=”on” 打开压缩功能
2)compressionMinSize=”2048″ 启用压缩的输出内容大小,这里面默认为2KB
3)noCompressionUserAgents=”gozilla, traviata” 对于以下的浏览器,不启用压缩
4)compressableMimeType=”text/html,text/xml” 压缩类型
最后不要忘了把8443端口的地方也加上同样的配置,因为如果我们走https协议的话,我们将会用到8443端口这个段的配置,对吧?
<!–enable tomcat ssl–>
<Connector port=”8443″ protocol=”HTTP/1.1″
URIEncoding=”UTF-8″ minSpareThreads=”25″ maxSpareThreads=”75″
enableLookups=”false” disableUploadTimeout=”true” connectionTimeout=”20000″
acceptCount=”300″ maxThreads=”300″ maxProcessors=”1000″ minProcessors=”5″
useURIValidationHack=”false”
compression=”on” compressionMinSize=”2048″
compressableMimeType=”text/html,text/xml,text/javascript,text/css,text/plain”
SSLEnabled=”true”
scheme=”https” secure=”true”
clientAuth=”false” sslProtocol=”TLS”
keystoreFile=”d:/tomcat2/conf/shnlap93.jks” keystorePass=”aaaaaa”
/>
好了,所有的Tomcat优化的地方都加上了。
2、优化JDK
Tomcat默认可以使用的内存为128MB,Windows下,在文件{tomcat_home}/bin/catalina.bat,Unix下,在文件$CATALINA_HOME/bin/catalina.sh的前面,增加如下设置:
JAVA_OPTS=”‘$JAVA_OPTS” -Xms[初始化内存大小] -Xmx[可以使用的最大内存]
或
设置环境变量:export JAVA_OPTS=””$JAVA_OPTS” -Xms[初始化内存大小] -Xmx[可以使用的最大内存]”
一般说来,你应该使用物理内存的 80% 作为堆大小。如果本机上有Apache服务器,可以先折算Apache需要的内存,然后修改堆大小。建议设置为70%;建议设置[[初始化内存大小]等于[可以使用的最大内存],这样可以减少平凡分配堆而降低性能。
本例使用加入环境变量的方式:
# vi /etc/profile
加入:export JAVA_OPTS=””$JAVA_OPTS” -Xms700 —Xmx700
# source /etc/profile
【参数说明】
-Xms 是指设定程序启动时占用内存大小。一般来讲,大点,程序会启动的 快一点,但是也可能会导致机器暂时间变慢。
-Xmx 是指设定程序运行期间最大可占用的内存大小。如果程序运行需要占 用更多的内存,超出了这个设置值,就会抛出OutOfMemory 异常。
-Xss 是指设定每个线程的堆栈大小。这个就要依据你的程序,看一个线程 大约需要占用多少内存,可能会有多少线程同时运行等。
-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64 。
-XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。
三、tomcat 有那几种Connector 运行模式?
tomcat的运行模式有3种.修改他们的运行模式.3种模式的运行是否成功,可以看他的启动控制台,或者启动日志.或者登录他们的默认页面http://localhost:8080/查看其中的服务器状态。
1)bio
默认的模式,性能非常低下,没有经过任何优化处理和支持.
2)nio
利用java的异步io护理技术,no blocking IO技术.
想运行在该模式下,直接修改server.xml里的Connector节点,修改protocol为
<Connector port=”80″ protocol=”org.apache.coyote.http11.Http11NioProtocol”
connectionTimeout=”20000″
URIEncoding=”UTF-8″
useBodyEncodingForURI=”true”
enableLookups=”false”
redirectPort=”8443″ />
启动后,就可以生效。
3)apr
安装起来最困难,但是从操作系统级别来解决异步的IO问题,大幅度的提高性能.
必须要安装apr和native,直接启动就支持apr。下面的修改纯属多余,仅供大家扩充知识,但仍然需要安装apr和native
如nio修改模式,修改protocol为org.apache.coyote.http11.Http11AprProtocol
http://zhidao.baidu.com/link?url=6FrnwvBQEZhjM-ooNCuiAra7T6qi9FsFhFvkHBKaOjqovZR86OCsIePi-05nM-fxRrlInEGbElSxlhgO6X7JsaGNdQdNrQ2xE58wglgeQO3
http://blog.csdn.net/liaq325/article/details/8281550
摘自以上
spring httpInvoke
spring httpInvoke 基于spring架构的服务器之间的远程调用实现。通过spring httpInvoke,可以调用远程接口,进行数据交互、业务逻辑操作
服务器端:(被调用一方)
- public class User implements Serializable{//必须实现serializable接口,远程调用的基础
- private String username;
- private Date birthday;
- //构造方法
- //set get 方法
- }
- public interface UserService{
- User getUser(String username);
- }
- public UserServiceImpl implements UserService{
- //实现userService
- }
重要的配置文件来了。。。。remote-servlet.xml放在项目根目录下面,跟web.xml相同的级别暴露给调用端:服务的实现,接口
- <bean id="userService" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
- <property name="service">
- <bean class="com.cd.Liaq.UserServiceImpl"/>
- </property>
- <property name="serviceInterface">
- <value>com.cd.Liaq.UserService</value>
- </property>
- </bean>
暴露了服务的实现和接口,那么怎么访问服务呢?spring封装访问url- <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
- 第一种:<property name="urlMap">
- <map>
- <entry key="TestUser" value-ref="userService"/>
- </map>
- </property>
- 第二种:<prop key="/TestUser">userService</prop>
- </bean>
web.xml:配置dispatcherServlet共调用一方使用- <!-- spring远程调用 -->
- <servlet>
- <servlet-name>remote</servlet-name>
- <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
- <load-on-startup>1</load-on-startup>
- </servlet>
- <servlet-mapping>
- <servlet-name>remote</servlet-name>
- <url-pattern>/remoting/*</url-pattern>
- </servlet-mapping>
到处为止:被调用端一方完毕!!!!客户端调用:- <!-- 通过http连接远程系统 -->
- <bean id="memberService"
- class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
- <property name="serviceUrl">
- <value>http://192.9.200.123:8080/MemberSystem/remoting/memberService</value>
- </property>
- <property name="serviceInterface">
- <value>com.cd.Liaq.UserService</value>
- </property>
- </bean>
通过spring容器调用UserService,用到HttpInvokerProxyFactoryBean工厂,配置serviceUrl和serviceInterface为了提高效率:客户端使用Commons-HttpClient,导入改包,改写配置- <bean id="memberService"
- class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
- <property name="serviceUrl">
- <value>http://192.9.200.123:8080/MemberSystem/remoting/memberService</value>
- </property>
- <property name="serviceInterface">
- <value>com.cd.Liaq.UserService</value>
- </property>
- <property name="httpInvokerRequestExecutor"> //使用指定的执行器执行
- <ref bean="httpInvokerRequestExecutor" />
- </property>
- </bean>
- <bean id="httpInvokerRequestExecutor" class="org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor">
- <property name="httpClient">
- <bean class="org.apache.commons.httpclient.HttpClient">
- <property name="connectionTimeout" value="2000" />
- <property name="timeout" value="5000" />
- </bean>
- </property>
- </bean>
配置超时时间timeout和连接超时connectionTimeout两个属性优化执行器:多线程===被调用端响应时间缩短很多- <bean id="httpInvokerRequestExecutor" class="org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor">
- <property name="httpClient">
- <bean class="org.apache.commons.httpclient.HttpClient">
- <property name="connectionTimeout" value="2000" />
- <property name="timeout" value="5000" />
- <property name="httpConnectionManager">//控制连接
- <ref bean="multiThreadedHttpConnectionManager" />
- </property>
- </bean>
- </property>
- </bean>
- <bean id="multiThreadedHttpConnectionManager" class="org.apache.commons.httpclient.MultiThreadedHttpConnectionManager">
- <property name="params">
- <bean class="org.apache.commons.httpclient.params.HttpConnectionManagerParams">
- <property name="maxTotalConnections" value="600" />
- <property name="defaultMaxConnectionsPerHost" value="512" />
- </bean>
- </property>
- </bean>
httpClient的3.1版本不支持这种配置- <property name="connectionTimeout" value="2000" />
- <property name="timeout" value="5000" />
另外httpClient本身也是多线程的。。HttpClient that uses a default MultiThreadedHttpConnectionManage<bean class="org.apache.commons.httpclient.params.HttpConnectionManagerParams"> <property name="maxTotalConnections" value="600" /> <property name="defaultMaxConnectionsPerHost" value="512" /> </bean> maxConnectionsPerHost 每个主机的最大并行链接数,默认为2 public static final int DEFAULT_MAX_HOST_CONNECTIONS = 2; maxTotalConnections 客户端总并行链接最大数,默认为20 public static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 20;
摘要: http://www.cnblogs.com/hoojo/archive/2012/07/19/2599534.htmlhttp://www.cnblogs.com/hellowood23/p/5210267.htmlhttp://blog.csdn.net/ni_hao_ya/article/details/9344779http://www.cnblogs.com/hellowood23/p/...
阅读全文
WEB项目:
方法1:
1 | ApplicationContext ac1 = WebApplicationContextUtils.getRequiredWebApplicationContext(ServletContext sc)
|
方法2:
1 | ApplicationContext ac2 = WebApplicationContextUtils.getWebApplicationContext(ServletContext sc)
|
方法3:
1 | 写一个工具类类继承ApplicationObjectSupport,并将这个加入到spring的容器
|
方法4:
1 | 写一个工具类类继承WebApplicationObjectSupport,并将这个加入到spring的容器
|
方法5:(推荐)
1 | 写一个工具类实现ApplicationContextAware接口,并将这个加入到spring的容器
|
示例:
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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | import java.util.Map;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/**
* 获取ApplicationContext和Object的工具类
* @author yzl
*
*/
@SuppressWarnings ({ "rawtypes" , "unchecked" })
public class SpringContextUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext arg0)
throws BeansException {
applicationContext = arg0;
}
/**
* 获取applicationContext对象
* @return
*/
public static ApplicationContext getApplicationContext(){
return applicationContext;
}
/**
* 根据bean的id来查找对象
* @param id
* @return
*/
public static Object getBeanById(String id){
return applicationContext.getBean(id);
}
/**
* 根据bean的class来查找对象
* @param c
* @return
*/
public static Object getBeanByClass(Class c){
return applicationContext.getBean(c);
}
/**
* 根据bean的class来查找所有的对象(包括子类)
* @param c
* @return
*/
public static Map getBeansByClass(Class c){
return applicationContext.getBeansOfType(c);
}
}
|
非WEB项目
1 | ApplicationContext ac = new FileSystemXmlApplicationContext( "applicationContext.xml" )
|
可选的操作方法有:
1 2 3 4 5 6 7 8 9 10 11 | 一:
String[] path={ "WebRoot/WEB-INF/applicationContext.xml" , "WebRoot/WEB-INF/applicationContext_task.xml" };
ApplicationContext context = new FileSystemXmlApplicationContext(path);
二:
String path= "WebRoot/WEB-INF/applicationContext*.xml" ;
ApplicationContext context = new FileSystemXmlApplicationContext(path);
三:
ApplicationContext ctx = new FileSystemXmlApplicationContext( "classpath:地址" );
没有classpath的话就是从当前的工作目录
|
摘要: http://ligf06.iteye.com/blog/17108875. 在 Spring 中运用 EHCache需要使用 Spring 来实现一个 Cache 简单的解决方案,具体需求如下:使用任意一个现有开源 Cache Framework,要求使用 Cache 系统中 Service 或则 DAO 层的...
阅读全文
1.文件上传,ajax引入common,在jsp中进行上传
2.webservice 客户端连接用axis2.jar连接,用axis2的包进行创建
或者用xfx配置发布
3.文件解析,将文件转换成i
4.ftp文件上传下载
5.网上银行农行校验
6.联动用ajax
7.dwrajax
8.邮件发送功能
9.短信发送功能
10.任务定时功能
http://blog.sina.com.cn/s/blog_6aefe42501018wnn.html
1缓存为什么要存在?
2缓存可以存在于什么地方?
3缓存有哪些属性?
4缓存介质?
搞清楚这4个问题,那么我们就可以随意的通过应用的场景来判断使用何种缓存了.
1. 缓存为什么要存在?
一般情况下,一个网站,或者一个应用,它的一般形式是,浏览器请求应用服务器,应用服务器做一堆计算后再请求数据库,数据库收到请求后再作一堆计算后把数据返回给应用服务器,应用服务器再作一堆计算后把数据返回给浏览器.这个是一个标准流程.但是随着互连网的普及,上网的人越来越多,网上的信息量也越来越多,在这两个越来越多的情况下,我们的应用需要支撑的并发量就越来越多.然后我们的应用服务器和数据库服务器所做的计算也越来越多,但是往往我们的应用服务器资源是有限的,数据库每秒中接受请求的次数也是有限的(谁叫俺们的硬盘转速有限呢).如果利用有限的资源来提供尽可能大的吞吐量呢,一个办法:减少计算量,缩短请求流程(减少网络io或者硬盘io),这时候缓存就可以大展手脚了.缓存的基本原理就是打破上图中所描绘的标准流程,在这个标准流程中,任何一个环节都可以被切断.请求可以从缓存里取到数据直接返回.这样不但节省了时间,提高了响应速度,而且也节省了硬件资源.可以让我们有限的硬件资源来服务更多的用户.
2 缓存可以存在于什么地方?
Java代码
浏览器---?浏览器和app之间---?分过层的app-?数据库
浏览器---?浏览器和app之间---?分过层的app-?数据库
在上图中,我们可以看到一次请求的一般流程,下面我们重新绘制这张图,让我们的结构稍微复杂一点点.
(将app分层)
浏览器---?浏览器和app之间---?分过层的app-?数据库
理论上来将,请求的任何一个环节都是缓存可以作用的地方.第一个环节,浏览器,如果数据存在浏览器上,那么对用户来说速度是最快的,因为这个时候根本无需网络请求.第二个环节,浏览器和app之间,如果缓存加在这个地方,那么缓存对app来说是透明的.而且这个缓存中存放的是完整的页面.第三个节点,app 中本身就有几个层次,那么缓存也可以放在不同的层次上,这一部分是情况或者场景比较复杂的部分.选择缓存时需要谨慎.第四个环节,数据库中也可以有缓存, 比如说mysql的querycache.
那么也就是说在整个请求流程的任何一点,我们都可以加缓存.但是是所有的数据都可以放进缓存的吗.当然不是,需要放进缓存的数据总是有一些特征的,要清楚的判断数据是否可以被缓存,可以被怎样缓存就必须要从数据的变化特征下手.
数据有哪些变化特征?最简单的就是两种,变和不变.我们都知道,不会变化的数据不需要每次都进行计算.问题是难道所有的数据理论上来讲都会变化,变化是世界永恒的主题.也就是说我们把数据分为变和不变两种是不对的,那么就让我们再加一个条件:时间.那么我们就可以把数据特征总结为一段时间内变或者不变.那么根据这个数据特征,我们就可以在合适的位置和合适的缓存类型中缓存该数据.
3缓存有哪些属性
从面向对象的角度来看,缓存就是一个对象,那么是对象,必然有属性.那么下面我们来探讨一下缓存有哪些属性.以下列举我们常用到的3个属性.
(1) 命中率
命中率是指请求缓存次数和缓存返回正确结果次数的比例.比例越高,就证明缓存的使用率越高.
命中率问题是缓存中的一个非常重要的问题,我们都希望自己缓存的命中率能达到100%,但是往往事与愿违,而且缓存命中率是衡量缓存有效性的重要指标.
(2) 最大元素
缓存中可以存放得最大元素得数量,一旦缓存中元素数量超过这个值,那么将会起用缓存清空策略,根据不同的场景合理的设置最大元素值往往可以一定程度上提高缓存的命中率.从而更有效的时候缓存.
(3) 清空策略
1 FIFO ,first in first out ,最先进入缓存得数据在缓存空间不够情况下(超出最大元素限制时)会被首先清理出去
2 LFU , Less Frequently Used ,一直以来最少被使用的元素会被被清理掉。这就要求缓存的元素有一个hit 属性,在缓存空间不够得情况下,hit 值最小的将会被清出缓存。
2 LRU ,Least Recently Used ,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。
4缓存介质
从硬件介质上来将无非就是两种,内存和硬盘(对应应用层的程序来讲不用考虑寄存器等问题).但是往往我们不会从硬件上来划分,一般的划分方法是从技术上划分,可以分成几种,内存,硬盘文件.数据库.
(1) 内存.将缓存放在内存中是最快的选择,任何程序直接操作内存都比操作硬盘要快的多,但是如果你的数据要考虑到break down的问题,因为放在内存中的数据我们称之为没有持久话的数据,如果硬盘上没有备份,机器down机之后,很难或者无法恢复.
(2) 硬盘.一般来说,很多缓存框架会结合使用内存和硬盘,比如给内存分配的空间有满了之后,会让用户选择把需要退出内存空间的数据持久化到硬盘.当然也选择直接把数据放一份到硬盘(内存中一份,硬盘中一份,down机也不怕).也有其他的缓存是直接把数据放到硬盘上.
(3) 数据库.说到数据库,可能有的人会想,之前不是讲到要减少数据库查询的次数,减少数据库计算的压力吗,现在怎么又用数据库作为缓存的介质了呢.这是因为数据库又很多种类型,比如berkleydb,这种db不支持sql语句,没有sql引擎,只是key和value的存储结构,所以速度非常的快,在当代一般的pc上,每秒中十几w次查询都是没有问题的(当然这个是根据业务特征来决定的,如果您访问的数据在分布上是均匀的,那ahuaxuan可不能保证这个速度了).
除了缓存介质之外,ahuaxuan根据缓存和应用的耦合程度将其划分为local cache和remote cache.
Local cache是指包含在应用之中的缓存组件.而remote cache指和应用解耦在应用之外的缓存组件.典型的local cache有ehcache,oscache,而remote cache有大名鼎鼎的memcached.
Localcache 最大的优点是应用和cache的时候是在同一个进程内部,请求缓存非常快速,完全不需要网络开销等.所以单应用,不需要集群或者集群情况下cache node不需要相互通知的情况下使用local cache比较合适.这也是java中ehcache和oscache这么流行的原因.
但是 Local cache是有一定的缺点的,一般这种缓存框架(比如java中的ehcache或者oscache)都是local cache.也就是跟着应用程序走的,多个应用程序无法直接共享缓存,应用集群的情况下这个问题更加明显,当然也有的缓存组件提供了集群节点相互通知缓存更新的功能,但是由于这个是广播,或者是环路更新,在缓存更新频繁的情况下会导致网络io开销非常大,严重的时候会影响应用的正常运行.而且如果缓存中数据量较大得情况下使用localcache意味着每个应用都有一份这么大得缓存,着绝对是对内存的浪费.
所以这个情况下,往往我们会 选择remote cache,比如memcached.这样集群或者分布式的情况下各个应用都可以共享memcached中的数据,这些应用都通过socket和基于 tcp/ip协议上层的memcached协议直接连接到memcached,有一个app更新了memcached中的值,所有的应用都能拿到最新的值.虽然这个时候多了很多了网络上的开销,但是往往这种方案要比localcache广播或环路更新cache节点要普遍的多,而且性能也比后者高.由于数据只需要保存一份,所以也提高了内存的使用率.
通过以上分析可以看出,不管是local cache,还是remote cache在缓存领域都有自己的一席之地,所以ahuaxuan建议在选择或者使用缓存时一定要根据缓存的特征和我们的业务场景准确判断使用何种缓存.这样才能充分发挥缓存的功能.
Ahuaxuan 认为,缓存的使用是架构师的必备技能,好的架构师能够根据数据的类型,业务的场景来准确的判断出使用何种类型的缓存,并且如何使用这种类型的缓存.在缓存的世界里也没有银弹,目前还没有一种缓存可以解决任何的业务场景或者数据类型,如果这种技术出现了,那架构师就又更不值钱了.呵呵.
OSCache
OSCache是个一个广泛采用的高性能的J2EE缓存框架,OSCache能用于任何Java应用程序的普通的缓存解决方案。
OSCache有以下特点:
缓存任何对象,你可以不受限制的缓存部分jsp页面或HTTP请求,任何java对象都可以缓存。
拥有全面的API--OSCache API给你全面的程序来控制所有的OSCache特性。
永久缓存--缓存能随意的写入硬盘,因此允许昂贵的创建(expensive-to-create)数据来保持缓存,甚至能让应用重启。
支持集群--集群缓存数据能被单个的进行参数配置,不需要修改代码。
缓存记录的过期--你可以有最大限度的控制缓存对象的过期,包括可插入式的刷新策略(如果默认性能不需要时)。
官方网站 http://www.opensymphony.com/oscache/
Java Caching System
JSC(Java Caching System)是一个用分布式的缓存系统,是基于服务器的java应用程序。它是通过提供管理各种动态缓存数据来加速动态web应用。
JCS和其他缓存系统一样,也是一个用于高速读取,低速写入的应用程序。
动态内容和报表系统能够获得更好的性能。
如果一个网站,有重复的网站结构,使用间歇性更新方式的数据库(而不是连续不断的更新数据库),被重复搜索出相同结果的,就能够通过执行缓存方式改进其性能和伸缩性。
官方网站 http://jakarta.apache.org/turbine/jcs/
EHCache
EHCache 是一个纯java的在进程中的缓存,它具有以下特性:快速,简单,为Hibernate2.1充当可插入的缓存,最小的依赖性,全面的文档和测试。
官方网站 http://ehcache.sourceforge.net/
JCache
JCache是个开源程序,正在努力成为JSR-107开源规范,JSR-107规范已经很多年没改变了。这个版本仍然是构建在最初的功能定义上。
官方网站 http://jcache.sourceforge.net/
ShiftOne
ShiftOne Java Object Cache是一个执行一系列严格的对象缓存策略的Java lib,就像一个轻量级的配置缓存工作状态的框架。
官方网站 http://jocache.sourceforge.net/
SwarmCache
SwarmCache是一个简单且有效的分布式缓存,它使用IP multicast与同一个局域网的其他主机进行通讯,是特别为集群和数据驱动web应用程序而设计的。SwarmCache能够让典型的读操作大大超过写操作的这类应用提供更好的性能支持。
SwarmCache使用JavaGroups来管理从属关系和分布式缓存的通讯。
官方网站 http://swarmcache.sourceforge.net
TreeCache / JBossCache
JBossCache是一个复制的事务处理缓存,它允许你缓存企业级应用数据来更好的改善性能。缓存数据被自动复制,让你轻松进行JBoss服务器之间的集群工作。JBossCache能够通过JBoss应用服务或其他J2EE容器来运行一个MBean服务,当然,它也能独立运行。
JBossCache包括两个模块:TreeCache和TreeCacheAOP。
TreeCache --是一个树形结构复制的事务处理缓存。
TreeCacheAOP --是一个“面向对象”缓存,它使用AOP来动态管理POJO(Plain Old Java Objects)
注:AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向方面编程。
官方网站 http://www.jboss.org/products/jbosscache
WhirlyCache
Whirlycache是一个快速的、可配置的、存在于内存中的对象的缓存。它能够通过缓存对象来加快网站或应用程序的速度,否则就必须通过查询数据库或其他代价较高的处理程序来建立。
首先你要理解OOP的思想,是
面向接口编程.
什么叫
面向接口编程呢?
假如你买了一个
多媒体设备,它给了你一个遥控,你想要知道的只是按什么按钮,它会播放什么
而遥控里面是怎样运行,还有屏幕里面怎么工作,你想知道吗?
你完全不会去想了解.
那如果
多媒体设备需要更新,比如优化内部运行效率,
但是优化完了,遥控的按钮不变,设备的所有操作方式都不变,按这个按钮还是显示相同的东西
那内部怎么变化你完全不需要在意.
这就是
面向接口编程.
无论类的内部怎么实现,它对外的接口不变,那它的使用方式就不会变
假设Main类要使用D类的一个draw的方法,
方法名叫 draw():void
不管draw里面是怎样的,Main类里就是这样用,
那么你就从这个接口出发,里面怎么实现是D类的事了,Main类只关心怎么用而已.
其他类要使用它,还是相同
这就大大减少了维护的成本.
因为如果D类出问题,Main类是完全不用改变的.
从上观察,公开的接口越多,维护成本就越大.
维护就越麻烦.所以我们先写接口,定死了公开的接口,
那维护就很方便,出错也只是一个类的事,而不用同时修改多个协同类
http://www.cnblogs.com/doit8791/p/4093808.html
Spring框架里的bean,或者说组件,获取实例的时候都是默认的单例模式,这是在多线程开发的时候要尤其注意的地方。
http://www.cnblogs.com/hoojo/archive/2011/05/05/2038101.html
单例模式的意思就是只有一个实例。单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。
当多用户同时请求一个服务时,容器会给每一个请求分配一个线程,这是多个线程会并发执行该请求多对应的业务逻辑(成员方法),此时就要注意了,如果该处理逻辑中有对该单列状态的修改(体现为该单列的成员属性),则必须考虑线程同步问题
同步机制的比较 ThreadLocal和线程同步机制相比有什么优势呢?ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。
在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的,使用同步机制要求程序慎密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题,程序设计和编写难度相对较大。
而ThreadLocal则从另一个角度来解决多线程的并发访问。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。
由于ThreadLocal中可以持有任何类型的对象,低版本JDK所提供的get()返回的是Object对象,需要强制类型转换。但JDK 5.0通过泛型很好的解决了这个问题,在一定程度地简化ThreadLocal的使用
概括起来说,对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。
Spring使用ThreadLocal解决线程安全问题
我们知道在一般情况下,只有无状态的Bean才可以在多线程环境下共享,在Spring中,绝大部分Bean都可以声明为singleton作用域。就是因为Spring对一些Bean(如RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等)中非线程安全状态采用ThreadLocal进行处理,让它们也成为线程安全的状态,因为有状态的Bean就可以在多线程中共享了。
一般的Web应用划分为展现层、服务层和持久层三个层次,在不同的层中编写对应的逻辑,下层通过接口向上层开放功能调用。在一般情况下,从接收请求到返回响应所经过的所有程序调用都同属于一个线程
ThreadLocal是解决线程安全问题一个很好的思路,它通过为每个线程提供一个独立的变量副本解决了变量并发访问的冲突问题。在很多情况下,ThreadLocal比直接使用synchronized同步机制解决线程安全问题更简单,更方便,且结果程序拥有更高的并发性。
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。 或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。 线程安全问题都是由全局变量及静态变量引起的。
若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则就可能影响线程安全。
1) 常量始终是线程安全的,因为只存在读操作。
2)每次调用方法前都新建一个实例是线程安全的,因为不会访问共享的资源。
3)局部变量是线程安全的。因为每执行一个方法,都会在独立的空间创建局部变量,它不是共享的资源。局部变量包括方法的参数变量和方法内变量。
有状态就是有数据存储功能。有状态对象(Stateful Bean),就是有实例变量的对象 ,可以保存数据,是非线程安全的。在不同方法调用间不保留任何状态。
无状态就是一次操作,不能保存数据。无状态对象(Stateless Bean),就是没有实例变量的对象 .不能保存数据,是不变类,是线程安全的。
有状态对象:
无状态的Bean适合用不变模式,技术就是单例模式,这样可以共享实例,提高性能。有状态的Bean,多线程环境下不安全,那么适合用Prototype原型模式。Prototype: 每次对bean的请求都会创建一个新的bean实例。
Struts2默认的实现是Prototype模式。也就是每个请求都新生成一个Action实例,所以不存在线程安全问题。需要注意的是,如果由Spring管理action的生命周期, scope要配成prototype作用域。
二、线程安全案例:
SimpleDateFormat(下面简称sdf)类内部有一个Calendar对象引用,它用来储存和这个sdf相关的日期信息,例如sdf.parse(dateStr), sdf.format(date) 诸如此类的方法参数传入的日期相关String, Date等等, 都是交友Calendar引用来储存的.这样就会导致一个问题,如果你的sdf是个static的, 那么多个thread 之间就会共享这个sdf, 同时也是共享这个Calendar引用, 并且, 观察 sdf.parse() 方法,你会发现有如下的调用:
Date parse() {
calendar.clear(); // 清理calendar
... // 执行一些操作, 设置 calendar 的日期什么的
calendar.getTime(); // 获取calendar的时间
}
这里会导致的问题就是, 如果 线程A 调用了 sdf.parse(), 并且进行了 calendar.clear()后还未执行calendar.getTime()的时候,线程B又调用了sdf.parse(), 这时候线程B也执行了sdf.clear()方法, 这样就导致线程A的的calendar数据被清空了(实际上A,B的同时被清空了). 又或者当 A 执行了calendar.clear() 后被挂起, 这时候B 开始调用sdf.parse()并顺利i结束, 这样 A 的 calendar内存储的的date 变成了后来B设置的calendar的date
这个问题背后隐藏着一个更为重要的问题--无状态:无状态方法的好处之一,就是它在各种环境下,都可以安全的调用。衡量一个方法是否是有状态的,就看它是否改动了其它的东西,比如全局变量,比如实例的字段。format方法在运行过程中改动了SimpleDateFormat的calendar字段,所以,它是有状态的。
这也同时提醒我们在开发和设计系统的时候注意下一下三点:
1.自己写公用类的时候,要对多线程调用情况下的后果在注释里进行明确说明
2.对线程环境下,对每一个共享的可变变量都要注意其线程安全性
3.我们的类和方法在做设计的时候,要尽量设计成无状态的
三.解决办法
1.需要的时候创建新实例:
说明:在需要用到SimpleDateFormat 的地方新建一个实例,不管什么时候,将有线程安全问题的对象由共享变为局部私有都能避免多线程问题,不过也加重了创建对象的负担。在一般情况下,这样其实对性能影响比不是很明显的。
2.使用同步:同步SimpleDateFormat对象
public class DateSyncUtil {
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static String formatDate(Date date)throws ParseException{
synchronized(sdf){
return sdf.format(date);
}
}
public static Date parse(String strDate) throws ParseException{
synchronized(sdf){
return sdf.parse(strDate);
}
}
}
说明:当线程较多时,当一个线程调用该方法时,其他想要调用此方法的线程就要block,多线程并发量大的时候会对性能有一定的影响。
3.使用ThreadLocal:
public class ConcurrentDateUtil {
private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>() {
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}
};
public static Date parse(String dateStr) throws ParseException {
return threadLocal.get().parse(dateStr);
}
public static String format(Date date) {
return threadLocal.get().format(date);
}
}
或
public class ThreadLocalDateUtil {
private static final String date_format = "yyyy-MM-dd HH:mm:ss";
private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>();
public static DateFormat getDateFormat()
{
DateFormat df = threadLocal.get();
if(df==null){
df = new SimpleDateFormat(date_format);
threadLocal.set(df);
}
return df;
}
public static String formatDate(Date date) throws ParseException {
return getDateFormat().format(date);
}
public static Date parse(String strDate) throws ParseException {
return getDateFormat().parse(strDate);
}
}
说明:使用ThreadLocal, 也是将共享变量变为独享,线程独享肯定能比方法独享在并发环境中能减少不少创建对象的开销。如果对性能要求比较高的情况下,一般推荐使用这种方法。
4.抛弃JDK,使用其他类库中的时间格式化类:
1.使用Apache commons 里的FastDateFormat,宣称是既快又线程安全的SimpleDateFormat, 可惜它只能对日期进行format, 不能对日期串进行解析。
2.使用Joda-Time类库来处理时间相关问题
做一个简单的压力测试,方法一最慢,方法三最快,但是就算是最慢的方法一性能也不差,一般系统方法一和方法二就可以满足,所以说在这个点很难成为你系统的瓶颈所在。从简单的角度来说,建议使用方法一或者方法二,如果在必要的时候,追求那么一点性能提升的话,可以考虑用方法三,用ThreadLocal做缓存。
Joda-Time类库对时间处理方式比较完美,建议使用。
一、filter基于filter接口中的doFilter回调函数,interceptor则基于Java本身的反射机制;
二、filter是依赖于servlet容器的,没有servlet容器就无法回调doFilter方法,而interceptor与servlet无关;
三、filter的过滤范围比interceptor大,filter除了过滤请求外通过通配符可以保护页面、图片、文件等,而interceptor只能过滤请求,只对action起作用,在action之前开始,在action完成后结束(如被拦截,不执行action);
四、filter的过滤一般在加载的时候在init方法声明,而interceptor可以通过在xml声明是guest请求还是user请求来辨别是否过滤;
五、interceptor可以访问action上下文、值栈里的对象,而filter不能;
六、在action的生命周期中,拦截器可以被多次调用,而过滤器只能在容器初始化时被调用一次
loginit
com.cenin.util.servlet.LogInit
log4jConfig
/WEB-INF/classes/log4j.properties
1
mail.mymail.cn
webmaster
password
true
!-- 天气预报的定时器 TianQiUtilTask 继承TimerTask,实现run功能-->
1000
3600
http://www.cnblogs.com/hoojo/archive/2011/05/05/2038101.html
package comz.autoupdatefile;
import java.util.Timer;
import java.util.TimerTask;
public class M {
public static void main(String[] args) {
// TODO todo.generated by zoer
Timer timer = new Timer();
timer.schedule(new MyTask(), 1000, 2000);
}
}
class MyTask extends TimerTask {
@Override
public void run() {
System.out.println("dddd");
}
}
这样,就可以在1秒钟之后开始执行mytask,每两秒钟执行一次。
当然,timer的功能也可以通过自己构造线程,然后在线程中用sleep来模拟停止一段时间,然后再执行某个动作。
其实,看一下timertask的源码就立即可以知道,timertask就是实现了runnable接口的。也就是说,通过timer来间隔一段时间执行一个操作,也是通过一个线程来做到的。
1、EXP:
有三种主要的方式(完全、用户、表)
1、完全:
EXP SYSTEM/MANAGER BUFFER=64000 FILE=C:\FULL.DMP FULL=Y
如果要执行完全导出,必须具有特殊的权限
2、用户模式:
EXP SONIC/SONIC BUFFER=64000 FILE=C:\SONIC.DMP OWNER=SONIC
这样用户SONIC的所有对象被输出到文件中。
3、表模式:
EXP SONIC/SONIC BUFFER=64000 FILE=C:\SONIC.DMP OWNER=SONIC TABLES=(SONIC)
这样用户SONIC的表SONIC就被导出
用定时器 + bat脚本做oracle的备份,已经备份了几个月了。这几天突然发现备份出来的dmp数据完全没法重新导入到新的数据库中。
起初以为是版本问题,或者导出参数的问题,于是在网上不停的搜索、尝试,最后还是没发现问题原因。
算了还是研究一下导入日志中的错误,于是将日志中出错误的表尝试单独导出,居然出现EXP-00011::表不存在 错误,可是数据库中明明有这个表呀。根据这个方向再上网一查,终于找到原因了,原来在11g中空表是默认是不占Segment的,导致备份导出的时候压根就没导出那些空表,这样才出现备份的dmp没法导入的问题,敢情我几个月的备份工作都白做了。
可ORACLE 你妈X的,备份导出时没导出空表这么大的事情你居然没有任何提示,你他*妈的是为了创造客服赚钱的机会么?
哎,处理过程如下:
1.用system帐号进入:
1.1 查看是否为true
show parameter deferred_segment_creation;
1.2 修改为false
alter system set deferred_segment_creation=false;
2.用数据库帐号登录:
2.1 查找所有数据表为空的表
select table_name from user_tables where NUM_ROWS=0;
2.2 把这些表组成修改Segment的脚本:
select 'alter table '||table_name||' allocate extent;' from user_tables where num_rows=0;
2.3 将2.2中查询的结果导出来,或者复制出来,并执行修改所有空表。
这个时候就能把所有空表导出来了。
感谢以下两位的帖子,给了我很大帮助
http://arthas-fang.iteye.com/blog/875258
http://wanwentao.blog.51cto.com/2406488/545154
regex为\\\\,因为在java中\\表示一个\,而regex中\\也表示\,所以当\\\\解析成regex的时候为\\。
由于unix中file.separator为斜杠"/",下面这段代码可以处理windows和unix下的所有情况:
String temp[] = name.replaceAll("\\\\","/").split("/");
if (temp.length > 1) {
name = temp[temp.length - 1];
}
版本验证:
java -version
2
环境变量安装
JAVA_HOME D:\javaIDE\sunjdks\jdk1.5.0_04
Path %JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;
classpath .;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar
java项目运行:cd到所在目录下
java -jar testedi.jar
摘要: Java Project 打包以及安装包制作
Java的桌面程序写好以后只能在eclipse下运行是不可以的,还需要将程序拷贝到其他电脑上运行才可以,所以需要制作成其他电脑可以运行的文件,当然在安装有jdk的电脑上只需要将程序导出为jar文件就可以运行了,但是除了开发java程序人员的电脑上会安装jdk,其他人的电脑上不会有这个环境,所以还需要将java可运行的环境一同打包到程序中去,这样,在用...
阅读全文
public static Map ConvertObjToMap(Object obj){
Map<String,Object> reMap = new HashMap<String,Object>();
if (obj == null)
return null;
Field[] fields = obj.getClass().getDeclaredFields();
try {
for(int i=0;i<fields.length;i++){
try {
Field f = obj.getClass().getDeclaredField(fields[i].getName());
f.setAccessible(true);
Object o = f.get(obj);
reMap.put(fields[i].getName(), o);
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return reMap;
}
Paynet paynet ;
Map map;
for(int i = 0 ; i < rs.size();i++)
{
map= ConvertObjToMap((Paynet)(rs.get(i)));
for(int j=0; j<fieldnames.length; j++)
{
//(String)map.get("p_id")!=null
if((String)map.get(fieldnames[j])!=null)
{
//String temp1 = rs.getString(fieldnames[j]);
String temp = new String(((String)map.get(fieldnames[j])).getBytes("ISO-8859-1"), "GBK");
sheet.addCell(new Label(j, i+1, temp));
}
else
sheet.addCell(new Label(j, i+1, ""));
}
}
String[] fieldNames = {"szVessel", "szVoyage", "szBlNo", "szCtnNo", "szSealNo", "szCtnType", "szCargoName", "fWeight", "fVolume", "szReceiver", "szSender", "szLoadPortCode", "szDischargePortCode"};
a. web.xml
add following code to web.xml
<servlet>
<servlet-name>log4j-init</servlet-name>
<servlet-class>com.legendinfo.log.Log4jInit</servlet-class>
<init-param>
<param-name>log4j-init-file</param-name>
<param-value>WEB-INF/classes/log4j.property</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
b.create a special servlet for log4j initialazation
save the file in the web-info/classes folder
package com.legendinfo.log;
import org.apache.log4j.PropertyConfigurator;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.io.IOException;
public class Log4jInit extends HttpServlet {
public void init() {
String prefix = getServletContext().getRealPath("/");
String file = getInitParameter("log4j-init-file");
// if the log4j-init-file is not set, then no point in trying
if(file != null) {
PropertyConfigurator.configure(prefix+file);
System.out.println("Init Log4j success!");
}
}
public void doGet(HttpServletRequest req, HttpServletResponse res) {
}
}
c.create a log4j.property file that define the log4j properties
the property file is setting in web.xml
a sample property file as following
log4j.rootLogger=INFO, A1 ,R
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] %m%n
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=../logs/log4j.log
log4j.appender.R.MaxFileSize=100KB
log4j.appender.R.MaxBackupIndex=1
log4j.appender.R.layout=org.apache.log4j.TTCCLayout
d.a test Jsp page
testLog.jsp:
<%@ page import="org.apache.log4j.*"%>
<html>
<body>
<%
//log4j.appender.appenderName = WEB-INF/classes/log4j.log
Logger logger = Logger.getLogger("com.legendinfo");
logger.setLevel(Level.INFO);
Logger barlogger = Logger.getLogger("com.legendinfo.log");
logger.warn("Low fuel level.");
logger.debug("Starting search for nearest gas station.");
barlogger.info("Located nearest gas station.");
barlogger.debug("Exiting gas station search");
%>
</body>
</html>
结合AbcBankB2B项目具体
log4j.rootLogger=info, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern= %d{yyyy-MM-dd HH:mm:ss,SSS} [%c] [%p] - %m%n
log4j.logger.freemarker = error
log4j.logger.com.opensymphony = error
log4j.logger.org.springframework = error
log4j.logger.org.hibernate = error
#配置数据库插入信息 start
log4j.logger.org.directwebremoting=info
#log4j.logger.com.cenin.web.ajax.OnlinehallAjax属于org.directwebremoting类下新建,应用MDC取值
log4j.logger.com.cenin.web.ajax.OnlinehallAjax=info,db
log4j.appender.db.Threshold=info
log4j.appender.db = org.apache.log4j.jdbc.JDBCAppender
log4j.appender.db.BufferSize=1
log4j.appender.db.driver=oracle.jdbc.driver.OracleDriver
log4j.appender.db.URL=jdbc:oracle:thin:@localhost:1521:TJGWL
log4j.appender.db.user=cy
log4j.appender.db.password=cy
log4j.appender.db.sql=insert into RESLOG(LogId,username,bankType,money,resultinfo,merchantno,Class,Method,createTime,LogLevel,MSG)values(S_RESLOG.Nextval,'%X{username}','%X{bankType}','%X{money}','%X{resultInfo}','%X{merchantNo}','%C','%M', to_date('%d{yyyy-MM-dd HH:mm:ss}','yyyy-MM-dd HH24:mi:ss'),'%p','%m')
log4j.appender.db.layout=org.apache.log4j.PatternLayout
# 这个配置是告诉当LOG4J吧日志存储数据库时用的SQL语句。SQ_RESLOG_LOGID.Nextval是我建的一个SEQUENCE;
# ‘%C’是日志中的CLASS;‘%M’是打印日志是执行到类里的方法;‘%d’是打印的时间,它支持格式化;
#‘%P’是日志级别,包括INFO、DEBUG、ERROR等;‘%m’是MSG,日志内容。注意这里的参数区分大小写。
#配置数据库插入信息 end
MDC取值:
MDC.put("username",username);
servelet引入:
<servlet>
<servlet-name>dwr-invoker</servlet-name>
<display-name>DWR Servlet</display-name>
<description>Direct Web Remoter Servlet</description>
<servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>activeReverseAjaxEnabled</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>initApplicationScopeCreatorsAtStartup</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>maxWaitAfterWrite</param-name>
<param-value>500</param-value>
</init-param>
<init-param>
<param-name>crossDomainSessionSecurity</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<record table="CkypHead" totalFields="21" tableType="vessel">
<primaryKey field="lID" />
<!--关别代码-->
<property maxLength="6" sequence="1" field="CUSTOMS_ID" fileInfo="receiverCode"/>
<!--舱单进/出口标志-->
<property maxLength="1" sequence="2" field="I_E_FLAG" />
<record table="CkypContainer" totalFields="7" tableType="ctn">
<primaryKey field="lID" />--表主键ID
<foreignKey refTable="CkypHead" refField="lID" field="lHeadID" />外键链接外键名lHeadID,链接的外键表CkypHead lID
<!-- 序号 -->
<property maxLength="5" sequence="1" field="CONTA_SEQ_NO"/>
<!-- 提运单号 -->
<property maxLength="20" sequence="2" field="BILL_NO" fieldType="bill"/>
<!-- 集装箱号 -->
<property maxLength="11" sequence="3" field="CONTA_NO" fieldType="ctnno"/>
<!-- 标准箱标志 -->
<property maxLength="1" sequence="4" field="CONTA_SIZE" />
<!-- 铅封号 -->
<property maxLength="10" sequence="5" field="SEAL_NO" />
<!-- 规格类型 -->
<property maxLength="4" sequence="6" field="CONTA_TYPE" />
<!-- 集装箱重量(总重) -->
<property maxLength="11" sequence="7" field="CONTA_WT" type="float" precision="2" />
</record>
document.getElementById("div01").style.height;
document.getElementById("div01").style.lineHeight;
document.getElementById("div01").style.backgroundColor;
CSS语法(不区分大小写) JavaScript语法(区分大小写)
border border
border-bottom borderBottom
border-bottom-color borderBottomColor
border-bottom-style borderBottomStyle
border-bottom-width borderBottomWidth
border-color borderColor
border-left borderLeft
border-left-color borderLeftColor
border-left-style borderLeftStyle
border-left-width borderLeftWidth
border-right borderRight
border-right-color borderRightColo
rborder-right-style borderRightStyle
border-right-width borderRightWidth
border-style borderStyle
border-top borderTop
border-top-color borderTopColor
border-top-style borderTopStyle
border-top-width borderTopWidth
border-width borderWidth
clear clear
float floatStyle
margin margin
margin-bottom marginBottom
margin-left marginLeft
margin-right marginRight
margin-top marginTop
padding padding
padding-bottom paddingBottom
padding-left paddingLeft
padding-right paddingRight
padding-top paddingTop
CSS 语法(不区分大小写) JavaScript 语法(区分大小写)
background background
background-attachment backgroundAttachment
background-color backgroundColor
background-image backgroundImage
background-position backgroundPosition
background-repeat backgroundRepeat
color color
CSS语法(不区分大小写) JavaScript 语法(区分大小写)
display display
list-style-type listStyleType
list-style-image listStyleImage
list-style-position listStylePosition
list-style listStyle
white-space whiteSpace
CSS 语法(不区分大小写) JavaScript 语法(区分大小写)
font font
font-family fontFamily
font-size fontSize
font-style fontStyle
font-variant fontVariant
font-weight fontWeight
CSS 语法(不区分大小写 ) JavaScript 语法(区分大小写)
letter-spacing letterSpacing
line-break lineBreak
line-height lineHeight
text-align textAlign
text-decoration textDecoration
text-indent textIndent
text-justify textJustify
text-transform textTransform
vertical-align verticalAlign
1.在本机oracle系统配串
HYORCLNEW =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 10.128.4.35)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = 10.128.4.36)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = hyorcl)
(FAILOVER_MODE =
(TYPE = select)
(METHOD = basic)
(RETRIES = 20)
(DELAY = 1)
)
)
)
2.
一 、创建dblink
Sql代码
create database link <DBLink名称> connect to <被连接库的用户名> identified by <被连接库的密码> using '<Oracle客户端工具建立的指向被连接库服务名>';
例如:
Sql代码
1.create database link XMDS_KF connect to XMDS identified by XMDS using 'HYORCLNEW ;
但这种方式有个缺点就是必须要在服务器建立一个被连接库的服务名,如果不建则会报错:
ORA-12154: TNS: 无法处理服务名
,但如果直接使用地址来建DBLink,就可以省去配置服务名的麻烦了:
Sql代码
1.create public database link XMDS_KF connect to XMDS identified by XNDS using '(DESCRIPTION =
2. (ADDRESS_LIST =
3. (ADDRESS = (PROTOCOL = TCP)(HOST = 145.24.16.182)(PORT = 1521))
4. )
5. (CONNECT_DATA =
6. (SERVICE_NAME = XMDS)
7. )
8. )';
网上营业厅系统操作说明
1.登录系统
2.输入计划类型、提箱单位、提箱日期、提箱时间段、费用截止日期、联系人电话
3.选箱:输入船名、航次、提单号,点击检索
4.海关放行:点击校核
5.保存计划
6.计费:点击确认支付,跳转至支付页面
|
B2B支付
1.登陆中国银行企业网银系统
2.进入支付页面,确认支付金额,提交订单
3.企业财务人员进入支付审核系统
4. 企业财务人员复合相应订单
5. 企业财务人员授权相应订单
6.完成订单授权,查询订单
7.完成B2B支付,生成订单号,公司收到推送通知,生成提箱计划 |
B2C支付
1.登陆中国银行个人网银系统
2.选择付款账户,提交订单
3.完成B2C支付,生成订单号,公司收到推送通知,生成提箱计划 |
附:详细操作步骤
第一部分 用户注册
第二部分 提重办理
2.1 登陆系统,进入“重箱出场计划”页面。点击页面左侧“提重办理” ,页面右侧出现“重箱出场计划”。
2.2 选择“计划类型”,输入“提箱单位”,选择“提箱日期”,选择“提箱时间段”,选择“费用截止日期”,输入“联系人电话”。
2.3 点击“选箱” ,进入选箱页面。输入“船名”,“航次”,“提单号” ,点击“检索” ,出现箱号列表,选择相应集装箱。
,点击“确认” ,返回“重箱出场计划”页面。
2.4 点击“海关放行” ,进入“报关单信息”页面。(注:进行“增、删、改“操作后,点击”保存,报关单详细中可添加修改箱号),点击“校核” ,核对海关放行信息,返回“重箱出场计划”页面。
2.5 点击“保存计划” ,出现保存成功提示 。
2.6 点击“计费” ,进入“费用统计”页面。确认统计箱号和费用总计无误后,点击“确认支付” ,进入中国银行网上支付页面。
第三部分 中国银行网上支付(B2B或B2C)
3.1B2B 企业支付(注:由于银行网上支付操作规定,请于在3个小时内完成订单授权,否则需要重新提交订单)
3.1.1 进入中国银行企业网上支付页面,输入“用户名”,“密码”,“验证码” ,点击“确认”,进入支付页面。
3.1.2 在支付页面确认支付金额,输入动态口令
,点击“确定”,完成订单提交。
3.1.3 企业财务审核人员进入“支付审核”页面,输入“用户名”,“密码”,“动态口令”,点击“登录”进入网上银行系统 。
3.1.4 点击“电子商务”,“B2B支付服务”,“订单复核”进行订单复合。 。点击相应订单号进入复合页面 ,在“复核意见”选项中选择“复合通过”,点击“确定”。
3.1.5 点击“订单授权”页面,选择相应订单号进行授权操作页面 ,在“授权意见”选项中选择“授权通过”,点击“确定”进入授权页面。
3.1.6 输入“动态口令” ,点击“确定”,完成授权。订单内容可在“订单查询”选项中查询。
3.1.7 企业完成B2B网上支付,生成订单号,公司收到推送通知,生成提箱计划。
3.2个人支付B2C(推荐使用)
3.2.1 进入中国银行个人网上支付页面,输入“用户名”,“密码”,“验证码” ,点击“确认”,进入支付页面。
3.2.2 进入支付页面,选择“付款账户” ,点击“确定”,输入“手机交易码”和“动态口令” ,点击“确定”。
3.2.3 个人完成B2C网上支付,生成订单号,公司收到推送通知,生成提箱计划。
function postToNethall(PARAMS) {
var pay_no;
var money;
var checkcode;
var feeetype;
var old_pay_no;
var old_money;
var splitAll = new Array();
//测试 PARAMS = "pay_no=jmW9n%2fJCCDo%3d&money=wB1k5PqI0oU%3d&checkcode=nhIAV2UrfsUreUdGf0wS3kcPYe5P6iTZ%2boRAgdGvPLN33eTEKYp75j%2f%2bhT7xSYg%2be%2bHGf2MZyyAcYpRMl6ng3ireWvV%2bj5kRZkldFCGF8nhE1ANvxGBMBQ%3d%3d&feeetype=Q1dQXRPDVOc%3d&old_pay_no=0GUN11ebpe4%3d&old_money=0GUN11ebpe4%3d";
splitAll = PARAMS.split("&");
var arrayvar;
for( var isplit = 0 ; isplit < splitAll.length ; isplit++){
arrayvar = new Array();
arrayvar = splitAll[isplit].split("=");
for(var i = 0; i < arrayvar.length;i++){
if(arrayvar[i] = "pay_no"){
pay_no = arrayvar[i+1];
//alert(pay_no);
break;
}
if(arrayvar[i] = "money"){
money = arrayvar[i+1];
// alert(money);
break;
}
if(arrayvar[i] = "checkcode"){
checkcode = arrayvar[i+1];
// alert(checkcode);
break;
}
if(arrayvar[i] = "feeetype"){
feeetype = arrayvar[i+1];
// alert(feeetype);
break;
}
if(arrayvar[i] = "old_pay_no"){
old_pay_no = arrayvar[i+1];
// alert(old_pay_no);
break;
}
if(arrayvar[i] = "old_money"){
old_money = arrayvar[i+1];
// alert(old_money);
break;
}
}
}
var name = "test"
var tempForm = document.createElement("form");
tempForm.id="tempForm1";
tempForm.method="post";
//tempForm.action="https://60.30.27.15/PayMent/login.aspx";
tempForm.action="https://10.128.141.53/PayMent/login.aspx";
tempForm.target=name;
var hideInput1 = document.createElement("input");
hideInput1.type="hidden";
hideInput1.name= "pay_no"
hideInput1.value= "EeM1whUd4q4%3d";
tempForm.appendChild(hideInput1);
var hideInput2 = document.createElement("input");
hideInput2.type="hidden";
hideInput2.name= "money"
hideInput2.value= "i6hN5C6DIN4%3d";
tempForm.appendChild(hideInput2);
var hideInput3 = document.createElement("input");
hideInput3.type="hidden";
hideInput3.name= "checkcode"
hideInput3.value= "nhIAV2UrfsWnq1I38RKp5%2b46w4bxah62p6tSN%2fESqefuOsOG8WoetiUOtz2bp40id93kxCmKe%2bY%2f%2foU%2b8UmIPnvhxn9jGcsgHGKUTJep4N4q3lr1fo%2bZEWZJXRQhhfJ4RNQDb8RgTAU%3d";
tempForm.appendChild(hideInput3);
var hideInput4 = document.createElement("input");
hideInput4.type="hidden";
hideInput4.name= "feeetype"
hideInput4.value= "Q1dQXRPDVOc%3d";
tempForm.appendChild(hideInput4);
var hideInput5 = document.createElement("input");
hideInput5.type="hidden";
hideInput5.name= "old_pay_no"
hideInput5.value= "0GUN11ebpe4%3d";
tempForm.appendChild(hideInput5);
var hideInput6 = document.createElement("input");
hideInput6.type="hidden";
hideInput6.name= "old_money"
hideInput6.value= "0GUN11ebpe4%3d";
tempForm.appendChild(hideInput6);
tempForm.attachEvent("onsubmit",function(){ openWindow(name); });
document.body.appendChild(tempForm);
tempForm.fireEvent("onsubmit");
alert("tempForm");
tempForm.submit();
document.body.removeChild(tempForm);
}
web.xml
<filter>
<filter-name>AuthorizationFilter</filter-name>
<filter-class>com.cenin.util.filter.AuthorizationFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AuthorizationFilter</filter-name>
<url-pattern>/**//*</url-pattern>
</filter-mapping>
AuthorizationFilter.java
public class AuthorizationFilter implements Filter
{
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException
{
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
HttpSession session = request.getSession();
String servletPath = request.getServletPath();//获得如: /baseinfo/codeBillTypeList.action
Object user = session.getAttribute(Config.getConfig().getSessionUser());
//判断权限
boolean passed = true;
/*if(user == null && (servletPath.indexOf("action")>=0 )){
passed = false;
String[] noLimit = Config.getConfig().getNoFilter().split(";");
for(int i=0;i<noLimit.length;i++){
if(servletPath.matches(noLimit[i])){
System.out.println(servletPath + " " + noLimit[i]);
passed = true;
break;
}
}
}*/
request.getRequestDispatcher(servletPath).forward(request, response);//控制struts or xwork跳转
// if(passed)
// chain.doFilter(request, response);
// else
// {
// String modelType = request.getParameter("model.bmoduleType");
// String particalUrl = request.getParameter("particalUrl");
// session.setAttribute("model.bmoduleType", modelType);
// session.setAttribute("particalUrl", particalUrl);
// String url = Config.getConfig().getPageLogin();
// RequestDispatcher dispatcher = request.getRequestDispatcher(url);
// dispatcher.forward(request, response);
// }
}
public void init(FilterConfig filterConfig) throws ServletException
{
}
public void destroy()
{
}
}
xwork.xml添加
<include file="xwork-onlinehall.xml"/>
xwork-onlinehall.xml文件内容:
<package name="onlinehall" extends="cenin" namespace="/onlinehall" externalReferenceResolver="com.atlassian.xwork.ext.SpringServletContextReferenceResolver">
<action name="myOrderLoadList" class="com.cenin.web.action.onlinehall.MyOrderAction" method="myOrderLoadList">
<result name="success" type="freemarker">/onlinehall/myOrder.ftl</result>
</action>
</package>
MyOrder.java内容
public class MyOrderAction extends BaseActionSupport {
public String myOrderLoadList() throws Exception {}
}
public List xmlElements(String xmlDoc) {
//创建一个新的字符串
StringReader read = new StringReader(xmlDoc);
//创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入
InputSource source = new InputSource(read);
//创建一个新的SAXBuilder
SAXBuilder sb = new SAXBuilder();
List list = new ArrayList();
try {
//通过输入源构造一个Document
Document doc = sb.build(source);
//取的根元素
Element root = doc.getRootElement();
System.out.println(root.getName());//输出根元素的名称(测试)
//得到根元素所有子元素的集合
List jiedian = root.getChildren();
//获得XML中的命名空间(XML中未定义可不写)
Namespace ns = root.getNamespace();
Element et = null;
DataModel dataModel = new DataModel();
Collections c ;
Ctnfee ctnfee = null;
for(int i=0;i<jiedian.size();i++){
et = (Element) jiedian.get(i);//循环依次得到子元素
ctnfee = new Ctnfee();
/** *//**//*
* 无命名空间定义时
* et.getChild("users_id").getText();
* et.getChild("users_address",ns).getText()
*/
/**//*System.out.println(et.getChild("users_id",ns).getText());
System.out.println(et.getChild("users_address",ns).getText());*/
System.out.println(et.getChild("p_id",ns).getText());
System.out.println(et.getChild("ctnno",ns).getText());
ctnfee.setP_id(et.getChild("p_id",ns).getText());
ctnfee.setCtnno(et.getChild("ctnno",ns).getText());
ctnfee.setFee_type(et.getChild("fee_type",ns).getText());
ctnfee.setStart_time(et.getChild("start_time",ns).getText());
ctnfee.setEnd_time(et.getChild("end_time",ns).getText());
ctnfee.setFee(Double.parseDouble(et.getChild("fee",ns).getText()));
ctnfee.setFee_count(Double.parseDouble(et.getChild("fee_count",ns).getText()));
ctnfee.setCpid(et.getChild("cpid",ns).getText());
ctnfee.setFee_name(et.getChild("fee_name",ns).getText());
ctnfee.setFee_rate_id(Double.parseDouble(et.getChild("fee_rate_id",ns).getText()));
ctnfee.setJffs(et.getChild("jffs",ns).getText());
ctnfee.setIf_hand(et.getChild("if_hand",ns).getText());
ctnfee.setSfid(et.getChild("sfid",ns).getText());
ctnfee.setWt_company(et.getChild("wt_company",ns).getText());
ctnfee.setOpid(et.getChild("opid",ns).getText());
ctnfee.setCy(et.getChild("cy",ns).getText());
ctnfee.setIf_bf(et.getChild("if_bf",ns).getText());
ctnfee.setDays_count(et.getChild("days_count",ns).getText());
ctnfee.setIf_collect(Double.parseDouble(et.getChild("if_collect",ns).getText()));
ctnfee.setIf_dd(et.getChild("if_dd",ns).getText());
ctnfee.setDd_fee_name(et.getChild("dd_fee_name",ns).getText());
ctnfee.setSpec_sign(et.getChild("spec_sign",ns).getText());
list.add(ctnfee);
counttotal = counttotal +Double.parseDouble(et.getChild("fee_count",ns).getText());
}
/** *//**//*
* 如要取<row>下的子元素的名称
*/
et = (Element) jiedian.get(0);
List zjiedian = et.getChildren();
for(int j=0;j<zjiedian.size();j++){
Element xet = (Element) zjiedian.get(j);
System.out.println(xet.getName());
}
} catch (JDOMException e) {
// TODO 自动生成 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成 catch 块
e.printStackTrace();
}
return list;
}
public static void main(String[] args) throws IOException {
String bocNo1="6124";
String orderNos1="104110059475569";
String signData1="eeb5705cffb3820d8cf8b6cae5774730_21ec2425-883b-4974-a036-360ddec9fb9a"+
"MIIDuAYJKoZIhvcNAQcCoIIDqTCCA6UCAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHAaCCAmww"+
"ggJoMIIB0aADAgECAhB9RyYZTkOnSvrpIjNNqTqUMA0GCSqGSIb3DQEBBQUAMFoxCzAJBgNVBAYT"+
"AkNOMRYwFAYDVQQKEw1CQU5LIE9GIENISU5BMRAwDgYDVQQIEwdCRUlKSU5HMRAwDgYDVQQHEwdC"+
"RUlKSU5HMQ8wDQYDVQQDEwZCT0MgQ0EwHhcNMTEwNjE4MTAyNjI0WhcNMjEwNDI2MTAyNjI0WjBH"+
"MQswCQYDVQQGEwJDTjEWMBQGA1UEChMNQkFOSyBPRiBDSElOQTENMAsGA1UECxMEVEVTVDERMA8G"+
"A1UEAx4IbUuL1VVGYjcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMNF+o1mNobAG60gm9cG"+
"DbOuq5KLKsRF/jjstfjzorz1qQdiY5ibCu3ngk2VHxAf3JV7beDw7OuWjxIaxntsWiOaFhujSlxS"+
"7dyefk4uOwHWuFOoZGIG/scXcjU74NLdSM0ptj42SfdMsbqzcQ8kqvV7MbPqJW8ztlefmafdYpJh"+
"AgMBAAGjQjBAMB8GA1UdIwQYMBaAFHjxtvO9ykQNfC/o0jbI/gawwPmfMB0GA1UdDgQWBBS6HTP9"+
"uBZMvHzqidY/hp7m9hx0zTANBgkqhkiG9w0BAQUFAAOBgQAyLyYGKopiY0fSaTM/fElg/3JRrOcv"+
"8xrNNr5tdym61W44d3Uh53zD+5cOhQnQfYEE6d6QeiRicNi3kwh3mr9BX0+H7uBq4SQ9Gq99gk3E"+
"tdLe4EMIZbE01SPzKViUE2A+7ewffHgFy5i4VweoB9MmppaF1RPj0pGftFp6d0+dWDGCARQwggEQ"+
"AgEBMG4wWjELMAkGA1UEBhMCQ04xFjAUBgNVBAoTDUJBTksgT0YgQ0hJTkExEDAOBgNVBAgTB0JF"+
"SUpJTkcxEDAOBgNVBAcTB0JFSUpJTkcxDzANBgNVBAMTBkJPQyBDQQIQfUcmGU5Dp0r66SIzTak6"+
"lDAJBgUrDgMCGgUAMA0GCSqGSIb3DQEBAQUABIGAa6dnWBArRLTMDYcWeYYLBFRVIeYX0WkQHniU"+
"AN4umk64gC/4r96v5BVm7tuetH2QtqVJIelvHZZKnvQsqAG108TkPR9+12JbxApu/eE5DTXmXqdj"+
"zfrQE7sk7rCBdqbFjqkETzU7oAwfqCuZGa6q+4TDWvdmYkM33ZdmtFJ53a0=";
/** *//**
java中两种发起POST请求,并接收返回的响应内容的方式 2011-07-22 09:43:29| 分类: 默认分类 | 标签: |字号大
中
小 订阅
1、利用apache提供的commons-httpclient-3.0.jar包
代码如下:
* 利用HttpClient发起POST请求,并接收返回的响应内容
*
* @param url 请求链接
* @param type 交易或响应编号
* @param message 请求内容
* @return 响应内容
*/
// public String transRequest(String url, String type, String message) {
// 响应内容
String result = "";
// 定义http客户端对象--httpClient
HttpClient httpClient = new HttpClient();
// 定义并实例化客户端链接对象-postMethod
PostMethod postMethod = new PostMethod("http://180.168.146.75:81/PGWPortal/CommonB2BQueryOrder.do");
try{
// 设置http的头
// postMethod.setRequestHeader("ContentType",
// "application/x-www-form-urlencoded;charset=UTF-8");
// 填入各个表单域的值
NameValuePair bocNo = new NameValuePair("bocNo", bocNo1);
NameValuePair orderNos = new NameValuePair("orderNos", orderNos1);
NameValuePair signData = new NameValuePair("signData", signData1);
// postMethod.setRequestBody( new NameValuePair[] {bocNo, orderNos,signData});
NameValuePair[] data = { bocNo,
orderNos,signData };
// NameValuePair[] data = { bocNo, orderNos,signData);
// 将表单的值放入postMethod中
postMethod.setRequestBody(data);
// 定义访问地址的链接状态
int statusCode = 0;
try {
// 客户端请求url数据
statusCode = httpClient.executeMethod(postMethod);
} catch (Exception e) {
e.printStackTrace();
}
// 请求成功状态-200
if (statusCode == HttpStatus.SC_OK) {
try {
result = postMethod.getResponseBodyAsString();
System.out.println(result);
} catch (IOException e) {
e.printStackTrace();
}
} else {
System.out.println("请求返回状态:" + statusCode);
}
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
// 释放链接
postMethod.releaseConnection();
httpClient.getHttpConnectionManager().closeIdleConnections(0);
}
/**//* GetMethod authpost1 = new GetMethod("http://180.168.146.75:81/PGWPortal/CommonB2BQueryOrder.do" );
httpClient.executeMethod(authpost1);
result = authpost1.getResponseBodyAsString();
System.out.println(result);*/
//查看cookie信息
/**//*Cookie[] cookies = httpClient.getState().getCookies();
httpClient.getState().addCookies(cookies);
if (cookies.length == 0) {
System.out.println("None");
} else {
for (int i = 0; i < cookies.length; i++) {
System.out.println(cookies[i].toString());
}
}*/
}
Tomcat部署Web应用方法总结
在Tomcat中部署Java Web应用程序有两种方式:静态部署和动态部署。
在下文中$CATALINA_HOME指的是Tomcat根目录。
一、静态部署
静态部署指的是我们在服务器启动之前部署我们的程序,只有当服务器启动之后,我们的Web应用程序才能访问。
以下3种方式都可以部署:(以PetWeb项目为例说明,PetWeb目录假设是F:/PetWeb)
1.利用Tomcat自动部署
将PetWeb目录拷贝到$CATALINA_HOME/webapps下,然后启动服务器就可以了,Tomcat启动时将自动加载应用。
访问地址如下:http://localhost:8080/PetWeb/
这种方式比较简单,但是web应用程序必须在webapps目录下。Tomcat的Webapps目录是Tomcat默认的应用目录,当服务器启动时,会加载所有这个目录下的应用。
2.修改Server.xml文件部署
这种方式可以不必将PetWeb目录拷贝到webapps下,直接在F:/部署。方法如下,更改$CATALINA_HOME/conf/server.xml文件,
找到以下内容:
Xml代码:
1.<Context path ="/Pet" reloadable ="false" docBase ="F:/PetWeb" workDir ="d:/Mywebapps/emp" />
path:是访问时的根地址,表示访问的路径;如上述例子中,访问该应用程序地址如下:http://localhost:8080/Pet/
reloadable:表示可以在运行时在classes与lib文件夹下自动加载类包。其中reloadable="false"表示当应用程序中的内容发生更改之后服务器不会自动加载,这个属性在开发阶段通常都设为true,方便开发,在发布阶段应该设置为false,提高应用程序的访问速度。
docbase:表示应用程序的路径,注意斜杠的方向“/”。 docBase可以使用绝对路径,也可以使用相对路径,相对路径相对于webapps。
workdir:表示缓存文件的放置地址
3.增加自定义web部署文件(推荐使用,不需要重启Tomcat )
这种方式和方法2差不多,但不是在Server.xml文件中添加Context标签,而是在$CATALINA_HOME/conf /Catalina/localhost中添加一个xml文件,如Pet.xml.在Tomcat安装目录conf/Catalina /localhost下,里面有Tomcat自带的三个应用,随意复制其中的一个XML文件,然后修改docbase指向你自己的应用程序,并把文件名改名,各参数参见方法2中的<Context>标签的参数,或者你也可以自己新建一个XML文件。(注意此文件名将作为Context中的path属性值,不管文件里的path属性值如何设置也是无效的 ),将以下内容复制过去,修改相应路径即可。
Xml代码:
1.<Context path ="/Pet" docBase ="F:/PetWeb"
2. debug ="0" privileged ="true" reloadable ="false" >
3.</Context>
访问地址如下:http://localhost:8080/Pet/
注: Web应用以.war文件的形式部署
可以将JSP程序打包成一个war包放在目录下,服务器会自动解开这个war包,并在这个目录下生成一个同名的文件夹。一个war包就是有特性格式的jar包,它是将一个Web程序的所有内容进行压缩得到。
我们刚才是将PetWeb文件夹部署在了服务器中,我们知道可以将Web应用程序的内容打成.war 包,然后在部署在服务器上。打包请参考如下步骤:
1、打开命令提示符(cmd)
2、设置jdk环境变量
3、在命令提示符中进入项目文件夹F:/PetWeb后,键入如下命令:jar cvf Pet.war */ . (注意最后有个“. ”)。这样在F:/PetWeb下应该有Pet.war文件。 (也可以打包到指定的地方,命令如下:jar cvf d:/Pet.war */ . )
部署Pet.war文件非常简单,将刚才xml文件中的docBase ="F:/PetWeb" 更改为docBase ="F:/Pet.war" 或者直接将其拷贝到webapps目录下就可以。然后重新启动服务器就可以将Pet.war部署为一个Web应用程序了。
如果你够细心的话你会发现,服务器将Pet.war文件解开,并且在webapps下面又生成了一个Pet文件夹,然后把Pet.war的内容拷贝到里面去了。我们可以通过以下方式取消自动解压缩,将xml配置文件中的unpackWAR 属性设置为"false" 即可。
二、动态部署
动态部署是指可以在服务器启动之后部署web应用程序,而不用重新启动服务器。动态部署要用到服务器提供的manager.war文件,如果在$CATALINA_HOME/webapps/下没有该文件,你必须去重新下载tomcat,否则不能完成以下的功能。要想使用该管理程序必须首先编辑$CATALINA_HOME/conf/tomcat-users.xml文件,内容如下:(关于这个文件的更多内容,请参考 Java Web应用程序的安全模型二 )
<tomcat-users>
<role rolename="tomcat"/>
<role rolename="role1"/>
<role rolename="manager"/>
<user username="coresun" password="coresun" roles="manager"/>
<user username="tomcat" password="tomcat" roles="tomcat"/>
<user username="both" password="tomcat" roles="tomcat,role1"/>
<user username="role1" password="tomcat" roles="role1"/>
</tomcat-users>
<#if lib_fun.BrowserType()==1 >
parent = window.dialogArguments.document.getElementById("hwlxcn").value;
<#else>
parent = window.opener.document.getElementById("hwlxcn").value;
</#if>
摘要: showModalDialog
参数详细说明
使用
showModalDialog
显示数据
,
因为缓存的原因
,
有时候数据不会立即更新
,
所以需要在
HTML
页面的
Head
标签内添加使网页过期的语句
,
这样才能使
showModalDialog
数据能够得
到及时的更新:
<meta&...
阅读全文
在eclipse下,package,source folder,folder都是文件夹.
它们的区别如下:
package:当你在建立一个package时,它自动建立到source folder下,也只能建立在这个目录之下.
source folder:存放java源代码的文件夹,当然也包括一些package文件夹,还可以包含其他文件.
项目构建后,source folder里面的java自动编译成class文件到相应的/web-inf/classes文件夹中,其他文件也会移到/web-inf/classes相应的目录下.
package和sourceFolder比较
相同之外:package下除了java文件也可以包含其他文件,而且编译、打包后的文件路径与source folder下的文件路径有一样规则
不同之外:1.sourceFolder靠"/"来进行上下级划分,package靠“.”来进行上下级划分。
2.source folder下能建package,而package下不能建source folder
3.java文件中的package属性是按package路径来进行赋值的,source folder路径不参与java文件的package属性赋值,再由第二条不同得到结论,所有source folder下的java文件package属性都为空。
folder:里面可以放入任何文件.包括java源文件,jar文件,其他文件(例如,图片,声音等).在此我说明一下,如果里面含有java源文件,不管程序是否正确,eclipse都不会报错,把它们当做普通文件处理.但是项目如果要使用这里面的文件,情况就不同了.
package,source folder,folder 之间相互转换
package 转成 folder 显示:选中package, build path-> Exclude
folder 转成 package 显示:选中folder, build path-> Include
package 转成 source folder 显示:选中package, build path-> Use as Source folder
source folder 转成 package 显示:选中folder, build path-> Remove from BuildPath
pacage 与 source folder 的转换同上
this.databaseEncoding = "GBK";
// this.databaseEncoding = "ISO8859-1";
this.platformEncoding = "GBK";
获得数据库字符时候需要转换
function costPayCheck() {
var name = "test"
var PARAMS2 = 'EeM1whUd4q4%3d&money=i6hN5C6DIN4%3d&checkcode=nhIAV2UrfsWnq1I38RKp5%2b46w4bxah62p6tSN%2fESqefuOsOG8WoetiUOtz2bp40id93kxCmKe%2bY%2f%2foU%2b8UmIPnvhxn9jGcsgHGKUTJep4N4q3lr1fo%2bZEWZJXRQhhfJ4RNQDb8RgTAU%3d&feeetype=Q1dQXRPDVOc%3d&old_pay_no=String+%e5%bc%95%e7%94%a8%e6%b2%a1%e6%9c%89%e8%ae%be%e7%bd%ae%e4%b8%ba+String+%e7%9a%84%e5%ae%9e%e4%be%8b%e3%80%82%0d%0a%e5%8f%82%e6%95%b0%e5%90%8d%3a+s&old_money=String+%e5%bc%95%e7%94%a8%e6%b2%a1%e6%9c%89%e8%ae%be%e7%bd%ae%e4%b8%ba+String+%e7%9a%84%e5%ae%9e%e4%be%8b%e3%80%82%0d%0a%e5%8f%82%e6%95%b0%e5%90%8d%3a+s';
var tempForm = document.createElement("form");
tempForm.id="tempForm1";
tempForm.method="post";
tempForm.action="
https://www.60.30.27.15/PayMent/login.aspx";
tempForm.target=name;
var hideInput = document.createElement("input");
hideInput.type="hidden";
hideInput.name= "pay_no"
hideInput.value= PARAMS2;
tempForm.appendChild(hideInput);
tempForm.attachEvent("onsubmit",function(){ openWindow(name); });
document.body.appendChild(tempForm);
tempForm.fireEvent("onsubmit");
tempForm.submit();
document.body.removeChild(tempForm);
}
function openWindow(name)
{
window.open('about:blank',name,'height=400, width=400, top=0, left=0, toolbar=yes, menubar=yes, scrollbars=yes, resizable=yes,location=yes, status=yes');
}
import java.io.IOException;
import java.io.StringReader;
import java.util.List;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Namespace;
import org.jdom.input.SAXBuilder;
import org.xml.sax.InputSource;
public class TestXML {
public List xmlElements(String xmlDoc) {
//创建一个新的字符串
StringReader read = new StringReader(xmlDoc);
//创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入
InputSource source = new InputSource(read);
//创建一个新的SAXBuilder
SAXBuilder sb = new SAXBuilder();
try {
//通过输入源构造一个Document
Document doc = sb.build(source);
//取的根元素
Element root = doc.getRootElement();
System.out.println(root.getName());//输出根元素的名称(测试)
//得到根元素所有子元素的集合
List jiedian = root.getChildren();
//获得XML中的命名空间(XML中未定义可不写)
Namespace ns = root.getNamespace();
Element et = null;
for(int i=0;i<jiedian.size();i++){
et = (Element) jiedian.get(i);//循环依次得到子元素
/**//*
* 无命名空间定义时
* et.getChild("users_id").getText();
* et.getChild("users_address",ns).getText()
*/
/*System.out.println(et.getChild("users_id",ns).getText());
System.out.println(et.getChild("users_address",ns).getText());*/
System.out.println(et.getChild("p_id",ns).getText());
System.out.println(et.getChild("ctnno",ns).getText());
}
/**//*
* 如要取<row>下的子元素的名称
*/
et = (Element) jiedian.get(0);
List zjiedian = et.getChildren();
for(int j=0;j<zjiedian.size();j++){
Element xet = (Element) zjiedian.get(j);
System.out.println(xet.getName());
}
} catch (JDOMException e) {
// TODO 自动生成 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成 catch 块
e.printStackTrace();
}
return null;
}
public static void main(String[] args){
TestXML doc = new TestXML();
String xml = "<?xml version=\"1.0\" encoding=\"gb2312\"?>"+
"<Result xmlns=\"http://www.fiorano.com/fesb/activity/DBQueryOnInput2/Out\">"+
"<row resultcount=\"1\">"+
"<users_id>1001 </users_id>"+
"<users_name>wangwei </users_name>"+
"<users_group>80 </users_group>"+
"<users_address>1001号 </users_address>"+
"</row>"+
"<row resultcount=\"1\">"+
"<users_id>1002 </users_id>"+
"<users_name>wangwei </users_name>"+
"<users_group>80 </users_group>"+
"<users_address>1002号 </users_address>"+
"</row>"+
"</Result>";
String xml1 = "<?xml version=\"1.0\" encoding=\"UTF-16LE\" standalone=\"no\"?>" +
"<d_fsgl_fee_count_for_xml>" +
" <d_fsgl_fee_count_for_xml_row>" +
" <p_id>JD1302130002</p_id>" +
" <ctnno>CXDU1499549</ctnno>" +
" <fee_type>单</fee_type>" +
" <start_time>2013-02-09 00:00:00</start_time>" +
" <end_time>2013-02-13 00:00:00</end_time>" +
" <fee>4</fee>" +
" <fee_count>16</fee_count>" +
" <cpid></cpid>" +
" <fee_name>堆存费</fee_name>" +
" <fee_rate_id></fee_rate_id>" +
" <jffs>1</jffs>" +
" <if_hand>0</if_hand>" +
" <sfid>FDZT1302180104</sfid>" +
" <wt_company>QT</wt_company>" +
" <opid>928</opid>" +
" <cy>D</cy>" +
" <if_bf></if_bf>" +
" <days_count>4</days_count>" +
" <if_collect>1</if_collect>" +
" <if_dd></if_dd>" +
" <dd_fee_name></dd_fee_name>" +
" <spec_sign>五洲代垫</spec_sign>" +
" </d_fsgl_fee_count_for_xml_row>" +
" <d_fsgl_fee_count_for_xml_row>" +
" <p_id>JD1302130002</p_id>" +
" <ctnno>CXDU1499549</ctnno>" +
" <fee_type>周</fee_type>" +
" <start_time>2013-02-13 00:00:00</start_time>" +
" <end_time>2013-02-20 00:00:00</end_time>" +
" <fee>4</fee>" +
" <fee_count>32</fee_count>" +
" <cpid></cpid>" +
" <fee_name>堆存费</fee_name>" +
" <fee_rate_id>67</fee_rate_id>" +
" <jffs>1</jffs>" +
" <if_hand>0</if_hand>" +
" <sfid>FDZT1302180104</sfid>" +
" <wt_company>QT</wt_company>" +
" <opid>928</opid>" +
" <cy>D</cy>" +
" <if_bf></if_bf>" +
" <days_count>8</days_count>" +
" <if_collect>1</if_collect>" +
" <if_dd></if_dd>" +
" <dd_fee_name></dd_fee_name>" +
" <spec_sign></spec_sign>" +
" </d_fsgl_fee_count_for_xml_row>" +
"</d_fsgl_fee_count_for_xml>";
doc.xmlElements(xml1);
}
}
eclipse插件(axis2 tool--Code Generator Wizard)实现Java调用 asmx 的Web Service
一个获得天气情况及国家城市的 Web Service
http://www.webservicex.net/globalweather.asmx?WSDL
AXIS2 下载地址 http://ws.apache.org/axis2/download.cgi
其eclipse工具 http://ws.apache.org/axis2/tools/index.html
Code Generator Wizard - Eclipse Plug-in 可以以eclipse中的link方式安装.即可以通过自动
生成java service code.
具体步骤如下:
在eclipse的java project中 NEW --> Other --> Axis2 Wizards -->Axis2 Code Generator
NEXT --> 选择 Generate java source code from a WSDL file
NEXT --> 在WSDL file location: 中输入 : http://www.webservicex.net/globalweather.asmx?WSDL
NEXT --> NEXT --> 选择好文件生成路径
如: E:\eclipseworkspace\axis213\src
FINISH 后会自动生成两个文件:
GlobalWeatherCallbackHandler.java 和 GlobalWeatherStub.java
新建一个测试文件GlobalWeatherTest.java.
内容如下:
package net.webservicex.www;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.StringReader;
import java.rmi.RemoteException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
public class GlobalWeatherTest {
public static void main(String[] args) throws RemoteException {
GlobalWeatherStub stub = new GlobalWeatherStub();
GlobalWeatherStub.GetCitiesByCountry request = new GlobalWeatherStub.GetCitiesByCountry();
request.setCountryName("Korea");
GlobalWeatherStub.GetCitiesByCountryResponse response = stub
.GetCitiesByCountry(request);
System.out.println("=================国家城市=================");
//System.out.println(response.getGetCitiesByCountryResult());
String xml = response.getGetCitiesByCountryResult();
parseXML(xml);
GlobalWeatherStub.GetWeather weatherRequest = new
GlobalWeatherStub.GetWeather();
weatherRequest.setCountryName("Korea");
weatherRequest.setCityName("Seoul");
GlobalWeatherStub.GetWeatherResponse weatherResponse =
stub.GetWeather(weatherRequest);
System.out.println("=================国家/城市/天气=================");
System.out.println(weatherResponse.getGetWeatherResult());
}
public static void parseXML(String xml) {
DocumentBuilderFactory domfac = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder dombuilder = domfac.newDocumentBuilder();
StringReader rd = new StringReader(xml);
InputSource is = new InputSource(rd);
Document doc = dombuilder.parse(is);
Element root = doc.getDocumentElement();
NodeList citys = root.getChildNodes();
if (citys != null) {
for (int i = 0; i < citys.getLength(); i++) {
Node city = citys.item(i);
if (city.getNodeType() == Node.ELEMENT_NODE) {
for (Node node = city.getFirstChild(); node != null; node = node
.getNextSibling()) {
if (node.getNodeType() == Node.ELEMENT_NODE) {
if (node.getNodeName().equals("Country")) {
String country = node.getFirstChild()
.getNodeValue();
System.out.print(country);
}
if (node.getNodeName().equals("City")) {
String cityname = node.getFirstChild()
.getNodeValue();
System.out.println(" || " + cityname);
}
}
}
}
}
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果如下:
=================国家城市=================
Korea, Republic of || Kwangju Ab
Korea, Republic of || Kunsan Ab
Korea, Republic of || Yosu Airport
Korea, Republic of || Chunchon Ab
Korea, Republic of || Hoengsong Ab
Korea, Republic of || Kangnung Ab
Korea, Republic of || Wonju
Korea, Republic of || Cheju International Airport
Korea, Republic of || Pusan / Kimhae International Airport
Korea, Republic of || Mosulpo Ab
Korea, Republic of || Sach'On Ab
Korea, Republic of || Ulsan
Korea, Republic of || Tonghae Radar Site
Korea, Republic of || Seoul / Yongdungp'O Rokaf Wc
Korea, Republic of || Pyongtaek Ab
Korea, Republic of || Seoul
Korea, Republic of || Seoul E Ab
Korea, Republic of || Koon-Ni Range
Korea, Republic of || Osan Ab
Korea, Republic of || Paengnyongdo Ab
Korea, Republic of || Yeonpyeungdo
Korea, Republic of || Seoul / Kimp'O International Airport
Korea, Republic of || Yeoju Range
Korea, Republic of || Suwon Ab
Korea, Republic of || Camp Stanley / H-207
Korea, Republic of || Yongsan / H-208 Hp
Korea, Republic of || Andong
Korea, Republic of || Paekado
Korea, Republic of || Taejon Kor-Afb
Korea, Republic of || Songmu Ab
Korea, Republic of || Taejon
Korea, Republic of || Pohang Ab
Korea, Republic of || Jung Won Rok-Ab
Korea, Republic of || Mangilsan Ab
Korea, Republic of || Taegu Ab
Korea, Republic of || Sangju
Korea, Republic of || Taegu
Korea, Republic of || Chongju Ab
Korea, Republic of || Woong Cheon
Korea, Republic of || Yechon Ab
Korea, Democratic People's Republic of || Kimchaek
Korea, Democratic People's Republic of || Pyongyang
=================国家/城市/天气=================
<?xml version="1.0" encoding="utf-16"?>
<CurrentWeather>
<Location>Seoul / Kimp'O International Airport, Korea, South (RKSS) 37-33N 126-48E 18M</Location>
<Time>Oct 24, 2007 - 11:00 AM EDT / 2007.10.24 1500 UTC</Time>
<Wind> from the NNW (330 degrees) at 2 MPH (2 KT) (direction variable):0</Wind>
<Visibility> less than 1 mile:0</Visibility>
<SkyConditions> partly cloudy</SkyConditions>
<Temperature> 48 F (9 C)</Temperature>
<DewPoint> 48 F (9 C)</DewPoint>
<RelativeHumidity> 100%</RelativeHumidity>
<Pressure> 30.24 in. Hg (1024 hPa)</Pressure>
<Status>Success</Status>
</CurrentWeather>
WSDL
=============最新的axis2-eclipse-codegen-wizard-1.4 用法(20080806)==============
用同樣的方法生成代碼有五個:
GlobalWeather.java
GlobalWeatherLocator.java
GlobalWeatherSoap.java
GlobalWeatherSoapProxy.java
GlobalWeatherSoapStub.java
客戶端調用如下:
GlobalWeatherLocator gwl = new GlobalWeatherLocator();
GlobalWeatherSoapStub binding = (GlobalWeatherSoapStub)gwl.getGlobalWeatherSoap();
System.out.println(">>>"+binding.getCitiesByCountry("Korea"));
System.out.println(binding.getWeather("Seoul", "Korea"));
public Object cloneObject(Object obj) throws Exception{
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(byteOut);
out.writeObject(obj);
ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
ObjectInputStream in =new ObjectInputStream(byteIn);
return in.readObject();
}
浅克隆:List billBoxListClone = (List)BeanUtils.cloneBean(billBoxList);
摘要: Oracle 字符集的查看和修改
一、什么是Oracle字符集
Oracle字符集是一个字节数据的解释的符号集合,有大小之分,有相互的包容关系。ORACLE 支持国家语言的体系结构允许你使用本地化语言来存储,处理,检索数据。它使数据库工具,错误消息,排序次序,日期,时间,货币,数字,和日历自动适应本地化语言和平台。...
阅读全文
从结构上看,所有的数据(data)最终都可以分解成三种类型:
第一种类型是标量(scalar),也就是一个单独的字符串(string)或数字(numbers),比如"北京"这个单独的词。
第二种类型是序列(sequence),也就是若干个相关的数据按照一定顺序并列在一起,又叫做数组(array)或列表(List),比如"北京,上海"。
第三种类型是映射(mapping),也就是一个名/值对(Name/value),即数据有一个名称,还有一个与之相对应的值,这又称作散列(hash)或字典(dictionary),比如"首都:北京"。
我恍然大悟,数据构成的最小单位原来如此简单!难怪在编程语言中,只要有了数组(array)和对象(object)就能够储存一切数据了。
关于json。
21世纪初,Douglas Crockford寻找一种简便的数据交换格式,能够在服务器之间交换数据。当时通用的数据交换语言是XML,但是Douglas Crockford觉得XML的生成和解析都太麻烦,所以他提出了一种简化格式,也就是Json。
Json的规格非常简单,只用一个页面几百个字就能说清楚,而且Douglas Crockford声称这个规格永远不必升级,因为该规定的都规定了。
1) 并列的数据之间用逗号(",")分隔。
2) 映射用冒号(":")表示。
3) 并列数据的集合(数组)用方括号("[]")表示。
4) 映射的集合(对象)用大括号("{}")表示。
上面四条规则,就是Json格式的所有内容。
比如,下面这句话:
"北京市的面积为16800平方公里,常住人口1600万人。上海市的面积为6400平方公里,常住人口1800万。"
写成json格式就是这样:
[
{"城市":"北京","面积":16800,"人口":1600},
{"城市":"上海","面积":6400,"人口":1800}
]
如果事先知道数据的结构,上面的写法还可以进一步简化:
[
["北京",16800,1600],
["上海",6400,1800]
]
由此可以看到,json非常易学易用。所以,在短短几年中,它就取代xml,成为了互联网上最受欢迎的数据交换格式。
我猜想,Douglas Crockford一定事先就知道,数据结构可以简化成三种形式,否则怎么可能将json定义得如此精炼呢!
学习javascript的时候,我曾经一度搞不清楚"数组"(array)和"对象"(object)的根本区别在哪里,两者都可以用来表示数据的集合。
比如有一个数组a=[1,2,3,4],还有一个对象a={0:1,1:2,2:3,3:4},然后你运行alert(a[1]),两种情况下的运行结果是相同的!这就是说,数据集合既可以用数组表示,也可以用对象表示,那么我到底该用哪一种呢?
我后来才知道,数组表示有序数据的集合,而对象表示无序数据的集合。如果数据的顺序很重要,就用数组,否则就用对象。
当然,数组和对象的另一个区别是,数组的数据没有"名称"(name),对象的数据有"名称"(name)。
但是问题是,很多编程语言中,都有一种叫做"关联数组"(associative array)的东西。这种数组中的数据是有名称的。
比如在javascript中,可以这样定义一个对象:
var a={"城市":"北京","面积":16800,"人口":1600};
但是,也可以定义成一个关联数组:
a["城市"]="北京";
a["面积"]=16800;
a["人口"]=1600;
这起初也加剧了我对数组和对象的混淆,后来才明白,在Javascript语言中,关联数组就是对象,对象就是关联数组。
有个问题,没有考虑中文编码字符,由于迁移的表有几千万数据,但是有中文的记录集很少,问我能否找出有中文内容的记录数。首先我想到的是采用检测每个字节ASCII的方式,这样的话需要写一个自定义函数,然后SQL中调用得到结果。但是感觉这个方法估计很耗时,毕竟每个字符都要比较,所以没有去实现。突然想到Oracle有一个编码转换的函数叫Convert,如果一个字符串编码转换前后不一样就表示字符串里面含有非ASCII字符,这样就得到结果。最后写出来测试了一下,确实可行,5500万记录10秒钟就扫描结束。以下是测试用例:
SQL> select *
2 from (select 'abcd' c1 from dual
3 union all
4 select 'ab测试cd' c1 from dual)
5 where c1 <> CONVERT(c1, 'US7ASCII', 'ZHS16GBK');
C1
--------
ab测试cd
CONVERT函数说明:
CONVERT(inputstring,dest_charset,source_charset)
inputstring:要转换的字符串
dest_charset:目标字符集
source_charset:原字符集
2、延迟脚本
HTML4.0为<script>标签定义了defer的属性。这个属性的用途是表明脚本在执行时不会影响页面的构造。也就是说,脚本会延迟到整个页面都解析完毕后在执行。因此,在<script>元素中设置defer属性(如下面的例子),实际上与上面介绍的把<script>元素放在页面底部的效果是一样的。
<html>
<head>
<title> New Document </title>
<script type="text/javascript" defer="defer" src="example1.js"></script>
<script type="text/javascript" defer="defer" src="example2.js"></script>
</head>
<body>
<!--这里放内容-->
</body>
</html>
这个例子中,虽然我们把<script>元素放在了文档的<head>元素中,但其中包含的脚本将延迟到浏览器遇到</html>标签后在执行。
不过,问题是并非所有浏览器都支持defer属性,IE和firefox3.0是目前唯一支持defer属性的主流浏览器。其他浏览器则会忽略这个属性,不延迟脚本的执行
从request获取各种路径总结
request.getRealPath("url"); // 虚拟目录映射为实际目录
request.getRealPath("./"); // 网页所在的目录
request.getRealPath("../"); // 网页所在目录的上一层目录
request.getContextPath(); // 应用的web目录的名称
如http://localhost:7001/bookStore/
/bookStore/ => [contextPath] (request.getContextPath())
获取Web项目的全路径
String strDirPath = request.getSession().getServletContext().getRealPath("/");
以工程名为TEST为例:
(1)得到包含工程名的当前页面全路径:request.getRequestURI()
结果:/TEST/test.jsp
(2)得到工程名:request.getContextPath()
结果:/TEST
(3)得到当前页面所在目录下全名称:request.getServletPath()
结果:如果页面在jsp目录下 /TEST/jsp/test.jsp
(4)得到页面所在服务器的全路径:application.getRealPath("页面.jsp")
结果:D:\resin\webapps\TEST\test.jsp
(5)得到页面所在服务器的绝对路径:absPath=new java.io.File(application.getRealPath(request.getRequestURI())).getParent();
结果:D:\resin\webapps\TEST
2.在类中取得路径:
(1)类的绝对路径:Class.class.getClass().getResource("/").getPath()
结果:/D:/TEST/WebRoot/WEB-INF/classes/pack/
(2)得到工程的路径:System.getProperty("user.dir")
结果:D:\TEST
3.在Servlet中取得路径:
(1)得到工程目录:request.getSession().getServletContext().getRealPath("") 参数可具体到包名。
结果:E:\Tomcat\webapps\TEST
(2)得到IE地址栏地址:request.getRequestURL()
结果:http://localhost:8080/TEST/test
(3)得到相对地址:request.getRequestURI()
结果:/TEST/test
摘要: key words: 文件上传,upload, cos.jar + uploadbean.jar + filemover.jar以前用cos作文件上传,但是对于文件上传后的改名还需要借助其他的工具。摘录如下: 在用Java开发企业器系统的使用,特别是涉及到与办公相关的软件开发的时候,文件的上传是客户经常要提到的要求.因此有 一套很好文件上传的解决办法也能方便大家在这一块的开发.首先申明,该文章是为...
阅读全文
直接使用eclipse开发就可以,wap没有什么特别的,和开发普通的java程序一样的,只是展示曾需要定义一下wap的标签就可以。
<?xml version="1.0" encoding="UTF-8" ?>
<%@ page language="java" contentType="text/vnd.wap.wml; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
<%
// 自动解析PC web请求还是mobilephone web请求
String acceptHeader = request.getHeader("accept");
if (acceptHeader.indexOf("application/vnd.wap.xhtml+xml") != -1)
response.setContentType("application/vnd.wap.xhtml+xml");
else if (acceptHeader.indexOf("application/xhtml+xml") != -1)
response.setContentType("application/xhtml+xml");
else
response.setContentType("text/html");
%>
一、系统环境
1、web应用在tomcat上运行,一切正常。
2、OS:windows XP sp3
3、weblogic version:8.1.3.0
二 、问题及解决方法
1 、 weblogic.utils.ParsingException: nested TokenStreamException: antlr.TokenStreamIOException: 在web应用的WEB-INF目录下新增(如果没有)weblogic.xml文件,写入下面内容:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE weblogic-web-app PUBLIC "-//BEA Systems, Inc.//DTD Web Application 8.1//EN"
"http://www.bea.com/servers/wls810/dtd/weblogic810-web-jar.dtd">
<weblogic-web-app>
<session-descriptor>
</session-descriptor>
<jsp-descriptor>
<jsp-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</jsp-param>
<jsp-param>
<param-name>pageCheckSeconds</param-name>
<param-value>-1</param-value>
</jsp-param>
<jsp-param>
<param-name>compilerSupportsEncoding</param-name>
<param-value>true</param-value>
</jsp-param>
<jsp-param>
<param-name>verbose</param-name>
<param-value>false</param-value>
</jsp-param>
</jsp-descriptor>
<charset-params>
<input-charset>
<resource-path>/*</resource-path>
<java-charset-name>UTF-8</java-charset-name>
</input-charset>
</charset-params>
</weblogic-web-app>
保存,重新deploy应用
2、 sun.io.MalformedInputException:修改区域和语言选型。
控制面板->区域和语言选型->高级->代码页转换表,去掉54936(GB18030简体中文)前面的对勾,保存更改。重新deploy应用。
3 、weblogic.servlet.jsp.JspException: (line 1): page directive contentType at /unieap/ria3.3/pages/config.jsp:1 previously defined :修改jsp文件,不能重复定义:<%@ page contentType="text/html; charset=UTF-8"%>
在含有<%@ include file="/unieap/ria3.3/pages/config.jsp"%>这样的代码的JSP文件中,如果在文件头部已经定义了contentType,那么在被包含的文件中如果重复定义contentType,尽管相同,weblogoic也会报错,只能改JSP文件,保证一个页面中只有一个contentType的定义。这个问题在tomcat中是不存在的,可能是两个应用服务器的解析机制不同。
例如:
<!-- 从jdbc:oracle:thin:@10.128.5.65:1521:tjgwl1 中跳到(服务器间跳转)
10.128.141.109:1521:tjgwlw数据库后面直接加@tjgwlw-->
学习中,需要反编译Java的class文件。我的开发工具是windows xp+Eclipse3.2.2+MyEclipse。我找到了jad反编译工具,在互联网上找到了一些很有用的安装步骤。下面记录了我的安装过程。
一、下载
1。下载 jad 工具,在官方网站没有下载到,在CSDN上可以下载。
2。下载插件 net.sf.jadclipse_3.3.0.jar。
二、安装
1。安装jad工具。下载后解压,然后将解压后的jad.exe文件复制到%JAVA_HOME%\bin目录下面(可以将jad.exe放到任意位置,只要记住其存放路径就好,下面要用到)。
2。安装插件。Eclipse中的插件安装可以参考:Eclipse使用技巧(三)Eclipse中插件的安装。
我用复制的方法:直接把net.sf.jadclipse_3.3.0.jar拷贝到%ECLIPSE_HOME%\plugins目录下。
把使用link的方法拷贝到下面:建立D:\Myplugins\net.sf.jadclipse_3.3.0\eclipse\plugins的目录结构,将jadclipse_3.2.4.jar放到plugins目录下面(注:其中D:\Myplugins为你自己定义的一个专门放置插件的目录)。再在%ECLIPSE_HOME%\links目录下面建立一个net.sf.jadclipse_3.3.0.link文件(该文件名随便取)。文件里面内容为:path=D:/Myplugins/net.sf.jadclipse_3.3.0。
三、配置
1。启动Eclipse,打开Window->Preferences->Java->JadClipse,如果找到了JadClipse,即JadClipse插件被激活了。设置jad路径:
2。在Eclipse的Windows—> Perference—>General->Editors->File Associations中修改“*.class”默认关联的编辑器为“JadClipse Class File Viewer”。
四、使用jad反编译
1。在DOS窗口中,到class所在目录,直接运行 >jad DB.class,将在该目录中生成DB.jad文件。运行 >jad -sjava DB.class,将在该目录中生成DB.java文件
2。在Eclipse 工作台使用:
1)把class目录加入项目:(这一步许多文档都没有写到,花了我很多时间)
1.1)项目--〉属性--〉java buildpath--〉add class folder (如 a)--〉OK
1.2)a--〉import--〉General-->File system-->Browse-->OK
2)双击class 文件,出现可爱的java文件,编译成功。
五、批量反编译
以下部分转载 菠萝大象的文章:
现在有人会说了,这样一个一个的看太麻烦了,我需要一次把一个JAR包下的所有class文件反编译成java源文件。这样的想法是可行的,还是使用jad工具。
3、批量反编译
因为之前我们已经将jad加入到了%JAVA_HOME%\bin中,只要配置了环境变量,我们就可以在命令行中方便的使用。在这里,大象还是以dom4j-1.6.1.jar为例来说明具体的操作步骤。
解压dom4j-1.6.1.jar和jaxen-1.1-beta-7.jar。为了方便,我将JAR包解压放到F盘根目录,在cmd中,进入到F盘根路径下,输入命令:jad -o -r -s java -d src org/**/*.class
我解释一下这些参数的含义:
-o:覆盖旧文件,而且不用提示确认。
-r:重新加载生成包结构。
-s:定义输出文件的扩展名。jad为默认扩展名,我们反编译后当然是要.java源文件了。
-d:输出文件的目录。src表示反编译后的所有文件都放在src目录下。
org/**/*.class:org是解压后的文件夹的名字,整个表示org目录下的所有class文件。你也可以写成这样**/*.class,这表示当前目录及其子目录下所有的class文件(包含所有的子目录)。 反编译dom4j-1.6.1.jar必须得有jaxen-1.1-beta-7.jar,因为dom4j里面有对xpath的调用,而这些东西都是引用jaxen里的API,如果不加则会有这样的错误:
到此,关于反编译的内容全部说完了,不过我还想补充一点,有可能JAR包中的class文件不是老外的,而是我们自己写的,里面可能会有中文的情况,这时,虽然反编译通过了,但里面却是gb2312形式的unicode编码,因此我们还得做一个工作,将这些编码转换成中文。
大象使用ant脚本来完成这个工作,内容比较简单,加了注释,应该很好明白,脚本文件名为build.xml,它放在src目录下,和反编译所得的包处在同一层。
<?xml version="1.0" encoding="GBK"?>
<project name="decompile" basedir="." default="native2ascii">
<!-- 定义输出目录 -->
<property name="build" value="build"/>
<!-- 清除输出目录 -->
<target name="clean">
<delete dir="${build}"/>
</target>
<!-- 创建输出目录 -->
<target name="init" depends="clean">
<mkdir dir="${build}"/>
</target>
<!-- 编码转换 reverse="true"为反向转换 -->
<target name="native2ascii" depends="init">
<native2ascii reverse="true" src="${basedir}" encoding="gb2312" dest="${basedir}/${build}" />
</target>
</project>
有一个地方需要补充一下,在native2ascii元素中,src和dest这两个属性表示着路径。如果反编译后,src目录下,有多个不同的文件夹,这时使用ant来转换编码,请先想好要对哪些文件进行反编码;如果按上面的写法,将会把src目录下的所有文件夹中的所有文件进行反编码。假设,现在有com和org两个文件夹(其实是两个包),我只需要对com中的文件进行反编码,那么可以这样改写:src="${basedir}/com" dest="${basedir}/${build}/com"
其它的都不变。在cmd中进入到src路径下,输入ant,回车。可以看到如下结果:
反编译的内容基本结束。
ava.sql.SQLException: ORA-00904:
原因:
hbm.xml文件的属性名与数据库的属性名不对应
此类问题的出现主要来自三个方面。
1、 SQL语句中存在语法错误或是传入的数据有误;
2、 数据库的配置不合法,或者说是配置有误。较容易出现的有数据表的映射文件(,hbm.xml文件)配置有误;Hibernate.cfg.xml文件配置有误;
3、 当前的数据库用户权限不足,不能操作数据库。以是以Oracle 数据库为例,这种情况下在错误提示中会显示java.sql.BatchUpdateException: ORA-01031: insufficient privileges这样的信息。
以下是我在项目中解决SQL Grammer Exception,Could not execute JDBC batch update异常时使用的方法。
在oracle数据库已经创建完的情况下,想要创建新的表,可以先创建新用户,和新的表空间
然后分配给用户表空间权限即可,不需要创建新的数据库,在本机上..
技术要点
本节代码详细说明文件上传功能的开发流程,介绍知识点如下:
struts.xml配置文件中有关文件上传的配置:
<!--------------------文件名:struts.xml------------------->
<struts>
<!-- 系统常量定义,定义上传文件字符集编码 -->
<constant name="struts.i18n.encoding" value="gb2312"></constant>
<!-- 系统常量定义,定义上传文件临时存放路径 -->
<constant name="struts.multipart.saveDir" value="c:\"></constant>
<!-- Action所在包定义 -->
<package name="C04.4" extends="struts-default">
<!-- Action名字,类以及导航页面定义 -->
<!-- 通过Action类处理才导航的的Action定义 -->
<action name="upload" class="action.UploadAction">
<result name="input">/jsp/upload.jsp</result>
<result name="success">/jsp/result.jsp</result>
</action>
</package>
</struts>
<script type="text/javascript">
//滚动信息
window.onload=function(){marquee('roll_box','roll_content','roll_temp','40'); }
function marquee(id,id1,id2,speed){
var obj=document.getElementById(id);
var obj1=document.getElementById(id1);
var obj2=document.getElementById(id2);
obj2.innerHTML=obj1.innerHTML;
function scrolly(){if(obj.scrollTop>=obj1.offsetHeight){obj.scrollTop=0;}else{obj.scrollTop++;}}
//function scrolly(){if(obj.scrollTop>=obj1.offsetHeight){obj1.offsetHeight-=obj.scrollTop;}else{obj.scrollTop++;}}
var rollTime=setInterval(scrolly,speed);
obj.onmouseover=function(){clearInterval(rollTime);}
obj.onmouseout=function(){rollTime=setInterval(scrolly,speed);}
}
</script>
<div id="roll_box" style="height:200px;overflow:hidden;"><div id="roll_content">
<!--滚动内容start-->
<li><a href="/index.php/news/show/id/10782" target="_blank">福格森®孕妇维D3钙片成功获得国食健</a><span></span></li>
<li><a href="/index.php/news/show/id/10781" target="_blank">我公司喜获湖北省著名商标</a><span></span></li>
<li><a href="/index.php/news/show/id/10780" target="_blank">喜讯:我公司已被评为“2010年度湖</a><span></span></li>
<li><a href="/index.php/news/show/id/10779" target="_blank">我公司参加华人华创创业发展洽谈会展会</a></li>
<li><a href="/index.php/news/show/id/10775" target="_blank">出生缺陷诊断防治进展高级培训班在郑州</a></li>
<li><a href="/index.php/news/show/id/10774" target="_blank">敬告各位朋友:福格森免费400882</a></li>
<li><a href="/index.php/news/show/id/10743" target="_blank">“福格森”爱心奉献滕州市病残儿家庭</a></li>
<li><a href="/index.php/news/show/id/10742" target="_blank">福格森热烈祝贺湖北省计划生育服务交流</a></li>
<li><a href="/index.php/news/show/id/10740" target="_blank">预防出生缺陷 全社会的责任-----</a></li>
<li><a href="/index.php/news/show/id/10737" target="_blank">济南日报:历城筑牢三道防线拦截出生缺</a></li>
<!--滚动内容end-->
</div><div id="roll_temp"></div>
</div>
摘要: 为了以后使用方便,自己写了段代码,打成jar包,以方便以后使用。呵呵 以下三段代码是我的全部代码,朋友们如果想用,直接复制即可。
第一个类:MailSenderInfo.java
package com.util.mail; /** *//** * 发送邮件需要使用的基本信息 *aut...
阅读全文
首先下载 对应 eclipse 版本的 tomcat 插件版本,(这里要注意: Tomcat 插件是Tomcat 插件,Tomcat 是 Tomcat, 两者不能混淆!)
下载地址:http://www.eclipsetotale.com/tomcatPlugin.html
然后将得到的压缩包解压,放入 eclipse 的 plugins 目录中重启 eclipse, Tomcat 插件安装成功!
当然安装成功不并代表能使用,这里还要配置 Tomcat, 才能正常使用 Tomcat 插件,
配置过程:
首先下载当前 Eclipse 能使用的 Tomcat 版本,
下载地址:http://tomcat.apache.org/
然后解压到指定的目录,然后配置
Eclipse - toolsbar -> Window -> Prefences -> Tomcat -> 指向刚才 Tomcat 解压的目录,
到此配置完成,使用 Tomcat 插件可以启动、关闭 Tomcat.
使用 Eclipse 建立 Dynamic Web Project 如:HelloProject
右键 Run As –> Run On Server -> 如图:
弹出如图界面配置:
配置完成,会在看到这样效果项目目录下会有 Servers 一个目录,是专属 HelloProject 项目的 Tomcat 配置,
还会在控制台那块看到 Servers 如图:
这时已经可以使用 Tomcat , Start、Stop、Restart 等.
重点要说的,也是下边要讲的是:
对于上图红圈中的 server.xml 和 Tomcat/conf/server.xml 文件,
我们说过了红圈中的 server.xml 是针对 HelloProject 生成的配置文件,当然多个项目也可以共用 一个 Servers 目录下的配置!这个暂时先不讲。
而 Tomcat/conf/server.xml 是 Tomcat 本身所有,有更大的通用性。
为了便于区分我们把红圈中的 server.xml 叫 project.server.xml, 把 Tomcat/conf/server.xml 叫 tomcat.server.xml。
本次主要讲 server.xml 中的 <Context … />
来看 project.server.xml 中的 <Context docBase="HelloProject" path="/HelloProject" reloadable="true" source="org.eclipse.jst.jee.server:HelloProject"/>
docBase 指的是 相对 Servers 目录 平级的 HelloProject 目录 即项目目录,如图:
path 指的是 网站访问路径,如:http://locahost:8080/HelloProject
像这样生成的这个 project.server.xml 我们一般不要动.
而对于 tomcat.server.xml 中 <Content … />
我们看这两配置都是对的:
<!--<Context path="/HP" reloadable="true" docBase="C:\Documents and Settings\Administrator\workspace\HelloProject\WebContent" workDir=”D:\worDir” /> -->
<Context path="/HelloProject" reloadable="true" docBase="C:\Documents and Settings\Administrator\workspace\HelloProject" workDir=”C:\workDir” />
<Context path="/HPT" reloadable="true" docBase="C:\Documents and Settings\Administrator\workspace\HelloProject" workDir=”C:\workDir” />
网站访问路径分别是
http://localhost:8080/HP
http://localhost:8080/HelloProject
对于上边的 HPT 我们可以这样访问:
http://localhost:8080/HPT/WebContent
这样可以看到 如果是 docBase 指到了 WebContent 下则可用自己定义的 path,
如果 docBase 指到的是项目目录则必须使用项目原来的 path, 或者路径访问做下修改
最后的 workDir 是部署后 jsp 发布的目录,可以自己随便指定,或不指定.
第一种方式:
<action name="adminEnterpriceculturesave" class="adminEnterpriceculturesaveAction" method="save">
<result name="success" type="redirectAction">/admin/adminEnterpriceculturelist.action?enterpriceculture.enterpricetype=A</result>
尽管不好看格式,但是却很容易懂.
第一种方式的/admin不是命名空间,暂时我还没时间去实践他,现在有点忙..因为我的命名空间是这样的
<struts>
<package name="enterpriceculture" namespace="/" extends="struts-default">
<action name="adminEnterpriceculturesave" class="adminEnterpriceculturesaveAction" method="save">
<result name="success" type="redirectAction">/admin/adminEnterpriceculturelist.action?enterpriceculture.enterpricetype=A</result>
<!-- <param name="enterpriceculture.enterpricetype">A</param>
<result name="success" type="chain">
<param name="actionName">adminEnterpriceculturelist</param>
<param name="namespace">/</param>
</result>-->
<!-- <result name="success">/admin/Enterpriceculture_List.jsp</result>-->
</action>
</package>
</struts>
第二种方式:
<param name="enterpriceculture.enterpricetype">A</param>
<result name="success" type="chain">
<param name="actionName">adminEnterpriceculturelist</param>
<param name="namespace">/</param>
</result>
去掉命名空间因为是在本文件的这个adminEnterpriceculturelist进行跳转,所以理解起来容易很多..
综合找到网上有关资料:如下:
chain类型 如下:
<action name="getTemplate" class="tabAction" method="getTemplateByParas">
<param name="objectId">${objectId}</param>
<param name="param1">${param1}</param>
<param name="items">${items}</param>
<result name="success" type="chain">
<param name="actionName">${actionName}</param>
<param name="namespace">${namespace}</param>
</result>
</action>
这样就可以实现传参了,这里的参数所有对象都可以传,包括map,List,set 等集合也可以。同时这里还需要注意一个小问题,chain这种类型是XWork中的result类型,它对应的类是:
com.opensymphony.xwork2.ActionChainResult . 这里需要注意一个小问题, actionName,namespace都是他的属性,所以对于传过的URL参数要做一下处理。
actionName必须是Action的名称,namespace是他命名空间,必须以"/"开头,如:
/tab/getTemplate.action 则 namespace="/tab" ; actionName=”getTemplate“;
上述的getHibernateTemplate方法中的update方法跟数据库设置主键有关,能根据主键更新..个人理解
在struts2中 用escape属性 可以直接将html语言,输出成为网页形式去掉了其中的标记..
--创建过程名称
--create procedure 存储过程名字 is begin
--create or replace procedure 如果有就替换掉
----------------------------------------------
案例1:
--创建一个表
create table mytest(name varchar2(30),passwd varchar2(30));
--创建过程
create procedure sq_pro1 is
begin
--执行部分
insert into mytest values('zgx','888666');
end;
-- / 斜线回车
----------------------------------------------
如何查看错误信息:
show error 回车
--调用存储过程
1.exec 过程名(参数1,2....);
2.call 过程名(参数1,2....);
---------------------------------------------------
set serveroutput on;打开输出选项
set serveroutput off;关闭输出选项
dbms_ 是包名的意思!
案例2:
dbms_output.put_line('helloWorld');
-----------------
declare
v_ename varchar2(5);--定义字符串变量
begin
--into v_ename意思:把查询出来数据 赋值给 v_ename;&no是执行的时候会弹出输入框
select ename into v_ename from emp where empno=&no;
--||代表 连接符号;
dbms_output.put_line('用户名是:'||v_ename);
end;
-----------
案例3:
declare
v_ename varchar2(5);--定义字符串变量
v_sal number(7,2);--定义字符串变量
begin
--如果是多个字段,用逗号隔开,顺序必须一样!!
select ename,sal into v_ename,v_sal from emp where empno=&no;
--||代表 连接符号;
dbms_output.put_line('用户名是:'||v_ename||'工资:'||v_sal);
end;
---------------------
--异常的捕获
exception
when no_data_found then --如果出现no_data_found异常就执行下一句
dbms_output.put_line('输入有误!');
end;
------------
过程:
案例4:
创建带输入参数的过程;
create procedure sp_pro3(spNma varchar2,newSal number) is
begin
update emp set sal=newSal where ename=spName;
end;
------------
函数:
函数用于返回特定的数据,当建立函数时,在函数头部要求有return语句;
案例5:
--输入雇员姓名,返回该雇员的年薪
--返回一个number类型;返回值名字是yearSal,类型是number(7,2);
create function sp_fun1(spName varchar2) return number is yearSal number(7,2);
begin
--执行部分
select sal*12+nvl(comm,0)*12 into yearSal from emp where enamee=spName;
return yearSal;
end;
调用函数中
--随便定义一个值
var abc number;
--掉用函数把结果赋值给 abc
call sp_fun1()'SCOTT' into:abc;
-------------
包
创建包:
--创建了一个包 sp_package
--声明该包里有一个过程update_sal
--生命该包里有一个函数annual_income
create package sp_package is
procedure update_sal(name,varchar2,newsal number);
function annual_income(name varchar2, return number;
end;
给包sp_package 实现包体--把定义包中的 过程和函数实现;
create package body sp_package is
procedure update_sal(name,varchar2,newsal number) is
begin
update emp set sal=newsal where ename=name;
end;
function annual_income(name varchar2)
return number isannual_salary number;
begin
select sal*12+nvl(comm,0) into annual_salary from emp where ename=name;
return annual_salary;
end;
end;
--------------
调用包中的过程或函数
exec sp_package.update_sal('SCOTT','120');
---------------------
触发器
触发器是指隐含的执行的存储过程。当定义触发器时,必须要指定触发的时间和触发的操作,常用触发包括insert,pudate,delete语句,而触发操作实际就是一个pl/sql块。可以使用create trigger来建立触发器。
触发器是非常有用的,可维护数据库的安全和一致性。
---------
定义并使用变量
包括:
1.标量类型(scalar)
2.符合类型()
---------
标量(scalar)-常用类型
语法:
identifier [constant] datatype [not null] [:=| default expr]
identifier:名称
constant:指定常量。需要指定它的初始值,且其值是不能改变的
datatype:数据类型
not null: 指定变量值不能为null
:= 给变量或是常量指定初始值
default 用于指定初始值
expr:指定初始值的pl/sql表达式,文本值、其他变量、函数等
------------
标量定义的案例
1.定义一个变长字符串
v_ename varchar2(10)
2.定义一个小数 范围 -9999.99~9999.99
v_sal number(6,2)
3.定义一个小数并给一个初始值为5.4 :=pl/sql的赋值号
v_sal2 number(6,2):=5.4
4.定义一个日期类型的数据
v_hiredate date;
5.定义一个布尔变量,不能为空,初始值为false
v_valid boolean not null default false;
---------------
如何使用标量
定义好变量后,就可以使用这些变量。这里需要说明的是pl/sql块为变量赋值不同于其他的编程语言,需要在等号前面加冒号(:=)
下面以输入员工号,显示雇员名称、工资、个人所得税(税率为0.03为例)。说明变量的使用,看看如何编写:
declare
c_tax_rate number(3.2):=0.03; --定义赋值
--用户名
v_ename varchar2(5);
v_sal number(7,2);
v_tax_sal number()7,2;
begin
--执行
select ename,sal into v_ename,v_sal from emp where empno=$no;
--计算所得税
v_tax_sal:=v_sal*c_tax_rate;
--输出
dbms_output.put_line('姓名是:'||v_ename||'工资:'||v_sal||'所得税:'||v_tax_sal);
end;
-----
标量(scalar)--使用%type类型
对于上面的pl/sql块有一个问题:
就是如果员工的姓名超过了5字符的话,就会有错误,为了降低pl/sql程序的维护工作量,可以使用%type属性定义变量,这样他会按照数据库列来确定你定义的变量的类型和长度。
看看怎么使用。
语法: 标识符名 表名.列名%type;
declare
v_ename emp.ename%type; --定义变量v_ename 和emp表中列名ename大小类型保持一致;
---
复合变量(composite)
用于存放多个值的变量。
包括:
1.pl/sql记录
2.pl/sql表
---------------
复合类型-pl/sql记录
类似与高级语言的结构体,需要注意的是,当引用pl/sql记录成员时,必须要加记录变量作为前缀(记录变量.记录成员)
如下:
declare
--定义一个pl/sql记录类型是:emp_record_type,类型包括三个数据name,salary,title;该类型中可以存放三个类型的数据;
type emp_record_type is record(name emp.ename%type,salary emp.sal%type,title emp.job%type);
--定义了一个sp_record变量,类型是emp_record_type
sp_record emp_record_type;
begin
select ename,sal,job into sp_record from emp where empno=7788;
dbms_output.put_line('员工名:'||sp_record.name); --显示定义emp_record_type类型中 name的值;
end;
end;
----------------
复合类型--pl/sql表
相当于高级语言中的数组。但是需要注意的是在高级语言中数组的下标不能为负数,而pl/sql是可以为负数的,并且表元素的下标没有限制。实例如下:
declare
--定义了一个pl/sql表类型sp_table_type,该类型是用于存放emp.ename%type类型的数组
--index by binary_integer标识下标是整数
type sp_table_type is table of emp.ename%type index by binary_integer;
--定义了一个sp_table变量,变量类型是sp_table_type
sp_table sp_table_type;
begin
--把查询出来的ename放到 table(0)下标为0的数据
select ename into sp_table(0) from emp where empno=7788;
dbms_output.put_lin('员工名:'||sp_table(0)); --要和存放下标一样
end;
说明:
sp_table_type 是pl/sql表类型
emp.ename%type 指定了表的元素的类型和长度
sp_table 为pl/sql表变量
sp_table(0) 表示下标为0的
---------------
参照变量
参照变量是指用于存放数值指针的变量。通过使用参照变量,可以使用得应用程序共享相同对象,从而降低占用的空间。在编写pl/sql程序时,可以使用游标变量和对象类型变量两种参照变量类型
游标变量用的最多
-----------
参照变量---游标变量
使用游标时,当定义游标时不需要指定相应的select语句,但是当使用游标时需要指定select语句,这样一个游标就与一个select语句结合了。
如下
1.请使用pl/sql编写一个块,可以输入部门号,并显示该部门所有员工姓名和他的工资。
declare
--定义游标类型
type sp_emp_cursor is ref cursor;
--定义一个游标变量
test_cursor sp_emp_cursor;
--定义变量
v_ename emp。ename%type;
v_sal emp。sal%type;
begin
--执行
--打开一个游标test_cursor和一个select结合
open test_cursor for select ename,sal from emp where deptno=&no;
--循环取出
loop
--fetch就是取出。取出test_cursor中的数据放到 v_ename,v_sal里面去;
fetch test_cursor into v_ename,v_sal;
--判断是否test_cursor为空
exit when test_cursor%notfound;
dbms_output.put_line('名字:'||v_ename||'工资:'||v_sal);
end loop;
end;
2.在1。基础上,如果某个员工的工资低于200元,就增加100元。
declare
--定义游标类型
type sp_emp_cursor is ref cursor;
--定义一个游标变量
test_cursor sp_emp_cursor;
--定义变量
v_ename emp。ename%type;
v_sal emp。sal%type;
begin
--执行
--打开一个游标test_cursor和一个select结合
open test_cursor for select ename,sal from emp where deptno=&no;
--循环取出
loop
--fetch就是取出。取出test_cursor中的数据放到 v_ename,v_sal里面去;
fetch test_cursor into v_ename,v_sal;
if v_sal<200 then
update emp set sal=sal+100 where ename=v_ename;
end if;
--判断是否test_cursor为空
exit when test_cursor%notfound;
dbms_output.put_line('名字:'||v_ename||'工资:'||v_sal);
end loop;
end;
----------
条件分支语句
if--then,
if--then--else,
if--then--elsif--else
----
循环语句
loop --end loop;至少会执行一次。
create or replace procedure sp_pro6() is
--定义赋值
v_num number:=1;
begin
loop
insert into users1 values(v_num,spName);
--判断是否要退出循环
exit when v_num=10;
--自增
v_num:=v_num+1;
end loop;
end;
-------------
循环语句-while先判断后执行
create or replace procedure sp_pro6() is
--定义赋值
v_num number:=11;
begin
while v_num<=20 loop
insert into users1 values(v_num,spName);
v_num:=v_num+1;
end loop;
end;
------------------
循环语句--for循环(不建议)
begin
for i in reverse 1。。10 loop
insert into users1 values(i,'aaa');
end loop;
end;
-------
循环语句--goto,null循环(不建议)
declare
i int:=1;
begin
loop
dbms_output.put_line('输出i='||i);
if i=10 then
goto end_loop;
end if;
i:=i+1;
end loop;
<<end_loop>> --到i到10后直接跳到该标记
dbms_output.put_line('循环结束');
end;
---------------------------
无返回值的存储过程(有输入参数)
create table book(
bookId number;
bookName varchar2(100);
publishHouse varchar2(50);
);
--编写过程
--in表示这是一个输入参数,不写默认是in
--out 表示一个输出参数
create or replace procedure sp_pro7(spBookId in number,spbookName in varchar2,sppublishHouse in varchar2) is
begin
insert into book values(spBookId,spbookName,sppublishHouse);
end;
---------------
有返回值的存储过程(有输入和输出参数)
create or replace procedure sp_pro8(ename in number,spName out varchar2) is
begin
--spName自动返回 因为他是out
select ename into spName from emp where empno=spno;
end;
----------------
有返回值是集合数组的存储过程(有输入和输出参数)
1.建立一个包
--创建包 里面定义一个游标类型;
create or replace package testpackage as
type test_cursor is ref cursor;
end testpackage;
2.建立存储过程。
create or replace procedure sp_pro8(spNo in number,p_cursor out testpackage.test_cursor) is
begin
--spName自动返回 因为他是out
open p_cursor for select * from emp where deptno=spNo;
end;
------------
oracle的分页 rn是别名
select t1.*,rownum rn from(select * from emp) t1;//多加一个列记录个数
select t1.*,rownum rn from(select * from emp) t1 where rownum<10;
select * from (select t1.*,rownum rn from(select * from emp) t1 where rownum<10) where rn>=6;
编写oracle的分页
--建立一个包
create or replace package testpackage as
type test_cursor is ref cursor;
end testpackage;
--建立存储过程
create or replace procedure fenye
(tableName in varchar2,
pageSize in number, --一页显示几条记录
pageNow in number, --显示哪一页
myrows out number, --总记录数
myPageCount out number,--总页数
p_cursor out testpackage.test_cursor --返回的记录集
) is
--定义部分
--定义sql语句 字符串
v_sql varchar2(1000);
--定义两个整数
v_begin number:=(pageNow-1)*pageSize+1;
v_end number:=pageNow*pageSize;
begin
--执行部分
v_sql:='select * from (select t1.*,rownum rn from(select * from '||tableName||') t1 where rownum<10'||?||') where rn>='||?||';';
--把游标和sql语句关联起来
open p_cursor for v_sql;
--计算myrows
v_sql:='select count(*) from '||tableName||'';
--执行sql,并把返回值,赋值给myrows;
execute immediate v_sql int myrows;
--计算myPagecount
if mod(myrows,pageSize)=0 then --mod()取余数
myPageCount:=myrows/pageSize;
else
myPageCount:=myrows/pagesize+1;
end if;
--关闭游标
--close p_cursor;
end;
------------------------
例外的分类
1.预定义例外用于处理常见的oracle错误
2.非预定义例外用于处理预定义例外不能处理的例外 6.53
3.自定义例外用于处理与oracle错误无关的其他情况
------------------------------------------------
-----------------------------------------------
-------JAVA中-调用无返回值的存储过程-----------------
try{
Class.forName();
Connection ct=DriverManager.getConnerction();
//调用无返回值存储过程
CallableStatement cs=ct.prepareCall("{call 存储过程名称(?,?,?)}") // ?代表存储过程参数
cs.setIn(1,10);
cs.setString(2,'java调用存储过程');
cs.setString(3,'人民出版社');
//执行
cs.execute();
}catch(Exception e)
{
e.printStackTrace();
}finally{
cs.close();
ct.close();
}
------------------------------------------------
-----------------------------------------------
------JAVA中--调用有回值的存储过程-----------------
try{
Class.forName();
Connection ct=DriverManager.getConnerction();
//调用有返回值存储过程
CallableStatement cs=ct.prepareCall("{call 存储过程名称(?,?)}") // ?代表存储过程参数 第一是输入,第二是输出
//第一个?输入参数
cs.setIn(1,10);
//给第二个?输出值赋值
cs.registerOutParameter(2,oracle.jdbc.OracleTypes.VARCHAR); //
//执行
cs.execute();
//取出返回值,
String name=cs。getString(2);
System.out。println("名称是:"+name);
}catch(Exception e)
{
e.printStackTrace();
}finally{
cs.close();
ct.close();
}
------------------------------------------------
-----------------------------------------------
-------JAVA中-调用有回值是多个 数组2011-12-5的存储过程-----------------
try{
Class.forName();
Connection ct=DriverManager.getConnerction();
//调用有返回值存储过程
CallableStatement cs=ct.prepareCall("{call 存储过程名称(?,?)}") // ?代表存储过程参数 第一是输入,第二是输出
//第一个?输入参数
cs.setIn(1,10);
//给第二个?输出值赋值
cs.registerOutParameter(2,oracle.jdbc.OracleTypes.cursor); //类型是cursor游标
//执行
cs.execute();
//取出返回值(结果集)
ReaultSet rs=(ResultSet)cs.getObject(2); //2是第二?
while(rs.next())
{
int =rs。getInt(1);
String name=rs。getString(2);
System.out。println("名称是:"+name);
}
}catch(Exception e)
{
e.printStackTrace();
}finally{
cs.close();
ct.close();
}
------------------------------------------------
-----------------------------------------------
------JAVA中--调用有回值的存储过程-----------------
try{
Class.forName();
Connection ct=DriverManager.getConnerction();
//调用有返回值存储过程
CallableStatement cs=ct.prepareCall("{call 存储过程名称(?,?)}") // ?代表存储过程参数 第一是输入,第二是输出
//第一个?输入参数
cs.setIn(1,10);
//给第二个?输出值赋值
cs.registerOutParameter(2,oracle.jdbc.OracleTypes.VARCHAR); //
//执行
cs.execute();
//取出返回值,
String name=cs。getString(2);
System.out。println("名称是:"+name);
}catch(Exception e)
{
e.printStackTrace();
}finally{
cs.close();
ct.close();
}
------------------------------------------------
-----------------------------------------------
-------JAVA中-测试分页调用存储过程-----------------
try{
Class.forName();
Connection ct=DriverManager.getConnerction();
//调用有返回值存储过程
CallableStatement cs=ct.prepareCall("{call 分页存储过程名称(?,?,?,?,?,?)}") // ?代表存储过程参数 第一是输入,第二是输出
//?输入参数
cs.setString(1,'表名'); //表名
cs.setInt(2,5); //一页显示几条记录
cs.setInt(3,1); //显示第几页
//?输出参数
//注册总记录数
cs.registerOutParameter(4,oracle.jdbc.OracleTypes.INTEGER);
//注册总页数
cs.registerOutParameter(4,oracle.jdbc.OracleTypes.INTEGER);
//注册返回的结果集
cs.registerOutParameter(4,oracle.jdbc.OracleTypes.CURSOR); //类型是cursor游标
//执行
cs.execute();
//取出总记录数
int rowNum=cs.getInt(4);//4表示参数中第四个?
//总页数
int pageCount=cs.getInt(5);
//返回的记录结果
ReaultSet rs=(ResultSet)cs.getObject(6);
while(rs.next())
{
int =rs。getInt(1);
String name=rs。getString(2);
System.out。println("名称是:"+name);
}
}catch(Exception e)
{
e.printStackTrace();
}finally{
cs.close();
ct.close();
}
A . 嵌套表
1. 声明数组类型
create or replace type tab_array is table of varchar2(38);暂时不要在包中声明该类型
2. 创建存储过程
-- 该例子存储过程是在包中创建的,包名 arraydemo
procedure testArray(resNumber in tab_array,procResult out tab_array) is
begin
procResult := new tab_array();
for i in 1..resNumber.Count loop
procResult.EXTEND;
procResult(i) := resNumber(i) || 'lucifer' || i;
end loop;
end;
3. Java调用代码
//必须使用Oracle的连接和Statement,使用了连接池的必须通过一些方法获取原始的连接
OracleConnection conn = null;
OracleCallableStatement stmt = null;
String[] param = { "1001", "1002", "1006" };
stmt =(转换类型) conn.prepareCall("{call arraydemo.testArray(?,?)}");
// 类型名必须大写
ArrayDescriptor descriptor = ArrayDescriptor.createDescriptor("TAB_ARRAY", conn);
stmt.setARRAY(1, new ARRAY(descriptor,conn,param));
stmt.registerOutParameter(2, OracleTypes.ARRAY, "TAB_ARRAY");
stmt.execute();
ARRAY array = stmt.getARRAY(2);
Datum[] data = array.getOracleArray();
for (int i = 0; i < data.length; i++) {
System.out.println(i + " : " + new String(data.shareBytes()));
}
4 . 注意的问题及尚未解决的问题
抛出:Non supported character set: oracle-character-set-852 异常---解决:添加 nls_charset12.jar 到classpath,该包在oracle/ora92/jdbc/lib目录下
待解决问题:
a) 如何调用在包声明的自定义类型
b) 比较不同声明类型的优缺点,及使用场合
嵌套表其它应用:http://zhouwf0726.itpub.net/post/9689/212253
B . 索引表
C . 内置数组
D . 游标方式
FCKEditor是一个很好的用于Web页面中的格式化文本编译控件。现在越来越多的论坛的发帖页面中更多的使用了这个控件,我们这里将如何在基于Java的web开发中使用FCKEditor控件的步骤提供给大家,为的是让更多的java开发者花费更少的时间去做重复劳动。
首先去下载FCKEditor2.6.3(当然本文编写的时候,这个是最新版本,也许你现在看到的已经是更新的版本了,那么可能某些配置办法已经变化了,本文也将跟进以保持最新动态,相反如果你使用的旧版本的控件,其配置和使用方法也有所区别),下载地址:http://www.fckeditor.net/download,我们需要下载两个文件
第一是FCKeditor_2.6.3.zip,就是FCKEditor的控件;
第二是FCKeditor.Java(fckeditor-java-2.4.1-bin.zip),就是在Java代码中使用FCKEditor的相关工具类;
有了这两个文件,使用FCKEditor的基础就具备了,接下来我们要做两件事情,一件事情就是要把FCKEditor控件放到web项目中,这个控件是用于网页的,所以其代码是使用JavaScript脚本编写的,需要和web网页一起被下载的浏览器上才能执行,第二件事情就是这个网页上的控件因为支持图片的上传与下载,所以在上传与下载的时候需要服务端的支持,那么我们我的java服务端如何支持这个控件的工作呢?FCKEditor自身提供了相关的java工具,就是我们下载的第二个文件。因此我们要做的第二件事情就是在服务端配置java工具,使得FCKEditor控件在处理上传图片时能够正确工作。
接下来我们就开始对配置FCKEditor控件进行两项工作:
第一:解压缩FCKeditor_2.6.3.zip,在其中我们能找到一个文件夹叫fckeditor,那么将这个文件夹整个复制到你的web应用的根目录下,就是存放jsp页面的地方。
第二:解压缩fckeditor-java-2.4.1-bin.zip,将这样几个jar文件复制到web应用的WEB-INF\lib目录中(commons-fileupload-1.2.1.jar,commons-io-1.3.2.jar,java-core-2.4.1.jar,slf4j-api-1.5.2.jar,slf4j-simple-1.5.2.jar),其中最后一个文件在这个zip包中可能不存在,那么你可以去这个链接地址下载一个文件叫fckeditor-java-2.4.1-bin.zip (下载地址:http://sourceforge.net/project/showfiles.php?group_id=75348&package_id=129511),在这个war文件中的lib中存在上述的5个jar文件,其实在war中也包含了FCKEditor控件的内容,也就是说如果你只是下载了war也可以了。然后在classpath目录中创建一个名叫为fckeditor.properties的文件,文件中放置一行内容为:connector.userActionImpl=net.fckeditor.requestcycle.impl.UserActionImpl,
在web.xml中添加一个Servlet的配置,配置内容如下:
<servlet>
<servlet>
<servlet-name>Connector</servlet-name>
<servlet-class>net.fckeditor.connector.ConnectorServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Connector</servlet-name>
<url-pattern>/fckeditor/editor/filemanager/connectors/*</url-pattern>
</servlet-mapping>
好了,现在你已经完成了配置的过程,接下来我们需要在jsp中使用FCKEditor控件了,在需要使用这个控件的jsp文件的开头添加标签库的引入语句:<%@ taglib uri="http://java.fckeditor.net" prefix="FCK" %>,在使用控件进行文本格式化输入的地方(原来你可能使用的textarea标签)使用如下的内容来替换原来的输入控件:
<FCK:editor instanceName="EditorDefault">
控件中要显示的初始内容
</FCK:editor>
其中instanceName属性的值就相当于form表单中的input的name值。就是表单提交时候的键值对中的键的名字。
web.xml中2.4版本的默认导入的standerd.jar,和jstl.jar是使用el表达式的包是启动的
而2.5版本的web.xml中默认是关闭的
所以在2.5的所有jsp中需要启动一下
用<% page isELIgnored="false"%>
el表达式不起作用 今天用el表达式,老是得不到后台传过来的值。该导入的jar包和标签库也都导入了。还是不起作用。后来在网上找到一篇文章。解决了。原来是版本的问题。现在贴一下。tomcat5.0的版本, 使用了低版本,只求稳定。web.xml<?xml version="1.0" encoding="ISO-8859-1"?><web-app 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" version="2.4">2.4版本默认启用el表达式,如果使用2.5版本,默认el表达式是关闭的<?xml version="1.0" encoding="UTF-8"?><web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.5" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">那么对应2.5的web.xml --> jsp页面里应该增加<%@ page isELIgnored="false"%>一句话,凡是部署描述文件遵循Servlet2.4规范的WEB应用,EL表达式的计算默认是启用的,而未遵循的,则EL表达式的计算默认是禁用的。所以解决方案还可以是:将web.xml中的DTD(文档类型定义)改问2.4的版本我用的是在公共页中加入<%@ page isELIgnored="false"%>,然后每个页面引入公共页。问题解决了。
今天演示EL表达式的时候发现自己jsp的基础实在是薄弱,在这个很简单的问题上迷惑了很久。
首先在看遇到的问题:
在浏览器地址输入,表示传入一个参数test,值为123
http://localhost:8888/Test/index.jsp?test=123
在index.jsp中尝试使用EL表达式取出,代码如下:
发现毫无结果,再使用requestScope尝试取出:
<body>
${requestScope.test}
</body>
发现还是毫无结果,感到非常诧异,遂干脆使用java脚本尝试取出。
<body>
<%request.getAttribute("test"); %>
</body>
依然无解。
之后发现,若使用已下代码向request作用域赋值,则用上面代码可以取出
<%
request.setAttribute("test", "123");
%>
查询资料后发现,使用以下代码可以取出之前的请求参数:
EL:
<body>
${param.test}
</body>
JAVA脚本:
<body>
<%=request.getParameter("test") %>
</body>
结论就是:${param.name} 等价于 request.getParamter("name"),这两种方法一般用于服务器从页面或者客户端获取的内容。
${requestScope.name} 等价于 request.getAttribute("name"),一般是从服务器传递结果到页面,在页面中取出服务器保存的值。
参考资料:
el表达式中的${param}
http://topic.csdn.net/u/20090103/15/779af9b8-c3a7-4f3e-82fe-b08bf2630996.html
今天演示EL表达式的时候发现自己jsp的基础实在是薄弱,在这个很简单的问题上迷惑了很久。
首先在看遇到的问题:
在浏览器地址输入,表示传入一个参数test,值为123
http://localhost:8888/Test/index.jsp?test=123
在index.jsp中尝试使用EL表达式取出,代码如下:
发现毫无结果,再使用requestScope尝试取出:
<body>
${requestScope.test}
</body>
发现还是毫无结果,感到非常诧异,遂干脆使用java脚本尝试取出。
<body>
<%request.getAttribute("test"); %>
</body>
依然无解。
之后发现,若使用已下代码向request作用域赋值,则用上面代码可以取出
<%
request.setAttribute("test", "123");
%>
查询资料后发现,使用以下代码可以取出之前的请求参数:
EL:
<body>
${param.test}
</body>
JAVA脚本:
<body>
<%=request.getParameter("test") %>
</body>
结论就是:${param.name} 等价于 request.getParamter("name"),这两种方法一般用于服务器从页面或者客户端获取的内容。
${requestScope.name} 等价于 request.getAttribute("name"),一般是从服务器传递结果到页面,在页面中取出服务器保存的值。
参考资料:
el表达式中的${param}
http://topic.csdn.net/u/20090103/15/779af9b8-c3a7-4f3e-82fe-b08bf2630996.html
JavaScript
<script type="text/javascript">
//<![CDATA[
//嵌入CDATA段可以防止不兼容Javacript的浏览器不产生错误信息
//增加正则表达式
String.prototype.getQueryString = function(name) {
var reg = new RegExp("(^|&|\\?)" + name + "=([^&]*)(&|$)"), r;
if (r = this.match(reg)) return unescape(r[2]);
return null;
};
var address = location.search.getQueryString("address"); //通过表达式获得传递参数
//针对两种浏览器,分别获取xmlDocument对象// 读取XML文件
function loadXML(xmlFile) {
var xmlDoc;
if (window.ActiveXObject) {
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = false;
xmlDoc.load(xmlFile);
}
else if (document.implementation && document.implementation.createDocument) {
xmlDoc = document.implementation.createDocument("", "", null);
xmlDoc.async = false;
xmlDoc.load(xmlFile);
} else {
alert('您的浏览器不支持该系统脚本!');
}
return xmlDoc;
}
//调用地图
var map; //全局GMap GOOGLE 地图 API
function load() {
if (GBrowserIsCompatible()) //检查浏览器兼容性
{
map = new GMap2(document.getElementById("map")); //地图加栽到ID为map的DIV中。
map.addControl(new GSmallMapControl()); //添加Gcontrol控件//放大缩小的那个
map.setCenter(new GLatLng(26.577014, 104.877977), 15); //设置地图中心
//创建多个坐标点(从INFO.XML文件中读取)
var xmlDoc = loadXML("Info.xml");
var members = xmlDoc.getElementsByTagName("number");
var maxRes = members.length;
for (var i = 0; i <= maxRes; i++) { //XML中记录了多个坐标点,要每个点都标记一下
var oName = members[i].getElementsByTagName("name");
var oLongitude = members[i].getElementsByTagName("Longitude");
var oLatitude = members[i].getElementsByTagName("Latitude");
var name = oName[0].firstChild.nodeValue
var Longitude = oLongitude[0].firstChild.nodeValue
var Latitude = oLatitude[0].firstChild.nodeValue
var marker = new GMarker(new GLatLng(Longitude, Latitude), { title: name }); //对每个点添加标记
marker.openInfoWindowHtml("<div style=line-height:20px;text-align:center;font-size:12px;'><a href=Left.aspx?info=" + name + " target=framLeft>" + name + ",点击查看信息</a></div>");
map.addOverlay(marker);
}
}
}
//]]>
</script>
XML文件
<?xml version="1.0" encoding="GB2312"?> <earth> <number id='1'> <name>213211212213213</name> <Longitude>26.577014</Longitude> <Latitude>104.877977</Latitude></number> <number id='2'> <name>112312332131212</name> <Longitude>26.586685</Longitude> <Latitude>104.863815</Latitude></number> <number id='3'> <name>123123121323112</name> <Longitude>26.572101</Longitude> <Latitude>104.866905</Latitude></number> <number id='4'> <name>123132123123321</name> <Longitude>26.572254</Longitude> <Latitude>104.891624</Latitude></number> </earth>
第一步是要创建一个可以远程连接的 MySQL 用户
mysql> GRANT ALL PRIVILEGES ON dbname.* TO 'user'@'%' IDENTIFIED BY 'userPWD' WITH GRANT OPTION;
mysql> flush privileges;
### "%"表示任意IP,如果要为特定的user指定从特定的IP访问,方法如下:
mysql> GRANT ALL PRIVILEGES ON dbname.* TO 'user'@'ip' IDENTIFIED BY 'userPWD' WITH GRANT OPTION;
mysql> flush privileges;
第二步是要修改 mysql 的配置文件 /etc/mysql/my.cnf
在旧版本中找到 skip-networking,把它注释掉就可以了
#skip-networking
在新版本中:
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
bind-address = 127.0.0.1
bind-address = 127.0.0.1 这一行要注释掉
#bind-address = 127.0.0.1
或者把允许访问的ip 填上
bind-address = 192.168.1.100
然后重启 MySQL
/etc/init.d/mysql restart
以上方法只完成了外网访问的配置,它只允许从主机上访问MYSQL,如果要完全从外网访问则需要将主机的3306端口映射到虚拟机的3306上(当然其它的端口也是可以的)
虚拟机端口映射:
http://wenku.baidu.com/view/b01c2ccca1c7aa00b52acb62.html###
这两天在搭建struts2+spring+hibernate框架的过程中遇到如题的错误,在百度和谷歌上查了两天,以致快到了崩溃的边缘。最后还是解决了。这个问题的出现,原因有很多,在这总结如下,以供分享:
框架搭建好后,启动服务器出现如下的信息:
log4j:WARN No appenders could be found for logger (org.apache.commons.digester.Digester).
log4j:WARN Please initialize the log4j system properly.
2009-11-6 21:39:17 org.apache.catalina.core.StandardContext start
严重: Error listenerStart
2009-11-6 21:39:17 org.apache.catalina.core.StandardContext start
严重: Context startup failed due to previous errors
2009-11-6 21:39:17 org.apache.catalina.core.StandardHostDeployer install
信息: Installing web application at context path /tomcat-docs from URL file:D:/server/Tomcat 5.0/webapps/tomcat-docs
2009-11-6 21:39:17 org.apache.catalina.core.StandardHostDeployer install
信息: Installing web application at context path /webdav from URL file:D:/server/Tomcat 5.0/webapps/webdav
。。。。
可能出错的地方:
1.web.xml文件 web应用部署描述符,里面的部署的xml文件或者类,如果这些找不到就会发生startup failed due to previous errors错误。
2.如果在应用spring的话,在配置文件applicationContext.xml中定义的类、xml文件找不到也会报这个错误。
3.在web.xml,struts.xml,applicationContext.xml文件中自身有任何一点错误都可能引起上面的这个问题,而不仅仅是附带的文件错误导致。
4.如果使用ibatis的话,在SqlMapConfig.xml中定义的xml文件找不到也会报这个错误。(hibernate的配置在整合spring的时候使用spring的配置文件)
5.JDK的版本问题,最好使用JDK5.0 或者更高的版本。
6.Eclipse和tomcat的版本兼容问题
7.框架整合的过程中在导入到lib下的jar包冲突也可能产生该错误。
8.jar包的缺少以及jar包的版本也可产生该错误。
9.其他的原因
解决该问题的途径:
由于上面问题可能已经是web服务器内部产生了错误,而且IDE中的Log信息较少,问题的解决很难入手。
而该问题的产生经常会导致页面跳转寻找不到文件的 Http 404 错误。。。。。
可以通过在tomcat中添加log文件来让log信息提示的更精确一些,即设置log输出的等级。
1.tomcat的安装路径下tomcat home下的common文件夹下的classes文件夹中创建log4j.properties文件,即
。。。Apache Software Foundation/Tomcat 5.5/common/classes
log4j.properties配置如下(配置是转载):
log4j.rootLogger=info,Console,R
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
#log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
log4j.appender.Console.layout.ConversionPattern=%d{yy-MM-dd HH:mm:ss} %5p %c{1}:%L - %m%n
log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.File=${catalina.home}/logs/tomcat.log
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d{yyyy.MM.dd HH:mm:ss} %5p %c{1}(%L):? %m%n
log4j.logger.org.apache=info,R
log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[localhost]=DEBUG, R
log4j.logger.org.apache.catalina.core=info,R
log4j.logger.org.apache.catalina.session=info,R
2.将log4j-1.2.15.jar和commons-logging.jar包拷贝到。。。Apache Software Foundation/Tomcat 5.5/common/lib下即可。
做好上面两步,启动服务器的时候,会在tomcat的安装路径下的。。Apache Software Foundation/Tomcat 5.5/logs下自动的
生成tomcat.log文件以记录日志信息。
注:tomcat.log文件中的日志信息会记载很多,如果过大就可能产生磁盘空间不足的问题,建议定时的清除日志信息。
通过上面的日志文件信息可以定位到比较具体的问题根源,在仔细的查看问题一一攻破即可解决。
我在搭建框架之后,在web.xml文件中配置的欢迎页面显示的时候报404的错误,通过上面的途径找到了两个错误,虽然花了两天的时间,最终还是解决了。
在hibernate2.0中hibernate.dialect的包路径是net.sf.hibernate.dialect.OracleDialect,
CREATE TABLE orders (
id number(11) NOT NULL ,
username varchar(22) NOT NULL ,
kind varchar(22) NOT NULL ,
phone varchar(11) DEFAULT '',
email varchar(22) DEFAULT '',
qq varchar(12) DEFAULT '',
name varchar(30) DEFAULT '',
address clob,
state varchar(30) DEFAULT '未处理',
time date DEFAULT '',
comname varchar(50) DEFAULT '',
comadd varchar(50) DEFAULT '',
PRIMARY KEY (id)
)
create sequence member_SEQ
minvalue 1
maxvalue 9999999
start with 21
increment by 1
cache 20;
CREATE OR REPLACE TRIGGER "member_trig"
BEFORE INSERT ON admin
REFERENCING OLD AS OLD NEW AS NEW FOR EACH ROW
DECLARE
BEGIN
SELECT member_seq.NEXTVAL INTO :NEW.ID FROM DUAL;
END member_trig;