Posts Tagged ‘决方’

WEB页面多语言支持解决方案

星期二, 06月 3rd, 2008

首先建立语言档,在项目中加入.resx文件
例如:
message.zh-cn.resx ‘简体中文
message.zh-tw.resx ‘繁体中文
message.en ‘英文
…………..
=========================================
然后利用Name –Value 键值对 填入您要在页面上显示de语言
如:
name value
message.zh-cn.resx中:
res_loginbname 登陆名 :
message.zh-tw.resx中:
res_loginbname 登陸名 :
message.zh-cn.resx中:
res_loginbname Login Name :

=========================================
然后在Golbal.asax中加入多语言设定支持相关代码(浏览器需要支持Cookie)

‘=========================================
‘ Application_BeginRequest Event

‘ The Application_BeginRequest method is an ASP.NET event that executes
‘ on each web request into the portal application.

‘ The thread culture is set for each request using the language
‘ settings

‘=========================================
Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
Try
If Not Request.Cookies(”resource”) Is Nothing Or Request.Cookies(”resource”).Value = “” Then
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(Request.Cookies(”resource”).Value)
Else
Thread.CurrentThread.CurrentCulture = New CultureInfo(ConfigurationSettings.AppSettings(”DefaultCulture”))
End If
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture
Catch ex As Exception
Thread.CurrentThread.CurrentCulture = New CultureInfo(ConfigurationSettings.AppSettings(”DefaultCulture”))
End Try
End Sub ‘Application_BeginRequest

在Web.Config中加入如下相关代码,用于设定编码和默认语种,在Global.asax中有调用:

=========================================
<globalization requestEncoding=”utf-8″ responseEncoding=”utf-8″ />
<appSettings>
<add key=”DefaultCulture” value=”zh-cn” />
<!– zh-cn:簡體中文 zh-tw:繁體中文 en:英文 –>
</appSettings>

=========================================
页面相关代码中使用多语言支持:

Imports System.Resources

Public Class 类名
Inherits System.Web.UI.Page
Protected LocRM As ResourceManager = New ResourceManager(”项目文件名.message”, GetType(类名).Assembly)

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
lblLogin.Text = LocRM.GetString(”res_login”)
End Sub
End Class


=========================================

到这里多语言支持de工作就作完了,接下来自己去慢慢Key
message.zh-cn.resx ‘简体中文
message.zh-tw.resx ‘繁体中文
message.en ‘英文

这几个语言档吧

ASP.Net防止刷新自动触发事件的解决方案

星期二, 06月 3rd, 2008

  使用asp.net,在刷新页面de时候会自动触发服务器端de事件.举个简单de例子,如:一个注册页面,我填写完注册信息之后,如果按F5刷新之后,会自动触发到Button事件上,这样就造成了又注册了一次de麻烦.

  我先前de解决方案:用关键字查询,如有相同,则提示已有此用户.

  但是这种方案不能在没有表识de情况下使用,他会重新提交.鉴于此,我寻找了一种新de解决方案,很庆幸,在朋友de提点下,迸发了这样de解决方案,肯定有更好de解决方案,不吝赐教.

  解决思路:刷新时,捕捉KeyPress,让他触发其他无用de事件.

  1、捕捉F5事件deJavaScript

window.document.onkeydown = KeyStroke;
function KeyStroke()
{
var key = event.keyCode;
event.srcElement.releaseCapture();
if(key == 116)
{
document.getElementById(”Button1″).click();
event.keyCode=0;
event.returnValue=false;
}
}

  2、aspx页面放置一个Button

<asp:Button id=”Button1″ style=”Z-INDEX: 102; LEFT: 344px; POSITION: absolute; TOP: 408px; WIDTH: 0px;” runat=”server”
Text=”Button”></asp:Button>

  3、Button事件

private void Button1_Click(object sender, System.EventArgs e)
{
Response.Write( “You have pressed the key F5″);
}

  这个“舍车保帅”de方案,能解决刷新自动触发事件de解决方案这个小问题,如果谁有更好de方案,希望告诉我一声,不胜感激!

第一次用.net2.0 LOGIN登陆控件的困惑和解决方法

星期二, 06月 3rd, 2008

1、我没有真正de服务器,我只是租用了.net2.0 SQLserver空间,SQL数据库名是固定de.
2、空间提供商不可能给我设定数据源或给您aspnetdb数据库权限.
3、我没有服务器de \Windows\Microsoft.Net\Framework\v2.x\Config 权限.

已知上面三点,如果直接把本地测试好de项目传到服务器肯定会出错(因为他默认是调用\Windows\Microsoft.Net\Framework\v2.x\Config ),我认为好de解决方法是把aspnetdb数据库内容全部导入自己de远程SQL数据库后,再定义项目deweb.config数据库连接字符串.
web.config
<?xml version=”1.0″?>

<!–
注意: 除了手动编辑此文件以外,您还可以使用
Web 管理工具来配置应用程序de设置.可以使用 Visual Studio 中de
“网站”->“Asp.Net 配置”选项.
设置和注释de完整列表在
machine.config.comments 中,该文件通常位于
\Windows\Microsoft.Net\Framework\v2.x\Config 中
–>
<configuration xmlns=”http://schemas.microsoft.com/.NetConfiguration/v2.0“>
<connectionStrings>

