Applet 数字签名技术全然攻略

 

在这里先对大家说声对不起,毕竟2年前就想写这篇文章,但由于自己太懒惰一直没有写,也是为了给自己留点东西好了,前些日子我老大让我又搞这个东西发现我曾经的资料没留,又凭着自己印象从新来过,但发现网上写的东西真的有些肤浅,实在说只是去,毕竟我们是程序猿,不是学生了,怎么也点多想些东西哦,于是将自己总结的东西写下来,留给刚開始学习的人一些启发好了,通过学习一下内容您将具备通过server全然訪问本地client的能力,不在受不论什么权限的困扰,(非常多文章都写须要改 client本地的策略文件,事实上根本不是必需,仅仅要client点了俺们的数字签名,俺们可就什么都能干了) ~oo~

简单说下 Applet 数字签名是怎么回事: 就是applet 利用 jdk 里的 工具   $JAVA_HOME/bin 以下的 一堆 exe 文件进行 server訪问本地client的安全签名。假设想让客户真的信任你的applet签名,能够花几百大元去 CA 旗下的 versign 公司购买可信任的 签名证书。

本文主要以Tomcat为中间件,讲述详细签名步骤,当中 $JAVA_HOME 为 jdk 的安装文件夹、$TOMCAT_HOME为 Tomcat 的安装文件夹

实现Applet的签名过程例如以下:

1. 设定环境变量   $JAVA_HOME (方便在windows 系统下的不论什么一个文件夹都能够直接 使用     $JAVA_HOME/bin 下的 exe 命令,当中的exe 包含 keytool.exe,jarsigner.exe和HtmlConverter.exe )。

2. 将 $TOMCAT_HOME 下 webapps 文件夹的ROOT文件夹拷贝一份,删除没实用的垃圾东西改成自己的web应用名字。比如 : webapplet  将须要签名的jar 复制到 $TOMCAT_HOME/webapps/webapplet  下,在这里须要 注意一点:签名jar 包 就要对 整个 project 引用涉及到的 jar 包都进行签名,否则少签一个你都执行不起来的!

3. 建立一个測试的html页面 applet.html

<APPLET
CODEBASE = "."
CODE = "com.aspire.reportPlatform.webagent.WebAgentApplet.class"
ARCHIVE ="applet.jar"
NAME = "TestApplet"
WIDTH = 400
HEIGHT = 300
HSPACE = 0
VSPACE = 0
ALIGN = middle

</APPLET>

4.  打开 cmd 命令提示符,在$TOMCAT_HOME/webapps/webapplet  下执行 HtmlConverter

比如:  F:/appletTomcat/webapps/webapplet>HtmlConverter

弹出个窗体,在窗体中输入须要转换的 html文件 比如我刚才写的applet.html,转换完的东西 写jsp 也相同适用的。

转换完例如以下所看到的 :

<!--"CONVERTED_APPLET"-->
<!-- HTML CONVERTER -->
<object
    classid = "clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
    codebase = "http://java.sun.com/update/1.5.0/jinstall-1_5-windows-i586.cab#Version=5,0,0,1"
    WIDTH = 400 HEIGHT = 300 NAME = "TestApplet" ALIGN = middle VSPACE = 0 HSPACE = 0 >
    <PARAM NAME = CODE VALUE = "com.aspire.reportPlatform.webagent.WebAgentApplet.class" >
    <PARAM NAME = CODEBASE VALUE = "." >
    <PARAM NAME = ARCHIVE VALUE = "applet.jar,commons-codec-1.3.jar,commons-httpclient-3.1.jar,commons-logging.jar,dom4j.jar,FlowMetaData.jar,ibatis-2.3.2.715.jar,jgraph.jar,log4j-1.2.9.jar,MetaDataManage.jar,ojdbc14.jar,RDPCommon.jar,swing-layout-1.0.jar,ws-commons-util-1.0.1.jar,xmlrpc-client-3.1.jar,xmlrpc-common-3.1.jar" >
    <PARAM NAME = NAME VALUE = "TestApplet" >
    <param name = "type" value = "application/x-java-applet;version=1.5">
    <param name = "scriptable" value = "false">

<comment>
 <embed
            type = "application/x-java-applet;version=1.5" /
            CODE = "com.aspire.reportPlatform.webagent.WebAgentApplet.class" /
            JAVA_CODEBASE = "." /
            ARCHIVE = "applet.jar" /
            NAME = "TestApplet" /
            WIDTH = 400 /
            HEIGHT = 300 /
            ALIGN = middle /
            VSPACE = 0 /
            HSPACE = 0
     scriptable = false
     pluginspage = "http://java.sun.com/products/plugin/index.html#download">
     <noembed>
           
            </noembed>
 </embed>
    </comment>
