您的位置:首页 > 其它

Servlet学习应该注意的几点

2017-04-24 14:15 375 查看

一、Servlet生命周期(即运行过程)

(1)初始阶段,调用init()方法

(2)响应客户请求阶段,调用service()方法。由service()方法根据提交方式不同执行doGet()或doPost()方法,其中service()方法判断了到底执行doGet()还是doPost()方法。



(3)终止阶段,调用destroy()方法。(服务器关闭)

Servlet生命周期中需要注意一下几点:

1)Servlet是长期贮存内存中的,当Servlet实例加载后,Servlet对象是长期保存在服务器内存中的。

2)Servlet被装载后,Web容器创建一个Servlet实例并且调用Servlet的init()方法进行初始化。在Servlet的整个生命周期内,init()方法只被调用一次。而service()方法在每次客户端请求的时候都会调用。

3)HttpServlet中有两个Service()方法,HttpServlet中两个service()方法的区别:


public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
// TODO Auto-generated method stub
super.service(arg0, arg1);
}

protected void service(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException {
// TODO Auto-generated method stub
super.service(arg0, arg1);
}


A:其中第一种方法是由tomcat自动调用,它将接收的客户端请求转交给HttpServlet中的第二个service()方法,此保护类行的service()方法再把请求分发给doPost()、doGet()方法进行下一步处理。

B:HttpServlet类继承自GenericServlet,HttpServletRequest和HttpServletResponse分别继承自ServletRequest,ServletResponse,简单说,就是第一个方法是HttpServlet的,第二个方法是GenericServlet的,HttpServlet因为继承GenericServlet,所以继承了这个service()方法。

二、Servlet与九大内置对象

Servlet中如何获取JSP的九大内置对象

JSP对象怎样获得作用域
outresponse.getWriter()page
requestservice方法中的request参数request
responseservice方法中的response参数response
sessionrequest.getSession()函数session
applicationthis.getServletContext()函数Application
exceptionnew Throwable()page
pagethispage
pageContextnew pageContext()page
configthis.getSerletConfig()函数page
将这九大对象分为

1、out对象和session对象

out对象是通过service()中的response的getWriter()方法获得,而response.getWriter()的返回的是PrintWriter类对象,而out对象是JspWriter类的实例,我们不妨对比一下两个类的方法。不难发现两个类都主要以print()方法为主。

session对象是通过service()中的request的getSession()方法获得,返回的对象就是对应了session实例。

代码示例(以out对象举例):

index.jsp代码

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">

<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>

<body>
<a href="Servlets/ServletDemo1"><h1>测试servletDemo1 servlet</h1></a>
</body>
</html>


servletDemo1.java代码

package Servlets;

import java.io.IOException;
import java.io.PrintWriter;import javax.el.ELContext;
import javax.servlet.Servlet;import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import javax.servlet.jsp.JspWriter;public class ServletDemo1 extends HttpServlet {

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//resp.setHeader("Content-type", "text/html;charset=gbk");
//resp.setCharacterEncoding("gbk");

System.out.println("测试ServletDemo1 doGet方法成功!");
PrintWriter out=resp.getWriter();
StringBuffer bf=new StringBuffer("<h1>这里是ServletDemo1 servlet!</h1>");
out.print(bf);
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}


运行结果截图:





分析:绿色背景的代码实现了在servlet中获取out对象,并进行相应操作。但是我们发现通过out对象打印输出的汉字出现了乱码。

关于Servlet中的printWriter中文乱码的问题:

先分析原因:首先我们应该了解servlet中的两个参数request和response分别用来存储客户端发送的请求、储存服务器端返回的数据,而不管是储存还是取出都涉及到重新编码解析的问题,在这个过程如果存储和取出时使用的编码方式不同,势必会导致乱码。printWriter对象是通过response参数调用getWriter()函数获得的,作为响应的信息会在响应存储的时候进行编码的相关操作,而sun公司使用的码表是ISO8859-1之类的码表,而当浏览器显示响应结果时,也会去查码表,而中文的windows下的浏览器使用的一般是gbk或者gb2312,这样两次编码就不同。

解决方法:(两种)

(1)doxxx()方法中添加:response.setCharacterEncoding("gbk");

(2)doxxx()方法中添加:response.setHeader("content-type","text/html;charset=gbk");

上面代码中蓝色部分就是解决方法示例:

运行之后的结果截图:



当然,通过request的getSession()方法获得的session对象对于中文字符也可能出现乱码的问题,我们也可以通过添加:request.setCharaterEncoding("utf-8/gbk");

2、request对象和response对象

request和response对象都是通过service()方法传进的参数获得的,并且这两个参数直接被传入doGet()和doPost()的参数中。

public void service(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException {
// TODO Auto-generated method stub
super.service(arg0, arg1);
}


@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}


3、page对象、config对象和application对象

page对象代表了JSP转译的servlet实例对象,而在继承HttpServlet类的自定义Servlet类中,其当前实例对象在类中的表达,很明显使用this。所以page对象对应this完美。

config对象其实是通过自定义Servlet类的getSerletConfig()方法获取,自定义Servlet类继承自HttpServlet类,而getServletConfig()方法是HttpServlet类继承自其父类GenericServlet类而来,返回类型为ServletConfig对应了config的类。既然是调用其自定义Servlet类本身的getServletConfig()方法,则调用的写法应该是:this.getServletConfig();

application对象其实是通过自定义Servlet类的getSerletcontext()方法获取,自定义Servlet类继承自HttpServlet类,而getServletContext()方法是HttpServlet类继承自其父类GenericServlet类而来,返回类型为ServletContext对应了application的类。既然是调用其自定义Servlet类本身的getSerletcontext()方法,则调用的写法应该是:this.getSerletcontext()。

代码演示:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">

<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>

<body>
<%
application.setAttribute("name", "小帅哥");
%>
<a href="Servlets/ServletDemo1"><h1>测试servletDemo1 servlet</h1></a>
</body>
</html>


package Servlets;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.util.Enumeration;

import javax.el.ELContext;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.el.ExpressionEvaluator;
import javax.servlet.jsp.el.VariableResolver;

public class ServletDemo1 extends HttpServlet {

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setHeader("content-type", "text/html;charset=gbk");
ServletConfig sc=this.getServletConfig();
Enumeration e=sc.getInitParameterNames();
ServletContext application= this.getServletContext();
String name=(String)application.getAttribute("name");
PrintWriter out=resp.getWriter();
out.print("<h2>name:"+name+"</h2>");
out.print("<h1>初始化的参数名:</h1>");
if(e.hasMoreElements()){
out.print(e.nextElement()+" ");
}else{
out.print("该Servlet没有初始化参数!");
}
//req.getRequestDispatcher("/index1.jsp").forward(req, resp);
}

@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); }
}


