使用URLConnection提交请求:
1.通过调用URL对象openConnection()方法来创建URLConnection对象
2.设置URLConnection的参数和普通的请求属性
3.如果只是发送GET方式请求,使用connet方法建立和远程资源之间的实际连接即可;如果发送POST方式的请求,需要获取URLConnection实例对应的输出流来发送请求参数。
4.远程资源变为可用,程序可以访问远程资的头字段,或通过输入流读取远程资源的数据。
提交数据到服务器端(存在中文乱码):
需求:示范如何向Web站点发送GET请求、POST请求,并从Web站点取的响应。
服务器端
模拟用户登录的Serlvet
public class LoginServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username"); String password = request.getParameter("password"); System.out.println("姓名="+username); System.out.println("密码="+password); if("lisi".equals(username) && "123".equals(password)){ response.getOutputStream().write("success".getBytes()); }else{ response.getOutputStream().write("failed".getBytes()); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
在地址栏中输入:
http://localhost:8080/ServerDemo1/servlet/LoginServlet?username=lisi&password=123
页面返回:
页面返回登录成功的信息:success.查看该页面的源文件也只是个:success
需求:从客户端请求数据到服务端,将服务端的信息返回个服务端。
客户端
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入用户名" android:id="@+id/et_username"/> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入密码" android:id="@+id/et_password"/> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="GET提交方式" android:onClick="doGet"/> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="POST提交方式" android:onClick="doPost"/> </LinearLayout>
工具类:
NetUtil.java
public class NetUtil { private static final String TAG = "NetUtil"; /** * 使用GET的方式登录 * @param username * @param password * @return 登录的状态 */ public static String loginOfGet(String username,String password){ HttpURLConnection conn = null; try { String data = "username="+username+"&password="+password; URL url = new URL("http://10.3.5.154:8080/ServerDemo1/servlet/LoginServlet?"+data); conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET");//GET和POST必须全大写 conn.setConnectTimeout(10000);//连接的超时时间 conn.setReadTimeout(5000);//读数据的超时时间 int responseCode = conn.getResponseCode(); if(responseCode==200){ //访问成功,通过流取的页面的数据信息 InputStream is = conn.getInputStream(); String status = getStringFromInputStream(is); return status; }else{ Log.i(TAG, "访问失败:"+responseCode); } } catch (Exception e) { e.printStackTrace(); } finally{ if(conn!=null){ conn.disconnect();//释放链接 } } return null; } /** * 使用POST提交方式 * @param username * @param password * @return */ public static String loginOfPost(String username, String password) { HttpURLConnection conn = null; try { URL url = new URL("http://10.3.5.154:8080/ServerDemo1/servlet/LoginServlet"); conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET");//GET和POST必须全大写 conn.setConnectTimeout(10000);//连接的超时时间 conn.setReadTimeout(5000);//读数据的超时时间 conn.setDoOutput(true);//必须设置此方法 允许输出 // conn.setRequestProperty("Content-Length", 234);//设置请求消息头 可以设置多个 //post请求的参数 String data = "username="+username+"&password="+password; OutputStream out = conn.getOutputStream(); out.write(data.getBytes()); out.flush(); out.close(); int responseCode = conn.getResponseCode(); if(responseCode==200){ //访问成功,通过流取的页面的数据信息 InputStream is = conn.getInputStream(); String status = getStringFromInputStream(is); return status; }else{ Log.i(TAG, "访问失败:"+responseCode); } } catch (Exception e) { e.printStackTrace(); } finally{ if(conn!=null){ conn.disconnect();//释放链接 } } return null; } /** * 通过字节输入流返回一个字符串信息 * @param is * @return * @throws IOException */ private static String getStringFromInputStream(InputStream is) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len=0; while((len=is.read(buffer))!=-1){ baos.write(buffer, 0, len); } is.close(); String status = baos.toString();// 把流中的数据转换成字符串, 采用的编码是: utf-8 baos.close(); return status; } }
Java代码:
MainActivity.java
public class MainActivity extends Activity { private EditText et_username; private EditText et_password; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); et_username = (EditText) findViewById(R.id.et_username); et_password = (EditText) findViewById(R.id.et_password); } //GET提交方式 public void doGet(View view){ final String username = et_username.getText().toString().trim(); final String password = et_password.getText().toString().trim(); new Thread(new Runnable() { @Override public void run() { //使用GET方式抓取数据 final String status = NetUtil.loginOfGet(username, password); //执行任务在主线程中 runOnUiThread(new Runnable() { @Override public void run() { //就是在主线程中操作 Toast.makeText(MainActivity.this, status, 0).show(); } }); } }).start(); } //POST提交方式 public void doPost(View view){ final String username = et_username.getText().toString().trim(); final String password = et_password.getText().toString().trim(); new Thread(new Runnable() { @Override public void run() { final String status = NetUtil.loginOfPost(username,password); runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this, status, 0).show(); } }); } }).start(); } }
运行效果图:
采用get或者post提交方式
从客户端提交数据到服务器端,将服务器端的信息,返回给了客户端。
但是以上代码存在严重的中文乱码问题:
乱码简单分析:
提交数据到服务器端(解决中文乱码)推荐:
明白了产生乱码的原因,这时候我们分析解决乱码的步骤:
(把握住:保证客户端与服务器端采用的编码必须一致)
1.修改客户端代码:
修改NetUtil.java
截图:
修改的代码:
/** * URLEncoder.encode(String s, String charsetName)对url中的中文参数进行编码,可以解决乱码 */ String data = "username="+URLEncoder.encode(username, "utf-8")+"&password="+URLEncoder.encode(password, "utf-8"); URL url = new URL("http://10.3.5.154:8080/ServerDemo1/servlet/LoginServlet?"+data); conn = (HttpURLConnection) url.openConnection();
2.修改服务器端的代码:
修改LoginServlet.java
截图:
修改的代码:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username");//请求过来的参数,是采用的编码是: iso8859-1 String password = request.getParameter("password"); //采用iso8859-1的编码对姓名进行逆转,转换成字节数组,再使用utf-8编码对数据进行转换,字符串 username = new String(username.getBytes("iso8859-1"), "utf-8"); password = new String(password.getBytes("iso8859-1"), "utf-8"); System.out.println("姓名="+username); System.out.println("密码="+password); if("lisi".equals(username) && "123".equals(password)){ response.getOutputStream().write("登录成功".getBytes("utf-8")); }else{ response.getOutputStream().write("登录失败".getBytes("utf-8")); } }
3.运行结果(成功解决乱码问题):
完整代码(已解决乱码问题):
服务器端:
public class LoginServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username");//请求过来的参数,是采用的编码是: iso8859-1 String password = request.getParameter("password"); //采用iso8859-1的编码对姓名进行逆转,转换成字节数组,再使用utf-8编码对数据进行转换,字符串 username = new String(username.getBytes("iso8859-1"), "utf-8"); password = new String(password.getBytes("iso8859-1"), "utf-8"); System.out.println("姓名="+username); System.out.println("密码="+password); if("lisi".equals(username) && "123".equals(password)){ /** * getBytes默认情况下,使用iso8859-1的编码,但如果发现码表中没有当前字符 * 会使用当前系统下的默认编码gbk; */ response.getOutputStream().write("登录成功".getBytes("utf-8")); }else{ response.getOutputStream().write("登录失败".getBytes("utf-8")); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
客户端代码:
工具类:
public class NetUtil { private static final String TAG = "NetUtil"; /** * 使用GET的方式登录 * @param username * @param password * @return 登录的状态 */ public static String loginOfGet(String username,String password){ HttpURLConnection conn = null; try { /** * URLEncoder.encode(String s, String charsetName)对url中的中文参数进行编码,可以解决乱码 */ String data = "username="+URLEncoder.encode(username, "utf-8")+"&password="+URLEncoder.encode(password, "utf-8"); //get方式,url是直接在后面拼接地址的 URL url = new URL("http://10.3.5.154:8080/ServerDemo1/servlet/LoginServlet?"+data); conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET");//GET和POST必须全大写 conn.setConnectTimeout(10000);//连接的超时时间 conn.setReadTimeout(5000);//读数据的超时时间 int responseCode = conn.getResponseCode(); if(responseCode==200){ //访问成功,通过流取的页面的数据信息 InputStream is = conn.getInputStream(); String status = getStringFromInputStream(is); return status; }else{ Log.i(TAG, "访问失败:"+responseCode); } } catch (Exception e) { e.printStackTrace(); } finally{ if(conn!=null){ conn.disconnect();//释放链接 } } return null; } /** * 使用POST提交方式 * @param username * @param password * @return */ public static String loginOfPost(String username, String password) { HttpURLConnection conn = null; try { //post请求的url地址是以流的方式写过去的 URL url = new URL("http://10.3.5.154:8080/ServerDemo1/servlet/LoginServlet"); conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET");//GET和POST必须全大写 conn.setConnectTimeout(10000);//连接的超时时间 conn.setReadTimeout(5000);//读数据的超时时间 conn.setDoOutput(true);//必须设置此方法 允许输出 // conn.setRequestProperty("Content-Length", 234);//设置请求消息头 可以设置多个 //post请求的参数 String data = "username="+username+"&password="+password; // 获得一个输出流, 用于向服务器写数据, 默认情况下, 系统不允许向服务器输出内容 OutputStream out = conn.getOutputStream(); out.write(data.getBytes()); out.flush(); out.close(); int responseCode = conn.getResponseCode(); if(responseCode==200){ //访问成功,通过流取的页面的数据信息 InputStream is = conn.getInputStream(); String status = getStringFromInputStream(is); return status; }else{ Log.i(TAG, "访问失败:"+responseCode); } } catch (Exception e) { e.printStackTrace(); } finally{ if(conn!=null){ conn.disconnect();//释放链接 } } return null; } /** * 通过字节输入流返回一个字符串信息 * @param is * @return * @throws IOException */ private static String getStringFromInputStream(InputStream is) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len=0; while((len=is.read(buffer))!=-1){ baos.write(buffer, 0, len); } is.close(); String status = baos.toString();// 把流中的数据转换成字符串, 采用的编码是: utf-8 baos.close(); return status; } }
MainActivity.java类没有改变和上面的一样。
时间: 2024-10-08 12:59:43