</object>

<!--
<APPLET CODE = "com.aspire.reportPlatform.webagent.WebAgentApplet.class" JAVA_CODEBASE = "." ARCHIVE = "applet.jar" WIDTH = 400 HEIGHT = 300 NAME = "TestApplet" ALIGN = middle VSPACE = 0 HSPACE = 0>

</APPLET>
-->
<!--"END_CONVERTED_APPLET"-->

这里须要注意一个东西,上面有写 <PARAM NAME = ARCHIVE VALUE = "applet.jar..  那块,正常转换完了 仅仅会写到 applet.jar , 后面是我直接把 applet 须要引用的 jar 包直接加上去的,再次反复提醒 : 在这里也要把 须要签名关联的全部jar 包都写上去,否则前功尽弃!

6. 为了省事自己写个bat文件玩,来进行签名,比如我写的 applet.bat

内容例如以下:

keytool -genkey -keystore pepper.store -alias pepper
keytool -export -keystore pepper.store -alias pepper -file pepper.cert
jarsigner -keystore pepper.store applet.jar pepper
jarsigner -keystore pepper.store commons-codec-1.3.jar pepper
jarsigner -keystore pepper.store commons-httpclient-3.1.jar pepper
jarsigner -keystore pepper.store commons-logging.jar pepper
jarsigner -keystore pepper.store dom4j.jar pepper
jarsigner -keystore pepper.store FlowMetaData.jar pepper
jarsigner -keystore pepper.store ibatis-2.3.2.715.jar pepper
jarsigner -keystore pepper.store jgraph.jar pepper
jarsigner -keystore pepper.store log4j-1.2.9.jar pepper
jarsigner -keystore pepper.store MetaDataManage.jar pepper
jarsigner -keystore pepper.store ojdbc14.jar pepper
jarsigner -keystore pepper.store RDPCommon.jar pepper
jarsigner -keystore pepper.store swing-layout-1.0.jar pepper
jarsigner -keystore pepper.store ws-commons-util-1.0.1.jar pepper
jarsigner -keystore pepper.store xmlrpc-client-3.1.jar pepper
jarsigner -keystore pepper.store xmlrpc-common-3.1.jar pepper

解说下 里面的意思 :

keytool -genkey -keystore pepper.store -alias pepper      #创建pepper.store 密钥库文件,这个密钥库的别名为  pepper

输入上面那段话后,会提示输入password jdk 默觉得  changeit ,这个password能够改动,怎样改动请到网上查下就好,我记不清列,但建议不改,由于有时由于改了password jdk1.4 会离奇的不好用。。。

password输完 ,就输入些相应的 一些签名信息,

F:/appletTomcat/webapps/applet>keytool -genkey -keystore pepper.store -alias pepper
输入keystorepassword:  changeit
您的名字与姓氏是什么?
  [Unknown]:  LEe
您的组织单位名称是什么?
  [Unknown]:  aspire
您的组织名称是什么?
  [Unknown]:  aspire
您所在的城市或区域名称是什么?
  [Unknown]:  sz
您所在的州或省份名称是什么?
  [Unknown]:  gd
该单位的两字母国家代码是什么
  [Unknown]:  cn
CN=LEe, OU=aspire, O=aspire, L=sz, ST=gd, C=cn 正确吗?
  [否]:  y

输入<pepper>的主password
        (假设和 keystore password同样,按回车):

输入password库导出证书的password,为了偷懒上面 那个 我直接 按 回车列。。。

keytool -export -keystore pepper.store -alias pepper -file pepper.cert   依据生成的密钥库导出 pepper.cert  证书,输入password changeit , 说一句 这块能够 输入 上步你自己设定 password库导出证书的password(假设不是 changeit)

jarsigner -keystore pepper.store applet.jar pepper 为  applet.jar  签名,输入 证书password  我这块能够写 changeit, 以下的 jar 包 都是反复输入这里不多说了,over !   写到大家应该能够玩自己的签名了,我还有个读取文件方面的经验: 那就是本来在 application 里写的好好的东西到了 applet 上就都不好用了,原因是applet 的载入机制就是 把 server上签名的jar 包都下载到 client的 暂时文件夹里,文名都给改了。。。  这个暂时文件夹比如我的 :  C:/Documents and Settings/x_lixin_a/Application Data/Sun/Java/Deployment/cache/javapi/v1.0/jar

