安卓应用开发学习:聚合数据API获取天气预报

一、引言

上个月我通过腾讯位置服务,实现了手机定位应用的开发学习。最近在看软件书籍时,又看到了聚合数据API方面的内容。 书上介绍了聚合数据天气预报API的应用,不过书上的代码看得有些难受,我到聚合数据官网,对天气预报API的接口文档进行了研究,感觉比书上的要简单。于是,我参照官网的接口文档设计查询部分的代码,UI等设计则借鉴了书上的内容,完成了这个应用的开发。实现的效果如下图:

二、聚合数据平台选择API

聚合数据平台提供了很多的API,其中免费的API也不少。要使用该平台的API自然需要先注册用户了。

注册号用户,登录后,先完成实名认证,否则无法使用API。我是后知后觉,申请API的时候出现了要求实名认证的提示。

大体的流程在网站上有说明。

完成注册和认证后,进入API页面,选择免费接口 (免费API接口工具大全 - 聚合数据)。我们要用到的天气预报接口就在第一行。

点击天气预报,进入天气预报接口页面。点击“立即申请”。这个页面里还可以获得接口的相关介绍和示例代码,方便我们进行应用开发。

完成申请后就可以在“个人中心 - 数据中心 - 我的API”中看到申请到的API了。聚合数据对免费接口有限制,普通会员只能申请3个。大多数免费接口每天的请求次数为50次,进行开发学习还是够用了。调用API需要的Key也在这个页面里。

完成了API的申请,就可以着手进行软件的设计开发了。

三、软件设计

我的天气预报应用的界面设计参考了书上的样式,但书上的代码将城市名写死了,我希望支持输入城市名进行查询。因此设计UI时,在页面顶部添加了SearchView组件,用于输入城市名称,输入后按下软键盘中的搜索按钮,执行获取天气预报操作。界面的中间部分放置了几个TextView组件用于显示实时天气信息,界面下部使用纵向的LinearLayout布局设置,该布局做了圆角处理,其下放置了多个TextView组件用于显示未来5天的预报信息。有参照做起来就很快了。

逻辑代码的设计则花了一些时间,主要是书上的代码看着不够简洁,比官网提供的示例要复杂不少。我就没有照搬书上的内容做,而是综合了书上的代码与官网示例进行的设计。其中GET请求部分的代码基本照搬了“接口文档”中提供的Java示例。有所区别的是,需要添加try语句,否则会报错。

官网提供了接口测试功能,可以先在接口测试页面查看获取天气预报的请求详情和返回结果。方便后续的代码设计。

这个API的调用接口URI格式如下:

http://apis.juhe.cn/simpleWeather/query?key=key&city=%E8%8B%8F%E5%B7%9E

其中key在“个人中心 - 数据中心 - 我的API”中获取。city则是从SearchView组件中获取。我将GET请求放在了SearchView组件的监听器中执行。监听器响应搜索按钮触发,获取组件中的文本内容,并将其传递给获取天气预报的方法。

获取天气预报的方法,我是参考了官网的java示例代码(如下):

package cn.juhe.test;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

public class JavaGet {
    public static void main(String[] args) throws Exception {
        String apiKey = "你申请的key";
        String apiUrl = "http://apis.juhe.cn/simpleWeather/query";

        HashMap<String, String> map = new HashMap<>();
        map.put("key", apiKey);
        map.put("city", "苏州");

        URL url = new URL(String.format(apiUrl + "?" + params(map)));
        BufferedReader in = new BufferedReader(new InputStreamReader((url.openConnection()).getInputStream()));
        String inputLine;
        StringBuffer response = new StringBuffer();
        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();
        System.out.println(response);
    }

    public static String params(Map<String, String> map) {
        return map.entrySet().stream()
                .map(entry -> entry.getKey() + "=" + entry.getValue())
                .collect(Collectors.joining("&"));
    }
}

上述代码也是将城市名写死的,且获取到的结果直接打印输出,不符合我们的实际应用需求,得修改,但关键的代码基本是可以照搬的。

在做逻辑代码设计时,我遇到了两个问题:

1.一开始,我的GET请求代码是放在主线程中执行的,结果测试时出现了报错。网上搜索后,才了解到从Android 4.0 之后不能在主线程中请求HTTP,需要将GET请求放在分线程中执行。

2.在分线程中执行GET请求获取到天气预报的信息后,我在分线程里更新UI的代码,结果测试时又报错了。一搜,Android不允许在分线程中直接修改UI界面,可以使用runOnUiThread方法更新UI界面。

解决了这两个问题,其它方面就很顺利了,完成后测试了几次,还可以。

请求次数可以在“个人中心-数据中心-我的API”找到天气预报,点击“统计”按钮,可以查看调用情况。

四、代码展示

最终的代码如下:

1. 界面设计文件  activity_weather.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".WeatherActivity">

    <TextView
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="天气预报"
        android:textSize="24sp"
        android:textStyle="bold"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <LinearLayout
        android:id="@+id/linearLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:orientation="horizontal"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/tv_title">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginEnd="10dp"
            android:text="城市"
            android:textSize="17sp" />

        <android.widget.SearchView
            android:id="@+id/sv_cityName"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:background="@drawable/shape_round_bg_gray"
            android:iconifiedByDefault="true"
            android:imeOptions="actionSearch"
            android:queryHint="请输入关键字"
            android:textColor="@color/gray_78"
            android:textSize="15sp" />
    </LinearLayout>

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginTop="10dp"
        android:background="@color/blue_415"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/linearLayout">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:orientation="vertical" >

            <TextView
                android:id="@+id/tv_result"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />

            <TextView
                android:id="@+id/tv_cityName"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="城市名"
                android:textColor="@color/white"
                android:textSize="24sp" />

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:orientation="horizontal">

                <TextView
                    android:id="@+id/tv_realTime_temp"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="~℃"
                    android:textColor="@color/white"
                    android:textSize="32sp"
                    android:textStyle="bold" />

                <TextView
                    android:id="@+id/tv_realTime_weather"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="10dp"
                    android:text="天气"
                    android:textColor="@color/white"
                    android:textSize="32sp"
                    android:textStyle="bold" />
            </LinearLayout>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:orientation="horizontal">

                <TextView
                    android:id="@+id/tv_realTime_dir"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="风向"
                    android:textColor="@color/white"
                    android:textSize="22sp"
                    android:textStyle="bold" />

                <TextView
                    android:id="@+id/tv_realTime_pow"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="10dp"
                    android:text="风级"
                    android:textColor="@color/white"
                    android:textSize="22sp"
                    android:textStyle="bold" />
            </LinearLayout>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:orientation="horizontal">

                <TextView
                    android:id="@+id/tv_realTime_hum"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="湿度~"
                    android:textColor="@color/white"
                    android:textSize="22sp"
                    android:textStyle="bold" />

                <TextView
                    android:id="@+id/tv_realTime_aqi"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="10dp"
                    android:text="空气质量指数~"
                    android:textColor="@color/white"
                    android:textSize="22sp"
                    android:textStyle="bold" />
            </LinearLayout>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="20dp"
                android:background="@drawable/radius_border_15"
                android:orientation="vertical">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="10dp"
                    android:layout_marginTop="10dp"
                    android:text="5天预报"
                    android:textSize="20sp" />

                <TextView
                    android:id="@+id/tv_date1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="10dp"
                    android:layout_marginTop="10dp"
                    android:text="日期1" />

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal">

                    <TextView
                        android:id="@+id/tv_temp1"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginStart="10dp"
                        android:text="~℃" />

                    <TextView
                        android:id="@+id/tv_weather1"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginStart="10dp"
                        android:text="天气" />

                    <TextView
                        android:id="@+id/tv_dir1"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginStart="10dp"
                        android:text="风向" />
                </LinearLayout>

                <TextView
                    android:id="@+id/tv_date2"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="10dp"
                    android:layout_marginTop="10dp"
                    android:text="日期2" />

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal">

                    <TextView
                        android:id="@+id/tv_temp2"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginStart="10dp"
                        android:text="~℃" />

                    <TextView
                        android:id="@+id/tv_weather2"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginStart="10dp"
                        android:text="天气" />

                    <TextView
                        android:id="@+id/tv_dir2"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginStart="10dp"
                        android:text="风向" />
                </LinearLayout>

                <TextView
                    android:id="@+id/tv_date3"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="10dp"
                    android:layout_marginTop="10dp"
                    android:text="日期3" />

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal">

                    <TextView
                        android:id="@+id/tv_temp3"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginStart="10dp"
                        android:text="~℃" />

                    <TextView
                        android:id="@+id/tv_weather3"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginStart="10dp"
                        android:text="天气" />

                    <TextView
                        android:id="@+id/tv_dir3"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginStart="10dp"
                        android:text="风向" />
                </LinearLayout>

                <TextView
                    android:id="@+id/tv_date4"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="10dp"
                    android:layout_marginTop="10dp"
                    android:text="日期4" />

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal">

                    <TextView
                        android:id="@+id/tv_temp4"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginStart="10dp"
                        android:text="~℃" />

                    <TextView
                        android:id="@+id/tv_weather4"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginStart="10dp"
                        android:text="天气" />

                    <TextView
                        android:id="@+id/tv_dir4"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginStart="10dp"
                        android:text="风向" />
                </LinearLayout>

                <TextView
                    android:id="@+id/tv_date5"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="10dp"
                    android:layout_marginTop="10dp"
                    android:text="日期5" />

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginBottom="10dp"
                    android:orientation="horizontal">

                    <TextView
                        android:id="@+id/tv_temp5"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginStart="10dp"
                        android:text="~℃" />

                    <TextView
                        android:id="@+id/tv_weather5"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginStart="10dp"
                        android:text="天气" />

                    <TextView
                        android:id="@+id/tv_dir5"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginStart="10dp"
                        android:text="风向" />
                </LinearLayout>

            </LinearLayout>

        </LinearLayout>
    </ScrollView>

</androidx.constraintlayout.widget.ConstraintLayout>

2. 逻辑代码 WeatherActivity.java

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.widget.SearchView;
import android.widget.TextView;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;  // 与官网示例不同,官网是net.sf.json.JSONObject

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;

public class WeatherActivity extends AppCompatActivity {
    private final static String TAG = "WeatherActivity";
    private SearchView sv_cityName;  // 搜索框
    private TextView tv_cityName;  // 显示城市名
    private TextView tv_realTime_temp;  // 显示实时温度
    private TextView tv_realTime_weather;  // 显示实时天气
    private TextView tv_realTime_dir;  // 显示实时风向
    private TextView tv_realTime_pow;  // 显示实时风级
    private TextView tv_realTime_hum;  // 显示实时湿度
    private TextView tv_realTime_aqi;  // 显示空气质量指数
    private TextView tv_date1, tv_date2, tv_date3, tv_date4, tv_date5;  // 日期
    private TextView tv_temp1, tv_temp2, tv_temp3, tv_temp4, tv_temp5;  // 温度
    private TextView tv_weather1, tv_weather2, tv_weather3, tv_weather4, tv_weather5;  // 天气
    private TextView tv_dir1, tv_dir2, tv_dir3, tv_dir4, tv_dir5;  // 风向
    private String mCityName;  // 保存用户在搜索框中输入的城市名
    // 天气情况查询接口地址
    private static final String API_URL = "http://apis.juhe.cn/simpleWeather/query";
    // 接口请求Key(在聚合数据网站申请天气预报API后生成的AppKey)
    private static final String API_KEY = "***********************";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_weather);

        sv_cityName = findViewById(R.id.sv_cityName);  // 城市名搜索框
        // 实时天气
        tv_cityName = findViewById(R.id.tv_cityName);
        tv_realTime_temp = findViewById(R.id.tv_realTime_temp);
        tv_realTime_weather = findViewById(R.id.tv_realTime_weather);
        tv_realTime_dir = findViewById(R.id.tv_realTime_dir);
        tv_realTime_pow = findViewById(R.id.tv_realTime_pow);
        tv_realTime_hum = findViewById(R.id.tv_realTime_hum);
        tv_realTime_aqi = findViewById(R.id.tv_realTime_aqi);
        // 未来5天预报天气
        tv_date1 = findViewById(R.id.tv_date1);
        tv_date2 = findViewById(R.id.tv_date2);
        tv_date3 = findViewById(R.id.tv_date3);
        tv_date4 = findViewById(R.id.tv_date4);
        tv_date5 = findViewById(R.id.tv_date5);
        tv_temp1 = findViewById(R.id.tv_temp1);
        tv_temp2 = findViewById(R.id.tv_temp2);
        tv_temp3 = findViewById(R.id.tv_temp3);
        tv_temp4 = findViewById(R.id.tv_temp4);
        tv_temp5 = findViewById(R.id.tv_temp5);
        tv_weather1 = findViewById(R.id.tv_weather1);
        tv_weather2 = findViewById(R.id.tv_weather2);
        tv_weather3 = findViewById(R.id.tv_weather3);
        tv_weather4 = findViewById(R.id.tv_weather4);
        tv_weather5 = findViewById(R.id.tv_weather5);
        tv_dir1 = findViewById(R.id.tv_dir1);
        tv_dir2 = findViewById(R.id.tv_dir2);
        tv_dir3 = findViewById(R.id.tv_dir3);
        tv_dir4 = findViewById(R.id.tv_dir4);
        tv_dir5 = findViewById(R.id.tv_dir5);

        // 设置搜索框监听器
        sv_cityName.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            // 当点击搜索按钮时触发该方法
            @Override
            public boolean onQueryTextSubmit(String s) {
                sv_cityName.clearFocus();  // 移除焦点
                mCityName = s;
                // Android 4.0 之后不能在主线程中请求HTTP
                new Thread(() -> queryWeather (mCityName)).start();  // 分线程中获取天气信息
                return false;
            }
            // 当搜索内容改变时触发该方法
            @Override
            public boolean onQueryTextChange(String s) {
                return false;
            }
        });
    }

    /**
     * 根据城市名查询天气情况
     *
     * @param cityName  城市名称
     */
    private void queryWeather(String cityName) {
        HashMap<String, String> map = new HashMap<>();  //组合参数
        map.put("city", cityName);
        map.put("key", API_KEY);
        String queryParams = params(map);
        try {
            URL url = new URL(API_URL + "?" + queryParams);
            Log.d(TAG, "URL=" + url);
            BufferedReader in = new BufferedReader(new InputStreamReader((url.openConnection()).getInputStream()));
            String inputLine;
            StringBuffer response = new StringBuffer();  // StringBuffer是线程安全的,StringBuilder效率更高,但不是线程安全的
            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }
            in.close();
            // Log.d(TAG, "查询天气返回的结果:");
            // Log.d(TAG, response.toString());

            // 将获取到的结果转换为JSONObject,从中获取天气信息
            try {
                JSONObject jsonObject = new JSONObject(response.toString());
                int error_code = jsonObject.getInt("error_code");
                if (error_code == 0) {
                    JSONObject result = jsonObject.getJSONObject("result");
                    String city = result.getString("city");
                    // 获取实时天气数据
                    JSONObject realtime = result.getJSONObject("realtime");
                    String temp = realtime.getString("temperature");  // 温度
                    String hum = realtime.getString("humidity");  // 湿度
                    String info = realtime.getString("info");  // 天气
                    String dir = realtime.getString("direct");  // 风向
                    String pow = realtime.getString("power");  // 风级
                    String aqi = realtime.getString("power");  // 空气质量指数
                    // 获取未来5天的天气数据
                    JSONArray futureArray = result.getJSONArray("future");
                    JSONObject f1 = futureArray.getJSONObject(0);
                    String date1 = f1.getString("date");
                    String temp1 = f1.getString("temperature");
                    String weather1 = f1.getString("weather");
                    String dir1 = f1.getString("direct");
                    JSONObject f2 = futureArray.getJSONObject(1);
                    String date2 = f2.getString("date");
                    String temp2 = f2.getString("temperature");
                    String weather2 = f2.getString("weather");
                    String dir2 = f2.getString("direct");
                    JSONObject f3 = futureArray.getJSONObject(2);
                    String date3 = f3.getString("date");
                    String temp3 = f3.getString("temperature");
                    String weather3 = f3.getString("weather");
                    String dir3 = f3.getString("direct");
                    JSONObject f4 = futureArray.getJSONObject(3);
                    String date4 = f4.getString("date");
                    String temp4 = f4.getString("temperature");
                    String weather4 = f4.getString("weather");
                    String dir4 = f4.getString("direct");
                    JSONObject f5 = futureArray.getJSONObject(4);
                    String date5 = f5.getString("date");
                    String temp5 = f5.getString("temperature");
                    String weather5 = f5.getString("weather");
                    String dir5 = f5.getString("direct");
                    // 分线程不能直接修改UI界面,可以使用runOnUiThread方法更新UI界面
                    runOnUiThread(() -> {
                        tv_cityName.setText(city);
                        // 更新实时天气
                        tv_realTime_temp.setText(String.format(Locale.CHINESE, "%s%s", temp, "℃"));
                        tv_realTime_weather.setText(info);
                        tv_realTime_dir.setText(dir);
                        tv_realTime_pow.setText(pow);
                        tv_realTime_hum.setText(String.format(Locale.CHINESE, "%s%s", "湿度:", hum));
                        tv_realTime_aqi.setText(String.format(Locale.CHINESE, "%s%s", "空气质量指数:", aqi));
                        // 更新未来5天预报天气
                        tv_date1.setText(date1);
                        tv_temp1.setText(temp1);
                        tv_weather1.setText(weather1);
                        tv_dir1.setText(dir1);
                        tv_date2.setText(date2);
                        tv_temp2.setText(temp2);
                        tv_weather2.setText(weather2);
                        tv_dir2.setText(dir2);
                        tv_date3.setText(date3);
                        tv_temp3.setText(temp3);
                        tv_weather3.setText(weather3);
                        tv_dir3.setText(dir3);
                        tv_date4.setText(date4);
                        tv_temp4.setText(temp4);
                        tv_weather4.setText(weather4);
                        tv_dir4.setText(dir4);
                        tv_date5.setText(date5);
                        tv_temp5.setText(temp5);
                        tv_weather5.setText(weather5);
                        tv_dir5.setText(dir5);
                    });  // 使用runOnUiThread更新界面
                } else {
                    Log.d(TAG, "调用接口失败:" + jsonObject.getString("reason"));
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 将map型转为请求参数型
     *
     * @param map  map型保存的参数
     */
    private static String params(Map<String, String> map) {
        return map.entrySet().stream()
                .map(entry -> entry.getKey() + "=" + entry.getValue())
                .collect(Collectors.joining("&"));
    }
}

  • 8
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

武陵悭臾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值