Java实现HTTP请求的几种方式-HttpURLConnection(一)

这篇具有很好参考价值的文章主要介绍了Java实现HTTP请求的几种方式-HttpURLConnection(一)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

背景

在实际开发过程中,我们经常需要调用对方提供的接口或测试自己写的接口是否合适。很多项目都会封装规定好本身项目的接口规范,所以大多数需要去调用对方提供的接口或第三方接口(短信、天气等)。

测试前准备

第一步(服务提供者)

准备两个项目:
项目A: 服务提供者
项目B:服务消费者

在项目A中做了两个接口,一个Post方式,一个Get方式,用于测试下面四种方式的调试

    @ApiOperation(value = "测试HTTP请求(POST方式)", notes = "\n开发者:")
    @PostMapping(value = "/testHttpAccess")
    //@SImplePermission
    public JsonResult<TestHttpAccessResponse> testHttpAccess(@RequestBody TestHttpAccessRequest request) {
        return JsonResult.success(testService.testHttpAccess(request));
    }


    @ApiOperation(value = "测试HTTP请求(GET方式)", notes = "\n开发者:")
    @GetMapping(value = "/testHttpAccessGet")
    //@SImplePermission
    public JsonResult<TestHttpAccessResponse> testHttpAccessGet(TestHttpAccessRequest request) {
        return JsonResult.success(testService.testHttpAccess(request));
    }

参数类和响应类:

@Data
@ApiModel("测试HTTP请求入参")
public class TestHttpAccessRequest {
    @ApiModelProperty(value = "名字")
    private String name;

    @ApiModelProperty(value = "年龄")
    private Integer age;

    @ApiModelProperty(value = "地址")
    private String address;
}


@Data
@ApiModel("测试HTTP请求响应")
public class TestHttpAccessResponse {
    @ApiModelProperty(value = "名字")
    private String name;

    @ApiModelProperty(value = "年龄")
    private Integer age;

    @ApiModelProperty(value = "地址")
    private String address;
}

Service:

public TestHttpAccessResponse testHttpAccess(TestHttpAccessRequest request) {
        return BeanUtil.toBean(request, TestHttpAccessResponse.class);
    }

第二步(服务提供者)

为了能够演示token校验,我写了一个最简单的token检验切面
注解@SImplePermission,只要有这个注解才对token进行校验,可以直接在Controller的方法中使用

@Target(value = ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SimplePermission {

}

切面:SimplePermissionInterceptor,对token进行校验
因为项目A我还有其他的切面,这个切面必须是最前面的,所以设置了order=-1

@Aspect
@Order(value = -1)
@Component
public class SimplePermissionInterceptor {

    @Resource
    private HttpServletRequest request;

    @Resource
    private AuthService authService;

    @Pointcut("@annotation(com.zby.annotation.SimplePermission)")
    public void pointcut() {
    }


    @Around("pointcut()")
    public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        SimplePermission annotation = method.getAnnotation(SimplePermission.class);
        if (Objects.nonNull(annotation)) {
            String value = request.getHeader(AuthConstant.AUTHORIZATION);
            if (StringUtils.isBlank(value) || !authService.isLogined(value)) {
                throw new BizException(NacosServiceProviderReturnCode.NEED_LOGIN);
            }
        }
        return joinPoint.proceed();
    }
}

登录服务:我做了一个简易的鉴权逻辑,用于测试请求头

@Data
@ApiModel(value = "登录请求")
public class LoginRequest {
    @ApiModelProperty(value = "用户名")
    private String userName;

    @ApiModelProperty(value = "密码")
    @NotNull(message = "密码不能为空")
    private String password;
}



@Data
@ApiModel(value = "登录响应")
public class LoginResponse {
    @ApiModelProperty(value = "用户名")
    private String uname;

    @ApiModelProperty(value = "鉴权")
    private String token;
}





@Service
public class AuthService {
    private static String userName = "xxx";
    private static String password = "xxx";
    private static Map<String, String> tokenMap = new HashMap<>();

