技术关键在于学习其原理,而不是浅浅淡淡的会用,免得别人问起的时候什么也不知道,尤其是在面试时! 首先页面上的数据请求被发送到服务器,此时的请求先进入到前端控制器(ActionServlet)。ActionServlet再将请求转发给后端控制器(Action),在转发中顺便送了一份礼物form(ActionForm),在Action中对form中的数据做实际的处理操作并返回一份礼物forward(ActionForward)给ActionServlet,ActionServlet收到这份礼物后根据其中的关键字从struts配置文件Struts-config.xml中获取具体的跳转页。 那么ActionServlet是怎么知道该找哪个后端控制器呢?又是怎么知道返回的ActionForward具体是什么呢?为了回答这个问题,我们参考一个用Struts做的登陆程序。
登陆表单代码:
<%@ page language= "java" import = "java.util.*" pageEncoding= "UTF-8" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" >
<html>
<head>
<title>struts工作流程分析</title>
</head>
<body>
<form action= "login.do" method= "POST" >
用户名:<input type= "text" name= "userName" ><br/>
密码:<input type= "password" name= "userPwd" ><br/>
<input type= "submit" value= "登录" >
</form>
</body>
</html>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <title>struts工作流程分析</title> </head> <body> <form action="login.do" method="POST"> 用户名:<input type="text" name="userName"><br/> 密码:<input type="password" name="userPwd"><br/> <input type="submit" value="登录"> </form> </body></html>
LoginAction代码:
package cn.ineeke.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import cn.ineeke.form.LoginForm;
*作者:Neeke
*BLOG:http://www.ineeke.com
*/
public class LoginAction extends Action {
@Override
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
LoginForm loginForm = (LoginForm)form;
String forwardName = "failure" ;
if (loginForm.getUserName().equals( "neeke" ) && loginForm.getUserPwd().equals( "123456" )){
forwardName = "success" ;
}
return mapping.findForward(forwardName);
}
}
package cn.ineeke.action;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.struts.action.Action;import org.apache.struts.action.ActionForm;import org.apache.struts.action.ActionForward;import org.apache.struts.action.ActionMapping;import cn.ineeke.form.LoginForm;/** *作者:Neeke *BLOG:http://www.ineeke.com */public class LoginAction extends Action { @Override public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { LoginForm loginFor
m = (LoginForm)form; String forwardName = "failure"; if(loginForm.getUserName().equals("neeke") && loginForm.getUserPwd().equals("123456")){ forwardName = "success"; } return mapping.findForward(forwardName); }}
LoginForm代码:
package cn.ineeke.form;
import org.apache.struts.action.ActionForm;
public class LoginForm extends ActionForm {
private String userName = null ;
private String userPwd = null ;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this .userName = userName;
}
public String getUserPwd() {
return userPwd;
}
public void setUserPwd(String userPwd) {
this .userPwd = userPwd;
}
}
package cn.ineeke.form;import org.apache.struts.action.ActionForm;public class LoginForm extends ActionForm { private String userName = null; private String userPwd = null; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getUserPwd() { return userPwd; } public void setUserPwd(String userPwd) { this.userPwd = userPwd; }}
Struts-config.xml文件:
<? xml version = "1.0" encoding = "UTF-8" ?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN" "http://struts.apache.org/dtds/struts-config_1_3.dtd" >
< struts-config >
< form-beans >
< form-bean name = "loginForm" type = "cn.ineeke.form.LoginForm" > </ form-bean >
</ form-beans >
< action-mappings >
< action path = "/login" type = "cn.ineeke.action.LoginAction" name = "loginForm" >
< forward name = "success" path = "/success.jsp" > </ forward >
< forward name = "failure" path = "/failure.jsp" > </ forward >
</ action >
</ action-mappings >
< message-resources parameter = "cn.ineeke.struts.ApplicationResources" />
</ struts-config >
<?xml version="1.
0" encoding="UTF-8"?><!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN" "http://struts.apache.org/dtds/struts-config_1_3.dtd"><struts-config> <form-beans> <form-bean name="loginForm" type="cn.ineeke.form.LoginForm"></form-bean> </form-beans> <action-mappings> <action path="/login" type="cn.ineeke.action.LoginAction" name="loginForm"> <forward name="success" path="/success.jsp"></forward> <forward name="failure" path="/failure.jsp"></forward> </action> </action-mappings> <message-resources parameter="cn.ineeke.struts.ApplicationResources" /></struts-config>
当我们的表单提交给login.do的时候,ActionServlet就会去读取Struts-config.xml文件并根据<action path="/login" type="cn.ineeke.action.LoginAction" name="loginForm">中的type属性找到具体的后端控制器LoginAction,与此同时又根据name属性找到<form-bean name="loginForm" type="cn.ineeke.form.LoginForm"></form-bean>并将表单中的数据存储在LoginForm的实例中(这个实例就是前端控制器送给后端控制器的礼物了),在LoginAction的execute方法中进行数据处理并返回一个ActionForward对象(回赠一份礼物)给ActionServlet。最后ActionServlet再根据这份礼物的关键字在 <forward name="success" path="/success.jsp"></forward> <forward name="failure" path="/failure.jsp"></forward> 中进行查找,并跳转到相应的path。
这是本次项目的最后一个问题了,把这个问题解决了,项目就彻底竣工了。先说说要达到的效果:点击一个关键字,使用URL重写传值给Servlet,然后从数据库中查出所有包含这个关键字的文章。 然而在JSP中我们点击这样一个超级链接:http://localhost:8080/wwwroot/tagservlet?tag =数据库 可是这样传递的值我们在Servlet中是没法获取到的,我们需要对这里的汉字进行URL编码,这样我们才能够在Servlet中使用request.getParameter("tag")获得我们传递过来的值。为此,我们需要导入java.net.URLEncoder这个包,接下来使用URLEncoder.encode("数据库")来将“数据库”这三个字进行转码得到的结果是“%CA%FD%BE%DD%BF%E2”,如此一来我们的链接就变为了:http://localhost:8080/wwwroot/tagservlet?tag=%CA%FD%BE%DD%BF%E2 然而,当用request.getParameter("tag")获取这个值并将其输出,你会发现是一堆“?”,这里还得在转码才能得到汉字: String tag = request.getParameter("tag"); tag = new String(tag.getBytes("ISO-8859-1"),"GBK"); 这下终于好了,为什么汉字总是这么麻烦,老要转来转去的,老外的字母就没有问题…
虽然也学了这么久的J2EE了(基础型),但是我一直都搞不明白:MVC模式是要分三层的,显示层、控制层(业务逻辑层)及数据层,业务逻辑层才能访问数据层,而显示层不能够直接访问数据层。既然如此,那么网站的首页所需要的数据都是来自数据库的,是要动态读取的,这就要在jsp中直接访问数据层,岂不是相互矛盾了吗? 去了几个技术论坛看了看,有人说那只是一个高效的框架模型,不一定非要遵守,可以直接在首页jsp中调用数据层的方法,活人岂能被尿憋死?话虽说有那么点道理,不过我还是不想这么试。 我是这么想的: 方法1.能不能打开网站地址时候访问的第一个文件是一个Servlet,在Servlet中获得首页用于显示所需要的所有数据,然后将它放在request中,接着在使用 request.getRequestDispatcher("index.jsp").forward(request, response); 跳转到真实的首页,如此即可在index.jsp中从request中获得所要的数据了。那么,如何才能打开网址就直接访问Servlet呢?在网站的根目录下WEB-INF中的web.xml中有这么一对标签: <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> 类似于配置IIS中的默认首页 ,我们把这里的index.jsp改为对应的Servlet即可。
方法2.创建一个过滤器,专门用来过滤首页文件,当请求首页文件时就在过滤器中取数据。过滤器本身其实也是Servlet。 我就晕了,无论用这里面哪一个方法,那这里面的Servlet到底属于哪一层啊?是不是我太钻牛角尖了?
有个地方需要用到文件的物理路径,因为我需要调用方法来删除用户上传至服务器的文件。代码如下:
* 用于删除上传的附件
* @param url String
* @return boolean
*/
public static boolean deleteUploadFileByUrl(String url)
{
File file = new File(url);
boolean ok = false ;
if (file.exists())
{
if (file.delete())
{
ok = true ;
}
}
return ok;
}
/** * 用于删除上传的附件 * @param url String * @return boolean */ public static boolean deleteUploadFileByUrl(String url) { File file = new File(url); boolean ok = false; if(file.exists()) { if(file.delete()) { ok = true; } } return ok; }
可是直接传文件的相对路径当然不行啦。起初我想到的是request.getContextPath(),结果返回的是网站的相对根目录,没用,PASS掉!哎~忘了是用哪个了,我记得好像有个Server中的一个方法可以用来获取物理路径,晕~ASP.NET学时间长了,J2EE忘了差不多了…经过我分别对request和response的个个方法逐一查看(速度还是很快的)。终于被我给找到了。
request.getSession().getServletContext().getRealPath(“”);
这样就可以获得网站所在的物理路径了,OK问题解决,继续折腾…
2008.04.01 / 标签:
jsp Servlet / 分类:
J2EE技术
doGet()
doGet(): 由服务器调用来处理客户端发出的GET() 请求。通过GenericServlet类 的service()方法 来调用此方法。重写GET方法 还支持HTTP HEAD请求 ,该请求返回没有主题只有标题字段的响应。提交响应之前,Servlet 容器要编写标题,这是因为在HTTP 中必须在发送响应主体之前发送标题。GET 方法必须是安全的,如果客户端请求更改存储的数据,则必须使用其他的HTTP 方法。如果请求的格式不正确,则doGet() 方法会返回HTTP “请求错误消息。doGet()方法的语法为:
public void doGet(HttpServeltRequest req,HttpServletResponse res) throws ServletException,IOException
其中,req是存储客户端请求的HttpServletRequest 对象;res是包含服务器对客户端作出响应的HttpSevletResponse 对象。