<!–定义数据库连接–>
<add name=”DbName” connectionString=”Persist Security Info=False;server=127.0.0.1;database=aspnetdb;uid=sa;pwd=123;pooling=true”/>
</connectionStrings>
<appSettings>
</appSettings>

<system.web>

<!–
connectionStringName 数据库连接.这个要在web.config设置
enablePasswordRetrieval 获得一个值,指示当前成员资格提供程序是否配置为允许用户检索其密码.
enablePasswordReset 获得一个值,指示当前成员资格提供程序是否配置为允许用户重置其密码.
requiresQuestionAndAnswer 获取一个值,该值指示默认成员资格提供程序是否要求用户在进行密码重置和检索时回答密码提示问题.
applicationName 获取或设置应用程序de名称.
requiresUniqueEmail 指示用户在创建用户时是否必须提供唯一de电子邮件地址值.
passwordFormat 指示在成员资格数据存储区中存储密码de格式.下面有详细说明
maxInvalidPasswordAttempts 获取锁定成员资格用户前允许de无效密码或无效密码提示问题答案尝试次数.
minRequiredPasswordLength 获取密码所要求de最小长度.
minRequiredNonalphanumericCharacters 获取有效密码中必须包含de最少特殊字符数.
passwordAttemptWindow 获取在锁定成员资格用户之前允许de最大无效密码或无效密码提示问题答案尝试次数de分钟数.

对PasswordFormat de详细说明
属性指示存储密码de格式.密码可以采用 Clear、Encrypted 和 Hashed 密码格式存储.Clear 密码以明文形式存储,这可以提高存储和检索密码de性能,但安全性较差,当数据源安全性受到威胁时此类密码很容易被读取.Encrypted 密码在存储时进行了加密,可以在比较或检索密码时进行解密.此类密码在存储和检索时需要进行额外de处理,但比较安全,在数据源de安全性受到威胁时不容易被获取.Hashed 密码在存储到数据库时使用单向哈希算法和随机生成de salt 值进行哈希处理.在验证某一密码时,将用数据库中de salt 值对该密码进行哈希计算以进行验证.无法检索哈希密码.
–>


<roleManager enabled=”true” />
<membership>
<providers>
<remove name=”AspNetSqlMembershipProvider”/>
<add name=”AspNetSqlMembershipProvider”
type=” System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a”
connectionStringName=”DbName”
enablePasswordRetrieval=”false”
enablePasswordReset=”true”
requiresQuestionAndAnswer=”true”
applicationName=”/”
requiresUniqueEmail=”false”
passwordFormat=”Hashed”
maxInvalidPasswordAttempts=”5″
minRequiredPasswordLength=”6″
minRequiredNonalphanumericCharacters=”0″
passwordAttemptWindow=”10″
passwordStrengthRegularExpression=”" />
</providers>
</membership>


<!–
设置 compilation debug=”true” 可将调试符号插入
已编译de页面中.但由于这会
影响性能,因此只应在开发过程中设置
此值.

Visual Basic 选项:
设置 strict=”true” 将禁止所有会导致
数据丢失de类型转换.
设置 explicit=”true” 将强制声明所有变量.
–>
<compilation debug=”true” strict=”false” explicit=”true”/>
<pages>
<namespaces>
<clear/>
<add namespace=”System”/>
<add namespace=”System.Collections”/>
<add namespace=”System.Collections.Specialized”/>
<add namespace=”System.Configuration”/>
<add namespace=”System.Text”/>
<add namespace=”System.Text.RegularExpressions”/>
<add namespace=”System.Web”/>
<add namespace=”System.Web.Caching”/>
<add namespace=”System.Web.SessionState”/>
<add namespace=”System.Web.Security”/>
<add namespace=”System.Web.Profile”/>
<add namespace=”System.Web.UI”/>
<add namespace=”System.Web.UI.WebControls”/>
<add namespace=”System.Web.UI.WebControls.WebParts”/>
<add namespace=”System.Web.UI.HtmlControls”/>
</namespaces>
</pages>
<!–
通过 <authentication> 节可以配置 ASP.NET 使用de
安全身份验证模式,
以标识传入de用户.
–>
<authentication mode=”Forms” />
<!–
如果在执行请求de过程中出现未处理de错误,
则通过 <customErrors> 节可以配置相应de处理步骤.具体说来,
开发人员通过该节可以配置
要显示de html 错误页
以代替错误堆栈跟踪.

<customErrors mode=”RemoteOnly” defaultRedirect=”GenericErrorPage.htm”>
<error statusCode=”403″ redirect=”NoAccess.htm” />
<error statusCode=”404″ redirect=”FileNotFound.htm” />
</customErrors>
–>

</system.web>
</configuration>

注:membership节点de那个注释是转载de,忘了地址了.

ASP.NET 2005 Treeview终极解决方案

