【Java核心技术】Request请求

ServletRequest

针对于请求报文的封装,JAVAEE规范制定的就是ServletRequest接口

我们在使用中绝大多数的情况都是使用HttpServletRequest

常用API

获取请求行

request.getmethod():获取请求的方法

request.getRequestURI():获取请求资源,/应用名/资源路径

request.getRequestURL():获取完整的访问的域名路径名

request.request.getProtocol():获取请求协议

获取请求头

request.getHeaderNames():获取请求头的key列表,类似迭代器

hasMoreElements():查看是否还有下一个元素

headerNames.nextElement():迭代

request.getHeader(headerName):获取请求头对应的value

Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()){
            String headerName = headerNames.nextElement();
            String headerValue = request.getHeader(headerName);
            System.out.println(headerName + ":" + headerValue);
        }

获取客户机和服务器主机的信息

request.getLocalAddr():获取服务器主机的地址

request.getLocalPort():服务器端口

request.getRemoteAddr():客户端地址

request.getRemotePort():客户端的端口

获取请求参数

只要提交的数据是key=value&key=value形式,那么都可以使用接下来介绍的API来获取请求参数,无论是在请求行还是请求体均适用

只能获取用=连接的键值对,并且多个键值对直接用&来连接

request.getParameter:获取单个参数的值

request.getParameterValues:获取多个参数的值,返回一个数组

request.getParameterNames():获取所有参数的key,返回一个 Enumeration,类似于迭代器,接下来只需循环迭代即可

Enumeration<String> parameterNames = request.getParameterNames();
        while (parameterNames.hasMoreElements()){
            String key = parameterNames.nextElement();
            String[] values = request.getParameterValues(key);
            if(values.length == 1){
                System.out.println(key + ":" + values[0]);
            }else {
                System.out.println(key + ":" + Arrays.toString(values));
            }
        }

获取请求体

request.getInputStream()

其他

req.getServletPath() = requestURI - 应用名 相当于是获取资源的相对路径名
req.getContextPath() //获取应用名

封装数据到对象

JavaBean的特征:

1.一定要有无参构造函数

2.成员变量必须是private

3.一定要提供public的get和set方法

使用反射来手动获取并封装

package com.fh.ServletReq;

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.lang.reflect.Method;
import java.util.Enumeration;

//通过反射获取请求参数并封装到对象
@WebServlet("/ref")
public class GetParamServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Class<?> user = null;
        User u = null;
        try {
            user = Class.forName("com.fh.ServletReq.User"); //获取字节码文件
            u = (User) user.newInstance(); //实例化
        } catch (Exception e) {
            e.printStackTrace();
        }

        //首先得拿到请求参数的key和value
        Enumeration<String> parameterNames = req.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String key = parameterNames.nextElement();
            String[] values = req.getParameterValues(key);
            String upKey = key.substring(0, 1).toUpperCase() + key.substring(1); //key就是用来封装的方法的名字,将首字母大写
            try {
                Method set = user.getDeclaredMethod("set" + upKey, String.class);//调用set方法,这里一定要注意参数列表需要匹配
                if (values.length == 1) { //当values长度为1时,直接放入
                    set.invoke(u, values[0]);
                } else { //长度大于1需要使用StringBuilder来拼接
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < values.length; i++) {
                        if (i == values.length - 1) {
                            sb.append(values[i]);
                        } else {
                            sb.append(values[i]).append(",");
                        }

                    }
                    String s = sb.toString();
                    set.invoke(u, s);
                }


            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        System.out.println(u);
    }
}

使用工具类commons-beanutils

此时注意如果要使用第三方jar包,那么需要对EE项目进行配置,主要有两种方案

1.直接将jar包赋值到web的WEB-INF目录下,这样项目可以通过快速通道复制到根目录下

2.在Artifacts下新建一个lib文件夹,并将idea目录下的lib添加进去

package com.fh.ServletReq;

import org.apache.commons.beanutils.BeanUtils;

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.lang.reflect.InvocationTargetException;

@WebServlet("/reg2")
public class RegServlet2 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        User user = new User();
        try {
            BeanUtils.populate(user,req.getParameterMap());
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        System.out.println(user);
    }
}

Debug

排查的过程:

1.查看状态码,如果是500,那么肯定表示代码出错了,但是如果没有出现500,不能说明没有错误

2.查看server(output)和localhost log,看看有无错误信息

3.具体去分析哪行代码出现了问题(仔细去查找,找和你的代码相关的部分)

在EE阶段要使用执行后续所有代码的按钮才能使页面正常响应

中文乱码问题

中文是否乱码要以debug的结果为准,不要看控制台的结果。

客户端发送的HTTP请求报文是UTF-8格式

请求报文被解析成为request对象之后,乱码了,解析的时候,解码用的不是utf-8 用的是ISO-8859-1 不支持中文

使用request.setCharacterEncoding来解决

注意事项:

1.只针对请求体有效

2.必须要在读取请求参数之前调用,也就是调用request.getParameter之前才可以使用

一般放在第一行,不容易出错

中文乱码只是在使用post请求方式时有乱码问题,如果使用get请求方式没有问题。前提是用的utf-8

网络路径总结

网络路径是指网络访问过程中的输入路径,与硬盘的路径有区别

全路径:htttp://localhost/app/1.html

​ 可读性比较好,但在开发的过程中域名可能不同

相对路径:相对于当前页面的路径

比如提交的表单页面:http://localhost/app/1.html,里面的form表单的提交地址是

​ http://localhost/app/upload

那么写成相对路径就可以相对于1.html出发,去掉1.html然后再拼接上最终的路径

这种方式不灵活,不推荐

/开头的路径(推荐):

​ /应用名/资源路径。浏览器会自行补充访问协议、主机、端口号

转发

应用场景:

比如点击登录按钮,请求交给一个servlet来处理,如果servlet处理完成之后,希望将页面显示给用户,需要去调用页面,就可以使用转发

一个servlet在执行过程中,如果需要调用另外一个servlet,那么此时就可以使用转发。

转发----页面跳转相关的

要注意,转发前后使用的方法应该相同

package com.cskaoyan.request.forward;

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;

/**
 * @ClassName ${NAME}
 * @Description: TODO
 * @Author 远志 zhangsong@cskaoyan.onaliyun.com
 * @Date 2021/12/9 11:15
 * @Version V1.0
 **/
@WebServlet("/forward1")
public class ForwardServlet1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //访问forward1,需要在代码中去调用forward2,把2里面的数据显示出来
        System.out.println("forward1");
        //需要在forward1中去调用forward2
        //千万不要自己去new一个servlet,然后调用service
        //生命周期应该交由tomcat来统一管理
        //你去给tomcat发送一个指令,让tomcat去调用它
        //这行代码的作用是给tomcat发送一个指令,告诉tomcat去加载当前应用下的/forward2
        //tomcat就去加载forward2,如果它之前没有被访问过,首先实例化;如果访问过,直接调用service方法
        //记住唯一的特殊情况:tomcat的转发中/开头不要加应用名
        //看路径的解析执行主体是谁,如果是浏览器,则/应用名/资源路径,如果是服务器,则/资源路径
        request.getRequestDispatcher("/forward2").forward(request, response);
    }
}
ackage com.cskaoyan.request.forward;

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;

/**
 * @ClassName ${NAME}
 * @Description: TODO
 * @Author 远志 zhangsong@cskaoyan.onaliyun.com
 * @Date 2021/12/9 11:15
 * @Version V1.0
 **/
@WebServlet("/forward2")
public class ForwardServlet2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

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

    }
}

request域

context域:一块内存空间,可以作为运行时共享数据的场所。

​ 只要是同一个应用下的不同资源,拿到的都是同一个servletContext对象,那么就可以共享context域

request域:只要可以拿到同一个request对象,那么也可以共享request域

如果一个地址频繁刷新,每次都会创建新的request对象

要注意只有同一个request对象才能共享request域

主要体现在转发的过程中

只有转发的两个组件间可以共享数据

用法:

1.比如查询数据,先到servlet中执行查询数据库的逻辑,拿到数据之后,放入request域中,然后将数据共享给jsp(本质来说就是servlet, 页面、servlet)

htttp://localhost/app/productList

------> servlet-----DB query List—放入request域中,转发请求到jsp页面,在页面中进行渲染数据

  • 14
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值