JavaWeb——(9)Request&Response

目录

一、HttpServletResponse

1.1响应行

1.2响应头

1.3响应正文

1.4常见应用

1.4.1响应编码字符输出流

1.4.2响应编码字节输出流

1.4.3文件下载

1.4.4验证码

1.4.5验证码——工具类实现

1.4.6设置客户端不使用缓存

1.4.7网页定时刷新

1.5请求重定向

1.6 HttpServletResponse对象细节

二、HttpServletRequest

2.1请求行

2.2请求消息头

2.3请求正文

2.3.1获取表单数据

2.3.2操作非表单数据

2.3.3请求转发和请求包含

2.3.4请求编码


 

Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求request对象和代表响应response对象。

首先我们要了解一下Http协议,然后学习HttpServletResponse和HttpServletRequest对象。

关于Http协议可以看之前整理的博客:https://blog.csdn.net/weixin_39478524/article/details/115336677

Http中很重要的就是请求和响应操作,对应的就是HttpServletRequest对象和HttpServletResponse对象,所有数据的操作都是基于这两个对象封装的。

 

 

一、HttpServletResponse

HttpServletResponse对应的是响应消息,负责操作响应的数据,

响应消息可以分为三部分:响应行、响应头和响应正文,我们也分三部分介绍HttpServletResponse如何操作这三部分。

 

1.1响应行

HTTP/1.1 200 OK

响应消息行主要包括两个部分:协议版本和响应状态码,操作响应行的函数主要就是设置响应状态码,

setStatus(int sc)//设置响应状态码

 

1.2响应头

响应消息头由一系列的键值对组成,主要有以下方法对响应头进行操作,

sendRedirect(String location)//请求重定向
addHeader(String name, String value)//添加响应头信息
setHeader(String name, String value)//设置响应头信息,没有键时自动添加

我们可以利用setHeader()方法告诉浏览器用什么码表,

response.setHeader("content-type", "text/html;charset=UTF-8");

 

1.3响应正文

getWrite();//返回字符输出流
getOutputStream();//返回字节输出流
setCharacterEncoding(String charset);//设置字符编码类型
setContentType(String type);//设置文本类型

 

1.4常见应用

下面我们依次介绍一下response的常见应用

1.4.1响应编码字符输出流

我们测试一下,在响应正文中输出我们想要的字符串,

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet(name = "ServletDemo1")
public class ServletDemo1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setCharacterEncoding("Unicode");//设置服务器编码方式,否则默认编码中文会乱码
        response.setHeader("content-type","text/html;charset=Unicode");//设置响应消息头编码方式
        PrintWriter out=response.getWriter();//得到一个字符输出流
        out.write("中文测试");//向客户端响应文本内容
    }
}

或者也可以直接设置文本编码方式,将设置服务器编码和消息头编码合并为一句,

response.setContentType("text/html;charset=Unicode");//设置文本编码格式

然后配置一下映射的路径,

<?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>servletDemo</servlet-name>
        <servlet-class>ServletDemo1</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servletDemo</servlet-name>
        <url-pattern>/demo</url-pattern>
    </servlet-mapping>
</web-app>

 显示效果如下:

 

1.4.2响应编码字节输出流

接着测试一下字节输出流输出信息,

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "ServletDemo2")
public class ServletDemo2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ServletOutputStream servletOutputStream=response.getOutputStream();//获取字节输出流
        servletOutputStream.write("字节输出流测试".getBytes());//向响应正文输出信息
    }
}

修改配置信息,

<?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>servletDemo2</servlet-name>
        <servlet-class>ServletDemo2</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servletDemo2</servlet-name>
        <url-pattern>/demo2</url-pattern>
    </servlet-mapping>
</web-app>

输出结果:

 

1.4.3文件下载

我们以图片为例,将资源放在工程的src文件夹下,

我们首先将文件输出到客户端,在网页中显示,

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;