星期二, 06月 3rd, 2008

  这几天在写HRMde时候 这问题搞了我两天,开始在使用Google 找了半天都是一堆垃圾,都是使用算法de较多, 后来就去了demsdn.yesky.com 找到点启示. 好了废话多说无用.
  首先表结构如下 表名 Test
按此在新窗口浏览图片
  写个存储过程 GetTreeview
  这个不用我说了吧下面用到
  为了速度缓存DataTable
Public Function GetTreeTable() As DataTable
 Dim dt As New DataTable()
 dt = HttpContext.Current.Cache(”Treeview”)
 If dt Is Nothing Then
  Dim Conn As New SqlConnection
  Dim clsConnDatabase As New ConnectionDatabase
  Conn = clsConnDatabase.ConnDatabase
  Dim Command As New SqlCommand
  Command.Connection = Conn
  Command.CommandText = “GetTreeview”
  Command.CommandType = CommandType.StoredProcedure
  Command.ExecuteNonQuery()
  Dim da As New SqlDataAdapter(Command)
  dt = New DataTable()
  da.Fill(dt)
  HttpContext.Current.Cache.Insert(”Treeview”, dt)
 End If
 Return dt
End Function
  这里是主要阿
Public Sub PopulateNodes(ByVal nodes As TreeNodeCollection, Optional ByVal intParentID As Int32 = 0)
 Dim dt As New DataTable()
 dt = clsWebForms.GetTreeTable()
 Dim strExpression As String
 strExpression = “[parentID] = ” & intParentID
 Dim foundRows() As DataRow
 foundRows = dt.Select(strExpression)
 
 Dim I As Integer
 For I = 0 To foundRows.GetUpperBound(0)
  Dim tn As New TreeNode()
  tn.Text = foundRows(I).Item(“TableName”).ToString()
  tn.Value = foundRows(I).Item(”ID”).ToString()
  Dim dr() As DataRow
  dr = dt.Select(”[parentID] = ” & tn.Value)
  If dr.GetUpperBound(0) > -1 Then
   tn.PopulateOnDemand = True
  End If
  nodes.Add(tn)
 Next
End Sub
  建立WebForm 放入Treeview
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
     
 If Not Page.IsPostBack Then
  PopulateNodes(TreeView1.Nodes, 0)
 End If
End Sub
Protected Sub TreeView1_TreeNodePopulate(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.TreeNodeEventArgs) Handles TreeView1.TreeNodePopulate
 PopulateNodes(e.Node.ChildNodes, e.Node.Value)
End Sub
  至于速度我没测试,如果大家有兴趣帮忙测测.

用Java实现FTP服务器解决方案

星期一, 06月 2nd, 2008

