Servlet学习应该注意的几点
一、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对象 | 怎样获得 | 作用域 |
out | response.getWriter() | page |
request | service方法中的request参数 | request |
response | service方法中的response参数 | response |
session | request.getSession()函数 | session |
application | this.getServletContext()函数 | Application |
exception | new Throwable() | page |
page | this | page |
pageContext | new pageContext() | page |
config | this.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)可以实现非项目目录的跳转。
Servlet学习应该注意的几点的更多相关文章
- JSP&Servlet学习手册
JSP&Servlet学习手册 沙琪玛 书 目录 JSP 指令... 3 书写方式... 3 指令列表... 3 JSP 内置对象... 3 内置对象特点... 3 常用内置对象... 3 o ...
- Servlet 学习笔记
Servlet 运行在服务器上的 java 类: Servlet 容器为 javaWeb 应用提供运行时环境,负责管理 servlet 和 jsp 生命周期,以及管理他们的共享数据. 现在我们知道了 ...
- Servlet学习:(三)Servlet3.0 上传文件
转: Servlet学习:(三)Servlet3.0 上传文件 2018年08月03日 11:57:58 iDark_CSDN 阅读数:362 一.注意事项 客户端(浏览器) 表单的提交方法必须是 ...
- Servlet学习(九)——request
request运行流程在Servlet学习(四)——response已介绍,不再赘述 1.通过抓包工具获取Http请求 因为request代表请求,所以我们可以通过该对象分别获得Http请求的请求行, ...
- # jsp及servlet学习笔记
目录 jsp及servlet学习笔记 JSP(Java Server Page Java服务端网页) 指令和动作: servlet(小服务程序) jsp及servlet学习笔记 JSP(Java Se ...
- Servlet学习笔记(四)
目录 Servlet学习笔记(四) 一.会话技术Cookie.session 1. 什么是会话技术? 2. 会话技术有什么用? 3. Cookie 3.1 什么是Cookie? 3.2 使用Cooki ...
- Servlet学习笔记(三)
目录 Servlet学习笔记(三) 一.HTTP协议 1.请求:客户端发送欸服务器端的数据 2.响应:服务器端发送给客户端的数据 3.响应状态码 二.Response对象 1.Response设置响应 ...
- Servlet学习笔记(二)
目录 Servlet学习笔记(二) Request对象 1.request和response对象: 2.request对象继承体系结构: 3.什么是HttpServletRequest ? 4.Htt ...
- servlet 学习(二)
一.ServletConfig讲解 1.1.配置Servlet初始化参数 在Servlet的配置文件web.xml中,可以使用一个或多个<init-param>标签为servlet配置一些 ...
- JavaWeb学习总结-04 Servlet 学习和使用
一 Servlet 1 Servlet概念 Servlet时运行在服务器端的Java程序. Servlet的框架核心是 javax.servlet.Servlet 接口. 所有自定义的Servlet都 ...
随机推荐
- Vim中常用的命令行
Vim中常用的命令行... ------------------- 一些真正强大的武器总不是那么容易驾驭的,主角总得付出一些努力才能收获到更加强大的力量,对于 Vim 这种上古神器来说更是如此.由于它 ...
- react后台开发框架搭建
最近整理了一下自己在用的react框架,主要涉及到的技术有react react-router redux Es6 webpack less ant-design等技术,可用于快速开发后台类系统. ...
- 七牛云数据存储Demo
利用七牛云的Python SDK实现文件上传.下载等操作. import os import requests import qiniu from qiniu import BucketManager ...
- 【渗透课程】特别篇-主流网站程序Oday大全以及拿shell思路
版权和内容说明: 这篇文章不是本站编写,是从网络上摘抄的,但是经过了本站的改写优化,并将内容,格式规范化. 本篇说明:这篇文章结合了前辈们前几年一路挖掘出来的主流程序漏洞以及思路, 小编写在前面是想让 ...
- 简说JS中的循环部分
JS中的循环语句是JS基础的最最重要的部分,没有之一,后面所学的其他的一些重要的知识也是需要在此的基础啥古玩城更高级的设置,先来简单的说一下循环的一些知识点. 一.循环结构的执行步骤 1.声明循环变量 ...
- Java的常用操作符
操作符用于接受一个或多个参数,并生成一个新的值.加号和一元的正号(+).减号和一元的负号(一).乘号(*).除号(/)以及赋值号(=)的用法和大多数编程语言都类似. 操作符作用于操作数,生成一个新值. ...
- Spring 事务管理笔记
本文为 Spring 框架的事务管理学习笔记,官网文档地址为:Transaction Management,隔离级别及传播属性解释来自 org.springframework.transaction. ...
- Day-11: IO编程
由于CUP的运行速度远高于其他外设,IO操作有两种方式: 同步IO:CUP登着,程序暂停直到执行完后续代码 异步IO:CUP不等待,去做其他的事情,磁盘做完该做的事情后,告诉CUP,CUP再进行后续代 ...
- 【1414软工助教】团队作业2——需求分析&原型设计 得分榜
题目 团队作业2--需求分析&原型设计 作业提交情况情况 本次作业所有团队都按时提交作业. 往期成绩 个人作业1:四则运算控制台 结对项目1:GUI 个人作业2:案例分析 结对项目2:单元测试 ...
- 201521123101 《Java程序设计》第6周学习总结
1. 本周学习总结 1.面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结. 2. 书面作业 1.clone方法 1.1 Object对象中 ...