@WebServlet(name = "ServletDemo3")
public class ServletDemo3 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String path=this.getServletContext().getRealPath("/WEB-INF/classes/snow.JPG");//得到文件的路径
        FileInputStream fileInputStream=new FileInputStream(path);//通过路径得到输入流
        ServletOutputStream servletOutputStream=response.getOutputStream();//获取输出到客户端的字节输出流

        int len=1;
        byte b[]=new byte[1024];
        while((len= fileInputStream.read(b))!=-1){
            servletOutputStream.write(b,0,len);//输出到客户端
        }
        
        servletOutputStream.close();
        fileInputStream.close();
    }
}

配置一下web.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>servletDemo3</servlet-name>
        <servlet-class>ServletDemo3</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servletDemo3</servlet-name>
        <url-pattern>/demo3</url-pattern>
    </servlet-mapping>
</web-app>

显示效果:

 

接下来我们更改一下代码,让用户可以直接下载图片,

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;

@WebServlet(name = "ServletDemo3")
public class ServletDemo3 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String path=this.getServletContext().getRealPath("/WEB-INF/classes/snow.JPG");//得到文件的路径
        FileInputStream fileInputStream=new FileInputStream(path);//通过路径得到输入流
        ServletOutputStream servletOutputStream=response.getOutputStream();//获取输出到客户端的字节输出流

        String filename=path.substring(path.lastIndexOf("\\")+1);//获取需要下载的文件名
        response.setHeader("content-disposition","attachment;filename="+filename);//告知客户端要下载文件
        response.setHeader("content-type","image/jpeg");//告知客户端下载文件的类型

        int len=1;
        byte b[]=new byte[1024];
        while((len= fileInputStream.read(b))!=-1){
            servletOutputStream.write(b,0,len);//输出到客户端
        }

        servletOutputStream.close();
        fileInputStream.close();
    }
}

网页效果,网页将图片已经下载好了:

 

1.4.4验证码

验证码是一种防止暴力破解的工具,在某种程度上可以区分人和机器,现在我们制作一个带验证码的登录界面,

首先我们用代码创建验证码,

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;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

@WebServlet(name = "ServletDemo4")
public class ServletDemo4 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        int width=100;//图片宽度
        int height=25;//图片高度
        BufferedImage img=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);//在内存中创建一个图像
        Graphics g=img.getGraphics();//创建一个画笔

        //设置背景
        g.setColor(Color.PINK);//设置背景填充颜色
        g.fillRect(1,1,width-2,height-2);//设置填充的范围
        g.setColor(Color.RED);//设置边框颜色
        g.drawRect(0,0,width-1,height-1);//以边框色画出边框

        //添加验证码数字
        g.setColor(Color.BLUE);//设置文本颜色
        g.setFont(new Font("宋体",Font.BOLD|Font.ITALIC,15));//设置字体样式
        Random rand=new Random();
        String code=rand.nextInt(10)+" "+rand.nextInt(10)+" "+rand.nextInt(10)+" "+rand.nextInt(10);//产生随机验证码
        g.drawString(code,20,18);

        //添加验证码干扰线
        for (int i = 0; i < 5; i++) {
            g.drawLine(rand.nextInt(width),rand.nextInt(height),rand.nextInt(width),rand.nextInt(height));//产生随机坐标的直线
        }

        ImageIO.write(img,"jpg",response.getOutputStream());//将图片对象以流的方式输出到客户端

    }
}

配置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>servletDemo4</servlet-name>
        <servlet-class>ServletDemo4</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servletDemo4</servlet-name>
        <url-pattern>/demo4</url-pattern>
    </servlet-mapping>
</web-app>

输入http://localhost:8080/demo4,看看验证码的效果图,

然后我们在html文件中访问该地址,需要注意要加上http协议,否则访问不成功,

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
    <script type="text/javascript">
        function changeCode(){
            var img=document.getElementsByTagName("img")[0];//得到图片元素
            img.src="http://localhost:8080/demo4?time="+ new Date().getTime();//重新赋值src路径,加入时间避免浏览器使用缓存的数据不刷新
        }
    </script>
</head>
<body>
    <form action="#" method="post">
        用户名:<input type="text" name="userName"/><br>
        密码:<input type="password" name="passWord"/><br>
        验证码:<input type="text" name="code"/>
        <img src="http://localhost:8080/demo4" onclick="changeCode()"/><a href="javascript:changeCode()">看不清换一张</a><br>
        <input type="submit" value="登录"/><br>
    </form>
</body>
</html>

访问界面:

刷新之后的效果:

 

1.4.5验证码——工具类实现

首先我们导入外部的工具类,以IDEA为例:

依次点击File->Project Structure->Libraries,点击加号添加我们的jar工具包ValidateCode.jar,然后新建Servlet导入该工具类,

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import cn.dsna.util.images.ValidateCode;

@WebServlet(name = "ServletDemo5")
public class ServletDemo5 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        int width=100;//图片宽度
        int height=25;//图片高度
        int codeCount=4;//验证码字符数量
        int lineCount=5;//干扰线数量
        ValidateCode validateCode=new ValidateCode(width,height,codeCount,lineCount);//生成验证码
        validateCode.write(response.getOutputStream());//输出到网页
    }
}

然后配置一下映射地址,

<?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>servletDemo5</servlet-name>
        <servlet-class>ServletDemo5</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servletDemo5</servlet-name>
        <url-pattern>/demo5</url-pattern>
    </servlet-mapping>
</web-app>

可以看到工具类实现的验证码如下,

 

1.4.6设置客户端不使用缓存

当页面进行刷新时,正常的验证码都会进行更新,但是如果我们不在验证码地址后加时间,那么浏览器就会认为该资源已经加载过了,

刷新的时候不访问服务器,直接从网页的缓存中提取资源,验证码也就不会刷新,这时我们也可以不在资源后加时间后缀,设置客户端不使用缓存,每次访问资源都要走服务器的通道,那么验证码自然刷新就会更新,

response.setHeader("pragma","no-cache");
response.setHeader("cache-control","no-cache");
response.setHeader("expires","0");

这样验证码每次就会从服务器获取,而不会从缓存中获取了。

 

1.4.7网页定时刷新

定时刷新用到的还是setHeader方法,设置响应消息头,

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Random;

@WebServlet(name = "ServletDemo6")
public class ServletDemo6 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setHeader("refresh","1");//设置响应消息头,1s刷新一次

        Random random=new Random();
        response.getWriter().write(random.nextInt(100)+"");
    }
}

刷新结果: 

还可以刷新的时候跳转到指定的url路径,

response.setContentType("text/html;charset=UTF-8");//设置客户端字符集
response.getWriter().write("3s后跳转到百度");
response.setHeader("refresh","3;url=http://www.baidu.com");

 

1.5请求重定向

请求重定向和请求转发类似,都是客户端请求Servlet1完成某个功能,但是Servlet1无法完成,转而让Servlet2完成,

二者不同的是:

  • 转发在服务器端完成的;重定向是在客户端完成的
  • 转发的速度快;重定向速度慢
  • 转发的是同一次请求;重定向是两次不同请求
  • 转发不会执行转发后的代码;重定向会执行重定向之后的代码
  • 转发地址栏没有变化;重定向地址栏有变化
  • 转发必须是在同一台服务器下完成;重定向可以在不同的服务器下完成

请求转发和请求重定向示意图如下,

请求重定向是通过setStatus方法来告诉客户端要重定向到新的url,

通过设置响应消息头来告诉客户端具体重定向的url地址,

response.setStatus(302);//告诉客户端要重定向操作
response.setHeader("location","url");//告诉客户端重定向的url地址

或者也可以将这两个方法使用一个方法替代,

response.sendRedirect("url");//告知客户端要重定向,并且重定向到url地址

我们测试一下请求重定向,新建两个Servlet:ServletDemo7、ServletDemo8,

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "ServletDemo7")
public class ServletDemo7 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("请求重定向");
        response.setStatus(302);//告知客户端需要重定向
        response.setHeader("location","http://localhost:8080/demo8");//告诉客户端重定向的地址
    }
}
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "ServletDemo8")
public class ServletDemo8 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("收到!");
    }
}

我们启动tomcat服务器,请求demo7,http://localhost:8080/demo7

结果会将请求重定向到demo8,http://localhost:8080/demo8

 

1.6 HttpServletResponse对象细节

  • getOutputStream和getWriter
    • getOutputStream方法用于得到输出二进制数据的ServletOuputStream对象
    • getWriter方法用于得到输出文本数据的Printwriter对象
    • 这两个方法互相排斥,调用了其中的任何一个方法后,就不能再调用另一方法。会抛异常
  • Servlet程序向ServletOutputStream或PrintWriter对象中写入的数据将被Servlet引擎从response里面获取,Servlet引擎将这些数据当作响应消息的正文,然后再与响应状态行和各响应头组合后输出到客户端
  • Serlvet的service方法结束后,Servlet引擎将检查getWriter或getOutputStream方法返回的输出流对象是否已经调用过close方法,如果没有,Servlet引擎将调用close方法关闭该输出流对象

 

二、HttpServletRequest

HttpServletRequest对象代表了客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,

开发人员通过这个对象的方法,可以获得用户的信息,如下:

getRequestURL();//方法返回客户端发出请求时的完整URL
getRequestURI();//方法返回请求行中的资源名部分
getQueryString();//方法返回请求行中的参数部分
getRemoteAddr();//方法返回发出请求的客户机的IP地址
getRemoteHost();//方法返回发出请求的客户机的完整主机名
getRemotePort();//方法返回客户机所使用的网络端口号
getLocalAddr();//方法返回WEB服务器的IP地址
getLocalName();//方法返回WEB服务器的主机名
getMethod();//得到客户机请求方式

 

2.1请求行

比如请求行消息:Get  http://localhost:8080/demo8?username=zs  http/1.1

getMethod();//获得请求方式
getRequestURL();//返回客户端发出请求时的完整URL
getRequestURI();//返回请求行中的资源名部分
getContextPath();//当前应用的虚拟目录 /demo8
getQueryString();//返回请求行中的参数部分

我们测试一下这几个方法,

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "ServletRequestDemo1")
public class ServletRequestDemo1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println(request.getMethod());//输出请求方式
        System.out.println(request.getRequestURL());//输出客户端发出请求时的完整URL
        System.out.println(request.getRequestURI());//输出请求行中资源名部分
        System.out.println(request.getContextPath());//输出当前应用的虚拟目录
        System.out.println(request.getQueryString());//输出请求行中的参数部分
    }
}

登录http://localhost:8080/Demo1?username=peru网站,输出结果如下:

 

2.2请求消息头

String getHeader(String name);/根据头名称得到头信息值
Enumeration getHeaderNames();//得到所有头信息name
Enumeration getHeaders(String name);//根据头名称得到相同名称头信息值

我们输出一下请求消息头的所有信息,

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;

@WebServlet(name = "ServletRequestDemo2")
public class ServletRequestDemo2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Enumeration names=request.getHeaderNames();//获取所有请求消息头的name
        while(names.hasMoreElements()){
            String nextElement=(String)names.nextElement();
            System.out.println(nextElement+":"+request.getHeader(nextElement));//逐个输出请求消息头的键值对
        }

        System.out.println(request.getHeader("User-Agent"));//获得请求消息头信息
    }
}

输出结果如下,

 

2.3请求正文

2.3.1获取表单数据

getParameter(name);//根据表单中name属性的名,获取value属性的值方法 
getParameterValues(String name);//专业为复选框取取提供的方法
getParameterNames();//得到表单提交的所有name的方法 
getParameterMap();//得到表单提交的所有值的方法。做框架用,非常实用
getInputStream();//以字节流的方式得到所有表单数据

我们首先制作一个注册界面,设置表单数据让用户填写,

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="http://localhost:8080/Demo3" method="post">
    用户名:<input type="text" name="userName"/><br/>
    密码:<input type="password" name="passWord"/><br/>
    性别:<input type="radio" name="sex" value="男" checked="checked"/>男
          <input type="radio" name="sex" value="女"/>女<br/>
    爱好:<input type="checkbox" name="hobby" value="运动"/>运动
          <input type="checkbox" name="hobby" value="听歌"/>听歌
          <input type="checkbox" name="hobby" value="看书"/>看书
          <input type="checkbox" name="hobby" value="睡觉"/>睡觉<br/>
    居住地:<select name="city">
                <option>————请选择————</option>
                <option value="北京">北京</option>
                <option value="上海">上海</option>
                <option value="广州">广州</option>
                <option value="深圳">深圳</option>
                <option value="武汉">武汉</option>
            </select><br/>
    <input type="submit" value="注册"/>

</form>
</body>
</html>

然后我们在servlet应用中获取表单数据,并输出(注意这里要将form标签的action属性设置为servlet应用的映射访问地址),获取表单数据一共有四种方法,

1、第一种为直接通过表单项的名字获取表单项的值然后输出,

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "ServletRequestDemo3")
public class ServletRequestDemo3 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");//设置服务器编码方式(要与浏览器编码方式相同),避免获取网页信息时中文显示乱码
        //获取提交的表单数据
        System.out.println("用户名:"+request.getParameter("userName"));//输出用户名
        System.out.println("密码:"+request.getParameter("passWord"));//输出密码
        System.out.println("性别:"+request.getParameter("sex"));//输出性别

        String[] hobbys=request.getParameterValues("hobby");//获取爱好字符串数组
        System.out.print("爱好:");
        for (int i = 0; hobbys!=null && i < hobbys.length; i++) {
            System.out.print(hobbys[i]);
        }
        System.out.println();

        System.out.println("居住地:"+request.getParameter("city"));//输出居住地
    }
}

然后我们进入到注册界面,填写好表单数据,点击注册可以看到输出结果:

 

2、我们还可以先获取所有的表单项名字,通过名字获取表单项的值,

request.setCharacterEncoding("UTF-8");//设置服务器编码方式(要与浏览器编码方式相同),避免获取网页信息时中文显示乱码
Enumeration names=request.getParameterNames();//获取所有表单项的名字
while(names.hasMoreElements()){
    String name=(String) names.nextElement();//获取表单的名字
    System.out.print(name+":");
    String[] values=request.getParameterValues(name);//得到该表单项的值
    for (int i = 0; values!=null && i < values.length; i++) {
        System.out.print(values[i]+" ");
    }
    System.out.println();
}

结果如图,

 

3、第三种方法为使用getParameterMap(),该方法可以获取表单提交的所有值,一般在框架中经常使用,

首先我们生成用户类,里面存放着对应的用户注册的信息,也就是表单的信息(同时还要实现toString、set和get方法),

//在实体类中的字段要与表单中的name名一致
public class User {
    private String userName;
    private String passWord;
    private String sex;
    private String[] hobby;
    private String city;
}

然后我们将得到的表单数据封装到用户类中,

