第四章 Servlet
1.Servlet的概述
什么是Servlet?
- Servlet 全称Java Servlet, 是用Java编写的服务器端程序,其主要功能在于交互式地浏览和修改数据,生成动态Web内容,狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。
- Servlet是JavaWeb的核心程序,是Java Web三大组件致以(Servlet,Filter,Listener)。
- 在HTTP请求过程中会把请求的参数存放在请求行的URL中,或者是请求体中,这个参数需要服务器来接收解析并处理,Servlet就是用来处理这个过程的
Servlet的作用
- 用来处理客户端发送过来的请求,并对该请求作出反应
1.获取接收客户端发送来的请求数据
2.处理请求
3.将处理的结果通过响发送到客户端
2.编写第一个Servlet
-
Servlet程序必须编写实现类
1.通常是继承javax.servlet.http.HttpServlet -
复写HttpServlet中的doGet(),doPost()方法
1.复写doGet(),doPost()方法 -
配置web.xml文件
其中<servlet>
是用来注册Servlet的 -
部署项目并通过浏览器访问servlet
-
Servlet的执行
3.IDEA在Servlet3.0版本下创建Servlet
1.创建项目的时候javaEE版本选择6.0以上
2.在IDEA的代码目录下直接右键new,选择Servlet
3.配置@WebServlet(urlPatterns="/TestServlet"
),注解内的访问路径等同于web.xml
下的url-parrtener
4.HttpServletRequest简介-获取请求行和请求头
1.HttpServletRequest简介
- 在Servlet的API中,定义看一个HttpServletRequest接口,它继承自ServletRequest接口。专门用于封装HTTP的请求,由于HTTP请求包含着请求行、请求头、请求体三部分,因此在 HttpServletRequest中分别定义了接收请求行、请求头、请求体的相关方法。
2.获取请求行的相关方法
1.getMethod()方法:返回请求方法,请求方法通常是GET或者POST但也有可能是HEAD,PUT或者DELETE。
2.getRequestURL()方法:返回URL(URL是URL的从主机和端口之后到表单数据之前的那一部分)
3.getRemoteAddr()方法:该方法用于获取请求客户端的IP地址
4.getRemoteport()方法:该方法用于获取请求客户的端口号
5.getLocalAddr()方法:该方法用于获取服务器当前接收请求的IP地址
6.getContextPath()方法:该方法用于获取URL中属于web应用程序的路径
7.getProtocal()方法:该方法用于获取请求行中的协议名和版本
3.获取请求头的方法
1.getHeader(String name):该方法用于获取一个指定头字段的值,如果请求头中不包含该字段则返回null,如果包含多个字段的值则获取第一个值
2.getIntHeader(String name):该方法用于获取指定头字段的值,并且将其值转为int类型,如果不存在该字段则返回-1,如果获取到的值不能转换为int则会发生NumberFormatException异常
3.getDateHeaders(String name):该方法用于获取指定头字段的值,并且其按照GMT时间格式转换成一个代表日期/时间的长整数
4.getHeaderName():该方法用于获取指定头字段的Enumeration
4.获取请求参数
1.getParameter(String name):用于获取某个指定名称的参数值,如果请求中没有包含指定名称的参数,则返回null,如果指定参数但是没有给设置值,则返回空串“ ”,如果包含多个该参数的值则返回第一个出现的参数值
2.getParameterNames():该方法用于返回一个包含请求消息中所有参数名的Enumernation
3.getParameterMap():该方法用于将请求中的所有参数和值装入一个map对象然后返回
5.Response对象发送响应行和响应头
1.HttpServletResponse简介
- 在Servlet的API中,定义看一个HttpServletResponse接口,它继承自ServletResponse接口。专门用于封装HTTP的响应,由于HTTP请求包含着响应行、响应头、响应体三部分,因此在 HttpServletResponse中分别定义了发送响应行、响应头、响应体的相关方法。
2.发送响应行
1.setstatus(int status):当Servlet向客户端回送响应消息时,需要设置一个状态码,该方法用于设置HTTP响应消息的状态码,并生成响应状态行。由于响应状态行中状态的描述直接和状态码相关,而HTTP协议版本由服务器决定,因此只需要设置该方法,就可以发送一个响应行,正常情况下,web服务器会默认发送一个200的状态码
2.sendError(int code):该方法用于发送表示错误信息的状态码,例如404找不到访问的资源,他还有一种重载的形式sendError(int
code,String errorMessage),errorMessage可以以文本形式显示在客户端浏览器
3.发送响应头
1.addHeader(String name,String value):该方法用了设置HTTP协议的响应头字段,其中name是响应头字段名,value是响应字段的值
2.setHeader(String name,String value):该方法和addHeader相同,唯一的区别是addHeader可以重复添加一个同名的响应头字段,setHeader会覆盖之前添加的同名的响应头
3.addIntHeader(String name,int value)、setHeader(String name,int value):这两个方法用于将value值为int字段加入到响应头中
4.setContentLength():该方法用于设置HTTP响应信息的内容大小,单位是字节
5.setContentType():该方法用于设置Servlet输出内容的类型,也就是HTTP协议中的Content-Type响应头,例如发送到客户端的内容是jpeg格式的图像数据,就需要将响应头字段的类型设置为“image/jpeg”,另外,如果相应的内容是文本,那这个时候setContentType还可以设置字符编码,例如text/html:charset=UTF-8
4.发送响应消息体
1.getOutputStream()方法:该方法获取的字节流输出对象未ServletOutputStream类型,它是OutputStream的子类,因此可以直接输出字节数组中的二进制数据
2.getWrite()方法:该方法获得的字符输出流对象是PrintWrite类型由于它可以直接输出文本类型,因此要输出网页文档,需要使用这个方法
案例:实现网站登录中验证码切换的功能
原理:浏览器显示文档和图片,是由服务器回送给浏览器的响应完成的,而一个响应封装成一个HttpServletResponse对象,所以我们只需要将验证码图片封装到HttpServletResponse对象返回给浏览器即可
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录</title>
</head>
<body>
<div class="login">
<%
String error = (String)request.getAttribute("error");
if(error !=null) {
out.print(error);
}
%>
<h3>用户登录</h3>
<form action="/retailer/login.jsp" method="post">
<p>
<label for="">用户名:</label><input type="text" name="loginName" id="">
</p>
<p>
<label for="">密码:</label><input type="password" name="loginPwd" id="">
</p>
<p>
<label for="">验证码:</label><input type="text" name="verify" id=""><img src="/retailer/verifycode" alt="" id="verify">
<span onclick="changeVerify()">刷新</span>
</p>
<p><input type="submit" value="登录"><input type="reset" value="重置"></p>
</form>
</div>
</body>
<script>
function changeVerify(){
var img = document.getElementById("verify");
img.src = "/retailer/verifycode?time="+new Date().getTime();
}
</script>
</html>
6.Servlet的生命周期
1.什么是Servlet的生命周期
生命周期:就是一个对象从创建到销毁的过程
Servlet的生命周期:Servlet从创建到销毁的过程
2.Servlet接口以及相关方法
Servlet接口:javax.servlet.Servlet接口
init(ServletConfig)方法:销毁servlet方法
service(ServletPequest,ServletResponse)方法:每次访问都会调用来处理请求
destoty()方法:销毁Servlet方法
HttpServlet接口:javax.servlet.http
继承自Servlet接口,补兵重新实现了service方法,根据不同请求方式调用不同的处理方法。
service(HttpServletPequest,HttpServletResponse)方法,获取请求方式,分别调用doGet(),或者doPost()方法
当服务器关闭或者项目被移除服务器,destory()方法会执行,生命周期结束
注意:Servlet实例是单例的,即无论请求多少次Servlet,最多只有一个Servlet实例,如果是多个客户端并发,同时访问Servlet的时候,服务器会启动多个线程分别执行Servlet的service方法
原因:如果我们每次访问都创建一个Servlet实例,会占用和浪费过多的计算机资源
7.ServletConfig对象
定义:ServletConfig对象是它所对应的Servlet对象的相关配置信息
特点:
- 每一个Servlet对象都有一个ServletConfig对象和它对应
- ServletConfig对象在多个Servlet对象之间是不能共享的
常见的ServletConfig对象的方法:
1.getInitParameter(String name):返回一个初始化变量的值
2.getInitParameterName():返回Servlet初始化参数的所有名称
3.getServletContext():获取ServletContext对象
4.getServletName():获取Servlet的name配置值
8.ServletContext-获取项目初始化参数
什么是ServletContext对象
-
ServletContext定义:ServletContext即Servlet上下文对象,该对象表示当前的web应用环境信息
-
获取ServletContext对象:
1.通过ServletConfig的getServletContext()方法可以得到ServletContext对象
2.HttpServlet中直接通过this.getServletContext()获取 -
域对象(域对象就是在不同资源之前来共享数据,保存数据,获取数据)
ServletContext对象通常称为Context域对象,ServletContext是我们学习的第一个域对象
9.ServletContext对象的应用
1.使用ServletContext获取整个web项目初始化参数
- 在web.xml中配置初始化参数:
<context-param>
<param-name>参数名</param-name>
<param-value>参数值</param-value>
</context-param>
- String getInitparmaeter(String name):根据名称获取初始化参数
- Enumeration getInitparmaeterNames():获取所有初始化的参数名称
2.使用ServletContext在多个Servlet中共享数据
- void SetAttribute(String name,Object object):存放数据
- Object SetAttribute(String name):获取数据
- void removeAttribute(String name):删除数据
3.使用ServletContext读取web项目的资源文件
10.请求转发
Servlet之间的跳转
Servlet之间可以实现跳转,从一个Servlet跳转到另一个Servlet,利用Servlet的跳转技术可以很方便的把一块业务模块分开,比如使用一个Servlet接收用户提交数据,使用另一个Servlet读取数据库,最后跳转到另一个Servlet把处理结果展示出来,这也就是MVC模式(modle,view,controller)。
MVC:用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入,处理和输出功能在一个逻辑的图形化用户界面的结构中。
转发Forward简介:
在Servlet中如果当前的web资源不想处理请求,可以通过forward方法将当前的请求传递给其他的Web资源处理,这种方式称为请求转发。
请求转发的相关方法:
RequestDispatcher对象,可以通过request.gerRequestDispatcher()方法获取调用这个对象的forward方法就可以实现请求转发
转发过程中携带数据:
request本身也是一个域对象,request可以携带数据传递给其他web资源
setSttribute方法;
getAttribute方法;
removeAttribute方法;
getAttributeName方法;
通过request对象的setAttribute方法
实验3-登录错误时显示错误界面
package net.zixue.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.lang.annotation.Repeatable;
/**
* Created by invinjun on 2017/6/2.
*/
@WebServlet(name = "LoginServlet", urlPatterns = "/login")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String userName = "xiaoming";
String userPass = "123456";
String name = request.getParameter("name");
String passWord = request.getParameter("passWord");
if (!name.equals(userName)) {
//账户不存在
request.setAttribute("errorMessage", "账户不存在");
request.getRequestDispatcher("/loginError.jsp").forward(request, response);
} else if (!passWord.equals(userPass)) {
//密码错误
request.setAttribute("errorMessage", "密码错误");
request.getRequestDispatcher("/loginError.jsp").forward(request, response);
} else {
// response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
// response.setHeader("Location","https://www.baidu.com/");
HttpSession session = request.getSession();
Cookie cookie = new Cookie("JSESSION", session.getId());
cookie.setMaxAge(60*60*24);
response.addCookie(cookie);
response.sendRedirect("/hello/home.html");
}
}
}
11.重定向介绍
重定向的简介:
重定向是根据服务器返回的状态码来实现的。客户端浏览器在请求服务器的时候,服务端会返回一个状态码。服务器通过HttpServletResponse的setStatus(int stauts)方法来设置状态码。如果服务器这个时候返回的状态码或者,则浏览器会到新的网址重新请求该资源。服务器的响应中会带着这个新资源的地址
请求重定向相关代码:
//设置状态码为302,SC_MOVED_TEMPORAILY就是302的静态常量
response.setStatus(HttpServletResponse.SC_MOVED_TEMPORAILY);
//在请求头中携带新的资源地址
response.setHeader("Location",","http://www.baidu.com");
为了使用方便HttpServletResponse中将setStatus和setHeader这两种方法合并到一起叫做sendRedirect(String location);
12.请求转发和重定向的区别
1.重定位的地址栏会发生变化看,转发不会
2.重定位是两次请求两次响应,转发是一次请求一次响应
3.重定位路径需要加工程名,转发路径不需要加工程名
4.重定位可以跳转到任何网站,转发只能在服务器内部进行
13.网页自动刷新
JSP中实现自动刷新<meta http-equiv="refresh" content="3:url=/hello/home.html>
14.Servlet线程安全
什么是线程安全
Servlet的线程安全相关:
当多个客户端并发访问同一个Servlet的时候,web服务器会为每一个客户端的访问创建一个线程,并在这个线程上调用Servlet的service方法,因此service方法内部如果访问了同一个共享资源的话,就可能引发线程安全问题