美文网首页
Java Web学习笔记(三):HttpWebRequest

Java Web学习笔记(三):HttpWebRequest

作者: 简单一点点 | 来源:发表于2019-07-24 22:40 被阅读0次

Java Web中使用HttpServletRequest和HttpServletResoponse来封装客户端发来的请求和返回给客户端的响应。整个流程大致如下图:

servlet-step.jpg

HttpServletRequest

HttpServletRequest对象代表客户端的请求,开发人员通过这个对象的方法,可以获得客户的这些信息。

获取客户机信息

通过HttpServletRequest对象可以获取客户端的信息。

方法 说明
getRequestURL() 返回客户端发出请求时的完整URL
getRequestURI() 返回请求行中的资源名部分
getQueryString() 返回请求行中的参数部分(参数名+值)
getRemoteAddr() 返回发出请求的客户机的IP地址
getRemoteHost() 返回发出请求的客户机的完整主机名
getRemotePort() 返回发出请求的客户机的网络端口号
getLocalPort() 返回web服务器所使用的网络端口号
getLocalAddr() 返回web服务器的IP地址
getLocalName() 返回web服务器的主机名
getPathInfo() 返回请求URL中的额外路径信息。额外路径信息是请求URL中的位于Servlet的路径之后和查询参数之前的内容,它以"/"开头

下面看一个例子,编写一个Servlet,获取客户机信息并展示出来。

public class HttpServletRequestDemo1 extends HttpServlet{

    private static final long serialVersionUID = -5563851992272269782L;
    
    public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        response.setHeader("content-type", "text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.write("<hr/>");
        out.write("请求的URL地址: " + request.getRequestURL().toString() + "<br/>");
        out.write("请求的资源: " + request.getRequestURI() + "<br/>");
        out.write("请求的URL地址中附带的参数: " + request.getQueryString() + "<br/>");
        out.write("客户端的IP地址: " + request.getRemoteAddr() + "<br/>");
        out.write("客户端的主机名: " + request.getRemoteHost() + "<br/>");
        out.write("客户端的端口号: " + request.getRemotePort() + "<br/>");
        out.write("客户端的用户: " + request.getRemoteUser() + "<br/>");
        out.write("请求的方法: " + request.getMethod() + "<br/>");
        out.write("请求的路径信息: " + request.getPathInfo() + "<br/>");
    }
    
    public void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        doGet(request, response);
    }

}

在web.xml中添加配置。

<servlet>
    <servlet-name>requestDemo1</servlet-name>
    <servlet-class>web.HttpServletRequestDemo1</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>requestDemo1</servlet-name>
    <url-pattern>/requestDemo1</url-pattern>
</servlet-mapping>

运行程序,在浏览器中可以查看结果。

request-client.jpg

获取客户机请求首部

通过HttpServletRequest可以获取请求报文的首部信息,获取客户机请求首部的方法包括:

  • getHeader(string name)方法:String
  • getHeaders(String name)方法:Enumeration
  • getHeaderNames()方法:Enumeration

同样编写一个简单的例子,创建一个Servlet。

public class HttpServletRequestDemo2 extends HttpServlet{

    private static final long serialVersionUID = 2156815314653251842L;
    
    public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        response.setHeader("content-type", "text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        // 获取所有请求首部的字段名
        Enumeration<String> reqHeaders = request.getHeaderNames(); 
        while(reqHeaders.hasMoreElements()) {
            String headName = reqHeaders.nextElement();
            String headValue = request.getHeader(headName);
            out.write(headName + ":" + headValue + "<br/>");
        }
    }
    
    public void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        doGet(request, response);
    }
}

然后在web.xml中进行配置。

<servlet>
    <servlet-name>requestDemo2</servlet-name>
    <servlet-class>web.HttpServletRequestDemo2</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>requestDemo2</servlet-name>
    <url-pattern>/requestDemo2</url-pattern>
</servlet-mapping>

运行程序,在浏览器中查看结果。

request2.jpg

获取客户机请求参数

通过HttpServletRequest可以获取前台提交的请求参数,获取客户机请求参数的方法包括:

  • getParameter(String)方法,获取请求参数。
  • getParameterValues(String name)方法,用来获取数组型的参数。
  • getParameterMap()方法 该方法在编写框架时经常使用
  • getParameterNames()方法 该方法不经常使用,获取参数名。