运行结果截图:





4、pageContext对象和exception对象

pageContex是通过在Servlet中通过构造起自己构造的,构造的方法是:PageContext pc=new pageContext(),但是pageContext类是抽象类,通过直接new的方式可以获得pageContext对象,但是其中的方法需要覆盖重写才有意义,而重写的,里面的方法的实现大多都需要借助于其他内置对象,pageContext是一个集大成者的内置对象,他的出现就是能实现,一个内置对象能够访问其他内置对象。

PageContext pc=new PageContext() {

@Override
public void setAttribute(String arg0, Object arg1, int arg2) {
// TODO Auto-generated method stub

}

@Override
public void setAttribute(String arg0, Object arg1) {
// TODO Auto-generated method stub

}

@Override
public void removeAttribute(String arg0, int arg1) {
// TODO Auto-generated method stub

}

@Override
public void removeAttribute(String arg0) {
// TODO Auto-generated method stub

}

@Override
public VariableResolver getVariableResolver() {
// TODO Auto-generated method stub
return null;
}

@Override
public JspWriter getOut() {
// TODO Auto-generated method stub
return null;
}

@Override
public ExpressionEvaluator getExpressionEvaluator() {
// TODO Auto-generated method stub
return null;
}

@Override
public ELContext getELContext() {
// TODO Auto-generated method stub
return null;
}

@Override
public int getAttributesScope(String arg0) {
// TODO Auto-generated method stub
return 0;
}

@Override
public Enumeration<String> getAttributeNamesInScope(int arg0) {
// TODO Auto-generated method stub
return null;
}

@Override
public Object getAttribute(String arg0, int arg1) {
// TODO Auto-generated method stub
return null;
}

@Override
public Object getAttribute(String arg0) {
// TODO Auto-generated method stub
return null;
}

@Override
public Object findAttribute(String arg0) {
// TODO Auto-generated method stub
return null;
}

@Override
public void release() {
// TODO Auto-generated method stub

}

@Override
public void initialize(Servlet arg0, ServletRequest arg1, ServletResponse arg2, String arg3, boolean arg4, int arg5,
boolean arg6) throws IOException, IllegalStateException, IllegalArgumentException {
// TODO Auto-generated method stub

}

@Override
public void include(String arg0, boolean arg1) throws ServletException, IOException {
// TODO Auto-generated method stub

}

@Override
public void include(String arg0) throws ServletException, IOException {
// TODO Auto-generated method stub

}

@Override
public void handlePageException(Throwable arg0) throws ServletException, IOException {
// TODO Auto-generated method stub

}

@Override
public void handlePageException(Exception arg0) throws ServletException, IOException {
// TODO Auto-generated method stub

}

@Override
public HttpSession getSession() {
// TODO Auto-generated method stub
return null;
}

@Override
public ServletContext getServletContext() {
// TODO Auto-generated method stub
return null;
}

@Override
public ServletConfig getServletConfig() {
// TODO Auto-generated method stub
return null;
}

@Override
public ServletResponse getResponse() {
// TODO Auto-generated method stub
return null;
}

@Override
public ServletRequest getRequest() {
// TODO Auto-generated method stub
return null;
}

@Override
public Object getPage() {
// TODO Auto-generated method stub
return null;
}

@Override
public Exception getException() {
// TODO Auto-generated method stub
return null;
}

@Override
public void forward(String arg0) throws ServletException, IOException {
// TODO Auto-generated method stub

}
};