所以我在搞读文件的东西都把 配置文件下载到了client本地,比例如以下载到

System.getProperty("java.io.tmpdir")    的文件夹以下,到这里去读就不会出问题列,日志有时也会出问题,建议直接写 ***.log ,这样在执行时会把 生成的日志文件 扔到桌面,事实上还是不提倡有日志,毕竟用户看见这个东西不爽。。。

顺便把俺写的 applet 让大家看看吧,

思路 : 1 .  将须要读取的 配置文件下载到本地。 2 .  执行 main 类,跑application 。 
測试 :  在  ie 中输入 http://localhost:8080/webapplet          看到有 applet 弹出一个框点击执行就成,顺便提一句: 查看错误能够注意下右下角任务栏出现的大茶壶图标,        执行applet 都会启动这个东西,点击右键看到有 打开主控制台的选项,点这个选项,弹出一个对话框,这个对话框        就能够查看你的 签名 哪里出问题了,用 System.out.println() 都能够打到这个控制台上,但建议先在本地的        Eclipse project里 执行通过在拿到上面试。   后记 :  写到这里大家应该都会知道怎么实现 applet 数字签名了,假设有什么疑问能够直接在 csdn抓我,或者发送邮件到   [email protected],  希望有log 日志那块配置 更好解决方式的一定要告诉我撒,互相交流下哇,认为我写的这篇文章还能够  朋友希望能帮我顶起来,希望一年以后我将不会在看到网上写的那篇垃圾文章(如今那篇文章写的哪都是,根本不能解决这个问题!)   ~oo~

代码例如以下:

package com.aspire.reportPlatform.webagent;

import java.applet.Applet;
import java.awt.Color;
import java.awt.Container;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import javax.swing.JApplet;

import com.aspire.rdp.flowdesinger.LogonDialog;