FTP 命令

  FTP de主要操作都是基于各种命令基础之上de.常用de命令有:
  · 设置传输模式,它包括ASCⅡ(文本) 和BINARY 二进制模式;
  · 目录操作,改变或显示远程计算机de当前目录(cd、dir/ls 命令);
  · 连接操作,open命令用于建立同远程计算机de连接;close命令用于关闭连接;
  · 发送操作,put命令用于传送文件到远程计算机;mput 命令用于传送多个文件到远程计算机;
  · 获取操作,get命令用于接收一个文件;mget命令用于接收多个文件.
  编程思路

  根据FTP de工作原理,在主函数中建立一个服务器套接字端口,等待客户端请求,一旦客户端请求被接受,服务器程序就建立一个服务器分线程,处理客户端de命令.如果客户端需要和服务器端进行文件de传输,则建立一个新de套接字连接来完成文件de操作.
  编程技巧说明

  1.主函数设计
  在主函数中,完成服务器端口de侦听和服务线程de创建.我利用一个静态字符串变量initDir 来保存服务器线程运行时所在de工作目录.服务器de初始工作目录是由程序运行时用户输入de,缺省为C盘de根目录.
  具体de相关代码如下:
  public class ftpServer extends Thread{
  private Socket socketClient;
  private int counter;
  private static String initDir;
  public static void main(String[] args){
  if(args.length != 0) {
   initDir = args[0];
  }else{ initDir = “c:”;}
  int i = 1;
  try{
   System.out.println(”ftp server started!”);
   //监听21号端口
   ServerSocket s = new ServerSocket(21);
   for(;;){
    //接受客户端请求
    Socket incoming = s.accept();
    //创建服务线程
    new ftpServer(incoming,i).start();
    i ;
   }
  }catch(Exception e){}
  }
  2. 线程类de设计
  线程类de主要设计都是在run()方法中实现.用run()方法得到客户端de套接字信息,根据套接字得到输入流和输出流,向客户端发送欢迎信息.
  3. FTP 命令de处理
  (1) 访问控制命令
  · user name(user) 和 password (pass) 命令处理相关代码如下:
  if(str.startsWith(”USER”)){
  user = str.substring(4);
  user = user.trim();
  out.println(”331 Password”);
  }
  if(str.startsWith(”PASS”))
  out.println(”230 User ” user ” logged in.”);
  User 命令和 Password 命令分别用来提交客户端用户输入de用户名和口令.
  · CWD (CHANGE WORKING DIRECTORY) 命令处理相关代码如下:
  if(str.startsWith(”CWD”)){
  String str1 = str.substring(3);
  dir = dir “/” str1.trim();
  out.println(”250 CWD command succesful”);
  }
  该命令改变工作目录到用户指定de目录.
  · CDUP (CHANGE TO PARENT DIRECTORY) 命令处理相关代码如下:
  if(str.startsWith(”CDUP”)){
  int n = dir.lastIndexOf(”/”);
  dir = dir.substring(0,n);
  out.println(”250 CWD command succesful”);
  }
  该命令改变当前目录为上一层目录.
  · QUIT命令处理相关代码如下:
  if(str.startsWith(”QUIT”)) {
  out.println(”GOOD BYE”);
  done = true;
  }
  该命令退出及关闭与服务器de连接,输出GOOD BYE.
  (2) 传输参数命令
  · Port命令处理相关代码如下:
  if(str.startsWith(”PORT”)) {
  out.println(”200 PORT command successful”);
  int i = str.length() - 1;
  int j = str.lastIndexOf(”,”);
  int k = str.lastIndexOf(”,”,j-1);
  String str1,str2;
  str1=”";
  str2=”";
  for(int l=k 1;lstr1 = str2 str.charAt(l);
  }
  for(int l=j 1;l<=i;l ){
  str2 = str2 str.charAt(l);
  }
  tempPort = Integer.parseInt(str1) * 16 *16 Integer.parseInt(str2);
  }
  使用该命令时,客户端必须发送客户端用于接收数据de32位IP 地址和16位 deTCP 端口号.这些信息以8位为一组,使用十进制传输,中间用逗号隔开.
  · TYPE命令处理相关代码如下:
  if(str.startsWith(”TYPE”)){
  out.println(”200 type set”);
  }
  TYPE 命令用来完成类型设置.
  (3) FTP 服务命令
  · RETR (RETEIEVE) 和 STORE (STORE)命令处理de相关代码
  if(str.startsWith(”RETR”)){
  out.println(”150 Binary data connection”);
  str = str.substring(4);
  str = str.trim();
  RandomAccessFile outFile = new
  RandomAccessFile(dir “/” str,”r”);
  Socket tempSocket = new Socket(host,tempPort);
  OutputStream outSocket = tempSocket.getOutputStream();
  byte byteBuffer[]= new byte[1024];
  int amount;
  try{
  while((amount = outFile.read(byteBuffer)) != -1){
   outSocket.write(byteBuffer, 0, amount);
  }
  outSocket.close();
  out.println(”226 transfer complete”);
  outFile.close();
  tempSocket.close();
  }
  catch(IOException e){}
  }
  if(str.startsWith(”STOR”)){
  out.println(”150 Binary data connection”);
  str = str.substring(4);
  str = str.trim();
  RandomAccessFile inFile = new
  RandomAccessFile(dir “/” str,”rw”);
  Socket tempSocket = new Socket(host,tempPort);
  InputStream inSocket = tempSocket.getInputStream();
  byte byteBuffer[] = new byte[1024];
  int amount;
  try{
  while((amount =inSocket.read(byteBuffer) )!= -1){
  inFile.write(byteBuffer, 0, amount);
  }
  inSocket.close();
  out.println(”226 transfer complete”);
  inFile.close();
  tempSocket.close();
  }
  catch(IOException e){}
  }
  文件传输命令包括从服务器中获得文件RETR和向服务器中发送文件STOR,这两个命令de处理非常类似.处理RETR命令时,首先得到用户要获得de文件de名称,根据名称创建一个文件输入流,然后和客户端建立临时套接字连接,并得到一个输出流.随后,将文件输入流中de数据读出并借助于套接字输出流发送到客户端,传输完毕以后,关闭流和临时套接字.
  STOR 命令de处理也是同样de过程,只是方向正好相反.
  · DELE (DELETE)命令处理相关代码如下:
  if(str.startsWith(”DELE”)){
  str = str.substring(4);
  str = str.trim();
  File file = new File(dir,str);
  boolean del = file.delete();
  out.println(”250 delete command successful”);
  }
  DELE 命令用于删除服务器上de指定文件.
  · LIST命令处理相关代码如下:
  if(str.startsWith(”LIST”)) {
  try{
  out.println(”150 ASCII data”);
  Socket tempSocket = new Socket(host,tempPort);
  PrintWriter out2= new PrintWriter(tempSocket.getOutputStream(),true);
  File file = new File(dir);
  String[] dirStructure = new String[10];
  dirStructure= file.list();
  String strType=”";
  for(int i=0;iif( dirStructure[i].indexOf(”.”) == -1) { strType = “d “;}
   else
   {strType = “- “;}
   out2.println(strType dirStructure[i]);
  }
  tempSocket.close();
  out.println(”226 transfer complete”);
  }
  catch(IOException e){}
  LIST 命令用于向客户端返回服务器中工作目录下de目录结构,包括文件和目录de列表.处理这个命令时,先创建一个临时de套接字向客户端发送目录信息.这个套接字de目de端口号缺省为1,然后为当前工作目录创建File 对象,利用该对象delist()方法得到一个包含该目录下所有文件和子目录名称de字符串数组,然后根据名称中是否含有文件名中特有de“.”来区别目录和文件.最后,将得到de名称数组通过临时套接字发送到客户端.

困扰JSP的一些问题与解决方法

星期一, 06月 2nd, 2008

  如今每一个使用servletsde开发者都知道JSP,一种由Sun公司发明并花费大量精力加以推行并建构在servlet技术之上deweb技术.JSP将servlet中dehtml相关代码脱离了出来,从而可以加速web应用开发和页面维护.实际上,由Sun发布de官方”应用开发模型”文档上说得更远: “JSP技术应该被视为标准,而servlets在多数情况下可视为一种补充.” ( Section 1.9, 1999/12/15听取意见版 ).

  本文de目de在于听取对该申明de合理性de评估 — 通过比较JSP和另一项基于servletsde技术: template engines(模板引擎).

  直接使用Servletsde问题

  起初,servlets被发明,整个世界都看到了它de优越.基于servletde动态网页可以被快速执行,可以在多个服务器之间轻易转移, 并且可以和后台数据库完美地集成. Servlets被广泛接受成为一种web服务器端de首选平台.
但是,通常通过简单方式即可实现dehtml相关代码现在却要让程序员通过 out.println()调用每一行HTML行,这在实际de servlet应用中成为了一个严重问题. HTML内容不得不通过相关代码来实现, 对于大deHTML页来说不啻是一项繁重费时de工作.另外,负责网页内容de人员不得不请开发人员来进行所有de更新.为此,人们寻求这一种更好de解决方式.

  JSP到!

  JSP 0.90出现了.在这种技术中您可以将Java相关代码嵌入到HTML文件,服务器将自动为页面创建一个 servlet. JSP被认为是一种写servletde简易方式.所有HTML可以直接得到而不必通过out.println()调用,而负责页面内容de人员可以直接修改HTML而不必冒破坏Java相关代码de风险.
  但是,让页面美术设计师和开发人员在同一文件上工作并不理想,让Java嵌入HTML被证明是就象将HTML 嵌入Java一样令人尴尬.读取一堆很乱de相关代码仍然是一件困难de事情.

  于是,人们在使用jsp方面变得成熟,更多地使用了JavaBeans. Beans包含了jsp所需de业务逻缉相关代码.JSP中de大多数相关代码都可以取出来放到bean中去,而只留下极少de标记用于调用bean.

  最近,人们开始认为这种方式下deJSP页面真de很象是视图(view).它们成为一个用于显示客户端请求de结果de组件.于是人们会想,为什么不直接对view发送请求呢? 目标view如果对该请求不合适又将如何? 说到底,很多de请求有多种可能来取得结果view视图.例如,同一请求可能产生成功de页面,数据库例外出错报告,或者是缺少参数de出错报告.同一请求可能产生一个英文页面也可能是西班牙文页面,这取决于客户端delocale.为什么客户端必须直接将请求发送给view?为什么客户端不应该将请求发送给一些通用de服务器组件并让服务器来决定JSP viewde返回?

  这使很多人接受了已被称为”Model 2″de设计, 这是在JSP 0.92中定义de基于model-view-controllerde模型.在这种设计中,请求被发送到一个servlet控制器,它执行了商业逻缉并产生一个相近de数据”model”来用于显示.这一数据随后通过内部送到一个JSP “view”来进行显示,这样看起来JSP页就象是一个普通de嵌入deJavaBean. 可以根据负责控制deservletde内部逻辑来选择适当deJSP页面进行显示.这样,JSP文件成为了一个漂亮detemplate view.这就是另一种发展,并被另外一些开发者所推崇至今.

  进入Template Engines

  使用template engine来代替通常目dedeJSP, 接下去de设计将变得简单,语法更简单,出错信息更易读,工具也更用户化. 一些公司已经做了这样de引擎,最著名de可能是WebMacro (http://webmacro.org, from Semiotek),他们de引擎是免费de.
  开发者应该明了,选定一个template engine来取代JSP提供了这么一些技术优势,这也正是jspde一些不足之处:

  问题 #1: Java相关代码太模板化了

  虽然被认为是不好de设计,JSP仍试图将Java相关代码加入web页面.这有些象是Java曾经做de,即对C de简化修改,template engines也通过将jsp中de较低层de源码移去来使之简化.Template engines实行了更好de设计.

  问题 #2: 要求Java相关代码

  在JSP页中要求写一些Java相关代码.例如,假设某页要决定当前web应用中根de上下文从而导向其主页,
在JSP中最好使用如下Java相关代码:

  <a href=”<%= request.getContextPath() %>/index.html”>Home page</a>
 
  您可以试图避免 Java相关代码,而使用 <jsp:getProperty> 标记但这将给您六下难以阅读de字串:

  <a href=”<jsp:getProperty name=”request”
  property=”contextPath”/>/index.html”>HomePage</a>

  使用template engine则没有Java相关代码和难看de语法.这里是同样要求下在WebMacro中de写法:

  <a href=”$Request.ContextPath;/index.html”>Home page</a>

  在WebMacro中, ContextPath 作为 $Request变量de一个属性,使用类似Perlde语法.其它er template engines使用了其它de语法类型.
  
  再看另 一个例子,假设一个高级de”view”需要设定一个cookie来记录用户缺省de颜色配置 — 这种任务看起来大概只能由view而不是servlet控制器来完成.在JSP中要有这样deJava相关代码:

  <% Cookie c = new Cookie(”colorscheme”, “blue”); response.addCookie(c); %>

  在WebMacro中则没有Java相关代码:

  #set $Cookie.colorscheme = “blue”

  作为最后一个离子,假如又要重新找回原来decookie中de颜色配置.对于JSP,我可以认为也有一个相应de工具类来提供帮助,因为用getCookies()直接做这样低层de会变得可笑而且困难.在JSP中:

  <% String colorscheme = ServletUtils.getCookie(request, “colorscheme”); %>

  在WebMacro中没有对工具类de需要,通常是:$Cookie.colorscheme.Value .对写jspde图形艺术师,又是哪一种语法更容易学习呢?

  JSP 1.1 引入了自定义标记(custom tags)允许任意de和HTML相似de标记在JSP页面中在后台执行Java相关代码,这将具有一定de价值,但前提是要有一个广泛知晓de,全功能de,可以免费得到de,标准化de标记库.目前还没有出现这样de标记库.

  问题 #3: 简单工作仍然很累人

  即使是很简单de工作,例如包含 header和 footer,在JSP中仍然很很困难. 假设有一个 “header”和一个 “footer”模板要包含到所有页面,而每一个模板要在content中包含当前de页标题.
在JSP中最佳办法是:
  <% String title = “The Page Title”; %>
  <%@ include file=”/header.jsp” %>
  …您de页面内容…
  <%@ include file=”/footer.jsp” %>

  页面设计者要记住不能遗漏第一行de分号并要将title定义为一个字符串.此外, /header.jsp和/footer.jsp必须在根目录下并且必须是可存取de完整文件.
  在WebMacro中包含headers和footers做起来比较简单:

  #set $title = “The Page Title”
  #parse “header.wm”
  Your content here
  #parse “footer.wm”

  这里对设计者来说没有要牢记de分号或对titlede定义, .wm文件可以放在可自定义de搜索路径下.

  问题 #4: 很粗de循环

  在JSP中循环很困难.这里是用JSP重复打印出每一个ISP对象名字.
  <%
  Enumeration e = list.elements();
  while (e.hasMoreElements()) {
  out.print(”The next name is “);
  out.println(((ISP)e.nextElement()).getName());
  out.print(”<br>”);
  }
  %>

  也许什么时候会有用户自定义标记来做这些循环.对”if”也是如此.JSP页可能看上去成了很古怪dejava相关代码.而同时,webmacro循环很漂亮:
  #foreach $isp in $isps {
  The next name is $isp.Name <br>
  }

  如果必要de话,#foreach指令可被自定义de #foreach-backwards指令很容易地取代.

  用jspde话很可能变这样:(这里是一个可能de <foreach>标记)

  <foreach item=”isp” list=”isps”>
  The next name is <jsp:getProperty name=”isp” property=”name”/> <br>
  </foreach>

  设计者当然地回选择前者.
  问题 #5: 无用de出错信息

  JSP常有一些令人惊讶de出错信息.这是因为页面首先被转换成为一个servlet然后才进行编译.好deJSP 工具可以相对增加找到出错位置de可能性,但即使是最好de工具也无法使所有出错信息都能容易地被读懂.由于转化de过程,一些错误对工具来说可能根本不可能被识别.
例如,假设JSP页面需要建立一个对所有页通用de标题.以下相关代码并没有错:

  <% static String title = “Global title”; %>

  但Tomcat会提供以下出错信息:
  work/:8080//JC_0002ejspJC_jsp_1.java:70: Statement expected.
  static int count = 0;
  ^

  此信息认为以上脚本被放入 _jspService()方法而静态变量不允许放入方法中.该语法应该是 <%! %>.页面设计者很难读懂这些出错信息.即使最好de平台在这方面也做得很不够.即使所有 Java相关代码都从页中移出也无法解决问题.另外,以下表达式有什么错?

  <% count %>
  tomcat给出:
  work/8080/_0002ftest_0002ejsptest_jsp_0.java:56: Class count not found in
  type declaration.
  count
  ^
  work/8080/_0002ftest_0002ejsptest_jsp_0.java:59: Invalid declaration.
  out.write(”\r\n”);
  ^

  换句话说,只是遗失了一个标记而已.应该是 <%= count %>.

  由于template engine可以在template文件中直接产生而没有任何戏剧性de向相关代码转化,所以可以非常容易地给出适当de出错报告. 依次类推,当c语言de命令被打入Unix shellde命令行, 您并不希望shell 会生成一个C程序来运行这个命令,而只是需要shell简单地解释命令并加以执行,如有错误也直接给出.

  问题 #6: 需要一个编译器

  JSP需要一个置放在webserver中de编译器.由于Sun拒绝放弃包含了他们dejavac编译器detools.jar库, 这其中就变得有问题了.Web服务器可以包含进一个第三方de编译器如ibmde jikes.但这样de编译器并不能在所有平台上顺利工作(用 C 写成de) 也不利于建立纯Java deweb服务器. JSP有一个预编译选项可以起到一定作用,尽管并不完美.

  问题 #7: 空间de浪费

  JSP消耗了额外de内存和硬盘空间.对服务器上每30KdeJSP文件,必须要有相应de大于30Kde类文件产生.实际上使得硬盘空间加倍.考虑到JSP文件随时可以很容易地通过 <%@ include>包含一个大de数据文件,这样de关注有着很现实de意义.同时,每一个JSPde类文件数据必须加载到服务器de内存中,这意味着服务器de内存必须永远地将整个JSP文档树保存下去.少数一些JVM有能力将类文件数据从内存中移去;但是,程序员通常无法控制这样de规则来重新申明,而且对大de站点来说重新申明可能不是很有效.对template engines由于没有产生第二个文件,所以节省了空间.Template engines还为程序员提供对templates在内存中进行缓存de完全控制.

  使用template engine也有一些问题:

  Templatede问题 #1: 没有严格定义

  template engine该如何工作并没有严格定义.可是,但相对jsp来说,其实这并不很重要,和 JSP不同de是,template engines对web服务器没有任何特殊要求 — 任何支持servletde服务器都可以支持template engines (包括API 2.0服务器如Apache/JServ,它们并不能完全支持 JSP)! 如果为最好detemplate engine设计提供健康de竞争本可以引起一场耀眼de革新,特别是有开放源码de促进,(可以让思想相互推动和促进),那么今天deWebMacro就会象Perl一样,没有严格定义但公开源码组织de推动就是它de标准.

  Templatede问题 #2: 没有获得公认

  Template engines并未被广泛知晓.JSP已经占据了极大de商业市场,并且深入人心.而使用g template engines只能是一种未被了解de替代技术.

  Templatede问题 #3: 尚未调配好

  Template engines还没有被高度地调配好.没有对template engine 和JSP两者进行性能测试和比较.理论上说一个调配完好detemplate engine实现应该和一个调配好deJSP相匹配;但是,考虑到第三方为jsp已经作出了这么深远de推动,结果只有jsp被很好地调配好了.

  JSPde角色

  当然地,JSP在将来必然会有其地位.即使从名称上也可以看出JSP和ASPde相似性,它们只有一个字母de差别.所以如果要让使用aspde人们转向java,非常相似dejsp环境将对此起到很大de推动作用,和asp保持这种对应关系所能起到de作用应该也是被推出jspde设计者重点考虑到de.
然而这里想要强调de一点是:有利于转入新环境de工作者,以及实际上是否是使用该环境de最佳方式,这两者是有很大不同de.

  JSP日益显示出它正成为最重要dejava技术之一, 它让人们离开ASPde世界 — 由此,Sun将支持这一强有力de商业case, Java相关技术支持者也将给予更大力de支持.

  可是,这并非java平台de最佳解决方案.这将使java解决方案变得好象是没有javade解决方案了.

关于JSP中文问题的解决方法

星期一, 06月 2nd, 2008

在jsp中,中文乱码常会让人心乱如麻.
  对于中文处理de常见对策,在网上经常可见de主要是下面2种:
<%@ page
contentType="text/html;charset=gb2312" %>
  或者:
<%
String Hi="您好";
byte[]
tmpbyte=Hi.getBytes("ISO8859_1");
Hi=new
String(tmpbyte);
out.print(Hi);
%>
  虚拟小龙亭也主要采用了上面2种方法进行了修改,从而变成了1.1版.
  通过简单总结,示例中de中文处理发生于以下几个地方:
  1 在url附带中文参数,可以直接读取.

  例如:
<%= request.getParameter("showword")%>
  2 与数据库有关de各种sql操作
  这里使用deAccess没有发生问题.

  3 读取HTML
  form表单中递交de中文值
  在jswdk中需要加以编码,较为简洁de写法如:

String name1=new
String(request.getParameter("user_id").getBytes("ISO8859_1"));
  另外,在jdk1.3de支持下,不需要加入
<%@
page contentType="text/html;charset=gb2312"
%>
  而在jdk1.2.2下面,即使2种方法同时运用也很不稳定.
  而在resin平台,情况较好.只要在页面第一行加入:
<%@
page contentType="text/html;charset=gb2312"
%>
  即可正确处理中文.
  如果再加编码则反而不对.
  5 session中包含de中文
  在jswdk中,奇怪de是如果从form中读出de值经过编码则可正确显示;
但直接赋予中文值则不行.
  resin平台很好,同上.
  6 对于对变量赋中文值后正确显示中文.
  例如以下程序:
<%@ page contentType="text/html;charset=gb2312"
%>
<html><head></head><body>
<%
String
Hi="您好";
byte[] tmpbyte=Hi.getBytes("ISO8859_1");
Hi=new
String(tmpbyte);
out.print(Hi);
%>
</body></html>
  同样是jswdk1.0.1,以上de表示方法在jdk1.2.2中没有问题,但在jdk1.3下却无法显示.
  resin平台很好,同上,经过测试,只需要在<head>中补上
<meta
http-equiv="Content-Type" content="text/html;
charset=gb2312">
而不需要<%@ page
contentType="text/html;charset=gb2312" %>也能正确显示中文.
  体会:
  jswdk也许只能用于普通开发,稳定性和其它问题可能不如商业软件.
由于jdk1.3版性能要好于jdk1.2.2很多倍,并且对中文de支持也较好,所以应该加以采用.
  作为免费de商业软件,resin不仅速度快,稳定,自动编译,可指出出错行,可在服务器端支持使用javascript等,而且,至少我觉得对中文de支持很好.
  当然,如果不必做任何处理即可正确显示中文将是我所期待de.
  另外,相信在unix/linux/solaris下应该没有这样de问题.

JSP显示中文问题的解决方案

星期一, 06月 2nd, 2008

这两天在win98下装apache1.3.9加jserv和gnujsp1.0,jdk1.2.2,jsdk2.0
发现中文无法正常显示.要么乱码,要么出错.
经网友提醒,总结了以下几条方法.
1:修改区域设置:在控制面版中选择区域设置,设为英语(美国)?nbsp;
然后重起.一切就都正常.
2:在jsp页中加入一条语句:
<%@ page contentType="text/html;charset=gb2312" %> ?
琷sp显示就正常了.
3:在编译servlet和jsp时加入相关代码选项.编译servlet使用
javac -encoding iso8859_1 myservlet.java
在jspdezone配置文件中.修改编译参数为:
compiler=builtin-javac -encoding ISO8859_1
使用这种方法后,不需要作其他de改动就可以正常显示中文了.
4:最土de办法,在servlet源程序中加入相关代码变换语句.如
try{
out.println(new ( (new String("我爱死您了")).getBytes("GBK"),"ISO8859_1"))
}
catch( UnsupportedEncodingException e)
{
…….
}
使用这种方法一定要注意捕获UnsupportedEncodingException

PHP4与PHP3中一个不兼容问题的解决方法

星期一, 06月 2nd, 2008

PHP4与PHP3中有些不兼容de地方,但这主要是PHP4中dePHP.ini
中de设置有些不同de地方,这些改变主要是提高PHP4de效率.
其中de改变中,track_vars de设置通常会是使旧dePHP3程序不能
再运行了,因为在PHP4de扩展设置中把track_vars de值设为了off
这样旧dePHP3程序中就不能直接用GET,POST,COOKIE从上页传送过来
de变量了.
我这里有一个简单de解决de方法,不用把track_vars de是设为on,
不过这只是一个权宜办法,以后大家还是用$HTTP_GET_VARS,
$HTTP_POST_VARS and $HTTP_COOKIE_VARS读取这些变量比较好.
下面是一个简单de程序,大家可以加到每个需要读取GET,POST,COOKIE
de变量de页前,就可以直接引用这些变量了.
get.variable.inc.php
<?
if(isset($HTTP_POST_VARS))
{
while ( list( $key, $val ) = each( $HTTP_POST_VARS ) )
{
$$key = $val;
}
}
if(isset($HTTP_GET_VARS))
{
while ( list( $key, $val ) = each( $HTTP_GET_VARS ) )
{
$$key = $val;
}
}

if(isset($HTTP_COOKIE_VARS))
{
while ( list( $key, $val ) = each( $HTTP_COOKIE_VARS ) )
{
$$key = $val;
}
}
?>
请大家多多指教!

PHP下MAIL的另一解决方案

星期一, 06月 2nd, 2008

前一段时间我接触到DEC Tru64 Unix 我在上面装了PHP APACHE,可以用提供demail函数始终不能正常发信,于是自编了一个函数,它利用UNIX下de管道和PHPdeSOCK函数进行发信,经过实验非常驻成功,下面是此函数原相关代码.
function mymail($mto,$mcc,$msubject,$mbody)
{
$from="webmaster@backhome.com.cn";
$sign = "\n";//随您便写些什么
$sendmailpath="/usr/lib/sendmail";//Semdmail路径
$bound = "========_".uniqid("BCFMail")."==_";//分界符
$headers = "MIME-Version: 1.0\n".
"Content-Type: multipart/mixed; boundary=\"$bound\"\n".
"Date: ".date("D, d M H:i:s Y ")."\n".
"From: $from\n".
"To: $mto\n".
"Cc: $mcc\n".
"Subject: $msubject\n".
"Status: \n".
"X-Status:\n".
"X-Mailer: MY Email Interface\n".
"X-Keywords:\n\n";
$content="–".$bound."\n"."Content-Type:text/plain;charset=\"GB2312\"\n\n".$mbody.$sign."\n";
$end = "\n"."–".$bound."–\n";
$sock = popen("$sendmailpath -t -f ‘webmaster@backhome.com.cn’",’w');
fputs($sock, $headers);
fputs($sock, $content);
fputs($sock, $end);
fputs($sock, ".\n");
fputs($sock, "QUIT\n");
pclose($sock);
}