首先下蝲WebWork2 的最新版?http://www.opensymphony.com/webwork/)?/p>
q里我们所谈及的WebWorkQ实际上是Webwork+XWork的总集QWebwork1.x 版本中,
整个框架采用了紧耦合的设计(cMStrutsQ,?.0 之后QWebwork被拆分ؓ两个部分Q?br />
即Webwork 2.x +XWork 1.xQ设计上的改良带来了pȝ灉|性上的极大提升?/p>
本例的部|如下图所C?
<body>
<form action="/login.action">
<p align="center">
d<br> </p>
用户?<input type="text" name="model.username" /><br>
??:<input type="password" name="model.password" /><br>
<p align="center"><input type="submit" value="提交" name="B1"/><input type="reset" value="重置" name="B2"/></p>
</form>
</body>
</html>
q里的index.jsp实际上是qhtml l成Q非常简单,其中包含一个表单:
<form action="/login.action">
q表明其提交对象?login.action . 表单中同时包含两个文本输入框Q?br /> <input type="text" name="model.username" />
<input type="password" name="model.password" />
可以看到Q两个输入框的名U均?#8220;model”开_q是因ؓ在这里我们采用了WebWork
中Model-Driven的Action驱动模式
……
<servlet>
<servlet-name>webwork</servlet-name>
<servlet-class>
com.opensymphony.webwork.dispatcher.ServletDispatcher
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>webwork</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
此后Q所有以.actionl尾的服务请求将由ServletDispatcher 接管?br />
ServletDispatcher 接受到Servlet Container 传递过来的hQ将q行一下几个动作:
1. 从请求的服务名(/login.actionQ中解析出对应的Action名称QloginQ?br />
2. 遍历 HttpServletRequest、HttpSession、ServletContext 中的数据Qƈ其复制?br />
Webwork的Map实现中,x之后Q所有数据操作均在此Mapl构中进行,从而将内部l构与Servlet API相分R?br />
xQWebwork 的工作阶D늻束,数据传递给XWork q行下一步处理。从q里也可以看
到Webwork和xwork之间的切分点QWebwork为xwork提供了一个面向Servlet 的协议{?br />
器,Servlet 相关的数据{构{换成xwork所需要的通用数据格式Q而xwork完成实际的
服务调度和功能实现?br />
q样一来,以xwork为核心,只需替换外围的协议{换组Ӟ卛_实现不同技术^C间的
切换Q如面向Servlet的Webwork替换为面向JMS的协议{换器实现Q即可在保留应用?br />
辑实现的情况下,实现不同外部技术^C间的ULQ?br />
3. 以上qC息作为参敎ͼ调用ActionProxyFactory创徏对应的ActionProxy实例?br />
ActionProxyFactory 根据Xwork 配置文gQxwork.xmlQ中的设定,创徏
ActionProxy实例QActionProxy中包含了Action的配|信息(包括Action名称Q?br />
对应实现cȝ{)?br />
4. ActionProxy创徏对应的Action实例QƈҎ(gu)配置q行一pd的处理程序。包?br />
执行相应的预处理E序Q如通过Interceptor Map 中的h数据转换为Action
所需要的Java 输入数据对象{)Q以及对Action q行l果q行后处理?br />
ActionInvocation 是这一q程的调度者。而com.opensymphony.xwork.
DefaultActionInvocation 则是XWork 中对ActionInvocation 接口的标准实玎ͼ?br />
果有_֊可以Ҏ(gu)c进行仔l研读,掌握了这里面的玄机,怿XWork的引?br />
׃再神U?/p>
下面我们来看配置文gQ?br />
xwork.xmlQ?br />
<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.0//EN"
"http://www.opensymphony.com/xwork/xwork-1.0.dtd">
<xwork>
<include file="webwork-default.xml" />
<package name="default" extends="webwork-default">
<action name="login" class="net.xiaxin.webwork.action.LoginAction">
<result name="success" type="dispatcher">
<param name="location">/main.jsp</param>
</result>
<result name="loginfail" type="dispatcher">
</result>
<interceptor-ref name="params" />
<interceptor-ref name="model-driven"/>
</action>
</package>
</xwork>
?include
通过include 节点Q我们可以将其他配置文g导入到默认配|文件xwork.xml 中?br /> 从而实现良好的配置划分?br /> q里我们导入了Webwork 提供的默认配|webwork-default.xmlQ位?br /> webwork.jar 的根路径Q?br /> ?package
XWork中,可以通过package对actionq行分组。类似Java 中package和class?br /> 关系。ؓ可能出现的同名Action提供了命名空间上的隔R?br /> 同时Qpackageq支持承关pR在q里的定义中Q我们可以看刎ͼ
extends="webwork-default"
"webwork-default"是webwork-default.xml文g中定义的packageQ这里?br /> q承,"default" package 自动拥有"webwork-default" package 中的所?br /> 定义关系?br /> q个Ҏ(gu)ؓ我们的配|带来了极大便利。在实际开发过E中Q我们可以根据自w?br /> 的应用特点,定义相应的package模板Qƈ在各个项目中加以重用Q无需再在重复
J琐的配|过E中消耗精力和旉?br /> 此外Q我们还可以在Package节点中指定namespaceQ将我们的action分ؓ若干?br /> 逻辑区间。如Q?br /> <package name="default" namespace="/user"
extends="webwork-default">
将此package中的action定义划归?user 区间Q之后在面调用action的时候,
我们需要用/user/login.action 作ؓform action 的属性倹{其中的/user/指定了?br /> action的namespaceQ通过q样的机Ӟ我们可以系l内的actionq行逻辑分类Q?br /> 从而得各模块之间的划分更加清晰?br /> ?action
Action配置节点Q这里可以设定Action的名U和对应实现cR?br /> ?result
通过result 节点Q可以定义Action q回语义Q即Ҏ(gu)q回|军_处理模式以及
响应界面?br /> q里Q返回?success"QAction 调用q回gؓString cdQ对应的处理模式?br /> "dispatcher"?br /> 可选的处理模式q有Q?br /> 1. dispatcher
本系l页面间转向。类似forward?br /> 2. redirect
览器蟩转。可转向其他pȝ面?br /> 3. chain
处理结果{交给另外一个Action处理Q以实现Action的链式处理?br /> 4. velocity
指定的velocity模板作ؓl果呈现界面?br /> 5. xslt
指定的XSLT 作ؓl果呈现界面?br /> 随后的param节点则设定了相匹配的资源名称?br /> ?interceptor-ref
讑֮了施加于此Action的拦截器QinterceptorQ。关于拦截器Q请参见E后?#8220;XWork
拦截器体p?#8221;部分?br /> interceptor-ref定义的是一个拦截器的应用,具体的拦截器讑֮Q实际上是
承于webwork-default packageQ我们可以在webwork-default.xml 中找?br /> 对应?params"?model-driven"拦截器设|:
<interceptors>
……
<interceptor name="params"
class="com.opensymphony.xwork.interceptor.ParametersInt
erceptor" />
<interceptor name="model-driven"
class="com.opensymphony.xwork.interceptor.ModelDrivenIn
terceptor" />
……
</interceptors>
"params"大概是Webwork 中最重要、也最常用的一个Interceptor。上面曾l将
MVC工作程划分为几个步骤,其中的第一?
“?Web 面中的输入元素装Z个(hQ数据对?#8221;
是通过"params"拦截器完成。Interceptor 在Action 之前被调用,因而,
Interceptor 也成为将Webwork传来的MAP 格式的数据{换ؓ强类型Java 对象?br />
最佛_现场所?br /> "model-driven"则是针对Action 的Model驱动模式的interceptor 实现。具体描
q请参见E后?#8220;Action驱动模式”部分
很可能我们的Action 都需要对q两个interceptor q行引用。我们可以定义一?br /> interceptor-stackQ将其作Z个interceptor l合在所有Action 中引用。如Q上?br /> 的配|文件可修改为:
<xwork>
<include file="webwork-default.xml" />
<package name="default" extends="webwork-default">
<interceptors>
<interceptor-stack name="modelParamsStack">
<interceptor-ref name="params" />
<interceptor-ref name="model-driven" />
</interceptor-stack>
</interceptors>
<action name="login"
class="net.xiaxin.webwork.action.LoginAction">
<result name="success" type="dispatcher">
<param name="location">/main.jsp</param>
</result>
<result name="loginfail" type="dispatcher">
<param name="location">/index.jsp</param>
</result>
<interceptor-ref name="modelParamsStack" />
</action>
</package>
</xwork>
通过引入interceptor-stackQ我们可以减interceptor 的重复申明?br /> 下面是我们的Model对象Q?br /> LoginInfo.javaQ?br /> public class LoginInfo {
private String password;
private String username;
private List messages = new ArrayList();
private String errorMessage;
public List getMessages() {
return messages;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
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;
}
}
很简单,q只是一个纯_的值对象(Value-ObjectQ。这里,它扮演着模型QModelQ的
角色Qƈ与Action的输入输出密切相兟?br /> ?SpringMVC中的Command对象不同QWebwork 中的Model对象Q扮演着承上启下
的角Ԍ它既是Action的输入参敎ͼ又包含了Action处理的结果数据?br /> 换句话说Q输入的Httph参数Q将被存储在Model对象传递给Actionq行处理QAction
处理完毕之后Q也结果数据放|到Model 对象中,之后QModel 对象与返回界面融合生
成最后的反馈面?br /> 也正׃此,W者徏议在实际开发中采用Model-Driven 模式Q而非Property-Driven ?br /> 式(见稍?#8220;Action驱动模式”部分Q,q将使得业务逻辑更加清晰可读?br /> 对应的Action代码
public class LoginAction implements Action, ModelDriven {
private final static String LOGIN_FAIL="loginfail";
LoginInfo loginInfo = new LoginInfo();
public String execute() throws Exception {
if ("erica".equalsIgnoreCase(loginInfo.getUsername())
&& "mypass".equals(loginInfo.getPassword())) {
//当前登录的用户名保存到Session
ActionContext ctx = ActionContext.getContext();
Map session = ctx.getSession();
session.put("username",loginInfo.getUsername());
//Z演示目的Q通过编码增加通知消息以供昄
loginInfo.getMessages().add("message1");
loginInfo.getMessages().add("message2");
loginInfo.getMessages().add("message3");
return SUCCESS;
}else{
loginInfo.setErrorMessage("Username/Password Error!");
return LOGIN_FAIL;
}
}
public Object getModel() {
return loginInfo;
}
}
1. Action
Action接口非常单,它指定了Action的入口方法(executeQ,q定义了
几个默认的返回值常量:
public interface Action extends Serializable {
public static final String SUCCESS = "success";
public static final String NONE = "none";
public static final String ERROR = "error";
public static final String INPUT = "input";
public static final String LOGIN = "login";
public String execute() throws Exception;
}
SUCCESS、NONE、ERROR、INPUT、LOGIN 几个字符串常量定义了常用?br /> 几类q回倹{我们可以在Action 实现中定义自qq回cdQ如本例中的
LOGIN_FAIL定义?br /> 而executeҎ(gu)Q则是Action的入口方法,XWork调用每个Action的execute
Ҏ(gu)以完成业务逻辑处理?br /> 2. ModelDriven
ModelDriven接口更ؓz:
public interface ModelDriven {
Object getModel();
}
ModelDriven仅仅定义了一个getModelҎ(gu)。XWork在调度ActionӞ?br /> q此Ҏ(gu)获取Model 对象实例QƈҎ(gu)h参数为其讑֮属性倹{而此后的
面q回q程中,XWork 也将调用此方法获取Model 对象实例q将其与讑֮
的返回界面相融合?br /> 注意q里与Spring MVC 不同QSpring MVC 会自动ؓ逻辑处理单元创徏
Command Class实例Q但Webwork不会自动为Action创徏Model对象实例Q?br /> Model 对象实例的创建需要我们在Action 代码中完成(如LoginAction ?br /> LoginInfo对象实例的创建)?br /> 另外Q如代码注释中所描述Q登录成功之后,我们随即username保存在Session之中Q?br /> q也是大多数d操作必不可少的一个操作过E?br /> q里面牵涉到了Webwork中的一个重要组成部分:ActionContext?br /> ActionContext为Action提供了与容器交互的途径。对于Web 应用而言Q与容器的交?br /> 大多集中在Session、ParameterQ通过ActionContext我们在代码中实现与Servlet API无关?br /> 容器交互?br /> 如上面代码中的:
ActionContext ctx = ActionContext.getContext();
Map session = ctx.getSession();
session.put("username",loginInfo.getUsername());
同样Q我们也可以操作Parameter:
ActionContext ctx = ActionContext.getContext();
Map params = ctx.getParameters();
String username = ctx.getParameters("username");
上述的操作,由XWorkҎ(gu)当前环境Q调用容器相关的讉KlgQWeb 应用对应?br /> 是WebworkQ完成。上面的ActionContext.getSession()QXWork 实际上将通过Webwork
提供的容器访问代?#8220;HttpServletRequest.getSession()”完成?br /> 注意刎ͼActionContext.getSessionq回的是一个Mapcd的数据对象,而非HttpSession?br /> q是׃WebWork对HttpSessionq行了{换,使其转变ZServlet API无关的Map对象?br /> 通过q样的方式,保证了Xwork 所面向的是一个通用的开攄构。从而得逻辑层与表现
层无兟뀂增加了代码重用的可能?br /> ?外, Z提供与Web 容器直接交互的可能。WebWork q提供了一?br /> ServletActionContext实现。它扩展了ActionContextQ提供了直接面向Servlet API的容器访
问机制?br /> 我们可以直接通过ServletActionContext.getRequest 得到当前HttpServletRequest 对象?
収ͼ且无太多变更的可能。不q,如果条g允许Q尽量通过ActionContext 与容器交互,?br /> 不是q_相关的ServletActionContextQ这样在利实现功能的同Ӟ也获得了q_q移?br /> 的潜在优势,何乐而不为?br /> d成功界面Q?br /> main.jsp:
<%@ taglib prefix="ww" uri="webwork"%>
<html>
<body>
<p align="center">Login Success!</p>
<p align="center">Welcome!
<ww:property value="#session['username']"/>
</p>
<p align="center">
<b>Messages:</b><br>
<ww:iterator value="messages" status="index">
<ww:if test="#index.odd == true">
!<ww:property/><br>
</ww:if>
<ww:else>
*<ww:property/><br>
</ww:else>
</ww:iterator>
</p>
</body>
</html>
q里我们引入了Webwork的taglibQ如面代码W一行的x语句?br /> 下面主要使用了三个tag:
<ww:property value="#session['username']"/>
dModel对象的属性填充到当前位置?br /> value指定了需要读取的Model对象的属性名?br /> q里我们引用了LoginAction在session中保存的’username’对象?br /> ׃对应的ModelQLoginInfoQ中也保存了username 属性。下面的语句与之
效果相同Q?br /> <ww:property value="username"/>
?JSP2中的ELcMQ对于联对象,q里我们也可以通过“.”操作W获?br /> 其属性|如value="user.username"得到Model 对象中所引用的user
对象的username 属性(假设LoginInfo中包含一个User 对象Qƈ拥有一个名
?#8220;username”的属性)?br /> 关于EL的内Ҏ(gu)较简单,本文׃再单独开辟章节进行探讨?br /> Webwork中包括以下几U特D的EL表达式:
parameter[‘username’] 相当于request.getParameter(“username”);
request[‘username’] 相当于request.getAttribute(“username”);
session[‘username’] 从session中取Z“username”为key的?br /> application[‘username’] 从ServletContext中取Z“username”为key
的?br /> 注意需要用“#”操作W引用这些特D表辑ּ?br /> 另外对于帔RQ需要用单引号包_?session['username'] 中的
'username'?br /> <ww:iterator value="messages" status="index">
q代器。用于对java.util.Collection、java.util.Iterator、java.util.Enumeration,?br /> java.util.Map、Arraycd的数据集q行循环处理?br /> 其中Qvalue属性的语义?lt;ww:property>中一致?br /> ?status属性则指定了@环中的烦引变量,在@环中Q它?yu)自动递增?br /> 而在下面?lt;ww:if>中,我们通过“#”操作W引用这个烦引变量的倹{?br /> 索引变量提供了以下几个常用判定方法:
first 当前是否为首ơP?br /> last 当前是否为最后一ơP?br /> odd 当前q代ơ数是否奇数
even 当前q代ơ数是否偶数
<ww:if test="#index.odd == true">?lt;ww:else>
用于条g判定?br /> test属性指定了判定表达式。表辑ּ中可通过“#”操作W对变量q行引用?br /> 表达式的~写语法与java 表达式类伹{?br /> cM的,q有<ww:elseif test="……">?br /> dp|界面
实际上,q个界面即登录界面index.jsp。只是由于之前出于避免干扰的考虑Q隐藏了
index.jsp中显C错误信息的部分?br /> 完整的index.jsp如下Q?br /> <%@ page pageEncoding="gb2312"
contentType="text/html;charset=gb2312"%>
<%@ taglib prefix="ww" uri="webwork"%>
<html>
<body>
<form action="/login.action">
<p align="center">
d<br>
<ww:if test="errorMessage != null">
<font color="red">
<ww:property value="errorMessage"/>
</font>
</ww:if>
</p>
用户?
<input type="text" name="model.username" />
<br>
??:
<input type="password" name="model.password" />
<br>
<p align="center">
<input type="submit" value="提交" name="B1"/>
<input type="reset" value="重置" name="B2"/>
</p>
</form>
</body>
</html>
q里首先我们q行判断Q如果Model中的errorMessage不ؓnullQ则昄错误信息。这
P在用L一ơ登录时Q由于Model对象未创徏QerrorMessage自然为nullQ错误信?br /> 不会昄Q即得到了与之前的index.jsp同样的效果?br />
]]>
]]>
<form name="form" method="post">
试表单:<input name="test"><br>
<input type="button" value="提交" onClick=send()>
<input type="button" value="预览" onClick=preview()>
</form>
<script language=javascript>
function send()
{
document.form.action="send.asp"
document.form.submit()
}
function preview()
{
document.form.action="preview.asp"
document.form.submit()
}
</script>
关于上面实例的两点说明:
1、在整个表单中,不应有名字ؓaction或submit的标{,否则会产生"对象不支持此属性和Ҏ(gu)"的错误。如代码 "<input type='xxxx' name='action' >"在表单中是不允许出现的;
2、在form标签中应该存在name属性。即Q应该给表单取一个名字。语句document.form.action和document.form.submit中的"form"也就是表单的名字?br /> 表单的分向提交不仅仅使用在论坛的E序中,它还可以q用在许多场合下。恰当的q用表单的分向提交功能可以大大的增强|站的h性化E度?
昨天Q我调试E序出Cq样的问题,是出现?对象不支持此属性和Ҏ(gu)"的错误,一直无法定位出来,都快疯掉了,后来在发C个button命名为submit了?br />
1.--------
<form name="formname" action="">
<input name="inputname">
<input type="submit" onclick="document.formname.action='a.asp'" value="button a">
<input type="submit" onclick="document.formname.action='b.asp'" value="button b">
<input type="submit" onclick="document.formname.action='c.asp'" value="button c">
</form>
2.----------
<input type=button name="a" value="a" onclick="this.form.action='a.asp';this.form.submit();">
<input type=button name="b" value="b" onclick="this.form.action='b.asp';this.form.submit();">
<input type=button name="c" value="c" onclick="this.form.action='c.asp';this.form.submit();">
<input type=button name="d" value="d" onclick="this.form.action='d.asp';this.form.submit();">
]]>
下面我们?#8220;_脓(chung)”中的“选择性粘?#8221;ZQ介l下自己创徏pȝ中所没有的快捷键的步骤。其它的快捷键以此类推?/p>
用wordӞ复制_脓(chung)是必不可的操作步骤。以前在word 97 时代Q能_脓(chung)到Word中的只是U文本的文字Q现在更多的Z用的?003、xp版本Q粘贴结果就是有格式的文字,q包括图片、甚臌根{这个新功能当然有它的好处,可是如果我只需要源文g中的U文字,不想要格式、图片,那就需要用到它所附带的选择性粘贴功能。目前word2007提供的方法有两个Q?/p>
1. 在粘贴结束后Q会自动出现一个Q动的“_脓(chung)选项”按钮Q用鼠标按这个按钮,选择“仅保留文?#8221;卛_。这个方法的~点是,_脓(chung)动作比较慢(因ؓ无用的内Ҏ(gu)较多Q?/p>
2. 不是用一般的“_脓(chung)”功能Q而在菜单中?#8220;~辑”--“选择性粘?#8221;--“无格式文?#8221;卛_。这个方法执行速度快,但操作步骤多Q太ȝ?/p>
下面通过自己创徏宏来解决q个问题Q实现快捷键操作Q就象按一下ctrl+V可以实现粘贴一栗这个过E分两步Q一是徏立一个实?#8220;选择性粘?#8221;的宏Q二是给q个宏指定键盘快捷键?/p>
一、创?#8220;选择性粘?#8221;功能的宏
1、打开word 2007Q选择开发工具下?#8220;Visual Basic~辑?#8221;Q或者直接按Alt+F11也可以。这时会出现一个Visual Basic~辑H口Q现在看看你的窗口中左侧位置是否有某个模块存在?如果已经有了Q你可以跌建立新模块这一步。如果你的系l在Normal下面不存在Q何模块,那么在Normal上,打开右键菜单Q选插入模块?/p>
2、现在模块已l有了,用鼠标点M之高亮,然后按F7键(直接双击模块也可以)。这样右侧就会出C码窗口?/p>
3、将下面的代码粘贴到“代码H口”中。关闭Visual Basic~辑H口。这P一个宏徏立好了?/p>
Sub 无格式粘?)
'无格式粘?Macro
'宏在 2005-9-22 ?SQ 录制
Selection.PasteSpecial Link:=False, DataType:=wdPasteText, Placement:=wdInLine, DisplayAsIcon:=False
End Sub
到这一步,可以自动q行选择性粘贴的宏就创徏成功了,但这时候用它q需要到“工具—宏—宏”Q选择相应的宏名称来运行它Q比较麻烦。想快捷使用Ql向下看?/p>
二、将宏拖到工hQƈ指定键盘快捷?/p>
在Wordȝ口中Q找到word选项,选择工具按钮中的“自定?#8221;?/p>
?#8220;从下列位|选择命o”选项卡,?#8220;?#8221;Q会出现我们刚徏立的宏。用鼠标这个宏拖到双快速访问工h位置Q松开鼠标键。请单击修改按钮Q在弹出菜单中作相应的图标、名U。这样工h中就有了刚才制作的选择性粘贴的宏的快捷按钮了?/p>
再指定快捷键Q此?#8220;自定?#8221;对话框依然打开着Q请?#8220;键盘快捷方式”按钮旁的“自定?#8221;?#8220;cd”?#8220;?#8221;Q在“?#8221;中选定EditPasteNoFormat。这?#8220;h新快捷键”应该是空白的Q用鼠标点一下这里,然后按一下你惌的快捷键。这里,假设我们参考粘贴的快捷键ctrl+V,而用alt+V,出现“未指?#8221;Q说明这是一个可用的快捷键,和其它功能不发生冲突。按“指定”按钮。现在alt+V被指定ؓq个宏的快捷键了。按“关闭”按钮Q再 关闭“自定?#8221;H口。(上面的步骤中既设|了工具栏按钮,也设|了键盘快捷键,也可以只指定其中的一个,看各Z用习惯而定。)
以后再用WORDӞ我们可以按这个工h钮,或者用alt+v快捷键方便地实现“_脓(chung)为纯文本”的功能了。其它功能的快捷键也可以照葫芦画瓢?/p>
2. Hibernate优化问题。如何优化数据库讉KQɽE序讉K数据库更优化?
初用HIBERNATE的h也许都遇到过性能问题Q实现同一功能Q用HIBERNATE与用JDBC性能相差十几倍很正常Q如果不及早调整Q很可能影响整个目的进度?
大体上,对于HIBERNATE性能调优的主要考虑点如?
* 数据库设计调?
* HQL优化
* API的正?如根据不同的业务cd选用不同的集合及查询API)
* 主配|参?日志Q查询缓存,fetch_size, batch_size{?
* 映射文g优化(ID生成{略Q二U缓存,延迟加蝲Q关联优?
* 一U缓存的理
* 针对二~存Q还有许多特有的{略
* 事务控制{略?
1?数据库设?
a) 降低兌的复杂?
b) 量不用联合主?
c) ID的生成机Ӟ不同的数据库所提供的机制ƈ不完全一?
d) 适当的冗余数据,不过分追求高范式
2?HQL优化
HQL如果抛开它同HIBERNATE本n一些缓存机制的兌QHQL的优化技巧同普通的SQL优化技巧一P可以很容易在|上扑ֈ一些经验之谈?
3?主配|?
a) 查询~存Q同下面讲的~存不太一P它是针对HQL语句的缓存,卛_全一L语句再次执行时可以利用缓存数据。但是,查询~存在一个交易系l?数据变更频繁Q查询条件相同的机率q不?中可能会起反作用:它会白白耗费大量的系l资源但却难以派上用场?
b) fetch_sizeQ同JDBC的相兛_C用类|参数q不是越大越好,而应Ҏ(gu)业务特征去设|?
c) batch_size同上?
d) 生pȝ中,切记要关掉SQL语句打印?
4?~存
a) 数据库~存:q~存是最高效和安全的Q但不同的数据库可管理的层次q不一P比如Q在ORACLE中,可以在徏表时指定整个表|于~存当中?
b) SESSION~存:在一个HIBERNATE SESSION有效Q这U缓存的可干预性不强,大多于HIBERNATE自动理Q但它提供清除缓存的Ҏ(gu)Q这在大扚w增加/更新操作是有效的。比如,同时增加十万条记录,按常规方式进行,很可能会发现OutofMemeroy的异常,q时可能需要手动清除这一U缓?Session.evict以及Session.clear
c) 应用~存:在一个SESSIONFACTORY中有效,因此也是优化的重中之重,因此Q各cȝ略也考虑的较多,在将数据攑օq一U缓存之前,需要考虑一些前提条?
i. 数据不会被第三方修改(比如Q是否有另一个应用也在修改这些数?)
ii. 数据不会太大
iii. 数据不会频繁更新(否则使用CACHE可能适得其反)
iv. 数据会被频繁查询
v. 数据不是关键数据(如涉及钱Q安全等斚w的问??
~存有几UŞ式,可以在映文件中配置:read-only(只读Q适用于很变更的静态数?历史数据)Qnonstrict-read-writeQread-write(比较普遍的Ş式,效率一?Qtransactional(JTA中,且支持的~存产品较少)
d) 分布式缓?同c)的配|一P只是~存产品的选用不同Q在目前的HIBERNATE中可供选择的不多,oscache, jboss cacheQ目前的大多数项目,对它们的用于集群的?特别是关键交易系l?都持保守态度。在集群环境中,只利用数据库U的~存是最安全的?
5?延迟加蝲
a) 实体延迟加蝲:通过使用动态代理实?
b) 集合延迟加蝲:通过实现自有的SET/LISTQHIBERNATE提供了这斚w的支?
c) 属性gq加?
6?Ҏ(gu)选用
a) 完成同样一件事QHIBERNATE提供了可供选择的一些方式,但具体用什么方式,可能用性能/代码都会有媄响。显C,一ơ返回十万条记录(List/Set/Bag/Map{?q行处理Q很可能D内存不够的问题,而如果用Z游标(ScrollableResults)或Iterator的结果集Q则不存在这L问题?
b) Session的load/getҎ(gu)Q前者会使用二~存Q而后者则不用?
c) Query和list/iteratorQ如果去仔细研究一下它们,你可能会发现很多有意思的情况Q二者主要区?如果使用了SpringQ在HibernateTemplate中对应find,iteratorҎ(gu)):
i. list只能利用查询~存(但在交易pȝ中查询缓存作用不?Q无法利用二U缓存中的单个实体,但list查出的对象会写入二~存Q但它一般只生成较少的执行SQL语句Q很多情况就是一?无关??
ii. iterator则可以利用二U缓存,对于一条查询语句,它会先从数据库中扑և所有符合条件的记录的IDQ再通过IDȝ存找Q对于缓存中没有的记录,再构造语句从数据库中查出Q因此很Ҏ(gu)知道Q如果缓存中没有MW合条g的记录,使用iterator会生N+1条SQL语句(N为符合条件的记录?
iii. 通过iteratorQ配合缓存管理APIQ在量数据查询中可以很好的解决内存问题Q如:
while(it.hasNext()){
YouObject object = (YouObject)it.next();
session.evict(youObject);
sessionFactory.evice(YouObject.class, youObject.getId());
}
如果用listҎ(gu)Q很可能出OutofMemory错误了?
iv. 通过上面的说明,我想你应该知道如何去使用q两个方法了?
7?集合的选用
在HIBERNATE 3.1文档?#8220;19.5. Understanding Collection performance”中有详细的说明?
8?事务控制
事务斚wҎ(gu)能有媄响的主要包括:事务方式的选用Q事务隔ȝ别以及锁的选用
a) 事务方式选用:如果不涉及多个事务管理器事务的话Q不需要用JTAQ只有JDBC的事务控制就可以?
b) 事务隔离U别:参见标准的SQL事务隔离U别
c) 锁的选用:(zhn)观?一般由具体的事务管理器实现)Q对于长事务效率低,但安全。乐观锁(一般在应用U别实现)Q如在HIBERNATE中可以定义VERSION字段Q显Ӟ如果有多个应用操作数据,且这些应用不是用同一U乐观锁机制Q则乐观锁会失效。因此,针对不同的数据应有不同的{略Q同前面许多情况一P很多时候我们是在效率与安全/准确性上找一个^衡点Q无论如何,优化都不是一个纯技术的问题Q你应该对你的应用和业务特征有够的了解?
9?扚w操作
即是用JDBCQ在q行大批数据更新ӞBATCH与不使用BATCH有效率上也有很大的差别。我们可以通过讄batch_size来让其支持批量操作?
举个例子Q要扚w删除某表中的对象Q如“delete Account”Q打出来的语句,会发现HIBERNATE扑և了所有ACCOUNT的IDQ再q行删除Q这主要是ؓ了维护二U缓存,q样效率肯定高不了,在后l的版本中增加了bulk delete/updateQ但q也无法解决~存的维护问题。也是_׃有了二~存的维护问题,HIBERNATE的批量操作效率ƈ不尽如h?
3. |站是动态的Q需要频J访问数据库Q如何提高访问速度Q减服务器压力Q?
提供JDBC数据库链接池׃n,大大降低数据库压力;
动态HTMLQ大大减网l数据流量;
量数据优化Q大大提高登录和讉K速度Q?
用户界面和数据缓存,大大提高d速度Q?
多层ơ体pȝ构,支持多个应用E序服务器ƈ行,大大提高pȝ伸羃性,q发讉K用户数目和数据安全?
4. 搜烦引擎优化Q如何提高网站排名。优化有哪些具体技术措施?
|站l构设计中面向搜索引擎的优化注意事项包括Q?
1)链接引用的重要?
a.以量取胜Q不一定加入传l门L站的分类目录才是|站推广Q来自其他网站的M反相链接都是有用?
b. 以质取胜Q被PageRank高的|站引用能更快地提高PageRank
c. 了解搜烦引擎?价D"Q不要通过Link Farm提高自n的站Ҏ(gu)名:Google会惩|那些主动链接到Link Farm站点以提高自w排名站点,相应站点的页面将不会被收入到索引中。但如果你的面被别的Link Farm链接了也不必担心Q因U被动的链接是不会被惩罚的?
d. 不要吝啬l其他网站的链接Q如果一个网只有大量的q入链接Q而缺乏导出链接,也会被搜索引擎认为是没有价值的站点?
2)如何H出关键词:|页标题、主题的设计
a.Theme Engine正在逐步过PRQ成为结果排序中更主要的因素
b.不要I着标题Q空着<title></title>无异于浪费了最有h(hun)值的一块阵?
c. 标题长度和内容:不要q长Q一般在40个字(80个字?以内Qƈ充分H出关键词的比重
d. 如果|页很多的话Q尽量用不同的|页标题Q争取让自己|站的内Ҏ(gu)多的q入搜烦引擎索引范围
e. 除了<title></title>外,q可以用<h1></h1>标题行突出内容主题, 加强标题的效?
3)面及站点结构设计注意事?
a. 静态链? 大部分搜索引擎都认ؓ静态链接的|页是优质网,Google在优先抓取烦引的|页?0%以上是不带参数链接的静态网c而且即同样的内容,静态网也 会比动态网|重高
b. 能够q入Google索引的页面数量越多越?
c. |站目录l构要扁qI因ؓ每深一U目录,PAGERANK降低1Q?个档ơ。假N|3Q其子可能目录就?了,更深可能无法列入评U范围了?
d. 表现和内容的分离Q?#8220;l色”|页
|页中的javascript和css可能和|页分离Q一斚w提高代码重用度(也方侉K面缓存)Q另外一斚wQ由于有效内容占|页长度的百分比高,也能提高相关关键词在面中的比重也增加了。MQ应该鼓励遵循w3c的规范,使用更规范的XHTML和XML作ؓ昄格式便于内容更长旉的保存?
e. 让所有的面都有能够快速入口:站点地图Q?方便|页爬虫QspiderQ快速遍历网站所有需要发布的内容。如果首就是用Flash或图片进入的话,无异于将搜烦引擎拒之门外Q除了UI设计的用?友好外,spider friendly也是非常重要?
f. 保持|站自n的健Pl常利用?链检查工h查网站中是否有死?
g. 保持|页内容/链接的稳定性和持久性:在搜索引擎烦引中|页存在的历史也是一个比较重要的因素Q而且历史比较久的|页被链接的几率高。ؓ?保证自己|页能够被比较持久的被其他网站的面引用Q如果自q中有链接更新时Q最好能保留旧的面q做好链接{向,以保持内容的q箋性?
h. 文gcd因素QGoogle有对PDF, Word(Power Point, Excel), PS文的烦引能力,׃q种文的内Ҏ(gu)一般的HTMLl过了更多的整理Q学术h(hun)g般比较高Q所以这些类型的文档天生比一般的HTMLcd的文?PageRank要高。因此,对于比较重要的文:技术白皮书QFAQQ安装文等使用PDF PS{高U格式存取,q样在搜索结果中也能获得比较靠前的位zhi点访问统计的重要性等Q,的设?nbsp;
4)以及站点讉Kl计的重要性等
5)Google的站点设计指?
1.Make a site with a clear hierarchy and text links. Every page should be reachable from at least one static text link. 让网站有着清晰的结构和文本链接Q所有的面臛_要有一个静态文本链接入?
Ҏ(gu)Q尽量不要用囄和JAVASCRIPT
2.Offer a site map to your users with links that point to the important parts of your site. If the site map is larger than 100 or so links, you may want to break the site map into separate pages.
为用h供一个站点地图:转向|站的重要部分。如果站点地N面超q?00个链接,则需要将面分成多个面?
Ҏ(gu)Q烦引页不要过100个链接:SPIDER只考虑面中头100个链?
3.Create a useful, information-rich site and write pages that clearly and accurately describe your content.
用一些有用的Q信息量丰富的站点,清晰q正的描述你的信息?
4.Think about the words users would type to find your pages, and make sure that your site actually includes those words within it.
惛_用户可能用来扑ֈ你的关键词,q保证这些关键词在网站中出现?
Ҏ(gu)Q少?#8220;最?#8221;Q?#8220;最?#8221;之类的Ş容词Q用用户最兛_的词Q比如:下蝲Q歌星名字,而不是一些抽象名词?
5.Try to use text instead of images to display important names, content, or links. The Google crawler doesn't recognize text contained in images.
可能用文本,而不是图片显C重要的名称Q内容和链接。GOOGLE的机器h不认识图片中的文字?
6.Make sure that your TITLE and ALT tags are descriptive and accurate.
保证Q页面的TITLE和ALT标记正确的精描q?
7.Check for broken links and correct HTML.
查坏铑ƈ修正q些HTML错误?
8.If you decide to use dynamic pages (i.e., the URL contains a '?' character), be aware that not every search engine spider crawls dynamic pages as well as static pages. It helps to keep the parameters short and the number of them small.
如果你打用动态页面:链接中包??"Q必M解:q所有的搜烦引擎的机器h能想对待静态页面一样对待动态页面,保持动态页面的参数可能的也?很有帮助?
9.Keep the links on a given page to a reasonable number (fewer than 100).
让一个页面中的链接少?00个?
Ҏ(gu)Q用lynx -dump http://www.chedong.com/ 可以模拟从robot角度看到的页面。其最后有链接l计
5. hibernate对动态查询的理解Q如何应用,q作应用CZ?
定义Q?
?静态查询:在编E时已经定要查询的字段Q这时编写的HQL或QBCUCؓ静态查询?
?动态查询:在编E时无法定要查询的字段Q这时编写的HQL或QBCUCؓ动态查询。比如组合查询时Q往往需要查询的很多,但不是每个项都必需?
QHQL适用于静态查询,QBC适用于动态查询)
以下分别用HQL和QBC实现动态查询:
1Q下面的E序通过对字W串的拼装用HQL语句实现动态查询:
Public List findStu(String name, int age){
StringBuffer queryString= new StringBuffer();
Boolean conditionFound= false;
if(name!=null){
queryString.append(“lower(s.name) like :name”);
conditionFound= true;
}if(age!= 0){
if(conditionFound) queryString.append(“and”);
queryString.append(“s.age= :age”);
conditionFound=true;
}
String fromClause= conditionFound?”fromStudent s where” : ”fromStudent s”;
queryString.insert(0,fromClause).append(“order by s.name”);
Query query=getSession().createQuery(“queryString.toString()”);
if(name!=null)query.setString(“name”,’%’+name.toLowerCase()+’%’);
if(age!=0)query.setInteger(“age”,newInteger(age));
return query.list();
}
上面的代码虽然可以正常工作,但是把简单的功能实现的相当复杂,l护h不方ѝ我们来看一下用QBC查询?
Public List findStu(String name, int age){
Criteria crit= getSession().createCriteria(Student.class);
if(name!=null){
crit.add(Restrictions.like(“name”,name,MatchMode.ANYWHERE));
}if(age!=0){
crit.add(Restrictions.eq(“age”,newInteger(age)));
}
crit.addOrder(Order.asc(“name”));
return crit.list();
}
6. Hibernate问题
?nbsp; a different object with the same identifier value was already associated with the session是什么原因导致的Q?
在hibernate中同一个session里面有了两个相同标识但是是不同实体,当这时运行saveOrUpdate(object)操作的时候就会报q个错误。种错误l常出现在一对多映射和多对多映射
在hibernate的开发中QHBM文g中会涉及到n2m的种U关p,但是Q只有在Z必要性考虑的时候,才加上cascade="all" Q同Ӟ需心规避由此引v的程序ExceptionQ?
考虑不周Q会D可能出现的最常见Exception是:
net.sf.hibernate.NonUniqueObjectException
a different object with the same identifier value was already associated with the session:......
解决办法是:
1. L引vException的associated ClassҎ(gu)HBM中的不必要cascadeQ?
2. 查Exception发生位置的session的用情况;
?nbsp; Object references an unsaved transient instance-save the transient instance before flushing是什么原因导致的Q?
某个对象的某个属性是一个实体,在这个实体没有保存之前就保存q个对象而造成了这个错误?
以下举个例子说明以下
Session session = dao.getSession();
Transaction tx = session.beginTransaction();
Bo.setBman( form ,man,session);
Bo.saveChangeTable( man,session); // 把man当作属性赋lChangeTable,q保存ChangeTable. 是q出的错Q?
dao.save(man,session); // 保存man
tx.commit();
==================== 应该q样写:===============
Session session = dao.getSession();
Transaction tx = session.beginTransaction();
Bo.setBman( form ,man,session);
dao.save(man,session); // 保存man
Bo.saveChangeTable( man,session); // 把man当作属性赋lChangeTable,q保存ChangeTable
tx.commit();
q样Q问题就解决了?
?nbsp; 如果修改一个列表中的一个数据,会发现这个数据不E_Q一会是修改后的Q一会是修改前的Q说出其原因
因ؓhibernate利用了缓存技术,sql适时提交Q当数据修改以后Q数据ƈ不一定及时提交到数据库,而是攑֜hibernate的缓存中Q当我们察看数据Ӟ可能是提交完的,也可能是没有提交的,所以就会出现数据的脏读?
如何避免使用~存技术所带来的脏数据问题呢?
在设计、实现和试Ӟ应该清晰定义~存数据的更斎ͼ
i. 不考虑~存数据的更斎ͼ重启软gpȝ是一U必要的方式Q?
ii. 不考虑~存数据的更斎ͼ~存数据不可能成数据(但在软gpȝ中,往往“不可?#8221;会在一ơ又一ơ的重构之后变ؓ“可能”)Q?
iii. 考虑~存数据的更斎ͼ当源数据变化Ӟ实时更新~存数据?
?nbsp; 对于数据库自增长来说Q在映射文g中主键配|,用哪U配|方案最好,最不容易出现问题?
Hibernate标识生成{略Q?
标识W生成器 描述
increment 适用于代理主键。由Hibernate自动以递增方式生成?
identity 适用于代理主键。由底层数据库生成标识符?
sequence 适用于代理主键。HibernateҎ(gu)底层数据库的序列生成标识W,q要求底层数据库支持序列?
hilo 适用于代理主键。Hibernate分局high/low法生成标识W?
seqhilo 适用于代理主键。用一个高/低位法来高效的生成longQshort或者intcd的标识符?
native适用于代理主键。根据底层数据库对自动生成标识符的方式,自动选择identity、sequence或hilo?
uuid.hex 适用于代理主键。Hibernate采用128位的UUID法生成标识W?
uuid.string 适用于代理主键。UUID被编码成一?6字符长的字符丌Ӏ?
assigned 适用于自然主键。由Java应用E序负责生成标识W?
foreign 适用于代理主键。用另外一个相兌的对象的标识W?
p个问题我认ؓ应该用increment、native都可?
7. 概括你常用的框架的优~点?
1. Struts的优~点Q?
具体来讲QStruts的优Ҏ(gu)Q?
1. 实现MVC模式Q结构清?使开发者只x业务逻辑的实?
2. 有丰富的tag可以?,Struts的标记库(Taglib)Q如能灵zd用,则能大大提高开发效率。另外,q前国内的JSP开发者而言Q除了用JSP自带的常用标记外Q很开发自q标记Q或许Struts是一个很好的L?
3. 面D.面D是今后的一个发展方向,事实上,q样做,使系l的脉络更加清晰。通过一个配|文Ӟ卛_把握整个pȝ各部分之间的联系Q这对于后期的维护有着莫大的好处。尤其是当另一批开发者接手这个项目时Q这U优势体现得更加明显?
4. 提供Exception处理机制 .
5. 数据库链接池理
6. 支持I18N
~点Q?
一?转到展示层时Q需要配|forwardQ每一ơ{到展C层Q相信大多数都是直接转到jspQ而涉及到转向Q需要配|forwardQ如果有十个展示层的jspQ需要配|十ơstrutsQ而且q不包括有时候目录、文件变_需要重C改forwardQ注意,每次修改配置之后Q要求重新部|整个项目,而tomcateq样的服务器Q还必须重新启动服务器,如果业务变更复杂频繁的系l,q样的操作简单不可想象。现在就是这P几十上百个h同时在线使用我们的系l,大家可以惌一下,我的烦恼有多大?
二?Struts 的Action必需是threadQsafe方式Q它仅仅允许一个实例去处理所有的h。所以action用到的所有的资源都必需l一同步Q这个就引v了线E安全的问题?
三?试不方? Struts的每个Action都同Web层耦合在一Pq样它的试依赖于Web容器Q单元测试也很难实现。不q有一个Junit的扩展工具Struts TestCase可以实现它的单元试?
四?cd的{? Struts的FormBean把所有的数据都作为StringcdQ它可以使用工具Commons-Beanutilsq行cd转化。但它的转化都是在ClassU别Q而且转化的类型是不可配置的。类型{化时的错误信息返回给用户也是非常困难的?
五?对Servlet的依赖性过? Struts处理Action时必需要依赖ServletRequest 和ServletResponseQ所有它摆脱不了Servlet容器?
六?前端表达式语a斚w.Struts集成了JSTLQ所以它主要使用JSTL的表辑ּ语言来获取数据。可是JSTL的表辑ּ语言在Collection和烦引属性方面处理显得很弱?
七?对Action执行的控制困? Struts创徏一个ActionQ如果想控制它的执行序会非常困难。甚至你要重新去写Servlet来实C的这个功能需求?
八?对Action 执行前和后的处理. Struts处理Action的时候是Zclass的hierarchiesQ很隑֜action处理前和后进行操作?
?ji)?对事件支持不? 在struts中,实际是一个表单Form对应一个Actionc?或DispatchAction)Q换一句话_在Struts中实际是一个表单只能对应一个事Ӟstrutsq种事g方式UCؓapplication eventQapplication event和component event相比是一U粗_度的事件?
Struts重要的表单对象ActionForm是一U对象,它代表了一U应用,q个对象中至包含几个字D,q些字段是Jsp面表单中的input字段Q因Z个表单对应一个事Ӟ所以,当我们需要将事g_度l化到表单中q些字段Ӟ也就是说Q一个字D对应一个事件时Q单U用Struts׃太可能,当然通过l合JavaScript也是可以转弯实现的?
2QHibernate的优~点Q?
Hibernate是一个开放源代码的对象关pL框Ӟ它对JDBCq行了非常轻量的对象封装,使得JavaE序员可以随心所Ʋ的使用对象~程思维来操U|据库?
Hibernate可以应用在Q何用JDBC的场合,既可以在Java的客LE序实用Q也可以在Servlet/JSP的Web应用中用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMPQ完成数据持久化的重仅R?
大多数开发机构经帔R取创建各自独立的数据持久层。一旦底层的数据l构发生改变Q那么修改应用的其余部分使之适应q种改变的代价将是十分巨大的。Hibernate适时的填补了q一I白Q它为Java应用提供了一个易用的、高效率的对象关pL框架。hibernate是个轻量U的持久性框Ӟ功能却非怸富?
优点Q?
a. Hibernate 使用 Java 反射机制而不是字节码增强E序来实现透明性?
b. Hibernate 的性能非常好,因ؓ它是个轻量框架。映的灉|性很?
c. 它支持各U关pL据库Q从一对一到多对多的各U复杂关pR?
~点Q它限制(zhn)所使用的对象模型?例如Q一个持久性类不能映射到多个表)其独有的界面和可怜的市场份额也让Z安,管如此QHibernate q是以其强大的发展动力减Mq些风险。其他的开源持久性框架也有一些,不过都没?Hibernate q样有市场冲d?
3Q?Spring框架的优~点
它是一个开源的目Q而且目前非常z跃Q它ZIoCQInversion of ControlQ反向控Ӟ和AOP的构架多层j2eepȝ的框Ӟ但它不强q你必须在每一层中必须使用SpringQ因为它模块化的很好Q允怽Ҏ(gu)自己的需要选择使用它的某一个模块;它实C很优雅的MVCQ对不同的数据访问技术提供了l一的接口,采用IoC使得可以很容易的实现bean的装配,提供了简z的AOPq据此实现Transcation ManagmentQ等{?
优点
a. Spring能有效地l织你的中间层对象,不管你是否选择使用了EJB。如果你仅仅使用了Struts或其他ؓJ2EE?API特制的frameworkQSpring致力于解军_下的问题?
b. Spring能消除在许多工程中常见的对Singleton的过多用。根据我的经验,q是一个很大的问题Q它降低了系l的可测试性和面向对象的程度?
c. 通过一U在不同应用E序和项目间一致的Ҏ(gu)来处理配|文ӞSpring能消除各U各栯定义格式的属性文件的需要。曾l对某个c要L的是哪个法般的属性项或系l属性感C解,为此不得不去读Javadoc甚至源编码?有了SpringQ你仅仅需要看看类的JavaBean属性。Inversion of Control的用(在下面讨论)帮助完成了这U简化?
d. 通过把对接口~程而不是对cȝE的代h(hun)几乎减少到没有,Spring能够促进L好的~程习惯?
e. Spring被设计ؓ让用它创徏的应用尽可能的依赖于他的APIs。在Spring应用中的大多C务对象没有依赖于Spring?
f. 使用Spring构徏的应用程序易于单元测试?
g. Spring能EJB的用成Z个实现选择,而不是应用架构的必然选择。你能选择用POJOs或local EJBs来实C务接口,却不会媄响调用代码?
h. Spring帮助你解册多问题而无需使用EJB。Spring能提供一UEJB的替换物Q它们适用于许多web应用。例如,Spring能用AOP提供声明性事务管理而不通过EJB容器Q如果你仅仅需要与单个数据库打交道Q甚至不需要一个JTA实现?
i. Spring为数据存取提供了一个一致的框架,不论是用的是JDBCq是O/R mapping产品
Spring实使你能通过最单可行的解决办法来解决你的问题。而这是有有很大h(hun)值的?
~点Q用hC多、jsp中要写很多代码、控制器q于灉|Q缺一个公用控制器
8. 是否了解设计模式Q将几种常用的设计模式的思想、ƈ举例?
创徏模式Q?
Factory、PrototypeQ原型)、Builder、Singleton
l构模式Q?
Facade(外观)、Proxy(代理)、Adapter(适配?、Composite(l合)、Decorator(Ҏ(gu)?、Bridge、Flyweight(享元)
行ؓ模式Q?
Template、Memento(备忘机制)、Observer、Chain of Responsibility(职责?、Command、State、Strategy({略)、Mediator(中介?、Interdivter(解释?、Visitor
9. 面重复hQ如何解冻I客户的行为是无法控制的,那如何控制客L重复hD的重复提交?
Jsp防止面h表单自提交重复提交思\Q?
1. 提交后禁用提交按钮(大部分h都是q样做的Q?
2. 用javascript实现
10. 如何_记录同时在线人数
我们可以利用Servlet规范中定义的事g监听器(ListenerQ来解决q个问题Q实现更准确的在Uh数统计功能。对每一个正在访问的用户QJ2EE应用服务器会为其建立一个对应的HttpSession对象。当一个浏览器W一ơ访问网站的时候,J2EE应用服务器会新徏一个HttpSession对象Qƈ触发HttpSession创徏事gQ如果注册了HttpSessionListener事g监听器,则会调用HttpSessionListener事g监听器的sessionCreatedҎ(gu)。相反,当这个浏览器讉Kl束时的时候,J2EE应用服务器会销毁相应的HttpSession对象Q触发HttpSession销毁事Ӟ同时调用所注册HttpSessionListener事g监听器的sessionDestroyedҎ(gu)?
可见Q对应于一个用戯问的开始和l束Q相应的有sessionCreatedҎ(gu)和sessionDestroyedҎ(gu)执行。这P我们只需要在HttpSessionListener实现cȝsessionCreatedҎ(gu)中让计数器加1Q在sessionDestroyedҎ(gu)中让计数器减1Q就L实现了网站在Uh数的l计功能?
下面是利用HttpSessionListener实现在线人数l计的一个例子,q个例子已经在中创Y件的J2EE应用服务器InforWeb中测试通过?
首先Q编写一个简单的计数器,代码如下Q?
package gongfei.cmc.articles.onlinecounter;
public class OnlineCounter {
private static long online = 0;
public static long getOnline() {
return online;
}
public static void raise(){
online++;
}
public static void reduce(){
online--;
}
}
然后Q编写HttpSessionListener实现c,在这个实现类的sessionCreatedҎ(gu)中调用OnlineCounter的raiseҎ(gu)Q在sessionDestroyedҎ(gu)中调用OnlineCounter的reduceҎ(gu)Q代码如下:
package gongfei.cmc.articles.onlinecounter;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class OnlineCounterListener implements HttpSessionListener {
public void sessionCreated(HttpSessionEvent hse) {
OnlineCounter.raise();
}
public void sessionDestroyed(HttpSessionEvent hse) {
OnlineCounter.reduce();
}
}
再然后,把这个HttpSessionListener实现cL册到|站应用中,也就是在|站应用的web.xml中加入如下内容:
<web-app>
……
<listener>
<listener-class>
gongfei.cmc.articles.example.OnlineCounterListener
</listener-class>
</listener>
……
</web-app>
OKQ在Uh数统计功能已l实玎ͼ只要在JSP面中加入下面这L脚本p昄但前在线人数了:
<%@ page language="java" pageEncoding="GB2312" %>
<%@ page language="java" pageEncoding="GB2312" %>
<%@ page import="gongfei.cmc.articles.onlinecounter.OnlineCounter" %>
<html>
<head><title>On Line Counert</title></head>
<body bgcolor="#FFFFFF">
On line:<%=OnlineCounter.getOnline()%>
</body>
</html>
11. q解决Ҏ(gu)。是否遇到过Q有哪些Q讲解具体遇到的情ŞQƈ说出你在具体的应用中的解x案?
1.JSP输出中文的ؕ码问?
所谓在jsp输出中文Q即直接在jsp中输Z文,或者给变量赋中文值再输出{,q种情况下的q问题往往是因为没有给jsp面制定昄中文字符的编码方式,解决办法如下Q?
1)在jsp面头部加上语句<%@ page contentType="text/html;charset=utf-8"%>(在Servlet中用httpServletResponse.setContentTypeQ?text/html;charset=utf-8"Q,最好同时在jsp面的head部分加上<meta http-equiv="Content-Type" content="text/html;charset="utf-8">
2)在每ơ要输出中文的地方主动{换编码方式,比如要在面中输?#8220;中文”二字Q就可以用以下的Ҏ(gu)Q?
<%
String str="中文";
byte[] tmpbyte=str.getBytes("ISO8859_1");
str=new String(tmpbyte);
out.println(str);
%>
对于以上q两U方法,昄W一U方法更通用一点,只需要在一个页面中d一ơ代码即可;而对于第二种Ҏ(gu)Q在每个需要输Z文的地方都需要{码,如果q样的地方很多,q将是一个繁重的工作?
2.获取表单提交的数据时的中文ؕ码问?
在没有加M其他处理之前Q用request.getParameter("paramName")获取表单提交中的数据Q且表单数据中含有中文时Q返回的字符串会呈现q。出现这U问题的原因是Tomcat的j2ee实现对表单提交,即以POST方式提交的参数采用默认的ISO-8859-1来处理?
解决此问题的办法有两个:
1)不修改其他配|,只是在将表单中的中文数据区出来后再{换编码,Ҏ(gu)如语?String str=request.getParameter("chStr");String str = new String(str.getBytes("ISO-8859-1"),"UTF-8");但这U方法只是从一个局部来考虑问题Q如果这L情况很多Q就要写很多ơ,势必加大工作量?
2)让对所有页面的h都通过一个FilterQ将处理字符集设|ؓutf-8Q根据自己需要也可以讄成其他的Q如gb2312QgbkQ。具体做法参考Tomcat的webapps/servlet-exemples目录有一个完整的例子,也可以参考其中web.xml和SetCharacterEncodingFilter的配|?
3.URL中的中文问题
对于直接通过在url中传递中文参??a href="http://localhost:8080/a.jsp?str">http://localhost:8080/a.jsp?str="中文"q样的gethQ在服务器端用request.getParameter("name")时返回的往往是ؕ码。按照以上的做法讄Filter没有用,用request.setCharacterEncoding("utf-8")的方式,仍然不管用。造成q种l果的原因是Tomcat中以get方式提交的请求对query-string处理旉用了和postҎ(gu)不一L处理方式?
解决q个问题的方法是是打开Tomcat安装目录下的/conf/server.xml文g,扑ֈConnector?往其中dURLEncoding="utf-8"/>
4.数据库访问时的ؕ码问?
数据库中所有表的编码方式和jsp中的使用的编码要保持一?q样做的目的可以减少不必要的~码转换问题.另外,在用jdbcq接MySQL数据库时,q接字符串写成如下Ş式可以避免一些中文问?
jdbc://mysql://hostname:port/DBname?user=username&password=pwd&useUnicode=true&character Encoding=utf-8
如果是以数据源的方式q接数据库,配置文g中用:
<parameter>
<name>url</name>
<value>jdbc:mysql://hostname:port/DBname?&useUnicode=true&characterEncoding=utf-8
</value>
</parameter>
但是如果使用一个已l存在的数据库,数据库的~码方式为ISO-8859-1Q而Web应用中用的utf-8Q且数据库已l有很多重要的信息,因此不能通过更改数据库的~码方式来解冟뀂这个时候,在往数据库中写数据时Q一定要在jdbcq接字符串中加入“useUnicode=true&characterEncoding=ISO-8859-1”Q这样可以顺利的王数据库写入正常的数据。但是,在将数据d数据库时Qؕ码又会出玎ͼq个时候就应该在数据取出时对其转码Q可以将转码功能写ؓ一个函敎ͼ具体实现如下Q?
public String charConvert(String src){
String result=null;
if(src!=null){
try{
result=new String(src.getBytes("ISO-8859-1"),"UTF-8");
}catch(Exception e){
result=null;
}
}
return result;
}
于是Q在数据库读出数据过后调用charConvert(rs.getString("colName"));q样可以正常的昄数据库中的中文数据了?/p>