1.请求对象
- 请求对象: HttpServletRequest(I), 继承了ServletRequest(I)
- 通过请求对象, 程序员可以在service方法中获取客户端提交的请求信息
package com.lc.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.Enumeration;
public class RequestServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求行
// getReqLine(req);
// 获取请求头
// getReqHeader(req);
// 获取请求实体
// getReqEntity(req);
// 其他信息
getReqOthers(req);
}
private void getReqOthers(HttpServletRequest req) {
System.out.println("主机名: " + req.getLocalName());
System.out.println("主机IP: " + req.getLocalAddr());
System.out.println("主机PORT: " + req.getLocalPort());
System.out.println("客户端IP: " + req.getRemoteAddr());
System.out.println("客户端PORT: " + req.getRemotePort());
System.out.println("上下文路径: " + req.getContextPath());
}
private void getReqEntity(HttpServletRequest req) {
// getParameter()可以获取请求实体, 通过表单域的name属性获取值
String username = req.getParameter("username");
String[] hobs = req.getParameterValues("hob");
System.out.println("username: " + username);
System.out.println("hob: " + Arrays.toString(hobs));
// ""和null
// 当输入框没有写数据提交, 此时拿到的是空字符串""
// 当复选框, 单选按钮没有选择时提交, 拿到的是null
// 当在Servlet中获取没有提交的数据时, 拿到的就是null
}
private void getReqHeader(HttpServletRequest req) {
String agent = req.getHeader("User-Agent");
System.out.println("User-Agent: " + agent);
System.out.println("------------------------------------------------");
Enumeration<String> names = req.getHeaderNames();
while(names.hasMoreElements()) {
String s = names.nextElement();
System.out.println(s + ": " + req.getHeader(s));
}
}
private void getReqLine(HttpServletRequest req) {
System.out.println("请求方式: " + req.getMethod());
System.out.println("资源路径(URL): " + req.getRequestURL());
System.out.println("资源路径(URI): " + req.getRequestURI());
System.out.println("Servlet路径: " + req.getServletPath());
System.out.println("协议版本号: " + req.getProtocol());
System.out.println("协议: " + req.getScheme());
}
}
2.响应对象
- HttpServletResponse(I), 继承了ServletResponse(I)
- 可以帮助程序员在service方法中对客户端的请求做出响应
package com.lc.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 测试响应对象
* 响应行: 协议版本号 状态码 描述信息. 不需要程序员操作
* 响应头: 服务器告诉浏览器的信息, Content-Type, Location
* 响应实体: 响应到浏览器的内容
*/
public class RespServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 不设置Content-Type响应头时, 默认值为 text/plain
// resp.setHeader("Content-Type", "text/html;charset=UTF-8");
resp.setContentType("text/html;charset=UTF-8");
// 可以设置自定义响应头, name和value都只允许出现ASCII
resp.setHeader("lc", "lhc");
// setHeader同名会覆盖, addHeader同名不会覆盖
resp.addHeader("lc", "test");
resp.addHeader("lc", "demo");
// 操作响应实体
resp.getWriter().print("<h2>这是响应信息</h2>");
}
}
3.解决中文乱码问题
- 乱码问题的根本原因是编码方式不一致
- 发生乱码的几种情况
> 前台页面乱码
> 后台乱码
- 请求乱码
* POST请求乱码
* GET请求乱码
- 响应乱码
前台解决办法
<!DOCTYPE html>
<html lang="en">
<head>
<!--告诉浏览器使用什么编码方式解析内容-->
<!--<meta charset="UTF-8">-->
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Title</title>
</head>
<body>
<h1>解决中文乱码问题</h1>
<form action="encoding" method="get">
<input type="text" name="uname" />
<input type="submit" />
</form>
</body>
</html>
后台乱码解决办法
package com.lc.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class EncodingServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 解决post乱码, 可以通过调用setCharacterEncoding来设置接收参数时使用的编码方式
req.setCharacterEncoding("UTF-8");
String uname = req.getParameter("uname");
// tomcat7在接收get提交的数据时, 默认使用的编码方式为ISO-8859-1
// 使用ISO-8859-1解码为字节数组
byte[] b = uname.getBytes("ISO-8859-1");
// 重新使用UTF-8编码字节数组为字符串
uname = new String(b, "UTF-8");
System.out.println("uname = " + uname);
// 响应乱码
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().print("大家好");
}
}
4.页面跳转的两种方式
- 请求转发: 不管跳转几个页面, 都是一次请求. 通过请求对象实现
> 发送一次请求
> 地址栏不会改变
> 参数可以一直传递
> 只能跳转到内部资源(项目中), 不能跳转外部资源(项目外)
> 可以访问受保护的资源(WEB-INF) - 响应重定向: 通过响应对象实现, 跳转几个页面就发送几次请求
> 发送多次请求
> 地址栏会发生改变(最后一次请求的路径)
> 参数不能一直传递, 需要手动传递(原因是不是同一次请求了)
> 既可以跳转到内部资源, 也可以跳转到外部资源
> 不能访问受保护的资源
package com.lc.dispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class Servlet2 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("进入Servlet2");
System.out.println(req.getParameter("computer"));
// 继续跳转到demo.html --> ok
// req.getRequestDispatcher("demo.html").forward(req, resp);
// 跳转到百度 --> no
// req.getRequestDispatcher("http://www.baidu.com").forward(req, resp);
// 跳转到受保护的资源 --> ok
req.getRequestDispatcher("WEB-INF/test.html").forward(req, resp);
}
}
package com.lc.redirect;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class Servlet2 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Servlet2执行...");
System.out.println(req.getParameter("computer"));
// 跳转页面到demo.html --> ok
// resp.sendRedirect("demo.html");
// 跳转到百度 --> ok
// resp.sendRedirect("http://www.baidu.com");
// 访问受保护的资源 --> no
resp.sendRedirect("WEB-INF/test.html");
}
}
5.ServletConfig
- ServletConfig, Servlet的配置对象, 用于在初始化Servlet时为Servlet提供相关信息.
- 初始化Servlet时的相关信息可以在web.xml中的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>
<servlet-name>config</servlet-name>
<servlet-class>com.lc.servlet.ConfigServlet</servlet-class>
<!--init-param要配置在servlet-class后, load-on-startup前-->
<!--服务器调用init方法对Servlet初始化时, 会将init-param中的信息封装为ServletConfig对象-->
<init-param>
<param-name>mouse</param-name>
<param-value>Razer</param-value>
</init-param>
<init-param>
<param-name>keyboard</param-name>
<param-value>deiog</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>config</servlet-name>
<url-pattern>/config</url-pattern>
</servlet-mapping>
</web-app>
package com.lc.servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ConfigServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// ServletConfig可以获取初始化参数进行使用
ServletConfig config = getServletConfig();
// 获取初始化参数
String mouse = config.getInitParameter("mouse");
String keyboard = config.getInitParameter("keyboard");
System.out.println("mouse = " + mouse);
System.out.println("keyboard = " + keyboard);
}
}
6.SerlvetContext
- ServletContext, Servlet上下文. 一个应用程序有且仅有一个ServletContext对象.
- 用于记录当前应用的所有信息, 代表了整个应用程序. 一般被称之为Application.
- 通过ServletContext对象可以实现如下操作:
> 加载全局配置参数
> 获取资源的绝对路径
> 加载静态资源
<?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">
<!--配置全局配置参数-->
<context-param>
<param-name>computer</param-name>
<param-value>DELL</param-value>
</context-param>
<servlet>
<servlet-name>context</servlet-name>
<servlet-class>com.lc.servlet.ContextServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>context</servlet-name>
<url-pattern>/context</url-pattern>
</servlet-mapping>
</web-app>
package com.lc.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class ContextServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取ServletContext对象
ServletContext c1 = getServletContext();
ServletContext c2 = getServletConfig().getServletContext();
ServletContext c3 = req.getServletContext();
System.out.println(c1 == c2);
System.out.println(c2.hashCode());
System.out.println(c3.hashCode());
System.out.println("=--------------------------------");
// 加载全局配置参数
String computer = c1.getInitParameter("computer");
System.out.println("computer = " + computer);
// 获取资源的绝对路径
String path = c1.getRealPath("/upload");
String contextPath = c1.getContextPath();
System.out.println("path = " + path);
System.out.println("contextPath = " + contextPath);
// 以流的形式加载静态资源 --> web.xml
InputStream is = c1.getResourceAsStream("WEB-INF/web.xml");
// 转换为字符流
InputStreamReader reader = new InputStreamReader(is);
// 包装为缓冲流
BufferedReader br = new BufferedReader(reader);
// 准备字符串
String line = null;
while((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
}
}