下面看一个通过前台提交表单的例子。首先编写页面info.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>个人信息</title>
</head>
<body>
    <fieldset style="width:500px;">
        <legend>个人信息填写</legend>
        <form action="requestDemo3" method="post">
            <!-- 文本框 -->
            编号:<input type="text" name="userid" value="NO." size="2" maxlength="2" /><br>
            <!-- 文本框 -->
            用户名:<input type="text" name="username" placeholder="请输入用户名" /><br>
            <!-- 密码框 -->
            密码:<input type="password" name="userpasswd" placeholder="请输入密码" /><br>
            <!-- 单选框 -->
            性别:<input type="radio" name="sex" value="男" checked />男
                <input type="radio" name="sex" value="女">女<br>
            <!-- 下拉框 -->
            职业:<select name="job">
                <option value="战士">战士</option>
                <option value="法师">法师</option>
                <option value="牧师">牧师</option>
            </select><br>
            <!-- 复选框 -->
            爱好:
            <input type="checkbox" name="inst" value="游戏">游戏
            <input type="checkbox" name="inst" value="编程" checked>编程
            <input type="checkbox" name="inst" value="读书">读书
            <input type="checkbox" name="inst" value="跑步">跑步
            <!-- 文本域 -->
            备注:<textarea name="note" cols="34" rows="5"></textarea> <br>
            <!-- 隐藏域 -->
            <input type="hidden" name="hiddenField" value="你看不到我"/>
            <!-- 提交按钮 -->   
            <button type="submit">提交</button>
            <!-- 重置按钮 -->
            <button type="reset">重置</button>
        </form>
    </fieldset>
</body>
</html>

然后编写后台的Servlet。

public void doGet(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException{
        request.setCharacterEncoding("UTF-8");
        //根据表单中标签的name读取表单提交的参数
        String userid = request.getParameter("userid");
        String username = request.getParameter("username");
        String userpasswd = request.getParameter("userpasswd");
        String sex = request.getParameter("sex");
        String userjob = request.getParameter("job");
        String note = request.getParameter("note");
        String hiddenField = request.getParameter("hiddenField");
        
        // 获取数组
        String[] insts = request.getParameterValues("inst");
        String instStr = String.join(",", insts);
        
        //将内容写入html
        String html = "<table>" +
                "<tr><td>填写的编号:</td><td>{0}</td><tr>" + 
                "<tr><td>填写的用户:</td><td>{1}</td><tr>" + 
                "<tr><td>填写的密码:</td><td>{2}</td><tr>" + 
                "<tr><td>选中的性别:</td><td>{3}</td><tr>" + 
                "<tr><td>选中的职业:</td><td>{4}</td><tr>" + 
                "<tr><td>选中的爱好:</td><td>{5}</td><tr>" + 
                "<tr><td>填写的备注:</td><td>{6}</td><tr>" + 
                "<tr><td>隐藏的内容:</td><td>{7}</td><tr>" + 
                "</table>";
        
        html = MessageFormat.format(html, userid, username, userpasswd, sex,
                userjob, instStr, note, hiddenField);
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().write(html);
        
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
        doGet(request, response);
    }
}

同样在web.xml中进行配置。

<servlet>
    <servlet-name>requestDemo3</servlet-name>
    <servlet-class>web.HttpServletRequestDemo3</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>requestDemo3</servlet-name>
    <url-pattern>/requestDemo3</url-pattern>
</servlet-mapping>

运行程序,首先打开表单所在的页面。

request-info.jpg

填写完表单后点击提交。

request3.jpg

request中文参数乱码问题

在前文的代码中可以看到,我们在接收POST请求的参数的时候进行了如下设置:

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

该方式通过将服务端的编码设置为和客户端一致来解决乱码问题。

GET请求由于是直接把参数放到URL中,需要获取request对象以ISO8859-1字符编码接收到的原始数据的字节数组,然后通过字节数组以指定的编码构建字符串,解决乱码问题:

String name = request.getParameter("name");//接收数据
name =new String(name.getBytes("ISO8859-1"), "UTF-8");

请求转发

请求转发指一个web资源收到客户端请求后,通知服务器去调用另外一个web资源进行处理。

在Servlet中实现请求转发的方式是通过ServeltContext或者HttpServletRequest的getRequestDispatcher(String path)方法,该方法返回RequestDispatcher对象,调用这个对象的forward方法可以实现请求转发。

看一个例子,编写一个简单的登陆页面login.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>登录</title>
</head>
<body>
    <form action="loginServlet" method="post">
        用户名:<input type="text" name="username" /><br>
        密码:<input type="text" name="password" /><br>
        <input type="submit" value="登录"><br>
    </form>
</body>
</html>

编写登录的Servlet,会转发到另一个Servlet。

public class LoginServlet extends HttpServlet {

    private static final long serialVersionUID = 8467143275313331548L;

    public void doGet(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        String name = request.getParameter("username");
        request.setAttribute("name", name);
        request.getRequestDispatcher("/servlet2").forward(request, response);
    }
    
    public void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        doGet(request, response);
    }
}

编写转发到的Servlet。

public class LoginServlet extends HttpServlet {

    private static final long serialVersionUID = 8467143275313331548L;

    public void doGet(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        String name = request.getParameter("username");
        request.setAttribute("name", name);
        request.getRequestDispatcher("/servlet2").forward(request, response);
    }
    
