-
-
-
-
- 请求转发是一次转发
- 请求转发URL地址不会发生变化,会保留当前Servlet的资源访问路径
- 共享同一个Request作用域,可用于多页面之间传递数据
-
-
-
-
- getServletContext()
-
-
- 返回一个ServletContext()对象
-
-
- 获取请求头信息
-
-
- getHeader(String key)根据key获取value
-
-
-
-
- 例如 request.getHeader("User-Agent")
-
-
-
-
- getHeaderNames()获取所有请求头名称
-
-
-
-
- 返回一个Enumeration<String>对象
-
-
-
-
-
-
- 类似集合迭代器的对象
-
-
-
-
-
-
-
-
- hasMoreElements()
-
-
-
-
-
-
-
-
-
-
- 返回boolean值
- 判断是否有下一个元素
-
-
-
-
-
-
-
-
-
-
- nextElement()
-
-
-
-
-
-
-
-
-
-
- 返回下一个元素
-
-
-
-
-
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
Enumeration<String> headerNames = request.getHeaderNames();
out.println("<h2>");
//Enumeration是一个类似集合迭代器的对象,可以存放多个数据,需要循环获取每个元素对象
while (headerNames.hasMoreElements()) {
String head = headerNames.nextElement();
out.println( head + "=" + request.getHeader(head) + "<br>");
}
out.println("</h2>");
}
-
- 获取请求网络数据
-
-
- getMethod()
-
-
-
-
- 获取网络请求的请求方式
-
-
-
-
- getProtocol()
-
-
-
-
- 获取网络协议
-
-
-
-
- getLocalPort()
-
-
-
-
- 获取请求的端口
-
-
-
-
- getServletPath()
-
-
-
-
- 获取请求资源的路径
- 如:/servlet
-
-
-
-
- getRequestURI()
-
-
-
-
- 获取请求的资源路径,包括应用上下文访问路径+请求的资源路径
- 应用上下文访问路径/请求资源的路径
- /web01/servlet
-
-
-
-
- getRequestURL()
-
-
-
-
- 获取请求的URL(SetvletURL)
- 协议+ip+端口+应用上下文访问路径+请求资源的路径
- http://localhost:8080/web01/servlet
-
-
-
-
- getContextPath()
-
-
-
-
- 获取应用上下文访问路径
- /web01
- 在请求资源路径之前动态获取应用上下文访问路径,避免因为应用上下文访问路径问题导致资源无法访问
-
-
-
-
-
-
- <a href = "<%=request.getContextPath()%>/servlet">超链接</a>
-
-
-
//获取请求方式
String method = request.getMethod();
out.println("请求方式 =" + method + "<br>");//请求方式 =GET
//获取请求协议
String protocol = request.getProtocol();
out.println("请求协议 =" + protocol + "<br>");//请求协议 =HTTP/1.1
//获取请求资源的路径
String servletPath = request.getServletPath();
out.println("servletPath = " + servletPath + "<br>");//servletPath = /servlet
//获取请求URI 包括应用上下文对象+请求的资源路径
String requestURI = request.getRequestURI();
out.println("URI =" + requestURI + "<br>");//URI =/web01/servlet
//获取请求URL地址栏完整路径 包括 协议+ip+端口+应用上下文访问路径+请求的资源路径
StringBuffer requestURL = request.getRequestURL();
out.println("URL =" + requestURL + "<br>");//URL =http://localhost:8080/web01/servlet
//获取请求的应用上下文访问路径
String contextPath = request.getContextPath();
out.println("contextPath = " + contextPath);//contextPath = /web01
HttpServletResponse用户响应对象
- 常用方法
-
- setCharacterEncoding(String charSet)设置输出编码格式
-
-
- 传入一个String类型的编码格式
-
-
- setContextType("text/html;charset=UTF-8")
-
-
- 设置响应数据的数据类型为html字符串,编码格式为UTF-8
-
-
- getWriter() 返回一个Writer类型的字符输出流对象,利用该对象可以向页面输出文本或Html
-
-
- 不推荐Servlet中进行数据输出,Servlet主要负责逻辑处理
-
-
- setContentLength()
-
-
- 设置响应时的响应数据大小
-
-
- 设置响应头
-
-
- 不支持中文
- setHeader(String key,String value)
- setDateHeader(String key,Date value)
- setIntHeader(String key,int value)
-
-
- sendRedirect(String url)重定向
-
-
- 可以跳转到某url
- 重定向是2次请求,地址栏会保留重定向的资源地址,不会共享同一个Request Scope(请求作用域)
- 可以写uri,但是可能会出问题,建议使用url
-
请求转发与重定向
- 区别
-
- 转发地址栏不变,转发请求1次,转发时不写工程虚拟路径
-
-
- 地址栏不变可防止重复发送请求
-
-
- 重定向地址栏变化,请求2次,重定向要写工程虚拟路径
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//请求转发
request.getRequestDispatcher("/servlet03");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//重定向
resp.sendRedirect(req.getContextPath() + "/servlet03");
}
- 应用场景
-
- 重定向
-
-
- 登录、购物车结算
-
-
- 请求转发
-
-
- 其余
-
- setHeader("Content-Disposition","attachment;filename=" + file.getName())
-
- 设置响应头,请求以下载的方式处理,以及下载文件时的默认文件名称
- response.setContentLength((int)file.length());
-
- 设置响应时的响应数据大小(利用文件大小设置)
- Servlet与JSP的跳转
-
- jsp跳Servlet
-
-
- a标签
- js(location.href='xxx')
- form表单action属性
-
-
- Servlet跳jsp
-
-
- 重定向:response.sendRedirect(String url)
- 请求转发: request.getRequestDispatcher(String uri).forward(request,response)
-
-
- servlet跳servlet
-
-
- 推荐重定向
-
下载功能的实现
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置响应输出编码格式,避免文件名中文乱码
response.setContentType("text/html;charset=UTF-8");
//获取输入流
//获取响应输出流
BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
File file =new File(request.getServletContext().getRealPath("/images/img.png"));
//获取输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
//设置响应头,请求以下载的方式处理,以及下载文件时的默认文件名称
response.setHeader("Content-Disposition","attachment;filename=" + file.getName());
//设置响应时的响应数据大小(利用文件大小设置)
response.setContentLength((int)file.length());
byte[] bytes = new byte[1024];
int length = 0;
while ((length = bis.read(bytes)) != -1) {
bos.write(bytes, 0,length);
}
//刷新缓存,数据推送
bos.flush();
}
图片验证码的实现
- 引入的包
-
- Hutool
<!--hutool工具类-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.26</version>
</dependency>
- 后端
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//定义图形验证码的父接口
ICaptcha lineCaptcha = null;
/**创建一个图形验证码对象
* param1:宽度
* param2:高度
* param3:字符数量
* param4:干扰线条数量
*/
lineCaptcha = new LineCaptcha(200,80,5,3);
//验证码生成
lineCaptcha.createCode();
//获取验证码信息
//后期我们应该将这个数据存入Session或其他某些其他容器中等待与用户输入的验证码校验
String code = lineCaptcha.getCode();
//使用输出流输出验证码图片到浏览器
response.setContentType("text/html;UTF-8");
ServletOutputStream sos = response.getOutputStream();
lineCaptcha.write(sos);
sos.close();
}
- 前端
<body>
<form method="post" action="servlet">
用户名:<input type="text" name="username"><br>
密 码 :<input type="password" name="pw"><br>
验证码:
<%--利用JSP脚本表达式,在请求资源路径之前通过动态获取应用上下文对象,避免通过应用上下文对象访问路径问题导致资源无法访问--%>
<a id="reset" href="javascript:void(0)">
<img src="<%= request.getContextPath() %>/servlet" id="myImg"><br>
看不清,换一张
</a>
<input type="submit" value="get">
</form>
</body>
<script type="text/javascript">
window.onload = function () {
document.getElementById("reset").addEventListener("click",function () {
//添加单击事件修改img路径,但是链接必须发生变化,因此使用时间戳
document.getElementById("myImg").src = "<%= request.getContextPath() %>/servlet?timeStemp=" + new Date().getTime()
})
}
/* var reset = function() {
}*/
</script>
- 细节:
-
- get请求重新执行要求链接不同,可通过添加时间戳实现
ServletConfig 初始化参数对象
- 常用方法
-
- getInitParameter(String key)
-
-
- 获取xml文件或注解中的初始化参数,返回String
-
- 在非init方法中取得ServletConfig对象
-
- this.getServletConfig()
ServletContext
- 常用方法
-
- getRealPath(String uri)
-
-
- 获取uri指向资源的绝对路径
- 例
-
-
-
-
- servletContext().getRealPath("/")
-
-
-
-
-
-
- 获取根目录真实路径
-
-
-
-
-
-
- servletContext().getRealPath("/images/img.png")
-
-
-
-
-
-
- 获取根目录下/images/img.png文件的真实目录
-
-
-
生命周期
- 注意:
-
- 单例模式,整个Tomcat生命周期中,每个Servlet只会被创建一次
a. init()初始化
-
- Servlet对象创建完成后被调用,因为Servlet是单例的,所以整个Tomcat生命周期中只会被调用一次
- 可与初始化参数配合使用,为Servlet类添加成员变量
- 必须调用super.init(),否则无法为当前类中的init()属性进行赋值,无法调用init方法以外的其他方法获取config对象
@Override
public void init(ServletConfig config) throws ServletException {
//调用super.init(config)当前类中的config属性赋值
super.init(config);
name = config.getInitParameter("name");
age = config.getInitParameter("age");
}
b. service()请求进入时
-
- 每次请求进入Servlet都会执行一次这个方法,用于分析请求是get还是post,根据请求方式帮助我们调用doGet或doPost方法
- 注意:必须利用super调用父类中的service方法,否则不会进入doGet或doPost()
c. destroy()销毁
-
- Servlet销毁时执行,,因为Servlet是单例的,所以整个Tomcat生命周期中只会被调用一次
- Servlet销毁的时机是Tomcat容器关闭时,用于释放一些资源
d. 初始化参数
ⅰ. 基于XML方式
<?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>servelet</servlet-name>
<servlet-class>com.wry.servlet.Servlet</servlet-class>
<init-param>
<param-name>i</param-name>
<param-value>1</param-value>
</init-param>
<init-param>
<param-name>j</param-name>
<param-value>100</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>servelet</servlet-name>
<url-pattern>/servlet</url-pattern>
</servlet-mapping>
</web-app>
ⅱ. 取得初始化参数的值
- 通过成员变量共享属性值
-
- Servlet的init方法只会执行一次,Servlet是单例的。非线程安全的,当出现并发访问,共享数据无法保证一致性.在使用Servlet不要定义共享成员变量.
public class Servlet extends HttpServlet {
private String name;
private String age;
@Override
public void init(ServletConfig config) throws ServletException {
name = config.getInitParameter("name");
age = config.getInitParameter("age");
}
}
- 通过在方法中获取ServletConfig对象获取初始化参数的值
-
- 必须在init()方法中调用super.init(config),否则GennericServlet类中的config属性为null,无法获取到ServletConig对象
- 利用这种方法,既可以获取初始化参数,又可以避免线程安全问题
public class Servlet extends HttpServlet {
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
}
/**
* 用于处理get请求
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");
//利用用户响应对象获取输出流
PrintWriter out = response.getWriter();
out.print(("<h1>收到一个get请求</h1>"));
//获取ServletConfig对象
ServletConfig config = this.getServletConfig();
//获取name属性值
String name1 = config.getInitParameter("name");
out.println(name1);
}
}
ⅲ. 设置Servlet值的初始化时机
- 通过<Servlet>中的<load-on-startup>标签指定创建实值
-
- 只要该标签值大于等于1即可在Tomcat启动时创建Servlet对象
- 如果有多个Servlet需要在启动时创建,可以利用这个数值决定创建顺序,如果数值相同则按照名称排序决定加载顺序
- 如果是基于注解配置Servlet则需要在@WebServlet注解中指定loadOnStartup来指定Servlet创建时机值,取值为整数类型
<servlet>
<servlet-name>servelet</servlet-name>
<servlet-class>com.wry.servlet.Servlet</servlet-class>
<init-param>
<param-name>name</param-name>
<param-value>Zhangsan</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
- JSP和Servlet的对比
Servlet中虽然可以写标签、css样式等,但使用起来没有在jsp或者html中书写方便。JSP可以做的事情,Servlet同样可以完成,只不过两者侧重点不同:JSP多用于数据展示,Servlet多用于逻辑控制。