一、HttpServletRequest
1、概述:
我们在创建Servlet时会覆盖service()方法,或doGet()/doPost(),这些方法都有两个参数,一个为代表请求的request和代表的响应response。
service方法中的request的类型是ServletRequest,而doGet/doPost方法的request的类型是HttpServletRequest,HttpServletRequest是ServletRequest的子接口,功能和方法更加强大,今天我们学习HttpServletRequest。
2、request的运行流程
3、通过抓包工具抓取Http请求
因为request代表请求,所以我们可以通过该对象分别获得Http请求的请求行,请求头和请求体
4、通过request获得请求行
获得客户端的请求方式:String
getMethod()
获得请求的资源:
String
getRequestURI()
获得请求地址
StringBuffer
getRequestURL()
获得网络地址
String
getContextPath()
---
获得
web
应用的名称
String
getQueryString()
----
只能获得
get
方式
提交
url
地址后的参数字符串 如:username=zhangsan&password=123
注意:request获得客户机(客户端)的一些信息
request.getRemoteAddr() --- 获得访问的客户端IP地址
5、通过request获得请求头
long
getDateHeader(
String name)
String
getHeader(
String name)
Enumeration
getHeaderNames()
Enumeration
getHeaders(
String name)
int
getIntHeader(
String name)
referer头的作用:执行该此访问的的来源,做防盗链 (referer的内容为访问的网络地址)
package com.oracle.demo01; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class RefererServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取referer请求头 String referer=request.getHeader("referer"); //对该访问的来源进行判断 //如果判断成功,代表我自己的域名,就可以访问 if(referer!=null&&referer.startsWith("http://localhost:8080")){ response.setContentType("text/html;charset=utf-8"); response.getWriter().write("习大大擘画新时代党的组织路线图"); }else{ response.setContentType("text/html;charset=utf-8"); response.getWriter().write("你是盗链者,丢不丢人"); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
Jsp代码:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <a href="/WEB04/RefererServlet">习大大说新时代</a> <form action="/WEB04/LoginServlet" method="get"> 用户名:<input type="text" name="username"><br> 密码:<input type="password" name="pwd"><br> <input type="submit" value="登陆"><br> <input type="reset" value="重置"> </form> </body> </html>
代码演示:
package com.oracle.demo01; import java.io.IOException; import java.util.Enumeration; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class LoginServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取请求行里信息的方法 //获取请求方式 String method=request.getMethod(); System.out.println(method); //获取请求资源的相关内容 String requestURI=request.getRequestURI(); StringBuffer requestURL=request.getRequestURL(); System.out.println("requestURI:"+requestURI); System.out.println("requestURL:"+requestURL); //获取WEB应用的名称 String name=request.getContextPath(); System.out.println(name); //获取get方式提交后url地址后的字符串 String queryString=request.getQueryString(); System.out.println(queryString); //获取客户机的信息----获取访问者的IP地址 String ip=request.getRemoteAddr(); System.out.println(ip); //获取请求头中的内容 //获取指定头 String header=request.getHeader("User-Agent"); System.out.println(header); //获得所有头的名称 Enumeration<String> en=request.getHeaderNames(); //以键值对的形式获得,并保存在集合中 while(en.hasMoreElements()){ //遍历,获得键和值 String headerName=en.nextElement(); String headerValue=request.getHeader(headerName); System.out.println(headerName+":"+headerValue); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
6、通过request获取请求体
String
getParameter(
String name)
String[]
getParameterValues(
String name)
Enumeration
getParameterNames()
Map<String,String[]>
getParameterMap()
注意:get请求方式的请求参数 上述的方法一样可以获得
解决post提交方式的乱码:request.setCharacterEncoding("UTF-8");
解决get提交的方式的乱码: parameter = new String(parameter.getbytes("iso8859-1"),"utf-8");
7、request的其他功能
(1)request是一个域对象
request对象也是一个存储数据的区域对象,所以也具有如下方法:
setAttribute(
String name,
Object o)
getAttribute(
String name)
removeAttribute(
String name)
注意:request域的作用范围:一次请求中
(2)request完成请求转发
获得请求转发器----path
是转发的地址
RequestDispatcher
getRequestDispatcher(
String path)
通过转发器对象转发
requestDispathcer.forward(
ServletRequest request,
ServletResponse response)
注意:
ServletContext
域与
Request
域的生命周期比较?
ServletContext
:
创建:服务器启动
销毁:服务器关闭
域的作用范围:整个
web
应用
request
:
创建:访问时创建
request
销毁:响应结束
request
销毁
域的作用范围:一次请求中
注意:转发与重定向的区别?
1
)重定向两次请求,转发一次请求
2
)重定向地址栏的地址变化,转发地址不变
3
)重新定向可以访问外部网站
转发只能访问内部资源
4
)转发的性能要优于重定向
代码演示:
package com.oracle.demo02; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Servlet01 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //向request域中存值 request.setAttribute("name", "wang"); //请求转发 //获得转发器对象,并调用转发方法 request.getRequestDispatcher("/Servlet02").forward(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
总结:
request
获得行的内容
request.getMethod()
request.getRequestURI()
request.getRequestURL()
request.getContextPath()
request.getRemoteAddr()
request
获得头的内容
request.getHeader(name)
request
获得体(请求参数)
String request.getParameter(name)
Map<String,String[]> request.getParameterMap();
String[] request.getParameterValues(name);
注意:客户端发送的参数
到服务器端都是字符串
获得中文乱码的解决:
post:request.setCharacterEncoding(“UTF-8”);
get:parameter = new String(parameter.getBytes(“iso8859-1”),”UTF-8”);
request
转发和域
request.getRequestDispatcher(
转发的地址
).forward(req,resp);
request.setAttribute(name,value)
request.getAttribute(name)
二、HttpServletResponse
1.HttpServletResponse概述
我们在创建Servlet时会覆盖service()方法,或doGet()/doPost(),这些方法都有两个参数,一个为代表请求的request和代表响应response。
service方法中的response的类型是ServletResponse,而doGet/doPost方法的response的类型是HttpServletResponse,HttpServletResponse是ServletResponse的子接口,功能和方法更加强大,今天我们学习HttpServletResponse。
2. Response运行流程
3. 通过抓包工具获取Http响应
因为response代表响应,所以我们可以通过该对象分别设置Http响应的响应行,响应头和响应体
4.通过response设置响应行
设置响应行的状态码: setStatus(int sc)
代码演示:
package com.oracle.demo01; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Servlet01 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置响应行的状态码:response.setStatus(int类型的数值);当响应成功后的状态码就是你设置的 response.setStatus(404); response.getWriter().write("hello dandan..."); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
5.通过response设置响应头
addHeader(
String name,
String value)
addIntHeader(
String name, int value)
addDateHeader(
String name, long date)
setHeader(
String name,
String value)
重定向
setDateHeader(
String name, long date)
setIntHeader(
String name, int value)
其中,add表示添加,而set表示设置
重定向需要:1.状态码:302
2.响应头:location 代表重定向地址
重定向代码演示:
package com.oracle.demo01; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Servlet02 extends HttpServlet { //重定向: //1.服务器访问两次 //2.地址栏地址会有变化 //当访问第一个Servletet02的时候,第一个没有资源,但是会返回一个响应,告知客户端Servlet03有资源 //客户端就会自己跳转到Servlet03的页面 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // //1.设置状态码 // response.setStatus(302); // //2.设置响应头Location,重定向 // response.setHeader("Location", "/WEB03/Servlet03"); //开发中上面的方法一般不用,会使用下面封装好的方法 //开发中封装好的 专门用于重定向的方法:response.sendRedirect(); response.sendRedirect("/WEB03/Servlet03"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
6.通过response设置响应体
(1)响应体设置文本
PrintWriter
getWriter()
流程:获得字符流,通过字符流的write(
String s)
方法可以将字符串设置到response缓冲区中,随后Tomcat会将response缓冲区中的内容组装成Http响应返回给浏览器端。(必须会说)
关于设置中文的乱码问题
原因:response缓冲区的默认编码是iso8859-1,此码表中没有中文,可以通过response的setCharacterEncoding(
String charset)
设置response的编码
但我们发现客户端还是不能正常显示文字
原因:我们将response缓冲区的编码设置成UTF-8,但浏览器的默认编码是本地系统的编码,因为我们都是中文系统,所以客户端浏览器的默认编码是GBK,我们可以手动修改浏览器的编码是UTF-8。
我们还可以在代码中指定浏览器解析页面的编码方式,
通过response的setContentType(
String type)
方法指定页面解析时的编码是UTF-8
response.setContentType("text/html;charset=UTF-8");
上面的代码不仅可以指定浏览器解析页面时的编码,同时也内含setCharacterEncoding的功能,所以在实际开发中只要编写response.setContentType("text/html;charset=UTF-8");就可以解决页面输出中文乱码问题。
解决中文乱码代码演示:
package com.oracle.demo01; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Servlet04 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //解决中文乱码的问题 //设置缓冲区的编码为UTF-8 // response.setCharacterEncoding("UTF-8"); // //告知客户端给我用UTF-8解码 // response.setHeader("Content-Type", "text/html;charset=UTF-8"); response.setContentType("text/html;charset=UTF-8"); response.getWriter().write("中国"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
(2)响应头设置字节
ServletOutputStream
getOutputStream()
在浏览器上输出一个文件,前提是浏览器可以解析,不能解析就是提供下载
获得字节流,通过该字节流的write(byte[] bytes)可以向response缓冲区中写入字 节,在由Tomcat服务器将字节内容组成Http响应返回给浏览器。
响应头设置时间自动跳转:
package com.oracle.demo01; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Servlet03 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //定时刷新的响应头:定时刷新跳转到另一个网页 response.setHeader("refresh", "5;url=http:///www.baidu.com"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
Jsp代码:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <script type="text/javascript"> var time=5; //全局函数,当全部页面加载完成后才会执行的函数 window.onload=function(){ var second=document.getElementById("second"); timer=setInterval(function(){ //定时器函数 second.innerHTML=time; time--; if(time==0){ clearInterval(timer); //清除定时器 location.href="http://www.baidu.com"; } }, 1000); } </script> </head> <body> 恭喜你,注册成功,<span style="color:red" id="second">5</span> 秒后跳转,如不跳转,请点击<a href="http://www.baidu.com">这里</a> </body> </html>
练习题:
1. 文件的下载:
package com.oracle.demo02; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URLEncoder; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; //import sun.misc.BASE64Encoder; public class DownloadServlet extends HttpServlet { //服务器提供文件下载的方法 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.获得下载的文件的名称 String filename=request.getParameter("filename"); //解决中文乱码的问题 filename=new String(filename.getBytes("ISO8859-1"),"UTF-8"); //获取浏览器的请求头User-Agent String agent=request.getHeader("User-Agent"); String filenameEncoding=""; //根据不同的浏览器进行编码(模板代码复制即可,不需要记忆) if (agent.contains("MSIE")) { // IE浏览器 filenameEncoding = URLEncoder.encode(filename, "utf-8"); filenameEncoding = filename.replace("+", " "); } // else if (agent.contains("Firefox")) { // // 火狐浏览器 // BASE64Encoder base64Encoder = new BASE64Encoder(); // filenameEncoding = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?="; // } else { // 其它浏览器 filenameEncoding = URLEncoder.encode(filename, "utf-8"); } //2.设置要下载的文件的类型----客户端通过文件的MIME类型区分文件的类型 response.setContentType(this.getServletContext().getMimeType(filename)); //3.告诉你的客户端该文件不能直接解析,而是以附件的形式打开(下载) response.setHeader("Content-Disposition", "attachment;filename="+filenameEncoding); //4.获取文件的绝对路径 String path=this.getServletContext().getRealPath("download/"+filename); //5.创建输入流 InputStream in=new FileInputStream(path); //6.获取输出流--通过response获得输出流 ServletOutputStream out=response.getOutputStream(); //7.文件复制的模板代码 int len=0; byte[] bytes=new byte[1024]; while((len=in.read(bytes))!=-1){ out.write(bytes,0,len); //输出到浏览器上 } //8.释放资源 in.close(); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
Jsp代码:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<h1>使用a标签直接指向服务器上的资源提供下载功能</h1>
<a href="/WEB03/download/中国.txt">中国.txt</a>
<a href="/WEB03/download/commons.zip">commons.zip</a>
<a href="/WEB03/download/dameinv.jpg">dameinv.jpg</a>
<h1>使用服务器端编码的方式实现下载功能</h1>
<a href="/WEB03/DownloadServlet?filename=中国.txt">中国.txt</a>
<a href="/WEB03/DownloadServlet?filename=commons.zip">commons.zip</a>
<a href="/WEB03/DownloadServlet?filename=dameinv.jpg">dameinv.jpg</a>
</body>
</html>
2. 将图片输出到页面:
package com.oracle.demo02; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class MyServlet01 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //使用response获取字节输出流,负责写给客户端的 ServletOutputStream out=response.getOutputStream(); //确定数据源,将图片读到程序中 String realPath=this.getServletContext().getRealPath("dameinv.jpg"); //获取图片路径 InputStream in=new FileInputStream(realPath); int len=0; byte[] bytes=new byte[1024]; while((len=in.read(bytes))!=-1){ //将程序中的字节数组写到客户端 out.write(bytes,0,len); } //释放资源 in.close(); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
3. 注册到数据库:
dao层代码:
package com.oracle.demo02; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class Dao { public int dao(String username,String pwd) throws SQLException{ Connection conn=JDBCUtils.getConnection(); String sql="insert into user (username,password) values(?,?)"; PreparedStatement pst=conn.prepareStatement(sql); pst.setString(1, username); pst.setString(2, pwd); int row=pst.executeUpdate(); JDBCUtils.close(pst, conn); return row; } }
service层代码:
package com.oracle.demo02; import java.sql.SQLException; public class Service { public String service(String username,String pwd) throws SQLException{ Dao d=new Dao(); int count=d.dao(username, pwd); String mes=""; if(count>0){ mes="注册成功"; }else{ mes="注册失败"; } return mes; } }
servlet层代码:
package com.oracle.demo02; import java.io.IOException; import java.sql.SQLException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class InsertServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); String username=request.getParameter("username"); String pwd=request.getParameter("pwd"); Service s=new Service(); try { String mes=s.service(username, pwd); response.getWriter().write(mes); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
JDButils代码:
package com.oracle.demo02; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class JDBCUtils { public static Connection getConnection(){ try{ //注册驱动 Class.forName("com.mysql.jdbc.Driver"); String username="root"; String password="123456"; String url="jdbc:mysql://localhost:3306/goods?characterEncoding=utf-8"; //获得连接 Connection conn=DriverManager.getConnection(url,username,password); return conn; }catch(Exception ex){ throw new RuntimeException(ex+"数据库连接失败"); } } //关闭数据库的方法 public static void close(ResultSet rs,Statement sta,Connection conn){ if(rs!=null){ try { rs.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(sta!=null){ try { sta.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static void close(Statement sta,Connection conn){ if(sta!=null){ try { sta.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
Jsp代码:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <script type="text/javascript"> function changeImg(obj){ obj.src="/WEB03/CheckImgServlet?time="+new Date().getTime(); } </script> </head> <body> <div><%=request.getAttribute("loginInfo")==null?"":request.getAttribute("loginInfo") %></div> <form action="/WEB03/LoginServlet" method="post"> 验证码:<input type="text" name="checkcode"> <img src="/WEB03/CheckImgServlet" onclick="changeImg(this)"> <input type="submit" value="登陆"> </form> </body> </html>