美文网首页
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