exception对象是一个异常对象,当一个JSP页面发生异常时就会产生这个对象,这个对象在Servlet中对应着Throwable类,调用的方法是:Throwable tb=new Throwable();而Throwable类的子类有Exception。几乎不使用这个。

三、Servlet路径跳转(假设在index.jsp页面进行跳转)

Servlet中有两种方式获得转发对象(RequestDispatcher):一种是通过HttpServletRequest的getRwquestDispatcher()方法获得,一种是通过ServletContext的getRequestDispatcher()方法获得。重定向的方法只有一种:HttpServletResponse的sendRedirect()方法。这三种方法的参数都是一个URL形式的字符串,但在使用相对路径或绝对路径上有所区别。

1、HttpServletResponse.sendRedirect(String):

(1)相对路径:

response.sendRedirect("index1.jsp");

(2)绝对路径:

response.sendRedirect("/index1.jsp"); 其中"/"表示是项目根目录

response.sendRedirect(request.getContextPath()+"/index.jsp"); request.getContextPath()获得项目的根目录路径

(3)其他Web应用:

response.sendRedirect("http://www.baidu.com");

2、HttpServletRequest.getRequestDispatcher(String)

(1)相对路径:

HttpServletRequest.getRequestDispacher("../index1.jsp").forward(request,response); 其中“../”表明返回上层目录

HttpServletRequest.getRequestDispacher("index1.jsp").forward(request,response);

(2)绝对路径:

HttpServletRequest.getRequestDispacher("/index1.jsp").forward(request,response); 其中“/”表示根目录路径

HttpServletRequest.getRequestDispacher(request.getContextPath()+"/index1.jsp").forward(request,response); request.getContextPath()获得项目的根目录路径

3、ServletContext.getRequestDispatcher():

(1)绝对路径:

ServletContext.getRequestDispatcher("/index1.jsp").forward(request,response); 其中“/”表示根目录路径

注意:HttpServletRequest.getRequestDispatcher(String)和ServletContext.getRequestDispatcher()的区别,其中ServletContext.getRequestDispatcher():只能使用绝对路径传值URL,且绝对路径必须是以"/"开头,其他都不行。而三种页面跳转只有HttpServletResponse.sendRedirect(String)可以实现非项目目录的跳转。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: