如何使用HTTPURLConnection从Servlet获取JSON对象?

时间:2018-01-01 20:07:09

标签: java android json servlets

我正在编写一个使用java Servlet管理登录的Android应用程序。 登录数据在MySQL数据库中检查。 这个servlet应该返回一个json对象。 在某些代码下面:

的Servlet

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package AndroidControllers;

import Database.Authentication;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.simple.JSONObject;

/**
 *
 * @author serge
 */
public class Android extends HttpServlet {

    /**
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code>
     * methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        try (PrintWriter out = response.getWriter()) {
            /* TODO output your page here. You may use following sample code. */
            out.println("<!DOCTYPE html>");
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Servlet Android</title>");
            out.println("</head>");
            out.println("<body>");
            out.println("<h1>Servlet Android at " + request.getContextPath() + "</h1>");
            out.println("</body>");
            out.println("</html>");
        }
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /**
     * Handles the HTTP <code>GET</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");
            PrintWriter writer = response.getWriter();
            String user = request.getParameter("username");
            String pass = request.getParameter("password");
            PrintWriter out = response.getWriter();
            JSONObject logged = Authentication.login_json(user, pass);
            if(logged != null)
                writer.print(logged);
            else{
                logged.put("type", "ERROR");
                logged.put("username", "ERROR");
                writer.print(logged);
            }
        //processRequest(request, response);
    }

    /**
     * Handles the HTTP <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {


        processRequest(request, response);

    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>

}

Authentication.login_json方法:

public static JSONObject login_json(String user, String pass){
        JSONObject json = new JSONObject();
        Connection conn = null;
        String sql = "select username, user_type from users where username = '" + user +
                "' and password = '" + pass + "';";
        try{
            Class.forName("com.mysql.jdbc.Driver");
            conn = Utilities.connect();
            Statement st = conn.createStatement();
            ResultSet rs = st.executeQuery(sql);
            if(rs.next()){
                json.put("username", user);
                json.put("type", rs.getString("user_type"));
            }
            else{
                json.put("username", "FAIL");
                json.put("type", "FAIL");
            }
        }
        catch(SQLException | ClassNotFoundException ecc){
            System.out.println("ERROR: " + ecc.getMessage());
        }
        finally{
            Utilities.disconnect(conn);
        }
        return json;
    }

Android中使用的身份验证方法:

    package com.example.serge.biblioteca;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
public class http_authentication{
    public static JSONObject login_json(String user, String pass) {
        String json_string = "";
        JSONObject stream = new JSONObject();
        JSONParser parser = new JSONParser();
        String url = "http://localhost:43746/Progetto_TWEB/Android?username=" + user
                + "&password=" + pass;
        try {
            URL link = new URL(url);
            HttpURLConnection urlConnection = (HttpURLConnection) link.openConnection();

            // Check the connection status
            if (urlConnection.getResponseCode() == 200) {
                // if response code = 200 ok
                InputStream in = new BufferedInputStream(urlConnection.getInputStream());

                // Read the BufferedInputStream
                BufferedReader r = new BufferedReader(new InputStreamReader(in));
                StringBuilder sb = new StringBuilder();
                String line;
                while ((line = r.readLine()) != null) {
                    sb.append(line);
                }
                json_string = sb.toString();
                stream = (JSONObject) parser.parse(json_string);

                // End reading...............
                // Disconnect the HttpURLConnection
                urlConnection.disconnect();
            } else {
                // Do something
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        } finally {

        }
        // Return the data from specified url
        return stream;
    }
}

这些方法在普通的Java类中使用效果很好,它们总是返回预期的json对象。在Andoid应用程序中,我总是得到一个空的json对象,我不知道为什么。

这里是活动代码:

package com.example.serge.biblioteca;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import org.json.simple.parser.JSONParser;

import org.json.simple.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;

/**
 * Created by serge on 28/12/2017.
 */