    public void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        doGet(request, response);
    }
}

在web.xml中注册Servlet。

<servlet>
    <servlet-name>loginServlet</servlet-name>
    <servlet-class>web.LoginServlet</servlet-class>
</servlet>
<servlet>
    <servlet-name>servlet2</servlet-name>
    <servlet-class>web.Servlet2</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>loginServlet</servlet-name>
    <url-pattern>/loginServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>servlet2</servlet-name>
    <url-pattern>/servlet2</url-pattern>
</servlet-mapping>

运行程序,在登陆界面随便输个名字,点击提交。

request-login.jpg

可以看到成功跳转。

request-forward.jpg

文件上传

要实现文件上传,在客户端表单的提交方法必须是post并且设置表单的enctype="multipart/form-data",其中还要包含一个文件上传组件。

在服务器中,在Servlet3.0以后只需要添加@MultipartConfig注解即可。

@MultipartConfig注解

@MultipartConfig可以带有以下属性,均为可选的:

  • maxFileSize:表示最多可以上传的文件的容量,超过设定值的文件将会遭到拒绝,默认值为-1,表示无限制。
  • maxRequestSize:表示允许多部分HTTP请求的最大容量,默认值为-1,意味着它是不受限制的。
  • location:将上传的文件保存在服务器中项目的指定位置,调用Part的write方法会使用,但是,只有write中填写为相对路径,那么意味着是相对于location的路径,如果是填写为绝对路径,则与location无关。
  • fileSizeThreshold:设定溢出大小,超过这个值那么上传的文件就会被写入磁盘。

Part类

其中表单的每一个域都会转换为Part。可以同通过HttpServletRequest的getParts()或getPart(String name)方法获取Part。

Part类中包含如下方法:

  • String getName() 获取这部分的名称,例如相关表单域的名称
  • String getContentType() 如果Part是一个文件,那么将返回Part的内容类型,否则返回null(可以利用这一方法来识别是否为文件域)
  • Collection<String> getHeaderNames() 返回这个Part中所有标头的名称
  • String getHeader(String headerName) 返回指定标头名称的值
  • void write(String path) 将上传的文件写入服务器中项目的指定地址下,如果path是一个绝对路径,那么将写入指定的路径,如果path是一个相对路径,那么将被写入相对于location属性值的指定路径。
  • InputStream getInputStream() 以inputstream的形式返回上传文件的内容

如果HTML的输入是一个文件域,那么Part将返回这些标头:

  • content-type:contentType
  • content-disposition:form-data; name="filedName"; filename="fileName"

如果是一个普通文本域,那么:

  • content-disposition:form-data; name="filedName"

如果是文件域,但没有上传文件,那么:

  • content-type:application/octet-stream
  • content-disposition:form-data; name="filedName"; filename=""

实战

下面编写一个上传图片并显示的例子。

编写上传文件的servlet。

@MultipartConfig
public class FileUploadDemo extends HttpServlet {
    public void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        // 创建目录
        File path = new File(getServletContext().getRealPath("/upload") );
        System.out.print("文件目录: " + path);
        if(!path.exists()) {
            path.mkdir();
        }
        // 获取文件
        Part img = request.getPart("file1");
        // 获取上传的文件名
        String cd = img.getHeader("Content-Disposition");
        String filename = cd.substring(cd.lastIndexOf("=")+2, cd.length()-1);
        // 文件全路径
        String filePath = path.getPath() + File.separator + filename;
        // 写入文件
        img.write(filePath);
        System.out.println("File Upload: " + filePath);
        // 跳转页面
        request.setAttribute("filename", filename);
        request.getRequestDispatcher("filedome.jsp").forward(request, response);
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doPost(request, response);
    }
}

编写上传文件的页面index.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>登录首页</title>
    </head>
<body>
    <form action="FileUploadServlet" enctype="multipart/form-data"  method="post">
        <input type="file" name="file1" /><br>
        <input type="submit" value="提交">
    </form>
</body>
</html>

然后编写显示图片的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>展示图片内容</title>
    </head>
    <body>
        <img alt="go" src="upload/<%= (String)request.getAttribute("filename")%>" />
    </body>
</html>

编写配置文件web.xml。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
              http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">
  <display-name>Archetype Created Web Application</display-name>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

  <servlet>
    <servlet-name>FileUploadServlet</servlet-name>
    <servlet-class>com.wyk.servletdemo.web.FileUploadDemo</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>FileUploadServlet</servlet-name>
    <url-pattern>/FileUploadServlet</url-pattern>
  </servlet-mapping>
</web-app>

运行程序,打开浏览器访问首页。

fileupload.jpg

上传图片,点击提交,会跳转到显示图片的界面。

img-show.jpg

相关文章

网友评论

      本文标题:Java Web学习笔记(三):HttpWebRequest

      本文链接:https://www.haomeiwen.com/subject/krrqrctx.html