Servlet简析
1.Servlet的实现
1.1新建Servlet类
1.2实现Servlet规范(继承 HttpServlet 类)
1.3重写service方法
1.4设置注解
@WebServlet("/路径") 注:"/"一定要加上!
在完成好了一切代码的编写后,还需要向服务器说明,特定请求对应特定资源。
1.5发布项目并启动服务
1.6 访问并查看结果
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/ser01")
//@WebServlet(value = "/ser01")
//@WebServlet(urlPatterns = "/ser01")
//@WebServlet(value = {"/ser01","/ser001"})
//@WebServlet(urlPatterns = {"/ser01","/ser001"},name = "Servlet01",loadOnStartup = 1)
public class Servlet01 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Hello...");
// 设置响应类型
resp.setContentType("text/html");
// 响应数据
resp.getWriter().write("<h3>Hello</h3>");
}
}
2.Servlet的生命周期
- 实例和初始化时机
当请求到达容器时,容器查找该 servlet 对象是否存在,如果不存在,则会创建实例并进行初始化。 - 就绪/调用/服务阶段
有请求到达容器,容器调用 servlet 对象的 service()方法,处理请求的方法在整个生命周期中可以被多次调用;
HttpServlet 的 service()方法,会依据请求方式来调用 doGet()或者 doPost()方法。但是, 这两个 do 方法默认情况下,会抛出异常,需要子类去 override。 - 销毁时机
当容器关闭时(应用程序停止时),会将程序中的 Servlet 实例进行销毁。
Servlet 的生命周期,简单的概括这就分为四步:servlet 类加载–>实例化–>服务–>销毁。
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/ser02")
public class Servlet02 extends HttpServlet {
/**
* 系统方法
* 每当有请求访问时,都会执行。执行多次。
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Servlet02 service...");
}
/**
* 销毁方法
* 系统方法,服务自动调用
* 当servlet实例被销毁时(服务器关闭)执行,只会执行一次
*/
@Override
public void destroy() {
System.out.println("Servlet02 destroy...");
}
/**
* 初始化方法
* 系统方法,服务器自动调用
* 当第一次请求时(Servlet实例不存在时)执行,只会执行一次
* @throws ServletException
*/
@Override
public void init() throws ServletException {
System.out.println("Servlet02 init...");
}
}
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/ser03")
public class Servlet03 extends HttpServlet {
/**
* GET请求
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 得到请求方式
String method = req.getMethod();
System.out.println(method);
doPost(req,resp);
}
/**
* POST请求
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("POST...");
}
}
3.HttpServletRequest对象
- 常用方法
获取请求路径 - 获取请求的参数(重要!!!)
request.getParameter(“参数名”); - 请求乱码问题
乱码原因:request有默认的解析编码,ISO-8859-1,这种编码格式不支持中文,传递中文参数必定乱码。
解决方案:
1. 只针对POST请求的乱码问题 (处理所有参数)
request.setCharacterEncoding(“UTF-8”);
2. 任意请求方式都有效 (一次处理一个参数)
new String(request.getParameter(“参数名”).getBytes(“ISO-8859-1”), “UTF-8”);
目前Tomcat8及以上版本GET请求不会出现乱码,所以目前只需要处理POST请求的参数乱码即可。 - 请求转发
一种跳转方式。- 服务端跳转。
- 地址栏不会发生改变
- 只有一次请求
- 数据可以共享
- request作用域
只在一次请求中有效,只在请求转发跳转有效
request.setAttribute(“参数名”,“参数值”); 设置作用域(任意类型的数据)
request.getAttribute(“参数名”); 获取指定作用域的值
request.removeAttribute(“参数名”); 移除指定作用域的值
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/ser04")
public class Servlet04 extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 设置请求乱码问题 (只针对POST有效)
request.setCharacterEncoding("UTF-8");
/**
* 1. 常用方法
* 1. 获取请求的方式 (GET|POST等)
* 2. 获取请求的完整路径 (从http开始,到?结束)
* 3. 获取请求的部分路径 (从项目路径开始,到?结束)
* 4. 获取请求的参数字符串 (从?开始,到最后)
* 5. 获取请求的协议版本
* 6. 获取项目的访问路径 (站点名)
*/
System.out.println(request.getMethod());
System.out.println(request.getRequestURL());
System.out.println(request.getRequestURI());
System.out.println(request.getQueryString());
System.out.println(request.getProtocol());
System.out.println(request.getContextPath());
/**
* 获取请求的参数
* 1. 获取指定参数名的参数值
* request.getParameter("参数名")
* 注:
* 1. 表单提交
* 参数名表示的是表单元素的name属性值
* 2. 地址栏输入
* 参数名表示的是"?键=值&键=值"中的键
* 2. 获取指定参数名的所有参数值
* request.getParameterValue("参数名")
*/
// 获取指定参数
String uname = request.getParameter("userName");
System.out.println("姓名:" + uname);
String upwd = request.getParameter("userPwd");
System.out.println("密码:" + upwd);
// 获取多个参数
//System.out.println(request.getParameterValues("hobby").length);
// 如果登录成功,跳转到index.jsp,欢迎xxx登录;如果失败,跳转到登录页面,显示错误原因
if (uname.equals("admin") && upwd.equals("admin")) {
/**
* 设置请求域:设置数据存放在作用域中,让客户端能够获取数据
*/
request.setAttribute("userName",uname);
/**
* 请求转发
*/
request.getRequestDispatcher("index.jsp").forward(request,response);
} else {
/**
* 设置请求域:设置数据存放在作用域中,让客户端能够获取数据
*/
request.setAttribute("msg","姓名或密码不正确!");
/**
* 请求转发
*/
request.getRequestDispatcher("login.jsp").forward(request,response);
}
}
}
4.HttpServletResponse对象
响应数据
字符输出流 getWriter()
字节输出流 getOutputStream();
注:两种流不能同时使用!
响应乱码问题
重定向
package com.shsxt.servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* HttpServletResponse对象
* 1. 响应数据
* 1. 字符输出流 getWriter()
* 2. 字节输出流 getOutputStream();
* 注:两种流不能同时使用!
* 2. 响应乱码问题
* 3. 重定向
*
*/
@WebServlet("/ser05")
public class Servlet05 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/**
* 响应乱码解决
* getWriter()
* 服务器默认编码是ISO-8859-1,响应中文必定乱码,客户端与服务端的编码格式不一致
* getOutputStream()
* 传输的是字节,如果客户端与服务端的编码格式一致时,不会乱码,否则乱码。
*
*
* 乱码原因:
* 1. 编码格式不支持中文
* 2. 客户端与服务端的编码格式不一致
* 解决方案:
* 1. 设置编码格式支持中文
* 2. 设置客户端与服务端编码格式一致
*
*
* 1.设置服务端的编码格式
* response.setCharacterEncoding("UTF-8");
* 2. 设置客户端的编码格式
* response.setHeader("content-type","text/html;charset=UTF-8");
* 或者
* 同时设置客户端与服务端的编码格式
* response.setContentType("text/html;charset=UTF-8");
*
*/
// 1.设置服务端的编码格式
// resp.setCharacterEncoding("UTF-8");
// 2. 设置客户端的编码格式
// resp.setHeader("content-type","text/html;charset=UTF-8");
// 同时设置客户端与服务端的编码
resp.setContentType("text/html;charset=UTF-8");
/**
* 响应数据
* 1. 字符输出流 getWriter()
* 2. 字节输出流 getOutputStream();
*/
// 得到字符输出流
PrintWriter writer = resp.getWriter();
// writer.write("Hello");
writer.write("你好");
// 得到字节输出流
//ServletOutputStream outputStream = resp.getOutputStream();
// outputStream.write("Hi".getBytes());
//outputStream.write("你好".getBytes());
}
}
5.Servlet的三大域对象
1. request域对象
在一次请求中有效。请求转发有效,重定向失效。
2. session域对象
在一次会话中有效。请求转发和重定向都有效,session销毁后失效。
3. servletContext域对象
在整个应用程序中有效。服务器关闭后失效。