07-Request&Response

Request

Servlet请求对应的是ServletRequest对象,它有一个子类HttpServletRequet基于Http协议的规则对请求数据进行了封装。我们可以使用HttpServletRequet对象的方法来获取请求数据,来完成功能的开发。

1.获取各种路径的方法

public String getContextPath()
    获取虚拟名称
public String getServletPath()
    获取servlet映射路径
public String getRemoteAddr()
    获取远程访问者ip地址
public String getQueryString()
    获取请求消息数据
public String getRequestURI()
    获取统一资源标识符(虚拟目录+访问地址)
public String getRequestURL()
    获取统一资源定位符(完整路径)    
@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> getHeaderNames()
    获取所有请求头名称
@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()
    获取所有参数的键值对

创建一个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目录下

1.手动封装方式
    获取所有的对象,把对象封装在我们新建的实体类中
2.反射封装的方式
3.工具类封装方式    
@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);
    }
}

5.流对象获取数据

public BufferedReader getReader()
    获取字符输入流(提交方式必须是post)
public ServletInputStream getInputStream()
    获取字节输入流

6.请求数据乱码问题

GET方式
    没有乱码问题
POST方式
    有乱码问题,可以通过setCharacterEncoding()方法来解决
//设置请求字符编码
req.setCharacterEncoding("UTF-8");    

7.请求域

1.请求域(request域):可以在一次请求范围内进行共享数据
2.一般用于请求转发的多个资源中的共享数据
3.请求对象操作共享数据方法
    设置数据、获取数据、移除数据
  • 在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);
    }
}

8.请求转发

1.请求转发:客户端的一次请求到达后,发现需要借助其他Servlet来实现功能
2.特点:
    浏览器地址栏不变
    域对象的数据不丢失
    负责转发的Servlet转发前后的响应正文会丢失
    由转发的目的地来响应客户端
    
public RequestDispatcher getRequestDispatcher(String name)
    获取请求调度对象
public void forward(HttpServletRequest req, HttpServletResponse resp)
    实现转发

Response

浏览器访问服务器后,服务器给客户端响应的数据会封装为ServletResponse对象,它有一个子类叫HttpServletResponse对象,用于封装按照Http协议封装的响应数据。

1.常见状态码

状态码状态
100只有请求的一部分已经被服务器接收,但只要它没有被拒绝,客户端应继续该请求
200请求成功
302重定向,所请求的页面已经临时转移到一个新的 URL
304访问缓存,所请求的页面已经临时转移到一个新的 URL
404客户端错误,请求路径服务器没有对应的资源
405客户端错误,请求方式找不到对应的方法
500服务端错误,可能服务器内部有异常

2.响应数据乱码解决

字节流:
public ServletOutputStream getOutputStream()
    获取响应字节输出流对象
字符流: 
public PrintWriter getWriter()
    获取响应字符输出流对象
    
解决乱码问题
public void setContentType("text/html;charset=UTF-8")
    设置响应内容类型,解决中文乱码问题
    
//设置响应编码
resp.setContentType("text/html;charset=utf-8");
  • 使用字符流响应数据
@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);
    }
}
  • 使用字节流响应数据
@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图片,把图片中所有的字节响应给客户端。

读取文件的时候注意图片的绝对路径(web目录是根目录)
    String realPath = getServletContext().getRealPath("/img/autumn.jpg");
@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)
    设置消息头添加缓存
    resp.setDateHeader("Expires",System.currentTimeMillis()+1*60*60*1000);

5.定时刷新

定时刷新:过了指定时间后,页面自动进行跳转
    
public void setHeader(String name,String value)
    设置消息头的定时刷新
    resp.setHeader("Refresh","3;URL=/response/login.html");
@WebServlet("/servletDemo05")
public class ServletDemo05 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.设置编码
        resp.setContentType("text/html;charset=UTF-8");
        //2.写数据
        PrintWriter pw = resp.getWriter();
        pw.write("定时刷新,3秒后跳转");
        //定时跳转
        resp.setHeader("Refresh","3;URL=/response/login.html");


    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}

6.重定向

1.重定向:客户端的一次请求到达后,发现需要借助其他servlet来实现功能
2.特点:浏览器地址栏会发生改变,俩次请求,请求域对象不能共享数据,可以重定向到其他服务器 
3.原理:
    设置响应状态码为302  (resp.setStatus(302))
    设置响应的资料路径(响应到到了去,通过响应消息头location来指定)
    
public void sendRedirect(String name)
    设置重定向
    resp.sendRedirect(req.getContextPath()+"/servletDemo07");
@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.文件下载

写一个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);
    }
}

8.路径问题

* 路径写法:
	1. 路径分类
		1. 相对路径:通过相对路径不可以确定唯一资源
			* 如:./index.html
			* 不以/开头,以.开头路径

			* 规则:找到当前资源和目标资源之间的相对位置关系
			* ./:当前目录
			* ../:后退一级目录
		2. 绝对路径:通过绝对路径可以确定唯一资源
			* 如:http://localhost/day15/responseDemo2		/day15/responseDemo2
			*/开头的路径

			* 规则:判断定义的路径是给谁用的?判断请求将来从哪儿发出
			* 给客户端浏览器使用:需要加虚拟目录(项目的访问路径)
			* 建议虚拟目录动态获取:request.getContextPath()
			* <a> , <form> 重定向...
			* 给服务器使用:不需要加虚拟目录
			* 转发路径
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值