Archive for the JAVA Category

Tomcat管理自定义的线程的关闭与启动

Monday, December 27th, 2010 | Permalink

如果希望在tomcat服务器启动时启动自己定义的线程如webgame的socket监听线程,关闭tomcat服务器是关闭这个线程。我们就需要自定一个Servlet或者是Listener来管理自己的线程。
管理的方式主要是在Servlet的init方法中启动自定义的线程,而在destroy方法中进行关闭。
如果使用Listener来管理的话就需要分别在contextInitialized与contextDestroyed方法中来处理自定义线程的启动与关闭。
下面我们通过具体代码来讲解具体的应用,我的demo使用的是Listener方式管理。
1.自定义一个Listener类。

public class ServerSocketListener implements ServletContextListener {
private ServerMain s;

public void contextInitialized(ServletContextEvent event) {
s = new ServerMain();
s.startServer();
}
//tomcat关闭时,关闭线程,释放端口
public void contextDestroyed(ServletContextEvent event) {
s.stopServer();//停止线程
System.exit(0);//关闭当前的jvm
}
}

2.在web.xml中配置这个监听。

Socket服务随web启动而启动
com.eunut.servlet.ServerSocketListener


就这样就可以通过tomcat的启动与关闭来控制你自定的线程随着应用服务器的操作味儿关闭或启动。

Flex+Java以AMF通讯方式截屏并保存到服务端的实例

Monday, November 22nd, 2010 | Permalink

今天闲着的时候研究了一下直接将flex中生成的报表转化成成图片直接通二进制流的方式传到服务端然后保存。

经过研究发现和简单。。。不罗嗦上代码。。。。
这个Demo使用了BlazeDS,有需要的朋友可以自己搭建环境,也可联系我索要工程。
Flex:

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml”
layout=”vertical” backgroundGradientAlphas=”[1.0, 1.0]”
backgroundGradientColors=”[#FFFFFF, #C0C0C0]”
width=”700″ height=”650″ fontSize=”14″>
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.rpc.events.ResultEvent;
import mx.core.Application;
import flash.display.BitmapData;
import mx.graphics.codec.JPEGEncoder;
import mx.graphics.codec.PNGEncoder;
import mx.collections.ArrayCollection;
import mx.core.UIComponent;
//将要保存的文件格式
public static const FORMAT_JPEG:uint = 0x00;
public static const FORMAT_PNG:uint = 0x01;
//文件扩展名
private static const EXT_JPEG:String = “.jpg”;
private static const EXT_PNG:String = “.png”;
//图标的初始化数据
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:”Jan”, Profit:2000, Expenses:1500, Amount:450},
{Month:”Feb”, Profit:1000, Expenses:200, Amount:600},
{Month:”Mar”, Profit:1500, Expenses:500, Amount:300}
]);
//将图片按指定的格式保存
private function saveImage(comp:DisplayObject,format:uint):void{
//将可视组件转换为Bitmapdata
var bmpd:BitmapData = new BitmapData(comp.width,comp.height);
bmpd.draw(comp);
//图片最终的而二进制数组(Bytearray)
var imgByteArray:ByteArray;
//保存文件的扩展名
var ext:String;
//验证指定的保存格式,并按指定格式调用相应的编码器生成相应的二进制图片数组
switch(format){
case FORMAT_JPEG:
ext = EXT_JPEG;
var jpgenc:JPEGEncoder = new JPEGEncoder(80);
imgByteArray = jpgenc.encode(bmpd);
break;
case FORMAT_PNG:
ext = EXT_PNG;
var pngenc:PNGEncoder = new PNGEncoder();
imgByteArray = pngenc.encode(bmpd);
break;
}
server.saveIMG(imgByteArray,getNowTimestamp()+ext);
}
//获取一个时间戳作为保存图片的名字
private function getNowTimestamp():String{
var d:Date = new Date();
var tstamp:String = d.getFullYear().toString()+d.getMonth()+d.getDate()+d.getHours()+d.getMinutes()+d.getSeconds()+d.getMilliseconds();
return tstamp;
}
//点击保存按钮时的处理方法
private function onClickSave(e:MouseEvent):void{
saveImage(myChart,FORMAT_PNG);
}
private function onResultHandler(event:ResultEvent):void{
Alert.show(event.result.toString());
}
]]>
</mx:Script>
<mx:RemoteObject id=”server” destination=”saveIMG” result=”onResultHandler(event)” endpoint=”http://localhost/Demo/messagebroker/amf”/>
<mx:Label text=”Save a chart snapshot” color=”#171717″ fontSize=”20″ fontWeight=”bold”/>
<mx:Panel title=”Line Chart”>
<mx:LineChart id=”myChart”
dataProvider=”{expenses}”
showDataTips=”true”>
<mx:horizontalAxis>
<mx:CategoryAxis
dataProvider=”{expenses}”
categoryField=”Month” />
</mx:horizontalAxis>
<mx:series>
<mx:LineSeries
yField=”Profit”
displayName=”Profit” />
<mx:LineSeries
yField=”Expenses”
displayName=”Expenses” />
</mx:series>
</mx:LineChart>
<mx:Legend dataProvider=”{myChart}”/>
</mx:Panel>
<mx:Button id=”save_btn” label=”Click to save a snapshot” width=”181″ click=”onClickSave(event)”/>
</mx:Application>

