Request对象和Response对象详解以及验证码的Java实现

Request
1.获取请求的基本信息
1>获取请求的url和uri
2>获取url后面的请求参数部分的字符串
3>获取请求方式
4>获取主机名,IP地址
5>获取 Contexpath
 
String url = request .getRequestURL().toString();
System. out .println( url );
 
String uri = request .getRequestURI().toString();
System. out .println( uri );
 
String params = request .getQueryString();
System. out .println( params );
 
String method = request .getMethod();
System. out .println( method );
 
String addr = request .getRemoteHost() + request .getRemotePort() + request .getRemoteAddr() +
     "==user=" + request .getRemoteUser();
System. out .println( "addr: " + addr );
 
String contextPath = request .getContextPath();
response .sendRedirect( contextPath + "/index.jsp" );
 
2.通过 Referer 请求头实现防盗链
Referer请求头的值表示从哪个网页上的链接访问到当前链接
盗链: 其他站点通过超链接链接到自己的站点,从而实现资源的盗窃称为盗链.
@WebServlet ( "/NewsServlet" )
public class NewsServlet extends HttpServlet {
     private static final long serialVersionUID = 1L;
     protected void doGet(HttpServletRequest request , HttpServletResponse response ) throws ServletException, IOException {
         response .setContentType( "text/html;charset=utf-8" );
       
       String referer = request .getHeader( "Referer" );
        if ( referer == null || "" .equals( referer ) || ! referer .contains( "localhost/" )) {
            response .sendRedirect( request .getContextPath() + "/index.jsp" );
       }
       
        response .getWriter().write( "习大大吃包子...." );
    }
 
     protected void doPost(HttpServletRequest request , HttpServletResponse response ) throws ServletException, IOException {
       doGet( request , response );
    }
}
 
如果Referer为空或者不是从自己的站点访问过来就重定向到自己站点的主页.
 
 
2.获取请求参数
Map<String, String[]> params = request .getParameterMap();
for (String name : params .keySet()) {
   String value = request .getParameter( name );
   System. out .println( "name=" + name + ", value=" + value );
}
 
解决请求乱码问题:
request.setCharacterEncoding(" Utf -8");
如果上面的代码只能解决POST的乱码问题, 则可以自行进行解码操作
String userName = request .getParameter( "username" );
userName new String( userName .getBytes( "ISO8859-1" ), "UTF-8" );
 
前段使用 UTF-8 进行编码, 传输到服务器, 服务器可以使用 ISO8859-1 解码得到UTF-8编码后的码值, 然后通过new String(bytes, charset)的方式进行解码.
 
3.设置和获取域属性
Object attr = request .getAttribute( "attr" );
request .setAttribute( "key" , "value" );
request .removeAttribute( "attr" );
Enumeration<String> attributeNames = request .getAttributeNames();
 
一般我们的应用是servlet处理数据, 将处理好的数据放到request域中,然后带到jsp页面上进行展示操作.
 
  1. 请求转发与请求包含
请求转发:
request .getRequestDispatcher( "/DispatcherTest2" ).forward( request , response );
this .getServletContext().getRequestDispatcher( "/DispatcherTest2" ).forward( request , response );
 
Note:
    1)一次请求只能转发一次, 否则会发生下面的异常: -- 可以得到第一次转发获取的数据
java.lang.IllegalStateException : Cannot forward after response has been committed
    2)当有数据已经写到客户端时再请求转发也会抛出异常.
    3)若转发前有数据写入到response缓冲区,则请求转发会清空response缓冲区的实体内容, 但不会清空请求头信息.
 
 
请求包含:
当需要将多个servlet的输出合并到一块打给浏览器时可以使用请求包含
request .getRequestDispatcher( "/DispatcherTest2" ).include( request , response );
this.getServletContext().getRequestDispatcher("/DispatcherTest2").include(request, response);
 
Notice:
    1)被包含的Servlet程序不能改变响应消息的状态码和响应头,如果它里面存在这样的语句,这些语句的执行结果将被忽略.
    2)常被用来进行页面布局
 
请求重定向:
response .sendRedirect( request .getContextPath() + "/DispatcherTest2" );
 
Notice:
1) 不能在数据已经发送到浏览器之后再进行请求重定向:
java.lang.IllegalStateException : Cannot call sendRedirect() after the response has been committed
 
2) 在请求重定向之前写入到response缓冲区的数据会被清空
3) 一次请求只能重定向一次
 
 
Summary:
请求重定向地址栏会发生变化.请求转发地址栏不发生变化.
请求重定向两次请求两次响应.请求转发一次请求一次响应.
 
如果需要在资源跳转时利用request域传递域属性则必须使用请求转发
如果希望资源跳转后修改用户的地址栏则使用请求重定向
 
如果使用请求转发也可以重定向也可以,则优先使用请求转发,减少浏览器对服务器的访问次数减轻服务器的压力.
 
 
 
Response
1.response
    ServletResponse -- 通用的response提供了一个响应应该具有最基本的属性和方法
        |
        |-HttpServletResponse -- 在ServletResponse的基础上针对于HTTP协议增加了很多强化的属性和方法
 
2.输出数据
 1)getOutputStream字节输出流
response.getOutputStream().write("中国".getBytes(" utf -8"));
 
string.getBytes()如果没有指定编码方式,会使用平台默认的编码方式
 
