一、简介
1.1 什么是 Servlet
- Servlet 是 JavaEE 规范之一。规范就是接口。
- Servlet 就 JavaWeb 三大组件之一。三大组件分别是:Servlet 程序、Filter 过滤器、Listener 监听器。
- Servlet 是运行在服务器上的一个 java 小程序,它可以接收客户端发送过来的请求,并响应数据给客户端。
1.2 示例代码
1.2.1 实现Servlet接口
public class ServletTest implements Servlet {
/**
* 第一次有人打开该网页之后,会构造该Servlet及初始化
*/
public ServletTest() {
System.out.println("构造器");
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("init 初始化");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
/**
* 每次刷新,会重新进行一次service服务
*
* @param servletRequest 请求
* @param servletResponse 响应
* @throws ServletException
* @throws IOException
*/
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("servlet 服务响应");
HttpServletRequest request = (HttpServletRequest) servletRequest;
String method = request.getMethod();
// 判断请求是GET请求还是POST请求
if (method.equals("GET"))
doGet();
else if (method.equals("POST"))
doPost();
}
public void doGet() {
System.out.println("GET 请求");
}
public void doPost() {
System.out.println("POST 请求");
}
@Override
public String getServletInfo() {
return null;
}
/**
* 关闭之后,会销毁
*/
@Override
public void destroy() {
System.out.println("销毁");
}
}
1.2.2 web.xml 文件配置
<servlet>
<!-- 一般取和类名一样的名字-->
<servlet-name>ServletTest</servlet-name>
<!-- 定位到指定的Servlet实现类上去
应该用了反射的方法,进行了类的实例化
-->
<servlet-class>com.servlet.test.ServletTest</servlet-class>
</servlet>
<servlet-mapping>
<!-- 与servlet上面的名字相对应。同样,取和类名相同的名字即可-->
<servlet-name>ServletTest</servlet-name>
<!-- 这个是网页访问之后的路径,也就是tomcat里面的那个config
访问的路径也就是"http://localhost:8080/demo/ServletTest"
-->
<url-pattern>/ServletTest</url-pattern>
</servlet-mapping>
1.2.3 Servlet 的生命周期
- 执行 Servlet 构造器方法
- 执行 init 初始化方法
- 执行 service 方法 第三步,每次访问都会调用
- 执行 destroy 销毁方法第四步,在 web 工程停止的时候调用
第一、二步,是在第一次访问的时候创建 Servlet 程序会调用。
1.2.4 GET 和 POST 请求的分发处理
- 通过
httpServletRequest.getMethod()获取请求方式
1.3 通过继承 HttpServlet 实现 Servlet 程序
- 一般在实际项目开发中,都是使用继承
HttpServlet类的方式去实现Servlet程序。- 编写一个类去继承
HttpServlet类 - 根据业务需要重写
doGet或doPost方法 - 到
web.xml中的配置Servlet程序的访问地址
- 编写一个类去继承
- Servlet 类的代码
public class HttpServletTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doGet(req, resp); 默认无此服务,会抛异常的。因此旧方法不能继续留
System.out.println("get 请求");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doPost(req, resp);
System.out.println("post 请求");
}
}
- Servlet 类的继承体系
二、ServletConfig 类
- Servlet 程序的配置信息类
- Servlet 程序和 ServletConfig 对象都是由 Tomcat 负责创建,我们负责使用
- Servlet 程序默认是第一次访问的时候创建,ServletConfig 是每个 Servlet 程序创建时,就创建一个对应的 ServletConfig 对象
- ServletConfig 类的三大作用
- 可以获取 Servlet 程序的别名,就是 servlet-name 的值
- 获取初始化参数 init-param,在xml文件中定义
- 获取 ServletContext 对象
init-param<servlet> <!-- 别名 --> <servlet-name>HttpServletTest</servlet-name> <servlet-class>com.servlet.test.HttpServletTest</servlet-class> <!-- 一个键值对 --> <init-param> <param-name>username</param-name> <param-value>root</param-value> </init-param> <!-- 一个键值对--> <init-param> <param-name>password</param-name> <param-value>123</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>HttpServletTest</servlet-name> <url-pattern>/HttpServletTest</url-pattern> </servlet-mapping>public class HttpServletTest extends HttpServlet { /** * 重写这个init会安全一点,不担心忘记对config操作 * 重写了无参的init方法,在Tomcat加载的时候,会调用那个有参的init方法,对config赋值之后,再调用这个无参的init方法 * ServletConfig 测试 * * @throws ServletException */ @Override public void init() throws ServletException { ServletConfig config = getServletConfig(); // 另一个init已经注入了,因此直接调用函数获取就好了 String username = config.getInitParameter("username"); // 获取指定key的value。类似于key-value System.out.println(username); String password = config.getInitParameter("password"); System.out.println(password); //遍历所有init parameter的名字 Enumeration<String> initParameterNames = config.getInitParameterNames(); while (initParameterNames.hasMoreElements()) { System.out.println(initParameterNames.nextElement()); } } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("get 请求"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("post 请求"); } }
三、ServletContext 类
ServletContext是一个接口,它表示Servlet上下文对象- 一个 web 工程,只有一个
ServletContext对象实例 ServletContext对象是一个域对象ServletContext是在 web 工程部署启动的时候创建。在 web 工程停止的时候销毁- 域对象:可以像
Map一样存取数据的对象,叫域对象。这里的域指的是存取数据的操作范围,整个 web 工程。方法 描述 setAttribute()存数据 getAttribute()取数据 removeAttribute()删除数据 ServletContext类的四个作用- 获取 web.xml 中配置的上下文参数 context-param
- 获取当前的工程路径,格式: /工程路径
- 获取工程部署后在服务器硬盘上的绝对路径
- 像 Map 一样存取数据
3.1 示例代码
web.xml文件(与Servlet标签并列关系)<!-- *********************Context*********************--> <!-- 有点全局变量的味道,在建立工程的时候,就会导入--> <context-param> <param-name>username</param-name> <param-value>root</param-value> </context-param> <context-param> <param-name>password</param-name> <param-value>123</param-value> </context-param>- 调用
@Override public void init() throws ServletException { //ServletContext servletContext = getServletConfig().getServletContext(); ServletContext servletContext = getServletContext(); // 直接通过方法调用获取ServletContext就好了 String username = servletContext.getInitParameter("username"); System.out.println(username); String password = servletContext.getInitParameter("password"); System.out.println(password); // 设置数据 和 initParameter没有关系 servletContext.setAttribute("username", "root1"); System.out.println(servletContext.getAttribute("username")); // 获取当前的工程路径 System.out.println(servletContext.getContextPath()); // /demo // 获取部署的绝对路径。部署的内容和工程内容有一个映射关系 System.out.println(servletContext.getRealPath("/")); //E:\Java\java-web\demo\target\demo-1.0-SNAPSHOT\ }
四、HttpServletRequest 类
- 作用:每次只要有请求进入 Tomcat 服务器,Tomcat 服务器就会把请求过来的 HTTP 协议信息解析好封装到 Request 对象中。 然后传递到 service 方法(doGet 和 doPost)中给我们使用。我们可以通过 HttpServletRequest 对象,获取到所有请求的信息。
4.1 常用方法
| 方法 | 描述 |
|---|---|
getRequestURI() | 获取请求的资源路径 |
getRequestURL() | 获取请求的统一资源定位符(绝对路径) |
getRemoteHost() | 获取客户端的 ip 地址 |
getHeader() | 获取请求头 |
getParameter() | 获取请求的参数 |
getParameterValues() | 获取请求的参数(多个值的时候使用) |
getMethod() | 获取请求的方式 GET 或 POST |
getRequestDispatcher() | 获取请求转发对象 |
setAttribute() | 设置属性,用于传递对象 |
getAttribute | 获取传递过来的对象 |
Parameter 和 Attribute 区别:介绍
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取请求资源的路径
System.out.println(request.getRequestURI()); //demo/HttpServletTest2
// 获取请求的统一资源定位符
System.out.println(request.getRequestURL()); // http://localhost:8080/demo/HttpServletTest2
// 获取客户端的ip
System.out.println(request.getRemoteHost()); // 127.0.0.1
// 获取请求头的内容
System.out.println(request.getHeader("Accept-Language"));
// 获取请求的参数(form传上来的数据)
System.out.println(request.getParameter("username"));
// 获取请求的多个参数(多选列表之类的)
String[] hobbies = request.getParameterValues("hobby");
System.out.println(Arrays.toString(hobbies));
// 获取请求的方式 GET 或 POST
System.out.println(request.getMethod());
}
4.2 doGet 请求的中文乱码解决(实测没用,反而捣乱)
// 获取请求参数
String username = req.getParameter("username");
//1 先以 iso8859-1 进行编码
//2 再以 utf-8 进行解码
username = new String(username.getBytes("iso-8859-1"), "UTF-8");
4.3 doPost 请求的中文乱码解决
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置请求体的字符集为 UTF-8,从而解决 post 请求的中文乱码问题
req.setCharacterEncoding("UTF-8");
System.out.println("-------------doPost------------");
// 获取请求参数
String username = req.getParameter("username"); S
tring password = req.getParameter("password");
String[] hobby = req.getParameterValues("hobby");
System.out.println("用户名:" + username);
System.out.println("密码:" + password);
System.out.println("兴趣爱好:" + Arrays.asList(hobby));
}
4.4 请求转发
- 请求的转发:服务器收到请求后,从一次资源跳转到另一个资源的操作叫请求转发。(自己跳,不需要浏览器跳)
// 通过注解的方法,就不需要在xml文件上写了
// name 就是xml上面的 servlet-name,value就是url-pattern
@WebServlet(name = "RequestDispatcherTest1", value = "/RequestDispatcherTest1")
public class RequestDispatcherTest1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取请求参数
String username = request.getParameter("username");
System.out.println(username);
// 设置两个servlet之间需要传递的内容
request.setAttribute("key", "盖章");
// 获取下一个传递的servlet
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/RequestDispatcherTest2");
// 将请求、响应传递给下一个servlet。然后就会触发下一个servlet的service方法
requestDispatcher.forward(request, response);
}
}
@WebServlet(name = "RequestDispatcherTest2", value = "/RequestDispatcherTest2")
public class RequestDispatcherTest2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取请求参数
String username = request.getParameter("username");
System.out.println(username);
// 获取通过context传递的参数
System.out.println(request.getAttribute("key"));
// 处理自己的任务
System.out.println("RequestDispatcherTest2 处理");
}
}
4.5 base 标签
- base 标签:可以设置当前页面中所有相对路径工作时,参照哪个路径来进行跳转
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>response</title>
</head>
<base href="http://localhost:8080/demo/">
<body>
<!--http://localhost:8080/demo/ResponseServlet-->
<form method="post" action="ResponseServlet">
<label>
<input type="text" name="msg" value="默认值"/>
</label>
<input type="submit">
</form>
</body>
</html>
- 在实际开发中,路径都使用绝对路径,而不简单的使用相对路径
- 绝对路径
- base+相对
- web 中
/斜杠的不同意义- 在 web 中 / 斜杠 是一种绝对路径
/斜杠 如果被浏览器解析,得到的地址是:http://ip:port/<a href="/">斜杠</a>/斜杠 如果被服务器解析,得到的地址是:http://ip:port/工程路径1、<url-pattern>/servlet1</url-pattern> 2、servletContext.getRealPath(“/”); 3、request.getRequestDispatcher(“/”);- 特殊情况:
response.sendRediect(“/”), 把斜杠发送给浏览器解析。得到http://ip:port/
五、HttpServletResponse 类
-
每次请求进来,Tomcat 服务器都会创建一个
Response对象传 递给Servlet程序去使用。 -
HttpServletResponse表示所有响应的信息,我们如果需要设置返回给客户端的信息,都可以通过HttpServletResponse对象来进行设置 -
两个输出流的说明:
流 描述 getOutputStream()字节流,常用于下载(传递二进制数据) getWriter()字符流,常用于回传字符串(常用) -
往客户端回传数据
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String msg = request.getParameter("msg"); PrintWriter writer = response.getWriter(); writer.write(msg); } -
响应的乱码解决
- 解决响应中文乱码方案一:
java // 设置服务器字符集为 UTF-8 resp.setCharacterEncoding("UTF-8"); // 通过响应头,设置浏览器也使用 UTF-8 字符集 resp.setHeader("Content-Type", "text/html; charset=UTF-8"); - 解决响应中文乱码方案二(将上面二合一):
java // 它会同时设置服务器和客户端都使用 UTF-8 字符集,还设置了响应头 // 此方法一定要在获取流对象之前调用才有效 resp.setContentType("text/html; charset=UTF-8");
- 解决响应中文乱码方案一:
-
请求重定向:请求重定向,是指客户端给服务器发请求,然后服务器告诉客户端说。我给你一些地址。你去新地址访问。
resp.sendRedirect("http://localhost:8080");