<?xml version=”1.0″ encoding=”utf-8″?><mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml”  layout=”vertical” backgroundGradientAlphas=”[1.0, 1.0]”  backgroundGradientColors=”[#FFFFFF, #C0C0C0]” width=”700″ height=”650″ fontSize=”14″> <mx:Script> <![CDATA[ import mx.controls.Alert; import mx.rpc.events.ResultEvent; import mx.core.Application; import flash.display.BitmapData; import mx.graphics.codec.JPEGEncoder; import mx.graphics.codec.PNGEncoder; import mx.collections.ArrayCollection; import mx.core.UIComponent; //将要保存的文件格式 public static const FORMAT_JPEG:uint = 0x00; public static const FORMAT_PNG:uint = 0x01; //文件扩展名 private static const EXT_JPEG:String = “.jpg”; private static const EXT_PNG:String = “.png”; //图标的初始化数据 [Bindable] public var expenses:ArrayCollection = new ArrayCollection([ {Month:”Jan”, Profit:2000, Expenses:1500, Amount:450}, {Month:”Feb”, Profit:1000, Expenses:200, Amount:600}, {Month:”Mar”, Profit:1500, Expenses:500, Amount:300} ]); //将图片按指定的格式保存 private function saveImage(comp:DisplayObject,format:uint):void{ //将可视组件转换为Bitmapdata var bmpd:BitmapData = new BitmapData(comp.width,comp.height); bmpd.draw(comp); //图片最终的而二进制数组(Bytearray) var imgByteArray:ByteArray; //保存文件的扩展名 var ext:String; //验证指定的保存格式,并按指定格式调用相应的编码器生成相应的二进制图片数组 switch(format){ case FORMAT_JPEG: ext = EXT_JPEG; var jpgenc:JPEGEncoder = new JPEGEncoder(80); imgByteArray = jpgenc.encode(bmpd); break; case FORMAT_PNG: ext = EXT_PNG; var pngenc:PNGEncoder = new PNGEncoder(); imgByteArray = pngenc.encode(bmpd); break; } server.saveIMG(imgByteArray,getNowTimestamp()+ext); } //获取一个时间戳作为保存图片的名字 private function getNowTimestamp():String{ var d:Date = new Date(); var tstamp:String = d.getFullYear().toString()+d.getMonth()+d.getDate()+d.getHours()+d.getMinutes()+d.getSeconds()+d.getMilliseconds(); return tstamp; } //点击保存按钮时的处理方法 private function onClickSave(e:MouseEvent):void{ saveImage(myChart,FORMAT_PNG); } private function onResultHandler(event:ResultEvent):void{ Alert.show(event.result.toString()); } ]]> </mx:Script> <mx:RemoteObject id=”server” destination=”saveIMG” result=”onResultHandler(event)” endpoint=”http://localhost/Demo/messagebroker/amf”/> <mx:Label text=”Save a chart snapshot” color=”#171717″ fontSize=”20″ fontWeight=”bold”/> <mx:Panel title=”Line Chart”> <mx:LineChart id=”myChart”     dataProvider=”{expenses}”     showDataTips=”true”>    <mx:horizontalAxis>       <mx:CategoryAxis             dataProvider=”{expenses}”             categoryField=”Month” />    </mx:horizontalAxis>    <mx:series>       <mx:LineSeries             yField=”Profit”             displayName=”Profit” />       <mx:LineSeries             yField=”Expenses”             displayName=”Expenses” />    </mx:series> </mx:LineChart> <mx:Legend dataProvider=”{myChart}”/> </mx:Panel> <mx:Button id=”save_btn” label=”Click to save a snapshot” width=”181″ click=”onClickSave(event)”/></mx:Application>

Java:

package com.eunut.demo;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class IMGServer {

public String saveIMG(byte [] io,String fileName){
BASE64Encoder encode = new BASE64Encoder();
String base64 = encode.encode(io);
if(generateImage(base64, "D:\\"+fileName))
return "图片保存成功!";
else
return "图片保存失败,请重新保存!";
}
// 将图片文件转化为字节数组字符串,并对其进行Base64编码处理
public static String GetImageStr(String imgFilePath) {
byte[] data = null;
// 读取图片字节数组
try {
InputStream in = new FileInputStream(imgFilePath);
data = new byte[in.available()];
in.read(data);
in.close();
} catch (IOException e) {
e.printStackTrace();
}
// 对字节数组Base64编码
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(data);// 返回Base64编码过的字节数组字符串
}

// 对字节数组字符串进行Base64解码并生成图片
public static boolean generateImage(String imgStr, String imgFilePath) {
if (imgStr == null) // 图像数据为空
return false;
BASE64Decoder decoder = new BASE64Decoder();
try {
// Base64解码
byte[] bytes = decoder.decodeBuffer(imgStr);

for (int i = 0; i < bytes.length; ++i) {
if (bytes[i] < 0) {// 调整异常数据
bytes[i] += 256;
}
}

// 生成图片
OutputStream out = new FileOutputStream(imgFilePath);
out.write(bytes);
out.flush();
out.close();
return true;
} catch (Exception e) {
return false;
}
}
}

Mina+AMF3 解码粘包解决方法

Monday, November 22nd, 2010 | Permalink

废话少说上代码
AMF3Decoder.java

package com.eunut.server.filter;

import java.io.DataInputStream;
import java.util.zip.InflaterInputStream;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;

import com.eunut.server.vo.RequestMessage;

import flex.messaging.io.SerializationContext;
import flex.messaging.io.amf.Amf3Input;

public class AMF3Decoder extends CumulativeProtocolDecoder
{
private final SerializationContext context = new SerializationContext();
private Amf3Input amf3in;
public AMF3Decoder()
{
}

@Override
protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception
{
long sid = session.getId();
if(in.prefixedDataAvailable(4)){
amf3in = new Amf3Input(context);
// 正常读取包头制定长度数据
int len = in.getInt();
Object message = null;
byte bytes[] = new byte[len];
in.get(bytes, 0, len);
IoBuffer tempIn = IoBuffer.wrap(bytes);
try {
amf3in.setInputStream(new InflaterInputStream(new DataInputStream(tempIn.asInputStream())));
message = amf3in.readObject();
if (message != null && (message instanceof RequestMessage)) {
out.write(message);
amf3in.close();
amf3in = null;
} else {
System.out.println(sid+":不是amf3 RequestMessage 跳出");
}
} catch (Exception e) {
System.out.println(sid+":AMF3Decoder doDecode Exception:" + e);
return false;
}finally{
tempIn.free();
tempIn = null;
bytes = null;
}
return true;
}else{
System.err.println("又粘包了!");
return false;
}
}
}

在tomcat下开发Red5应用

Monday, May 10th, 2010 | Permalink

客户端和服务器端的方法相互调用比较重要,在线列表基本上全是用这种方式实现的,当然也有使用RemoteSharedObject来实现的,但本人不太喜欢用RemoteSharedObject,只是用RemoteSharedObject来进行广播等操作。

1.编辑第二篇(抛弃LCDS和FMS,在tomcat下开发Red5应用(第二篇)-建立新的Red5应用)中的Application.java:

Java代码

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
package red5.example.red5server;
 
import org.red5.server.adapter.ApplicationAdapter;
import org.red5.server.api.IConnection;
import org.red5.server.api.Red5;
import org.red5.server.api.service.IServiceCapableConnection;
 
public class Application extends ApplicationAdapter {
 
	private String userName;
 
	//客户端调用的方法
	public String callFromClient(String userName) {
		this.userName = userName;
		callClient();
		return "Hello:"+userName;
	}
 
	//服务器端调用客户端的方法
	public void callClient() {
		IConnection conn=Red5.getConnectionLocal();
		if (conn instanceof IServiceCapableConnection) {
			IServiceCapableConnection sc = (IServiceCapableConnection) conn;
	        sc.invoke("callFromServer", new Object[]{"hi,"+userName+" this message from server"});
		}
	}
}

PS:记得将编译好的class文件放入webapps\ROOT\WEB-INF\classes。

2.编辑第二篇(抛弃LCDS和FMS,在tomcat下开发Red5应用(第二篇)-建立新的Red5应用)中的red5client001.mxml:

Xml代码

1.
2.
3.    
4.        
44.    
45.

将编译好的swf拷贝到webapps\red5Server目录下。

3.重新启动tomcat 运行浏览器,在地址栏输入http://localhost:8080/red5Server/red5client001.html 看到弹出窗口了吧。

客户端和服务器端方法相互调用就这么简单,实际上原有的基于FMS开发的Flex客户端代码修改量是非常小的。在下一篇将讲解客户端和服务器端方法调用中的参数传递。

SWT学习站点

Monday, May 10th, 2010 | Permalink

http://www.java2s.com/CN/Code/Java/SWT-JFace-Eclipse/Droppeddatatypedependsontargetitemintable.htm

http://www.java2s.com/CN/Code/Java/SWT-JFace-Eclipse/AfacadeforthesaveFileDialog.htm

swt 打印http://www.jb51.net/article/18829.htm

struts2的s:iterator标签详解

Saturday, May 8th, 2010 | Permalink

struts2的s:iterator 可以遍历 数据栈里面的任何数组,集合等等 以下几个简单的demo:
s:iterator 标签有3个属性:
value:被迭代的集合
id :指定集合里面的元素的id
status 迭代元素的索引

1:jsp页面定义元素写法 数组或list


A

打印结果为: 1A2A3A4A5A
2:索引的用法
如果指定了status,每次的迭代数据都有IteratorStatus的实例,它有以下几个方法
int getCount()返回当前迭代了几个元素
int getIndex()返回当前元素索引
boolean isEven()当然的索引是否偶数
boolean isFirst()当前是否第一个元素
boolean isLast()
boolean isOdd()当前元素索引是否奇数


现在的索引是奇数为:

当前元素值:

3:遍历map
value可以直接定义为:
value=”#{“1″:”a”,”2″:”b”}”
每个元素以都好隔开。元素之间的key和value 冒号隔开
value也可以是数据栈里面的java.util.Map对象
遍历写法如下:

key :
value:

当然key 和value 都可以使java 的 Object
3:遍历数据栈.简单的List类,
List
class Attr{String attrName;String getAttrName(){return “123”;}}



当然value 还可以写成 value=”%{label}” label可以有.操作
label的属性List 可以写成value=”%{label.list}” 相当于:getLabel().getList();
4:遍历2个list;
List attrN {color,size,style}
List attrV {red,20,gay}
这2个list的元素是一一对应的,一个attrN对应一个attrV

index is :
attrName is : or
attrName is :

原文来自:http://blog.sina.com.cn/s/blog_49d3ec2f0100hagw.html

  • You are currently browsing the archives for the JAVA category.