??xml version="1.0" encoding="utf-8" standalone="yes"?> <data-sources>
<data-source key="rki" type="org.apache.commons.dbcp.BasicDataSource"> //type代表c,rki表示当有多个数据源时?br />//当于一个烦引,id?/span>
<set-property property="driverClassName" value="org.gjt.mm.mysql.Driver" />//q接mysql所需的类?/span>
<set-property property="url" value="jdbc:mysql://172.20.0.40:3306/test?useUnicode=true&characterEncoding=GBK" />
<set-property property="username" value="root" />
<set-property property="password" value="你的密码" />
<set-property property="maxActive" value="10" />
<set-property property="maxWait" value="500" />
<set-property property="defaultAutoCommit" value="false" />
<set-property property="defaultReadOnly" value="false" />
</data-source>
</data-sources>
datasource = getDataSource(request, "rki");
conn = datasource.getConnection();
Statement state = conn.createStatement();
System.out.println("hello");
String sql = "select * from notice where title='test'";
ResultSet rs = state.executeQuery(sql);
while (rs.next())
{
request.getSession().setAttribute("cont",
rs.getString("content"));
System.out.println("database connect true");
}
rs.close();
]]>
2Q如果没有封装的话,那么是不是需要在Action中把Actionform通过request.setAttribute("","")攑ֈrequest?br />q是要放到Session中,
我测试时候出的问?br /> 有一ơ就是在1Q的情况下测试成功的Q但是以后再怎么试都不行Q那ơ是引用的Struts-config.xml里给ActionForm定义的类名。非常奇怪,
q有是2Q的情况Q测试中如果Action和Frombean在一个包下面Q那么通过request.setAttribute("","")Q就可以获取到BeanQ如果不是的话,有时候行Q有时候不行,
如果通过request.getSession.setAttribute()讄ActionForm的话Q每ơ都可以Q他们的Scope肯定在一个Request中,那么Z么Session可以,而Request不行?l论Q因为是在Actionfoward中设|了“redirect='true'Q这L话一跌{ӞRequest中的内容都会被重|,所以不行,把这一句去掉就可以?/strong>?
源代?br />Strust-config.xml
Listing 1 //... //initialize RequestDispatcher object; set forward to home page by default RequestDispatcher rd = request.getRequestDispatcher("home.jsp"); //Prepare connection and statement rs = stmt.executeQuery("select password from USER where userName = '" + userName + "'"); if (rs.next()) { //Query only returns 1 record in the result set; only 1 password per userName which is also the primary key if (rs.getString("password").equals(password)) { //If valid password session.setAttribute("User", userName); //Saves username string in the session object } else { //Password does not match, i.e., invalid user password request.setAttribute("Error", "Invalid password."); rd = request.getRequestDispatcher("login.jsp"); } } //No record in the result set, i.e., invalid username else { request.setAttribute("Error", "Invalid user name."); rd = request.getRequestDispatcher("login.jsp"); } } //As a controller, loginAction.jsp finally either forwards to "login.jsp" or "home.jsp" rd.forward(request, response); //... |
Listing 2 //... session.removeAttribute("User"); session.invalidate(); //... |
Listing 3 //... String userName = (String) session.getAttribute("User"); if (null == userName) { request.setAttribute("Error", "Session has ended. Please login."); RequestDispatcher rd = request.getRequestDispatcher("login.jsp"); rd.forward(request, response); } //... //Allow the rest of the dynamic content in this JSP to be served to the browser //... |
//... response.setHeader("Cache-Control","no-cache"); //Forces caches to obtain a new copy of the page from the origin server response.setHeader("Cache-Control","no-store"); //Directs caches not to store the page under any circumstance response.setDateHeader("Expires", 0); //Causes the proxy cache to see the page as "stale" response.setHeader("Pragma","no-cache"); //HTTP 1.0 backward compatibility String userName = (String) session.getAttribute("User"); if (null == userName) { request.setAttribute("Error", "Session has ended. Please login."); RequestDispatcher rd = request.getRequestDispatcher("login.jsp"); rd.forward(request, response); } //... |
//... RequestDispatcher rd = request.getRequestDispatcher("home.jsp"); //Forward to homepage by default //... if (rs.getString("password").equals(password)) { //If valid password long lastLogonDB = rs.getLong("lastLogon"); if (lastLogonForm Q?lastLogonDB) { session.setAttribute("User", userName); //Saves username string in the session object stmt.executeUpdate("update USER set lastLogon= " + lastLogonForm + " where userName = '" + userName + "'"); } else { request.setAttribute("Error", "Session has ended. Please login."); rd = request.getRequestDispatcher("login.jsp"); } } else { //Password does not match, i.e., invalid user password request.setAttribute("Error", "Invalid password."); rd = request.getRequestDispatcher("login.jsp"); } //... rd.forward(request, response); //... |
public abstract class BaseAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form,HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { response.setHeader("Cache-Control","no-cache"); //Forces caches to obtain a new copy of the page from the origin server response.setHeader("Cache-Control","no-store"); //Directs caches not to store the page under any circumstance response.setDateHeader("Expires", 0); //Causes the proxy cache to see the page as "stale" response.setHeader("Pragma","no-cache"); //HTTP 1.0 backward compatibility if (!this.userIsLoggedIn(request)) { ActionErrors errors = new ActionErrors(); errors.add("error", new ActionError("logon.sessionEnded")); this.saveErrors(request, errors); return mapping.findForward("sessionEnded"); } return executeAction(mapping, form, request, response); } protected abstract ActionForward executeAction(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException; private boolean userIsLoggedIn(HttpServletRequest request) { if (request.getSession().getAttribute("User") == null) { return false; } return true; } } |
Qaction path="/secure1" type="com.kevinhle.logoutSampleStruts.Secure1Action" scope="request"Q?BR>Qforward name="success" path="/WEB-INF/jsps/secure1.jsp"/Q?BR>Qforward name="sessionEnded" path="/login.jsp"/Q?BR>Q?actionQ?/TD> |
public class Secure1Action extends BaseAction { public ActionForward executeAction(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { HttpSession session = request.getSession(); return (mapping.findForward("success")); } } |
Struts的TokenQo牌)机制能够很好的解册单重复提交的问题Q基本原理是Q服务器端在处理到达的请求之前,会将h中包含的令牌?/I>与保存在当前用户会话中的令牌D行比较,看是否匹配。在处理完该h后,且在{复发送给客户端之前,会产生一个新的o牌,该o牌除传给客户端以外,也会用户会话中保存的旧的o牌进行替换。这样如果用户回退到刚才的提交面q再ơ提交的话,客户端传q来的o牌就和服务器端的令牌不一_从而有效地防止了重复提交的发生?/P>
q时其实也就是两点,W一Q你需要在h中有q个令牌|h中的令牌值如何保存,其实和我们qx在页面中保存一些信息是一LQ通过隐藏字段来保存,保存的Ş式如Q?〈input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="6aa35341f25184fd996c4c918255c3ae"〉,q个value是TokenProcessorcM的generateToken()获得的,是根据当前用Lsession id和当前时间的long值来计算的。第二:在客L提交后,我们要根据判断在h中包含的值是否和服务器的令牌一_因ؓ服务器每ơ提交都会生成新的TokenQ所以,如果是重复提交,客户端的Token值和服务器端的Token值就会不一致。下面就以在数据库中插入一条数据来说明如何防止重复提交?/P>
在Action中的addҎ中,我们需要将Token值明的要求保存在页面中Q只需增加一条语句:saveToken(request);Q如下所C:
public ActionForward add(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
//前面的处理省?BR>saveToken(request);
return mapping.findForward("add");
}在Action的insertҎ中,我们Ҏ表单中的Tokeng服务器端的Token值比较,如下所C:
public ActionForward insert(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
if (isTokenValid(request, true)) {
// 表单不是重复提交
//q里是保存数据的代码
} else {
//表单重复提交
saveToken(request);
//其它的处理代?BR>}
}
其实使用h很简单,举个最单、最需要用这个的例子Q?BR>一般控刉复提交主要是用在Ҏ据库操作的控制上Q比如插入、更新、删除等Q由于更新、删除一般都是通过id来操作(例如QupdateXXXById, removeXXXByIdQ,所以这cL作控制的意义不是很大Q不排除个别现象Q,重复提交的控制也׃要是在插入时的控制了?BR>
先说一下,我们目前所做项目的情况Q?BR>目前的项目是用StrutsQSpringQIbatisQ页面用jstlQStruts复杂View层,Spring在Service层提供事务控ӞIbatis是用来代替JDBCQ所有页面的讉K都不是直接访问jspQ而是讉KStructs的ActionQ再由Action来ForwardC个JspQ所有针Ҏ据库的操作,比如取数据或修改数据Q都是在Action里面完成Q所有的Action一般都l承BaseDispatchActionQ这个是自己建立的类Q目的是为所有的Action做一些统一的控Ӟ在Struts层,对于一个功能,我们一般分Z个ActionQ一个Action里的功能是不需要调用Struts的验证功能的Q常见的Ҏ名称有add,edit,remove,view,listQ,另一个是需要调用Struts的验证功能的Q常见的Ҏ名称有insert,updateQ?BR>
拿论坛发脓来说吧,论坛发脓首先需要蟩转到一个页面,你可以填写帖子的主题和内容,填写完后Q单几Z提交”,贴子发表了Q所以这里经q两个步骤:
1、{C个新增的面Q在Action里我们一般称为addQ例如:
public ActionForward add(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
//q一句是输出调试信息Q表CZ码执行到q一D了
log.debug(":: action - subject add");
//your code here
//q里保存Token?BR> saveToken(request);
//跌{到add面Q在Structs-config.xml里面定义Q例如,跌{到subjectAdd.jsp
return mapping.findForward("add");
}
2、在填写标题和内容后Q选择 提交 Q会提交到insertҎQ在insertҎ里判断,是否重复提交了?BR>public ActionForward insert(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response){
if (isTokenValid(request, true)) {
// 表单不是重复提交
//q里是保存数据的代码
} else {
//表单重复提交
saveToken(request);
//其它的处理代?BR>}
}
下面更详l一点(注意Q下面所有的代码使用全角括号Q:
1、你惛_贴时Q点几Z我要发贴”链接的代码可以里这LQ?BR>〈html:link action="subject.do?method=add"〉我要发贴?html:link?BR>subject.do ?method q些在struct-config.xml如何定义我就不说了,点击链接后,会执行subject.do的addҎQ代码如上面说的Q蟩转到subjectAdd.jsp面。页面的代码大概如下Q?BR>〈html:form action="subjectForm.do?method=insert"?BR> 〈html:text property="title" /?BR> 〈html:textarea property="content" /?BR> 〈html:submit property="发表" /?BR> 〈html:reset property="重填" /?BR>〈html:form?BR>如果你在addҎ里加了“saveToken(request);”这一句,那在subjectAdd.jsp生成的页面上Q会多一个隐藏字D,cM于这栗input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="6aa35341f25184fd996c4c918255c3ae"〉,
2、点d表后Q表单提交到subjectForm.do里的insertҎ后,你在insertҎ里要表单的数据插入到数据库中,如果没有q行重复提交的控Ӟ那么每点Mơ浏览器的刷新按钮,都会在数据库中插入一条相同的记录Q增加下面的代码Q你可以控制用L重复提交了?BR>if (isTokenValid(request, true)) {
// 表单不是重复提交
//q里是保存数据的代码
} else {
//表单重复提交
saveToken(request);
//其它的处理代?BR>}
注意Q你必须在addҎ里用了saveToken(request)Q你才能在insert里判断,否则Q你每次保存操作都是重复提交?BR>C一点,Struts在你每次讉KAction的时候,都会产生一个o牌,保存在你的Session里面Q如果你在Action里的函数里面Q用了saveToken(request);Q那么这个o牌也会保存在q个Action所Forward到的jsp所生成的静态页面里?BR>如果你在你Action的方法里使用了isTokenValidQ那么Struts会将你从你的request里面去获取这个o牌|然后和Session里的令牌值做比较Q如果两者相{,׃是重复提交,如果不相{,是重复提交了?BR>
׃我们目的所有Action都是l承自BaseDispatchActionq个c,所以我们基本上都是在这个类里面做了表单重复提交的控Ӟ默认是控制addҎ和insertҎQ如果需要控制其它的ҎQ就自己手动写上面这些代码,否则是不需要手写的Q控制的代码如下Q?BR>public abstract class BaseDispatchAction extends BaseAction {
protected ActionForward perform(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
String parameter = mapping.getParameter();
String name = request.getParameter(parameter);
if (null == name) { //如果没有指定 method Q则默认?list
name = "list";
}
if ("add".equals(name)) {
if ("add".equals(name)) {
saveToken(request);
}
} else if ("insert".equals(name)) {
if (!isTokenValid(request, true)) {
resetToken(request);
saveError(request, new ActionMessage("error.repeatSubmit"));
log.error("重复提交Q?);
return mapping.findForward("error");
}
}
return dispatchMethod2(mapping, form, request, response, name);
}
}
|
|
|
|
|
|
|
|