Servlet请求
Servlet请求对应的是ServletRequest对象,它有一个子类HttpServletRequet基于Http协议的规则对请求数据进行了封装。我们可以使用HttpServletRequet对象的方法来获取请求数据,来完成功能的开发。
1.获取路径的方法
public String getContextPath() //发布项目时所写的虚拟目录 /servlet
获取虚拟目录路径
public String getServletPath()//访问资源的路径 /ServletDemo1
获取Servlet的映射路径
public String getRemoteAddr()
获取访问者的ip地址
public String getQueryString()
获取请求的消息数据
public String getRequestURI()//虚拟目录和访问资源的路径一起获取到 /servlet/ServletDemo1
获取统一资源标识符
public String getRequestURL()//完整路径 http://localhost:8080/servlet/ServletDemo1
获取统一资源定位符
ps:URI比URL范围更大
@WebServlet("/servletRequestDemo1")
public class ServletRequestDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取虚拟目录
String contextPath = req.getContextPath();
System.out.println("虚拟目录:"+contextPath);
//获取Servlet映射路径
String servletPath = req.getServletPath();
System.out.println("servlet访问路径:"+servletPath);
//获取访问者ip地址:
String remoteAddr = req.getRemoteAddr();
System.out.println("访问者ip:"+remoteAddr);
//获取统一资源标识符
String requestURI = req.getRequestURI();
System.out.println("资源标识符:"+requestURI);
//获取统一资源定位符
StringBuffer requestURL = req.getRequestURL();
System.out.println("统一资源定位符:"+requestURL);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
2.获取请求头信息
请求头是浏览器告诉服务器的一些请求配置信息,以键值对的形式存在。
public String getHeader(String name)
获取一个请求头的值
public Enumeration<String> getHeaders(String name)
获取一个请求头的多个值
public Enumeration<String> getHeadNames()
获取所有请求头名称
@WebServlet("/servletRequestDemo2")
public class ServletRequestDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取一个请求头
String connection = req.getHeader("connection");
System.out.println(connection);
System.out.println("----------------");
//获取一个请求头的多个值
Enumeration<String> values = req.getHeaders("accept-encoding");
while (values.hasMoreElements()) {
String value = values.nextElement();
System.out.println(value);
}
System.out.println("------------");
//获取所有的请求头名称
Enumeration<String> headerNames = req.getHeaderNames();
//遍历请求头名称,根据名称获取值
while (headerNames.hasMoreElements()) {
String headName = headerNames.nextElement();
String headValue = req.getHeader(headName);
System.out.println(headName+"="+headValue);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
3.获取请求参数信息
public String getParameter(String name)
根据参数名获取一个参数值
public String[] getParameterValues(String name)
根据参数名获取多个参数值
public Enumeration<String> getParameterNames()
获取所有的参数名称
public Map<String,String[]> getParameterMap()
获取所有的参数名和参数值,并封装为Map集合
创建一个regist.html页面(参考源代码),然后使用Servlet获取参数信息
@WebServlet("/servletRequestDemo3")
public class ServletRequestDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//根据参数名获取参数指
String username = req.getParameter("username");
System.out.println("姓名:"+username);
//根据参数名获取多个值
String[] hobbies = req.getParameterValues("hobby");
System.out.println("爱好:"+ Arrays.toString(hobbies));
System.out.println("---------");
//获取所有的参数名称
Enumeration<String> parameterNames = req.getParameterNames();
while (parameterNames.hasMoreElements()) {
String parameterName = parameterNames.nextElement();
String[] values = req.getParameterValues(parameterName);
System.out.println(parameterName+":"+Arrays.toString(values));
}
System.out.println("----------");
//获取所有的参数名和参数指,存入一个Map集合
Map<String, String[]> parameterMap = req.getParameterMap();
Set<String> keys = parameterMap.keySet();
for (String key : keys) {
String[] values = parameterMap.get(key);
System.out.println(key+"="+Arrays.toString(values));
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
4.请求数据封装对象
需要用到beanutils工具类,把jar包复制到web/WEB-INF/libs目录下
@WebServlet("/servletRequestDemo5")
public class ServletRequestDemo5 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取所有的参数名和参数指,存入一个Map集合
Map<String, String[]> parameterMap = req.getParameterMap();
Student stu=new Student();
try {
BeanUtils.populate(stu,parameterMap);
System.out.println(stu);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
通过流对象获取数据
public BufferedReader getReader()
----获取字符输入流
ps:借住io流获取数据,表单的请求方式必须是post
public ServletInPutStream getInPutStream()
----获取字节输入流
5.请求数据乱码解决
//设置请求字符编码
req.setCharacterEncoding("utf-8");
6.请求转发-请求域
-
请求域(也叫request域):可以在一次请求范围内进行共享数据(一般用于请求转发的多个资源中共享数据)
-
当客户端请求一个Servlet1时,Servlet1可以将请求转发给Servlet2,同时可以转发过程中共享数据。多次转发形成的一条请求链,叫做请求域。可以在请求域访问内共享数据。
-
请求转发:客户端的一次请求到达后,发现需要借住其他Servlet来实现功能
-
特点:
- 浏览器地址栏不变
- 域对象中的数据不丢失
- 负责转发的Servlet转发前后的响应正文会丢失
- 由转发的目的地来响应客户端
-
方法
- public RequestDispatcher getRequestDispacher(String name) ---获取请求调度对象 String name---转发的Servlet的映射路径 - public void forward(ServletRequest req,ServletReponse resp) ---实现转发
-
在Servlet7中设置共享数据
@WebServlet("/servletRequestDemo7")
public class ServletRequestDemo7 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置请求编码
req.setCharacterEncoding("utf-8");
//设置请求参数
req.setAttribute("user","李四");
req.getRequestDispatcher("/servletRequestDemo8").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
- 在Servlet8中获取共享数据
@WebServlet("/servletRequestDemo8")
public class ServletRequestDemo8 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置请求编码
req.setCharacterEncoding("utf-8");
//获取请求共享数据
Object user = req.getAttribute("user");
System.out.println(user);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
Servlet响应
浏览器访问服务器后,服务器给客户端响应的数据会封装为ServletResponse对象,它有一个子类叫HttpServletResponse对象,用于封装按照Http协议封装的响应数据。
- 响应:就是回馈结果,在B/S架构中,就是服务器端给客户端浏览器反馈结果
- 响应对象:就是在项目中用于发送响应的对象
1.响应状态码
状态码 | 状态 |
---|---|
100 | 只有请求的一部分已经被服务器接收,但只要它没有被拒绝,客户端应继续该请求 |
200 | 请求成功 |
302 | 重定向,所请求的页面已经临时转移到一个新的 URL |
304 | 访问缓存,所请求的页面已经临时转移到一个新的 URL |
404 | 客户端错误,请求路径服务器没有对应的资源 |
405 | 客户端错误,请求方式找不到对应的方法 |
500 | 服务端错误,可能服务器内部有异常 |
2.响应数据乱码解决
//设置响应编码,解决中文乱码问题
public void setContentType("text/html;charset=utg-8")
resp.setContentType("text/html;charset=utf-8");
-
使用字符流响应数据
-
public PrintWriter getWriter()
获取响应字符流输出对象
-
@WebServlet("/servletResponseDemo1")
public class ServletResponseDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置响应编码
resp.setContentType("text/html;charset=utf-8");
//输出响应数据
resp.getWriter().println("<h1>你好,这是一个响应消息</h1>");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
-
使用字节流响应数据
-
public ServletOutputStream getOutputStream()
获取响应字节输出流对象
-
@WebServlet("/servletResponseDemo2")
public class ServletResponseDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置响应编码
resp.setContentType("text/html;charset=utf-8");
//输出响应数据
ServletOutputStream outputStream = resp.getOutputStream();
outputStream.write("你好世界".getBytes("utf-8"));
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
3.响应图片
在web/img目录下放一张a.jpeg图片,把图片中所有的字节响应给客户端。
- 创建字节输入流对象,关联读取的图片路径
- 注意:发布项目后图片路径会变,要获取项目发布后的绝对路径
- 通过响应对象获取字节输出流对象
- 循环读取和写出图片
@WebServlet("/servletResponseDemo3")
public class ServletResponseDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取输出流对象
ServletOutputStream out = resp.getOutputStream();
//获取文件的绝对路径
String imgPath = getServletContext().getRealPath("img/a.jpeg");
//获取输入流对象
FileInputStream fis = new FileInputStream(imgPath);
byte[] bs=new byte[1024];
int len;
while ((len=fis.read(bs))!=-1){
out.write(bs,0,len);
}
fis.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
4.设置缓存[了解]
-
缓存:对于不经常变化的数据,我们可以合理设置缓存时间,以避免浏览器频繁请求服务器,以此来提高效率.
-
public void setDateHeader(String name,long time)
设置消息头添加缓存
String name 直接写成Expires
-
注意:像Chrome和Firefox等高级的浏览器无法进行显示
@WebServlet("/servletDemo4") public class ServletDemo4 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String str = "这是一条劲爆的新闻"; //设置缓存时间1小时 resp.setDateHeader("Expires",System.currentTimeMillis()+1000*1*60*60); //设置编码格式 resp.setContentType("text/html;charset=utf-8"); //输出消息 resp.getWriter().write(str); //添加一条信息,查看缓存是否设置 System.out.println("我执行了..."); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
-
5.设置定时刷新
- 定时刷新:过了指定时间后,页面自动进行跳转
- pubIic void setHeader(String name,String value)
设置消息头定时刷新(消息头的名称,指定时间和跳转目的地)
@WebServlet("/servletResponseDemo5")
public class ServletResponseDemo5 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setHeader("Refresh","3;url=/day03_Servlet/login.html");
resp.setContentType("text/html;charset=utf-8");
resp.getWriter().println("你好世界 三秒钟跳转到登录页面");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
6.重定向
- 重定向:客户端的一次请求到达后,发现需要借助其他Servlet来实现功能
- 特点:浏览器地址栏会发生改变,两次请求,请求域对象中不能共享数据,可以重定向到其他服务器
- public void setRedirect(String name) ------设置重定向
重定向和请求转发不太一样,请求转发是只有一个请求,而重定向有两次请求。所以重定向不能通过请求域共享数据,只有在同一个请求链中才能通过请求域中心数据。
@WebServlet("/servletResponseDemo6")
public class ServletResponseDemo6 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
//重定向到servletResponseDemo5
//resp.sendRedirect(req.getContextPath()+"/servletResponseDemo5");
//也可以使用下面两个方法,完成重定向;302表示重定向的状态码
resp.setStatus(302);
resp.setHeader("location",req.getContextPath()+"/servletResponseDemo5");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
7.文件下载
-
创建字节输入流,关联读取的文件
-
设置响应消息头支持的类型
-
public void setHeader(“Content-Type”,applicatin/octet-stream)
/*
Content-Type:消息头名称 支持的类型
application/octet-stream:消息头参数 应用的类型为字节流
*/
-
-
设置响应消息头以下载方式打开资源
-
public void setHeader(“Content-Disposition”,“attachement;filename=a.jpg”)
/*
Content-Disposition:消息头名称 处理形式
attachment;filename=a.jpg:消息头参数 附件形式进行处理 指定下载文件的名称
*/
-
-
通过响应对象获取字节输出流对象
-
循环读写
-
释放资源
写一个html页面,点击图片开始下载
<a href="/day03_Servlet/servletResponseDemo7">点击下载图片</a>
写以Servlet处理下载的请求,给客户端响应一张图片
@WebServlet("/servletResponseDemo7")
public class ServletResponseDemo7 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//准备要下载的图片
File file=new File("img/a.jpeg");
//设置响应头,告诉浏览器以附件形式接受
resp.setHeader("content-disposition","attachment;filename="+file.getName());
//获取输出流对象
ServletOutputStream out = resp.getOutputStream();
//获取文件的绝对路径
String imgPath = getServletContext().getRealPath(file.getPath());
//获取输入流对象
FileInputStream fis = new FileInputStream(imgPath);
byte[] bs=new byte[1024];
int len;
while ((len=fis.read(bs))!=-1){
out.write(bs,0,len);
}
fis.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}