public class WebAgentApplet extends JApplet {

public static Applet m_runningApplet = null;

protected char m_osPrefix;

// private OctetSeqHolder resp = null;

private Container contentPane = null;

public static String agentID;

private static Long agentLongID;

// private static final String DLLFOLDERPATH= System.getProperty("user.dir")
// ;

// private static final String
// DLLFOLDERPATH=System.getProperty("java.home")+File.separator+"lib"+File.separator+"ext";

private static final String DLLFOLDERPATH = System.getProperty("java.home")
+ File.separator + "bin";

String TEMP_DIR = System.getProperty("java.io.tmpdir");

private int result = 1;

private int count = 0;

public static String certerIP = null;

private String nickname = null;

public static String serverFullAddress;

/**
* @throws java.lang.AbstractMethodError
*/
public void init() {

certerIP = getParameter("centerAddress");

certerIP = new String("192.168.168.111");

System.err.println("centerIP is" + certerIP);
System.out.println(" user.dir = "+ System.getProperty("user.dir"));
nickname = getParameter("nickname");
serverFullAddress = String.valueOf(getCodeBase());
m_osPrefix = System.getProperty("os.name").toLowerCase().charAt(0);
// installLibraries();

DirectoryVO directoryVOArray[] = createDirectories();

for(int i=0;i< directoryVOArray.length;i++) {
installConfigResources(directoryVOArray[i]);
}

drawPane();

LogonDialog logonDialog = new LogonDialog();
logonDialog.setVisible(true);

try {
// add(panel);
if (m_runningApplet != null) {
StatusPanel.getStatusPanelInstance().setStatus((byte) 11);
} else {
m_runningApplet = this;
// webAgent = new WebAgent();
// initializeCommunication(webAgent);
StatusPanel.getStatusPanelInstance()
.setStatus((byte) 11);
// if (result == 0) {
// StatusPanel.getStatusPanelInstance()
// .setStatus((byte) 0);
// } else {
// StatusPanel.getStatusPanelInstance()
// .setStatus((byte) 8);
// }
// heartbeatInfo = new HeartbeatInfo();
// new Thread(heartbeatInfo).start();
// webAgent.initialize(webAgent, this);
// sendHeartInfo();
}
} catch (Exception _ex) {
// LogFile.getInstance().print(0, "WebAgentApplet.init()",
// " Applet initial Failed !");
// _ex.printStackTrace();
StatusPanel.getStatusPanelInstance().setStatus((byte) 8);
_ex.printStackTrace();
// destroy();
}
}

private DirectoryVO[] createDirectories() {
DirectoryVO[] directoryVOArray = new DirectoryVO[3];
DirectoryVO directoryVO = new DirectoryVO();

String config = TEMP_DIR+"rdp";

File configFile=new File(config);
if(!configFile.exists()) {
configFile.mkdir();
}
String plugins = config + File.separator + "plugins";
File pluginsFile= new File(plugins);
if(!pluginsFile.exists()) {
pluginsFile.mkdir();
}
String email = plugins + File.separator + "email";
File emailFile= new File(email);
if(!emailFile.exists()) {
emailFile.mkdir();
}

directoryVO.setPathName(email);
directoryVO.setZipName("emailPlugins.zip");
directoryVOArray[0] = directoryVO;
String images = config + File.separator + "images";
File imagesFile = new File(images);
if(!imagesFile.exists()) {
imagesFile.mkdir();
}

String cfg = config + File.separator + "cfg";
File cfgFile = new File(cfg);
if(!cfgFile.exists()) {
cfgFile.mkdir();
}
DirectoryVO directoryVO1 = new DirectoryVO();
directoryVO1.setZipName("images.zip");
directoryVO1.setPathName(images);
directoryVOArray[1] = directoryVO1;

DirectoryVO directoryVO2 = new DirectoryVO();
directoryVO2.setZipName("cfg.zip");
directoryVO2.setPathName(cfg);
directoryVOArray[2] = directoryVO2;

return directoryVOArray;
}

private void installConfigResources(DirectoryVO directoryVO){
String archivePath = String.valueOf(getCodeBase()) + "native" + "/" + directoryVO.getZipName();
System.out.println(" archivePath = " + archivePath);
ZipInputStream zis = null;
ZipEntry entry = null;
URLConnection con = null;

try {
con = (new URL(archivePath)).openConnection();
con.setUseCaches(false);
con.connect();
zis = new ZipInputStream(con.getInputStream());
while ((entry = zis.getNextEntry()) != null){
installConfigResource(zis, entry.getName(),directoryVO.getPathName());
}
} catch (IOException ioe) {
StatusPanel.getStatusPanelInstance().setStatus((byte) 8);
ioe.printStackTrace();
// LogFile.getInstance().print(0,
// "WebAgentApplet.installLibraries()",
// "install have IOException ");
}catch(Exception e){
e.printStackTrace();
}finally {
con = null;
try {
zis.close();
} catch (IOException e) {
// TODO 自己主动生成 catch 块
e.printStackTrace();
}
}
}

private void installConfigResource(ZipInputStream archive, String configResourceName,String path){
BufferedOutputStream out = null;
byte buffer[] = new byte[1024];
int count = 0;
String configFullPathName = path + File.separator + configResourceName;

try {
out = new BufferedOutputStream(
new FileOutputStream(configFullPathName));
while ((count = archive.read(buffer)) > 0)
out.write(buffer, 0, count);
out.close();
} catch (IOException e) {

e.printStackTrace();
}catch(Exception e){
e.printStackTrace();
}finally{
try {
out.close();
} catch (IOException e1) {
// TODO 自己主动生成 catch 块
e1.printStackTrace();
}
}

}

public void drawPane() {
contentPane = getContentPane();
contentPane.setBackground(Color.white);
contentPane.add(StatusPanel.getStatusPanelInstance());
}

public void destroy() {

try {
if (m_runningApplet == this) {
// webAgent.testManagerModule.close();
// StatusControl.getStatusControlInstance().notifyToCenter(StatusControlModuleConstant.AGENT_DOWN_SUCCESS,agentLongID);
// appletCommunicateModule.stop();

}
} catch (Exception e) {
// LogFile.getInstance().print(0, "WebAgentApplet.destroy()",
// "UnknownHostException : cannot destory applet ");

e.printStackTrace();
} finally {
System.exit(0);
System.err.println("in applet close !!!!");
}

}

private void installLibraries() {

String archivePath = String.valueOf(getCodeBase()) + "native";
System.err.println(getCodeBase());
ZipInputStream zis = null;
ZipEntry entry = null;
URLConnection con = null;
String archiveName;
switch (m_osPrefix) {
case 119: // &apos;w&apos;
archiveName = "winLib.zip";
break;

case 108: // &apos;l&apos;
archiveName = "linuxLib.zip";
break;

case 115: // &apos;s&apos;
archiveName = "solarisLib.zip";
break;

default:
archiveName = "winLib.zip";
break;
}
try {
con = (new URL(archivePath + "/" + archiveName)).openConnection();
con.setUseCaches(false);
con.connect();
zis = new ZipInputStream(con.getInputStream());
while ((entry = zis.getNextEntry()) != null){
installLibrary(zis, entry.getName());
}
} catch (IOException ioe) {
StatusPanel.getStatusPanelInstance().setStatus((byte) 8);
ioe.printStackTrace();
// LogFile.getInstance().print(0,
// "WebAgentApplet.installLibraries()",
// "install have IOException ");
}catch(Exception e){
e.printStackTrace();
}finally {
con = null;
try {
zis.close();
} catch (IOException e) {
// TODO 自己主动生成 catch 块
e.printStackTrace();
}
}
}

private void installLibrary(ZipInputStream archive, String dllName) {
BufferedOutputStream out = null;
byte buffer[] = new byte[1024];
int count = 0;
String dllFullPathName = DLLFOLDERPATH + File.separator + dllName;
System.out.println(" dllFullPathName = " + dllFullPathName);
try {
out = new BufferedOutputStream(
new FileOutputStream(dllFullPathName));
while ((count = archive.read(buffer)) > 0)
out.write(buffer, 0, count);
out.close();
// if(m_osPrefix != &apos;w&apos;)
// CommandLineUtility.runCommand("chmod 0775 " + dllFullPathName);
} catch (IOException e) {

e.printStackTrace();
// LogFile.getInstance().print(0, "WebAgentApplet.installLibrary()",
// "install single Library failed ");

// exitDueToException(e, "copying a native library file into JRE
// directory");
}catch(Exception e){
e.printStackTrace();
}finally{
try {
out.close();
} catch (IOException e1) {
// TODO 自己主动生成 catch 块
e1.printStackTrace();
}
}
}

// private void installLogFile(){
// try {
// String
// logProperties=System.getProperty("java.home")+File.separator+"bin"+File.separator+"log4j.properties";
// File f=new File(logProperties);
// f.createNewFile();
// FileOutputStream fopt=new FileOutputStream(f);
// String firstParagraph=new String("##LOGGERS##/r/n#define a logger named
// SEAMISLogger/r/nlog4j.rootLogger=INFO,file/r/n/r/n");
// fopt.write(firstParagraph.getBytes());
// String senondParagraph=new String("##APPENDERS##/r/n#define an appender
// named file,which is set to be a
// RollingFileAppender/r/nlog4j.appender.file=org.apache.log4j.RollingFileAppender/r/n"+"log4j.appender.file.File="+System.getProperty("java.home")+File.separator+"bin"+File.separator+"agentlog.txt"+"/r/n/r/n");
// fopt.write(senondParagraph.getBytes());
// String thirdParagraph=new String("##LAYOUTS##/r/n#assign a SimpleLayout
// to file
// appender/r/nlog4j.appender.file.layout=org.apache.log4j.SimpleLayout/r/n");
// fopt.write(thirdParagraph.getBytes());
// fopt.close();
// } catch (FileNotFoundException e) {
// // TODO 自己主动生成 catch 块
// e.printStackTrace();
// } catch (IOException e) {
// // TODO 自己主动生成 catch 块
// e.printStackTrace();
// }
// }
}