    /**
     * 测试功能,仅使用一个用户名和密码进行登录
     *
     * @param loginRequest
     */
    public LoginResponse login(LoginRequest loginRequest) {
        if (!loginRequest.getUserName().equals(userName)) {
            throw new BizException(NacosServiceProviderReturnCode.LOGIN_USER_NOT_EXIST);
        }
        if (!loginRequest.getPassword().equals(password)) {
            throw new BizException(NacosServiceProviderReturnCode.LOGIN_PASSWORD_FAIL);
        }
        LoginResponse response = new LoginResponse();
        String token = UUID.randomUUID().toString().replaceAll("-", "");
        tokenMap.put(token, userName);
        response.setToken(token);
        response.setUname(userName);
        return response;
    }

    public boolean isLogined(String token) {
        return tokenMap.containsKey(token);
    }
}

接口:

@Slf4j
@Api(tags = "权限控制器")
@RestController
@RequestMapping(value = "/auth")
@RequiredArgsConstructor
public class AuthController {
    private final AuthService authService;


    @ApiOperation(value = "登录")
    @PostMapping(value = "/login")
    public JsonResult<LoginResponse> login(@RequestBody @Validated LoginRequest request) {
        return JsonResult.success(authService.login(request));
    }
}

通过JDK网络类Java.net.HttpURLConnection

比较原始的一种调用做法,这里把get请求和post请求都统一放在一个方法里面。

Post方式和Get方式使用步骤

(1)Post方式请求过程:

  1. 创建远程链接对象
  2. 设置请求方式(get,post,…)
  3. 设置连接超时时间
  4. 设置响应超时时间
  5. 发起连接
  6. 传入请求参数(可选)
  7. 获取请求响应
  8. 关闭连接

(2)Get方式请求过程:

  1. 拼接url参数,中文需要UrlEncode
  2. 创建远程链接对象
  3. 设置请求方式(get,post,…)
  4. 设置连接超时时间
  5. 设置响应读取时间
  6. 发起连接
  7. 获取请求响应
  8. 关闭连接

其实主要就是传递参数时不同

Post请求方式

测试程序:

根据步骤,新建doPost方法:
这里的param是已经被序列化后的JSON

 public <T, R> R doPost(String httpUrl, T params, Class<R> returnType,String token) throws IOException {
    StringBuilder result = new StringBuilder();
    //连接
    HttpURLConnection connection = null;
    OutputStream os = null;
    InputStream is = null;
    BufferedReader br = null;
    try {
        //创建连接对象
        URL url = new URL(httpUrl);
        //创建连接
        connection = (HttpURLConnection) url.openConnection();
        //设置请求方法
        connection.setRequestMethod("POST");
        //设置连接超时时间(必须)
        connection.setConnectTimeout(15000);
        //设置读取超时时间(必须)
        connection.setReadTimeout(15000);
        //DoOutput设置是否向httpUrlConnection输出,DoInput设置是否从httpUrlConnection读入,此外发送post请求必须设置这两个
        //设置是否可读取
        connection.setDoOutput(true);
        connection.setDoInput(true);
        //设置通用的请求属性
        connection.setRequestProperty("accept", "*/*");
        connection.setRequestProperty("connection", "Keep-Alive");
        connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
        connection.setRequestProperty("Content-Type", "application/json;charset=utf-8");
        //(可选)设置请求头鉴权信息
        if(StringUtils.isNotBlank(token)){
            connection.addRequestProperty("Authorization",token);
        }


        // 建立实际的连接
        connection.connect();
        //拼装参数
        if (null != params) {
            String param = objectMapper.writeValueAsString(params);
            //设置参数
            os = connection.getOutputStream();
            OutputStreamWriter writer = new OutputStreamWriter(os, "UTF-8");
            //拼装参数
            writer.write(param);
            writer.flush();

            //另一种方式
            //设置参数
            //os = connection.getOutputStream();
            //拼装参数
            //os.write(param.getBytes("UTF-8"));
        }
        //设置权限
        //设置请求头等
        //开启连接
        //connection.connect();
        //读取响应
        if (connection.getResponseCode() == 200) {
            is = connection.getInputStream();
            if (null != is) {
                br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                String temp = null;
                while (null != (temp = br.readLine())) {
                    result.append(temp);
                    result.append("\r\n");
                }
            }
        }

    } finally {
        //关闭连接
        if (br != null) {
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (os != null) {
            try {
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (is != null) {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //关闭连接
        connection.disconnect();
    }
    R object = objectMapper.readValue(result.toString(), returnType);
    return object;

}

getToken方法:

/**
 * 获取第三方接口的token
 */
public String getToken() throws IOException {
    String token = null;
    Map<String, String> object = new HashMap<>();
    object.put("userName", "xxx");
    object.put("password", "xxx");

    String url = "http://localhost:8082/nacos-service-provider/auth/login";
    JsonResult jsonResult = doPost(url, object, JsonResult.class);


    if (Objects.isNull(jsonResult) || !ReturnCode.SUCCESS.getCode().equals(jsonResult.getCode())) {
        if (Objects.isNull(jsonResult)) {
            throw new BizException(ReturnCode.ERROR);
        } else {
            throw new BizException(jsonResult.getCode(), jsonResult.getMessage());
        }
    }
    LoginResponse loginResponse = objectMapper.convertValue(jsonResult.getData(), LoginResponse.class);
    token = loginResponse.getToken();
    return token;
}

Service方法:

/**
  * 使用HttpURLConnection发送Post请求
  */
 @SneakyThrows
 public TestHttpAccessResponse sendHttpRequestByJdk() {
     TestHttpAccessRequest request = new TestHttpAccessRequest();
     request.setAge(16);
     request.setName("刘伞");
     request.setAddress("佛山市");

     String httpUrl = "http://localhost:8082/nacos-service-provider/testHttpAccess";

     /**
      * 如果是List<T>这种带泛型的对象,则需要使用TypeReference<类型> typeRef = new TypeReference...
      * 注意日期的类型,需要事前设置类型转换器
      */
     String token = httpUrlConnectionService.getToken();
     JsonResult jsonResult = httpUrlConnectionService.doPost(httpUrl, request, JsonResult.class,token);
     if (Objects.isNull(jsonResult) || !ReturnCode.SUCCESS.getCode().equals(jsonResult.getCode())) {
         if (Objects.isNull(jsonResult)) {
             throw new BizException(ReturnCode.ERROR);
         } else {
             throw new BizException(jsonResult.getCode(), jsonResult.getMessage());
         }
     }


     /**
      * 由于我做了统一的返回体JsonResult,所以还需要再转一遍
      * 这里不封装进去是因为,除了JsonResult可能还会有其他的返回体
      */
     TestHttpAccessResponse response = objectMapper.convertValue(jsonResult.getData(), TestHttpAccessResponse.class);
     return response;
 }

调试结果(软件:apifox):
无授权:

{
    "code": "40026",
    "message": "token不存在或过期,请登录",
    "data": null
}

正常:

{
    "code": "40000",
    "message": "操作成功",
    "data": {
        "name": "刘伞",
        "age": 16,
        "address": "佛山市"
    }
}

Get请求方式

虽然正常工作中不太会使用到Get请求,但是还是要了解一下

测试程序:
根据步骤,新建doGet方法:

注意:
(1)注意这里不要把参数放到OutputStream里面,否则会自动变成POST请求
(2)String参数都用UrlEncode编码,否则有可能会提示Invalid Character

    /**
     * Http get请求
     *
     * @param httpUrl 连接
     * @return 响应数据
     */
    public String doGet(String httpUrl, String param,String token) {
        //链接
        HttpURLConnection connection = null;
        InputStream is = null;
        BufferedReader br = null;
        StringBuffer result = new StringBuffer();
        try {
            //创建连接
            if (StringUtils.isNotBlank(param)) {
                httpUrl = httpUrl + "?" + param;
            }
            URL url = new URL(httpUrl);
            connection = (HttpURLConnection) url.openConnection();
            //设置请求方式
            connection.setRequestMethod("GET");
            //设置连接超时时间
            connection.setReadTimeout(15000);
            //(可选)设置请求头鉴权信息
            if(StringUtils.isNotBlank(token)){
                connection.addRequestProperty("Authorization",token);
            }


            //开始连接
            connection.connect();

            //请求参数(这里不要把参数放到outputStream中,会自动变成post请求)
           /* if (StringUtils.isNotBlank(param)) {
                OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream(), "UTF-8");
                writer.write(param);
                writer.flush();
            }*/

            //获取响应数据
            if (connection.getResponseCode() == 200) {
                //获取返回的数据
                is = connection.getInputStream();
                if (null != is) {
                    br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                    String temp = null;
                    while (null != (temp = br.readLine())) {
                        result.append(temp);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != br) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != is) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            //关闭远程连接
            connection.disconnect();
        }
        return result.toString();
    }

测试方法:

     /**
     * 使用HttpURLConnection发送Post请求
     */
    @SneakyThrows
    public TestHttpAccessResponse sendHttpGetRequestByJdk() {
        TestHttpAccessRequest request = new TestHttpAccessRequest();
        request.setAge(16);
        request.setName("刘伞");
        request.setAddress("佛山市");

        //拼接参数
        String httpUrl = "http://localhost:8082/nacos-service-provider/testHttpAccessGet";
        List<String> params = Lists.newArrayList();
        Class<TestHttpAccessRequest> clazz = TestHttpAccessRequest.class;
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            declaredField.setAccessible(true);
            Object o = declaredField.get(request);
            if (declaredField.getType().equals(String.class)) {
                String s = (String) declaredField.get(request);
                s = URLEncoder.encode(s);
                o = s;
            }
            params.add(declaredField.getName() + "=" + o);
        }
        String param = params.stream().collect(Collectors.joining("&"));
        //这里getToken方法沿用上面的
        String token = httpUrlConnectionService.getToken();
        String responseJson = httpUrlConnectionService.doGet(httpUrl, param,token);

        /**
         * 如果是List<T>这种带泛型的对象,则需要使用TypeReference<类型> typeRef = new TypeReference...
         * 注意日期的类型,需要事前设置类型转换器
         */
        JsonResult<Object> jsonResult = objectMapper.readValue(responseJson, JsonResult.class);
        /**
         * 由于我做了统一的返回体JsonResult,所以还需要再转一遍
         */
        if (Objects.isNull(jsonResult) || !ReturnCode.SUCCESS.getCode().equals(jsonResult.getCode())) {
            if (Objects.isNull(jsonResult)) {
                throw new BizException(ReturnCode.ERROR);
            } else {
                throw new BizException(jsonResult.getCode(), jsonResult.getMessage());
            }
        }
        TestHttpAccessResponse response = objectMapper.convertValue(jsonResult.getData(), TestHttpAccessResponse.class);
        return response;
    }

结果展示:
无授权:

{
    "code": "40026",
    "message": "token不存在或过期,请登录",
    "data": null
}

正常:

{
    "code": "40000",
    "message": "操作成功",
    "data": {
        "name": "刘伞",
        "age": 16,
        "address": "佛山市"
    }
}

相关阅读

Java实现HTTP请求的几种方式-Apache HttpClient(二)文章来源地址https://www.toymoban.com/news/detail-601333.html

到了这里,关于Java实现HTTP请求的几种方式-HttpURLConnection(一)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 构造http请求的几种方式(附源码)

    博主个人社区:开发与算法学习社区 博主个人主页:Killing Vibe的博客 欢迎大家加入,一起交流学习~~ form (表单) 是 HTML 中的一个常用标签. 可以用于给服务器发送 GET 或者 POST 请求. form 的重要参数: action: 构造的 HTTP 请求的 URL 是什么. method: 构造的 HTTP 请求的 方法 是 GET 还是

    2023年04月09日
    浏览(47)
  • hutool Http 工具发送POST请求的几种方式。

    Hutool是一个Java工具库,提供了丰富的功能模块,包括HTTP请求发送。以下是使用Hutool发送POST请求的几种方式: 使用HttpUtil.post方法: 使用HttpUtil.post方法可以发送简单的POST请求,示例如下: 使用HttpUtil.createPost方法: 使用HttpUtil.createPost方法可以创建一个HttpPost对象,然后设置

    2024年02月13日
    浏览(37)
  • hutool Http 工具发送POST请求的几种方式

            目录 依赖 🍊Maven 🍐Gradle 实践 hutool源码 hutool调用实践 其它自定义项         本质上,HttpUtil中的get和post工具方法都是HttpRequest对象的封装,因此如果想更加灵活操作Http请求,可以使用HttpRequest。今天咱们就列举一下hutool工具中常用的几种发送post请求的方式。

    2024年02月08日
    浏览(55)
  • http请求和响应格式说明,http的get和post请求方式说明,http的请求体body的几种数据格式

    一个HTTP请求报文由 请求行(request line)、请求头部(header)、空行和请求数据 4个部分组成, 请求报文的一般格式 1、第一行必须是一个请求行(request-line),用来说明请求类型,要访问的资源以及所使用的HTTP版本 2、紧接着是一个请求头(header),用来说明服务器要使用的附加信息

    2024年02月02日
    浏览(59)
  • 【Http协议④】常见的几种构造http请求的方式,form表单构造,Ajax构造,postman构造

    前言: 大家好,我是 良辰丫 ,这篇文章我将协同大家一起去学习几种构造http请求的方式.💞💞💞 🧑个人主页:良辰针不戳 📖所属专栏:javaEE初阶 🍎励志语句:生活也许会让我们遍体鳞伤,但最终这些伤口会成为我们一辈子的财富。 💦期待大家三连,关注,点赞,收藏。

    2024年02月06日
    浏览(54)
  • java中几种http请求方式

    在Java中,发送HTTP请求的方式主要有以下几种: 使用 java.net.HttpURLConnection 类: HttpURLConnection是Java中用于发送HTTP请求和接收HTTP响应的类。它是java.net包中的一部分,基于Java的网络编程API。 HttpURLConnection的一些常用参数和方法如下: 优点:这是Java标准库提供的方法,不需要额

    2024年02月05日
    浏览(39)
  • java 发送 http 请求练习两年半(HttpURLConnection)

    1、起一个 springboot 程序做 http 测试: 2、写一个 HttpURLConnection 自定义客户端 3、测试 get 和 post 请求 4、控制台输出结果 中间遇到一些坑,经常以为 http 会有方法像 openfeign 那样传入请求参数,忽略了路径拼接, 启动的 springboot 接收的 post 的请求体为 List 类型,且 Content-Type

    2023年04月22日
    浏览(45)
  • Java实现异步的几种方式

    普通线程实现异步,但频繁创建、销毁线程比较耗资源,所以一般交给线程池执行 结果: Future异步 和普通线程实现异步区别不大,只是使用Future是要获取执行后的返回值 结果: Spring的@Async异步 使用@Async注解实现异步的前提是需要在启动类上标注@EnableAsync来开启异步配置

    2024年02月04日
    浏览(70)
  • Java如何实现下载文件的几种方式

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/Boy_Martin/article/details/126058565

    2024年02月13日
    浏览(70)
  • java 实现开启异步线程的几种方式

    在Java中,有多种方式可以实现异步线程以避免在主线程中执行耗时操作导致界面卡顿的问题。以下是几种常用的方式: 使用 Thread 类:可以使用 Thread 类来创建一个新的线程,并在其 run() 方法中执行耗时操作。例如: 使用 Runnable 接口:可以通过实现 Runnable 接口并在其中实现

    2024年02月14日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包