2)getWriter字符输出流
response .getWriter().write( "北京" );
    Notice: getWriter和getOutputStream在一次请求中只能使用一个
    使用字符输出流输出中文时, 由于网线上只能输出高低电平,如果没有指定编码方式,那么服务器在发送数据时会使用默认的ISO-8859-1对数据编码(该码表中没有汉字, 因此汉字会被编码为?, 传送到浏览器上的数据实际就是?).
 
3)解决乱码
    1> 通知服务器发送数据时使用utf-8编码
response.setCharacterEncoding(" utf -8");
 
    2> 通知浏览器接受数据时使用utf-8解码
response.setHeader("Content-Type", "text/ html ; charset = utf -8");
 
    3> Notice:
        a. response对象中对Content-Type响应头进行了封装,可以使用一下代码代替 2>
response .setContentType( "text/html;charset=utf-8" );
        b. 如果设置了Content-Type,服务器会自动的设置 characterEncoding,因此解决乱码只需要设置Content-Type响应头一行代码就可以了,但是为了代码的可读性更高,一般还是建议同时设置 characterEncoding 和 Content-Type.
 
 
3)实现下载
protected void doGet(HttpServletRequest request , HttpServletResponse response ) throws ServletException, IOException {
     response .setHeader( "Content-Disposition" , "attachment;filename=" + URLEncoder. encode ( "美女.jpg" ) );
    InputStream in = new FileInputStream( this .getServletContext().getRealPath( "美女.jpg" ));
    OutputStream out = response .getOutputStream();
     byte [] bytes = new byte [1024];
     int len = -1;
     while (-1 != ( len = in .read( bytes ))) {
        out .write( bytes , 0, len );
    }
     in .close();
}
 
4) 实现定时刷新
    1.Servlet实现
response .setContentType( "text/html;charset=utf-8" );
response .getWriter().write( "恭喜您注册成功, 3秒后回到主页" );
response .setHeader( "Refresh" , "3;url=OutServlet" );
 
    2.html实现
< meta charset = "UTF-8" >
< meta http-equiv = "Refresh" content = "3; url=index.jsp" >
< title > Insert title here </ title >
</ head >
< body >
    恭喜您注册成功, 3秒后回到主页....
</ body >
 
 
5)控制浏览器是否缓存
response .setIntHeader( "Expires" , -1);
response .setHeader( "Cache-Control" , "no-cache" );
response .setHeader( "Pragma" , "no-cache" );
response .getWriter().write( new Date(). toLocaleString () );
 
6)实现请求重定向
response.sendRedirect( this.getServletContext().getContextPath());
 
7)输出验证码图片
package com.inetsoft.response;
 
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
 
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * @Description : 用于输出验证码图片的 Servlet
 * @Warning :
 * @Author DreamLi
 * @Package Day04 - Response - Request  --   com.inetsoft.response.ValidServlet
 * @Date : 2017年12月17日 下午4:51:22
 * @Version : 1.0.0
 */
@WebServlet( "/ValidServlet")
public class ValidServlet extends HttpServlet {
    
     private static final long serialVersionUID = -70985881600765636L;
     private Random rand = new Random();
 
     public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //设置响应头让浏览器不再缓存验证码图片
        response.setDateHeader( "Expires", -1);
        response.setHeader( "Cache-Control", "no-cache");
        response.setHeader( "Pragma", "no-cache");
       
        //创建验证码图片
        //1.创建一张图片到内存中
        int width = 120;
        int height = 30;
       BufferedImage img = new BufferedImage( width, height, BufferedImage. TYPE_INT_RGB);
        //2.获取该图片上的画笔
       Graphics2D g = (Graphics2D) img.getGraphics();
        //3.设置背景色以及图片边框
        g.setColor( new Color(199,237,204));
        g.fillRect(0, 0, width, height);
        g.setColor(Color. black);
        g.drawRect(0, 0, width-1, height-1);
 
        //4.设置干扰线
        int lineNum = randNumber(3,7); //干扰线的条数
        for( int i = 0; i < lineNum; i++){
            g.setColor( new Color(randNumber(0,255),randNumber(0,255),randNumber(0,255)));
            g.drawLine(randNumber(0, width), randNumber(0, height),randNumber(0, width), randNumber(0, height) );
       }
 
        //5.设置验证码内容
        int row = 10;
        int col = 22;
        g.setFont( new Font( "黑体", Font. BOLD, 20));
       StringBuffer buffer = new StringBuffer();
        for( int i = 0; i < 4; i++){
            g.setColor( new Color(randNumber(0,255),randNumber(0,255),randNumber(0,255)));
            double theta = Math. toRadians(randNumber(-50, 50));
            g.rotate( theta, row, col);
            int num = randNumber(0, 9);
            buffer.append( num);
            g.drawString( num+ "", row, col);
            g.rotate(0- theta, row, col);
            row += 30;
       }
        //将验证码加入到session
         request.getSession().setAttribute( "valid", buffer.toString());
       System. out.println( buffer);
        //6.写入到输出流中
       ImageIO. write( img, "jpg", response.getOutputStream());
    }
 
     /**
     * 产生一个区间里面的随机数
     * @param left 区间左值
     * @param right 区间右值
     * @return 区间里面的一个随机数
     */
     private int randNumber( int left, int right){
        return  rand.nextInt( right - left) + left;
    }
 
     public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
       doGet( request, response);
    }
}
 
 
 
发布了25 篇原创文章 · 获赞 36 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/DreamLi1314/article/details/78906783