User user=new User();
Map<String,String[]> map=request.getParameterMap();//获取提交的表单数据集合
for (Map.Entry<String,String[]> m:map.entrySet()) {
    String name=m.getKey();
    String[] value=m.getValue();

    //创建一个属性描述器
    try {
        PropertyDescriptor propertyDescriptor=new PropertyDescriptor(name,User.class);//将集合中的值内省到User类的变量上
        Method setter=propertyDescriptor.getWriteMethod();//得到User类中的set方法

        if (value.length==1){
            setter.invoke(user,value[0]);//给一个值的变量赋值
        }else{
            setter.invoke(user,(Object)value);//给多个值的变量赋值,比如数组
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
System.out.println(user);//输出用户信息

结果如下图, 

 

基于这个方法,我们可以直接使用框架来提取表单数据,我们导入两个jar包:commons-beanutils-1.8.3.jar和commons-logging-1.1.1.jar,这种方法代码就很简洁了,jar包地址为:

链接:https://pan.baidu.com/s/1NcpIN_uFD1sIKZKLYIVX4g 
提取码:1qyv 
复制这段内容后打开百度网盘手机App,操作更方便哦

request.setCharacterEncoding("UTF-8");//设置服务器编码方式(要与浏览器编码方式相同),避免获取网页信息时中文显示乱码
try {
    User user=new User();
    BeanUtils.populate(user,request.getParameterMap());
    System.out.println(user);
} catch (Exception e) {
    e.printStackTrace();
}

结果如下,

 

4、最后一种方式是以字节流的形式获取表单数据,使用的方法为getInputStream(),

ServletInputStream servletInputStream=request.getInputStream();//获取字节输入流
int len=0;
byte[] bytes=new byte[1024];
while((len=servletInputStream.read(bytes))!=-1){
    String name=new String(bytes,0,len);
    System.out.println(new String(name.getBytes("iso-8859-1"),"UTF-8"));
}
servletInputStream.close();

 

2.3.2操作非表单数据

非表单数据就是非表单提交的数据,这些数据在request域对象中存储,一般我们使用以下的方法进行操作,

void setAttribute(String name, Object value);
Object getAttribute(String name);
Void removeAttribute(String name);

这里我们用转发来测试一下非表单数据如何进行传输的,我们在Demo4中将非表单数据放在request中,

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "ServletRequestDemo4")
public class ServletRequestDemo4 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");//设置服务器编码方式(要与浏览器编码方式相同),避免获取网页信息时中文显示乱码
        response.setContentType("text/html;charset=UTF-8");

        String str="java";//非表单数据
        request.setAttribute("data",str);//将非表单数据添加到request域中

        RequestDispatcher requestDispatcher=request.getRequestDispatcher("/Demo5");//获取服务器资源包装器
        requestDispatcher.forward(request,response);//请求转发

    }
}

然后在Demo5中获取数据,

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "ServletRequestDemo5")
public class ServletRequestDemo5 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        String att=(String)request.getAttribute("data");
        System.out.println(att);
    }
}

输出结果如下,

 

2.3.3请求转发和请求包含

转发和1.5的重定向类似,都是客户端发送请求给Servlet1,Servlet1无法完成让Servlet2完成,

转发是Servlet1来将请求转发给Servlet2,客户端只用发送一次请求;而重定向则是Servlet1告诉客户端Servlet2可以做,让客户端自己重新发送请求,客户端一共发送了两次请求。

RequestDispatcher getRequestDispatcher(String path);//得到请求转发或请求包含的协助对象
forward(ServletRequest request, ServletResponse response);//转发的方法
include(ServletRequest request, ServletResponse response);//请求包含

我们新建一个Servlet,将请求转发给Demo1,

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "ServletRequestDemo4")
public class ServletRequestDemo4 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");//设置服务器编码方式(要与浏览器编码方式相同),避免获取网页信息时中文显示乱码
        response.setContentType("text/html;charset=UTF-8");

        RequestDispatcher requestDispatcher=request.getRequestDispatcher("/Demo1");//获取服务器资源包装器
        requestDispatcher.forward(request,response);//请求转发

    }
}

然后配置一下web.xml配置文件,开启服务器访问http://localhost:8080/Demo4,请求转发结果如下,

 

请求包含就是Servlet(源组件)把其他Servlet(目标组件)生成的响应结果包含到自身的响应结果中,

request.getRequestDispatcher(“接收请求的Servlet 路径”). include(request,response)

 

2.3.4请求编码

表单的提交方式一般分为post和get,为了解决乱码问题有不同的方法,

request.setCharacterEncoding("UTF-8");//告诉服务器客户端什么编码,只能处理post请求方式
String name = new String(name.getBytes(“iso-8859-1”),”UTF-8”);//对每个字符串进行重新编码,用于处理get请求方式

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值