时间: 2025-01-02 16:17:34

Applet 数字签名技术全然攻略的相关文章

Applet 数字签名技术完全攻略

  这里说声对不起大家.毕竟2几年前,我想写这篇文章,但因为他才懒得一直没有写.同时也给自己的东西好.前些日子我老大让我又搞这个东西发现我曾经的资料没留,又凭着自己印象从新来过.但发现网上写的东西真的有些肤浅,实在说只是去.毕竟我们是程序猿,不是学生了,怎么也点多想些东西哦,于是将自己总结的东西写下来,留给刚開始学习的人一些启发好了.通过学习一下内容您将具备通过server全然訪问本地client的能力.不在受不论什么权限的困扰,(非常多文章都写须要改 client本地的策略文件.事实上根本不是

程序猿技术练级攻略

伯乐人才网6月9日发表了<写给即将入行的程序猿的一封信>,翻译自<An open letter to those who want to start programming>.我的朋友(他在本站的id是Mailper)告诉我,他希望在酷壳上看到一篇更具操作性的文章. 由于他也是喜欢编程和技术的家伙.于是,我让他把他的一些学习Python和Web编程的一些点滴总结一下.于是他给我发来了一些他的心得和经历,我在把他的心得做了不多的增改,并依据我的经历添加了"进阶"一

技术人攻略访谈:开放制造的机器之心

本文首发于雷锋网,经作者本人推荐分享至InfoQ中文站.<技术人攻略访谈>系列将在InfoQ上开辟专栏,我们会定期挑选好的访谈在这里分享. <<<-------------  <_< 向左看 罗未@WRTnode,豌豆机器小组(WRTnode machine team)发起人.开源硬件领域的万千开发板中,WRTnode是一支新秀,这个体积娇小的板子跑着最新的Linux内核,天生强大的网络交互能力,加上功耗低.信价比高.计算能力强等一系列优势,在公开发售前,就被创客

北京簋街 美食全然攻略 + 簋街好吃的夜宵去处-----店铺介绍大全

作者:lihao102 为什么叫簋街? 簋街东起二环路东直门立交桥西端,西到交道口东大街东端.在这条全长1442米的东内大街上,沿街共同拥有各种商业店铺150多家,当中餐饮服务业100多家,约占东内大街所有店铺的60%以上.饭馆密度如此之大,全北京恐怕再也找不出第二条来了.至于簋街名字的由来,据说是来自老北京的“鬼市”.早年北京那些以贩卖杂货菜果为主的集市,后半夜开市,黎明即散,摊主以煤油灯取亮,远处看上去灯影憧憧,故名“鬼市”.另一种通常的说法是东直门内大街餐厅生意红火,因为来此宵夜的出租汽车

Moon.Orm3.8技术全攻略

Moon.ORM技术全攻略  一.绪论 本文主要是针对Moon.ORM的技术的讨论及其使用使用指导.如有其它疑问,请留言.本文主要针对Moon.ORM3.9版本,同时将会对4.0做一个技术预览.本文从实际出发解析Moon.ORM.(技术群:21696534)  二.Moon.ORM的特色及优势 ----但凡众多的智慧都是及其简单的,但不为人所知.这也是Moon.ORM的主要特色:大道至简. 1.高性能是Moon.ORM优势之一,也是我架构它的主要目的之一,如以前我说的那样,是为了弥补项目中遇到的

转载 程序员技术练级攻略

转载 程序员技术练级攻略 博客分类: 转载 本文转载自陈皓(http://coolshell.cn/articles/author/haoel) 博客: http://coolshell.cn/articles/4990.html 月光博客6月12日发表了<写给新手程序员的一封信>,翻译自<An open letter to those who want to start programming>,我的朋友(他在本站的id是Mailper)告诉我,他希望在酷壳上看到一篇更具操作性的

程序员技术练级攻略

以下全文来自http://coolshell.cn/articles/4990.html 前言 你是否觉得自己从学校毕业的时候只做过小玩具一样的程序?走入职场后哪怕没有什么经验也可以把以下这些课外练习走一遍(朋友的抱怨:学校课程总是从理论出发,作业项目都看不出有什么实际作用,不如从工作中的需求出发) 建议: 不要乱买书,不要乱追新技术新名词,基础的东西经过很长时间积累而且还会在未来至少10年通用. 回顾一下历史,看看历史上时间线上技术的发展,你才能明白明天会是什么样. 一定要动手,例子不管多么简

程序员技术练级攻略(经典)

前言 你是否觉得自己从学校毕业的时候只做过小玩具一样的程序?走入职场后哪怕没有什么经验也可以把以下这些课外练习走一遍(朋友的抱怨:学校课程总是从理论出发,作业项目都看不出有什么实际作用,不如从工作中的需求出发) 建议: 不要乱买书,不要乱追新技术新名词,基础的东西经过很长时间积累而且还会在未来至少10年通用. 回顾一下历史,看看历史上时间线上技术的发展,你才能明白明天会是什么样. 一定要动手,例子不管多么简单,建议至少自己手敲一遍看看是否理解了里头的细枝末节. 一定要学会思考,思考为什么要这样,

负载均衡技术全攻略

转自:http://www.blogjava.net/carter0618/archive/2007/10/16/153131.html 大量的负载均衡相关文档链接,在这里收集起来,以备后用 负载均衡技术 2005-08-20 shenghuafen 集群的负载均衡技术 2005-04-04 liumyong 使用负载均衡技术建设高负载的网络站点2004-08-22 johnathan 基于linux的负载均衡技术 2005-12-02 yhb72 web集群服务的负载均衡方案选择与实现 200