public class login extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        final Button login = (Button) findViewById(R.id.login_login);
        final EditText username = (EditText) findViewById(R.id.txtUser);
        final EditText password = (EditText) findViewById(R.id.txtPass);


        login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

        JSONObject logged = new JSONObject();
        boolean vuoto = false;
        String logged_type = "";
        String logged_user = "", user_type = "";
        TextView welcome = (TextView)findViewById(R.id.normal_intro);
        String user = username.getText().toString();
        String pass = password.getText().toString();
        try {
            logged = http_authentication.login_json(user, pass);
                vuoto = logged.isEmpty();
//The following setText always returns an empty String so I think the object is null
                username.setText(logged.toString());
        }
        catch(Exception ecc){
            username.setText(ecc.getMessage());
        }
            }
        });
    }
}

你能帮助我理解为什么Android Activity总是得到一个null对象,但普通的java类运行良好吗? 谢谢

1 个答案:

答案 0 :(得分:0)

我设法解决了这个问题。 如果有人想知道我将如何解释如下:

首先,我创建了一个新的Servlet,它执行相同的操作但代码少得多:

package AndroidControllers;
import Database.Authentication;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.simple.JSONObject;
import org.json.simple.parser.*;

public class Login extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public Login() {
        super();
    }

    protected void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        JSONObject logged = Authentication.login_json(username, password);
        if(!logged.isEmpty()){
            out.println(logged);
        }
        else{
            logged.put("username", "NULL");
            logged.put("type", "NULL");
            out.println(logged);
        }
    }
}

此servlet获取两个参数(用户名和密码)并检查它们是否存在MySQL数据库。如果它们存在,则返回类型为:{“username”:“username”,“type”:“admin”或“type”:“normal”}的JSONObject。 Authentication.login_json(用户名,密码)方法是相同的......

我还开发了Android Activity:

package com.example.serge.biblioteca;

import android.content.Intent;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;

public class login_page extends AppCompatActivity implements View.OnClickListener{
    Button login;
    EditText user, pass;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login_page);
        findViewsByID();
        login.setOnClickListener(this);
    }

    private void findViewsByID(){
        login = (Button) findViewById(R.id.login_login);
        user = (EditText) findViewById(R.id.txtUser);
        pass = (EditText) findViewById(R.id.txtPass);
    }


    @Override
    public void onClick(View view) {
        String username = user.getText().toString();
        String password = pass.getText().toString();
        String URL = "http://192.168.1.4:43746/Progetto_TWEB/Login?username=" + username
                + "&password=" + password;
        GetXMLTask task = new GetXMLTask();
        task.execute(new String[] { URL });
    }

    private class GetXMLTask extends AsyncTask<String, Void, JSONObject> {
        @Override
        protected JSONObject doInBackground(String... urls) {
            JSONObject output = null;
            for (String url : urls) {
                String json_string = getOutputFromUrl(url);
                JSONParser parser = new JSONParser();
                try {
                    output = (JSONObject) parser.parse(json_string);
                }
                catch(ParseException ecc){

                }
            }
            return output;
        }

        private String getOutputFromUrl(String url) {
            StringBuffer output = new StringBuffer("");
            try {
                InputStream stream = getHttpConnection(url);
                BufferedReader buffer = new BufferedReader(
                        new InputStreamReader(stream));
                String s = "";
                while ((s = buffer.readLine()) != null)
                    output.append(s);
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            return output.toString();
        }

        // Makes HttpURLConnection and returns InputStream
        private InputStream getHttpConnection(String urlString)
                throws IOException {
            InputStream stream = null;
            URL url = new URL(urlString);
            URLConnection connection = url.openConnection();

            try {
                HttpURLConnection httpConnection = (HttpURLConnection) connection;
                httpConnection.setRequestMethod("GET");
                httpConnection.connect();

                if (httpConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                    stream = httpConnection.getInputStream();
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            return stream;
        }

        @Override
        protected void onPostExecute(JSONObject output) {
            Intent redirect_normal = new Intent(login_page.this, normal_user.class);
            String type = output.get("type").toString();
            if(type.equals("normal"))
                startActivity(redirect_normal);
            else if(type.equals("NULL"))
                user.setText("LOGIN FAILED");
            else if(type.equals("admin"))
                user.setText("NOT NORMAL");

        }
    }
}

如您所见,Activity可以使用AsyncTask,HTTPURLConnection和InputStream与Servlet通信。 这一切一切正常,因为Android Activity得到了预期的JSONObject。 我想对在这里帮助过我的所有人说谢谢。 希望这对某人有用,对不起我的英语。