05.Servlet
一、简介
- 全称:Servlet Applet,服务器端的小程序,主要用来处理用户请求
- 狭义上的概念:Servelet接口及其子接口
- 广义上的概念:实现了Servlet接口的实现类我们都称为Servlet
二、创建HelloWorld的步骤
1.创建一个类实现Servlet接口
package com.atguigu.servlet;
import javax.servlet.*;
import java.io.IOException;
import java.io.PrintWriter;
public class HelloServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
//用来处理用户请求的方法
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("您的请求我已经收到!");
//获取一个打印流
PrintWriter writer = servletResponse.getWriter();
//给浏览器响应一个字符串(先不要响应汉字,因为会乱码)
writer.write("Response Success!");
// writer.print("响应成功!");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
2.在动态Web工程的配置文件web.xml中注册Servlet的实现类
- 使用servlet标签注册Servlet的实现类
- 让Servlet容器(Tomcat)帮我们创建Servlet对象
- 使用servlet-mapping标签映射当前Servlet处理的请求
- 设置当前Servlet处理的请求地址是什么
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--注册Servlet:目的就是为了告诉TomcatServlet的实现类在哪儿-->
<servlet>
<!--给当前的Servlet起一个名称,可用任意指定,通常我们以类名作为它的名称-->
<servlet-name>HelloServlet</servlet-name>
<!--设置Servlet实现类的全类名,Servlet容器(Tomcat)会利用反射技术创建对象-->
<servlet-class>com.atguigu.servlet.HelloServlet</servlet-class>
</servlet>
<!--映射Servlet:目的是为了告诉Servlet处理的请求是什么-->
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<!--设置要处理的请求地址,注意:必须以 / 开头-->
<url-pattern>/MyFirstServlet</url-pattern>
</servlet-mapping>
</web-app>
3.启动Tomcat通过浏览器向Servlet发送请求
- 我们可以在首页index.html中创建一个超链接,超链接的href的属性值要设置为web.xml配置文件中url-pattern标签中设置的地址
- 点击超链接向服务器发送请求,HelloServlet就可以调用service方法处理用户的请求
<a href="MyFirstServlet">Hello Servlet</a>
三、Servlet的生命周期
- Servlet的生命周期即Servlet对象从被创建到被销毁的一个过程
- Servelet生命周期主要体现在以下方法中
- 构造器
- 用来创建对象,第一次发送请求时调用
- 在整个生命周期过程中只被调用一次,说明Servlet是单例的
- init()方法
- 用来初始化对象,第一次发送请求时调用
- 在整个生命周期过程中只被调用一次
- service()方法
- 用来处理用户请求,每次发送请求都会被调用
- 在整个生命周期过程中会被调用多次
- destory()方法
- 在服务器关闭时调用
- 在整个生命周期过程中只被调用一次
- 构造器
四、ServletConfig与ServletContext的作用
1.ServletConfig
-
代表了当前Servlet的配置信息
-
它有以下三个作用
-
1)获取Servlet的名称
-
2)获取Servlet的初始化参数
- 前提是配置了初始化参数
<servlet> <servlet-name>MyServletConfig</servlet-name> <servlet-class>com.atguigu.servlet.MyServletConfig</servlet-class> <!--配置当前Servlet的初始化参数--> <init-param> <param-name>username</param-name> <param-value>admin</param-value> </init-param> </servlet>
-
3)获取ServletContext对象
//1.获取Servlet的名称 String servletName = servletConfig.getServletName(); System.out.println(servletName); //2.获取Servlet的初始化参数 String username = servletConfig.getInitParameter("username"); System.out.println(username); //3.获取ServletContext对象 ServletContext servletContext = servletConfig.getServletContext();
-
2.ServletContext
-
代表了当前Web应用
-
它有以下三个作用
-
1)获取当前Web应用的初始化参数
- 前提是配置了当前web应用的初始化参数
<!--配置当前Web应用的初始化参数--> <context-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </context-param>
-
2)获取资源在服务器端的真实路径(文件上传下载时会用到)
-
3)它是一个域对象(下回分解)
//1.获取当前Web应用的初始化参数 String encoding = servletContext.getInitParameter("encoding"); System.out.println(encoding); //2.获取资源在服务器端的真实路径 String realPath = servletContext.getRealPath("/index.html"); System.out.println(realPath);
-
五、请求与响应
1.HttpServletRequest request
-
代表了浏览器给服务器发送的请求报文,该对象由服务器创建并以参数的形式传入到doGet和doPost方法中,在这两个方法中可以直接使用
-
request常用的作用
- 1)获取请求参数
- 2)获取项目的虚拟路径
- 3)转发
- 4)它是一个域对象(下回分解)
//1.获取请求参数 String username = request.getParameter("username"); String password = request.getParameter("password"); System.out.println(username); System.out.println(password); //2.获取项目的虚拟路径 String contextPath = request.getContextPath(); System.out.println(contextPath); //3.转发 //获取转发器 RequestDispatcher requestDispatcher = request.getRequestDispatcher("success.html"); //进行请求的转发 requestDispatcher.forward(request,response);
2.HttpServletResponse response
-
代表了服务器发送给浏览器的响应报文,该对象由服务器创建并以参数的形式传入到doGet和doPost方法中,在这两个方法中可以直接使用
-
response常用的作用
- 1)给浏览器响应一个字符串或一个页面
- 2)重定向
//1.给浏览器响应要给字符串或一个页面 PrintWriter writer = response.getWriter(); // writer.write("Response Success!"); // writer.write("<!DOCTYPE html>\n" + // "<html lang=\"en\">\n" + // "<head>\n" + // " <meta charset=\"UTF-8\">\n" + // " <title>漂亮的页面</title>\n" + // "</head>\n" + // "<body>\n" + // " <h1>我是一个要多漂亮就多漂亮的页面!</h1>\n" + // "</body>\n" + // "</html>"); //2.重定向 response.sendRedirect("success.html");
六、转发与重定向的区别
- 1)转发发送一次请求;重定向发送两次请求
- 2)转发浏览器地址栏地址无变化;重定向浏览器地址栏地址有变化
- 3)转发可以访问WEB-INF目录下的资源;重定向不可以访问WEB-INF目录下的资源
- 4)转发可以共享request域中的数据;重定向不可以共享request域中的数据
七、中文乱码问题
-
编码:将字符转换为二进制数
-
解码:将进制数转换为字符
-
乱码:编码和解码使用的字符集不一致就会导致乱码
-
常见的字符集:ISO-8859-1(欧码),GBK(国标),GB2312,UTF-8(万国码)
-
请求乱码
-
浏览器编码
- 使用的字符集就是在HTML页面的meta标签中指定的字符集
<meta charset="UTF-8">
-
服务器解码
- 服务器默认的字符集为ISO-8859-1
-
编码与解码使用的字符集不一致导致乱码
-
解决方案
-
对于POST请求
- 在第一次获取请求参数之前通过request设置字符集为UTF-8
//解决POST请求请求中文乱码问题 request.setCharacterEncoding("UTF-8");
-
对于GET请求
-
由于GET请求的请求参数通过浏览器地址栏进行传输,在浏览器地址栏进行解码,所以在Servlet中设置字符集无效
-
需要修改Tomcat的server.xml配置文件(Tomcat8之后就不需要设置了)
- 在第一个Connector标签中添加属性URIEncoding=“UTF-8”
<Connector URIEncoding="UTF-8" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
-
-
-
-
响应乱码
-
服务器编码
- 使用的字符集是ISO-8859-1
-
浏览器解码
- 使用的是GBK
-
编码和解码使用的字符集不一致导致乱码
-
解决方案
- 方案一:获取流之前通过response设置服务器端编码的字符集为GBK(不建议这样)
response.setCharacterEncoding("GBK");
-
方案二:获取流之前设置服务器端编码的字符集为UTF-8,同时通过响应头告诉浏览器也使用UTF-8进行解码
- 方式一
response.setContentType("text/html;charset=utf-8");
- 方式二
response.setHeader("Content-Type","text/html;charset=utf-8");
-
八、关于路径问题
- 由于转发时浏览器地址栏地址无变化,此时如果使用的是相对路径,就又可能会导致解析路径出现异常,所以建议使用绝对路径
- 什么是绝对路径?
- 以 / 开头的路径即为绝对路径
- 但是在不同的地方,/代表的意义不一样
- 如果路径由浏览器解析,那么 / 代表http://localhost:8080/
- 以下路径由浏览器解析
- 1)HMTL标签中的路径:如a标签href中的路径、form标签action中的路径、img标签src中的路径等
- 2)重定向中的路径
- 以下路径由浏览器解析
- 如果路径由服务器解析,那么 / 代表http://localhost:8080/web_servlet_ex_war_exploded/
- 以下路径由服务器解析
- 1)web.xml配置文件中url-pattern标签中的路径
- 2)转发中的路径
- 以下路径由服务器解析
- 如果路径由浏览器解析,那么 / 代表http://localhost:8080/