1該項目主要實現Android客戶端以get的方式或者post的方式向java web服務器提交參數java
Android客戶端經過get方式或者post方式將參數提交給後臺服務器,後臺服務器對收到的參數進行規制校驗以後,通常把數據都存儲在數據庫中。android
如今 準備向服務器提交下面的兩個參數:web
一、 key videoTitle :value數據庫
二、 key videoTimeLength:valuejson
準備將視頻的名稱和時間長度提交到後臺服務器瀏覽器
java web後臺的框架如上圖所示服務器
1 客戶端向服務器提交參數,就會存在中文亂碼的問題網絡
向前面23 、2四、55視頻中講解的中的服務器向客戶端返回字符串、返回xml數據、返回json數據,客戶端的編碼方式都必須和服務器jsp頁面中的編碼方式同樣,不然客戶端顯示的時候客戶端會出現亂碼架構
同理:客戶端向服務器提交參數的時候,服務器的得到的字符串的編碼方式必須和客戶端的編碼方式同樣,不然服務器得到參數就會存在亂碼問題。mvc
客戶端向服務器提交中文參數:解決亂碼問題能夠有下面的方式進行解決:
一、客戶端指定上傳參數的編碼方式:
可使用URLEncoder類指定客戶端的編碼方式
二、服務器按照客戶端指定的編碼方式編碼
這裏須要注意的是tomacat服務器運行默認採用iso—99859編解碼。例如:客戶端採用了utf-8編解碼,在網絡中傳輸的是utf-8解碼的二進制數據,到了java web後臺,若是不指定對應編碼方式,tomacat中的servlet
會按照將字節流數據按照iso—99859編碼成字符串,原本應該按照utf-8編碼的,卻按照iso—99859編碼,這樣就會引發中文亂碼。
服務器這裏的處理亂碼的方式有下面的兩種方式:
(1)服務器將得到字符串按照iso—99859解碼得到網絡中傳輸的字節流數據,而後將字節流數據按照正確的utf-8格式編碼
Byte[] bytes =Title.getbytes(「iso8859-1」)就是得到原始的網絡中傳輸的字節流
而後new String(bytes,」utf-8」)而後將字節流按照正確的方式編碼就能夠了
上面這種方式對post提交和get提交都有效。對應post提交還可使用
request.setCharacterEncoding("utf-8");這種方式只能post的提交方式有效,對get的方式無效
若是工程項目中存在不少servlet,每個servlet都這樣處理,工做量會不少,爲了減小工做量可使用java web中的Filter進行處理中文的亂碼問題
創建一個filter該filter對全部的request的url路徑都進行過濾處理/*表示全部的請求路徑
Myelipse如何建立Filter
右鍵,New->other->顯示所有(記得勾選下邊的show all wizards),就再到查找中輸入filter就找到啦.
1 、該過濾類繼承Filter
一、 該類的URL設置爲/*
咱們來看下EncodingFilter
package com.videos.utils;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
/**
* Servlet Filter implementation class EncodingFilter
*/
@WebFilter("/*")
public class EncodingFilter implements Filter {
/**
* @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//瀏覽器傳遞過來的request進行封裝,封裝以後的請求對象是MyRequestWapper,該對象對
//getParameter 進行了正確的封裝,ShowServlet得到request對象就是封裝以後的requestWapper對象
MyRequestWapper requestWapper = new MyRequestWapper((HttpServletRequest)request); chain.doFilter(requestWapper, response);
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
}
咱們來說下思路:tomacat收到客戶端的任何的request請求的時候,會將請求首先轉交到
EncodingFilter 這個過濾器處理,會調用doFilter方法,在doFliter函數中,咱們對原始的請求的request對象進行封裝處理,對request對象中的getParameter()方法採用正確的編碼方式。requestWapper就是封裝以後的request對象,而後將requestWapper傳遞給servlet,sevlet中調用的
getParameter()得到的參數就是通過編碼處理的參數。
咱們來看看MyRequestWapper
package com.videos.utils;
import java.io.UnsupportedEncodingException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
/*
* 這個類就是繼承的經典例子:HttpServletRequestWrapper首先是request對象的包裝類,實現了request對象的全部功能
* ,既然是request的封裝類,內部確定必須有一個等待包裝的request對象,全部MyRequestWapper對象繼承
* HttpServletRequestWrapper咱們在構造函數中必須傳遞進來一個request對象。將request對象傳輸給父類HttpServletRequestWrapper使用super(request)就是傳遞給父類。
2 HttpServletRequestWrapper對象實現了request對象的全部方法,固然也實現了父類的getParameter(),
如今子類要對父類的getParameter()方法進行重寫。在外面調用者調用的時候調用的是子類重寫的方法,而不是父類的方法。
3 子類除了能夠重寫父類的方法以外,固然能夠增長新的函數實現新的功能,因此本質上繼承的主要目的是修改父類的功能和實現父類功能的擴展。
至關的經典。
三、 將封裝以後的request對象wrapper傳遞給servlet,servlet自己得到wrapper對象就是一個封裝的request對象,servlet調用wrapper對象的getPramas()得到的參數就是解決了中文亂碼的。
四、 本質上就是過濾器對request對象進行封裝處理,對getPatamets()函數進行重寫,在重寫的函數體裏面採用正常的編碼。將封裝以後的wrapper對象傳遞給servlet對象使用,servlet對象調用的getPatamets()已經對亂碼進行了處理,wrapper對象本質上就是servlet對象。
* */
public class MyRequestWapper extends HttpServletRequestWrapper{
private HttpServletRequest request;
public MyRequestWapper(HttpServletRequest request) {
super(request);
// TODO Auto-generated constructor stub
this.request = request;
}
@Override
public String getParameter(String name) {
// TODO Auto-generated method stub
String value = request.getParameter(name);
if(value != null){
//對請求的參數採用正確的編碼方式進行編碼
try {
value = new String(value.getBytes("iso8859-1"),"utf-8");
return value;
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return super.getParameter(name);
}
}
咱們來分析下代碼:
一、第一MyRequestWapper必須繼承HttpServletRequestWrapper;
二、HttpServletRequestWrapper類也是對request類的封裝類,實現了request對象的全部操做方法;
三、MyRequestWapper類的做用是對request對象的封裝,全部構造函數中須要傳人被封裝的request對象,將request對象傳輸給父類HttpServletRequestWrapper使用super(request)就是傳遞給父類HttpServletRequestWrapper;
全部經過構造函數傳遞進來的request對象有兩個做用:
(1)使用super(request)就是傳遞給父類HttpServletRequestWrapper,HttpServletRequestWrapper實現對request對象中函數的封裝處理;
(2)request傳遞給MyRequestWapper調用,使用正確的編碼對getParameter進行處理
四、HttpServletRequestWrapper對象實現了request對象的全部方法,固然也實現了request的getParameter(),如今子類MyRequestWapper要對HttpServletRequestWrapper父類的getParameter()方法進行重寫使用正確的字符串編碼。在外面調用者調用的時候調用的是子類MyRequestWapper重寫的方法getParameter,而不是父類HttpServletRequestWrapper的方法getParameter。
上面就是繼承的做用:
一、子類除了能夠重寫父類的方法以外修改原來的功能入上面的getParameter;
二、子類能夠增長新的函數實現新的功能,實現父類功能的擴展。
接下來看看servlet的處理,這裏沒有就簡單的將收到的參數打印到控制檯上面,沒有保存到數據庫中:
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class ShowServlet */ @WebServlet("/ShowServlet") public class ShowServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub String title = request.getParameter("title"); String timeLength = request.getParameter("timeLength"); System.out.println(title); System.out.println(timeLength); //在實際的開發過程當中,這裏獲得參數以後,對參數進行校驗,經過業務類操做接口將數據保存到數據庫中 } }
Android客戶端的代碼:
客戶端框架也是採用mvc的架構:
VideoService業務類:
package application.weiyuan.com.lihuoming_27.bussiness; import android.util.Log; import java.io.IOException; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; import java.util.Map; /** * Created by Administrator on 2017/4/19. */ public class VideoService { //採用get的方式提交參數 //http://localhost:8080/lihuoming_27/ShowServlet?title=中國&timeLenth=100 public static boolean submitByGet(String url, Map<String,String> params) throws IOException { //對參數進行封裝 StringBuilder builder = new StringBuilder(url); builder.append("?"); //對params參數進行遍歷 for(Map.Entry<String,String> entry: params.entrySet()){ builder.append(entry.getKey()); builder.append("="); builder.append(URLEncoder.encode(entry.getValue(),"utf-8"));//對值進行URL中文編碼 builder.append("&"); } //把提交最好的一個"&"刪除掉 builder.deleteCharAt(builder.length()-1); URL newURL = new URL(builder.toString()); HttpURLConnection connection = (HttpURLConnection)newURL.openConnection(); connection.setRequestMethod("GET");//必須是大寫 connection.setConnectTimeout(5000); connection.connect(); if(connection.getResponseCode() == 200){ Log.d("123456","get方式提交參數成功"); return true; } return false; } //採用post的方式提交參數 //http://localhost:8080/lihuoming_27/ShowServlet?title=中國&timeLenth=100 public static boolean submitByPost(String url, Map<String,String> params) throws IOException { //對參數進行封裝 StringBuilder builder = new StringBuilder(); //對params參數進行遍歷 for(Map.Entry<String,String> entry: params.entrySet()){ builder.append(entry.getKey()); builder.append("="); builder.append(URLEncoder.encode(entry.getValue(),"utf-8")); builder.append("&"); } //把提交最好的一個"&"刪除掉 builder.deleteCharAt(builder.length()-1); URL newURL = new URL(url); HttpURLConnection connection = (HttpURLConnection)newURL.openConnection(); connection.setRequestMethod("POST");//必須是大寫 connection.setConnectTimeout(5000); connection.setDoOutput(true); //必須是true,運行向外輸出數據,在消息體中提交參數 // 設置請求頭的字段 connection.setRequestProperty("Content-Length", String.valueOf(builder.toString().length())); //內容的長度。該字段屬性值必須有 connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");//內容提交的方式form是表單的形式,urlencoded表示以URL編碼的方式 //post的提交必須轉換成字節的形式,默認是UTF-8的形式 byte[] data = builder.toString().getBytes(); OutputStream outputStream = connection.getOutputStream(); outputStream.write(data); connection.connect(); if(connection.getResponseCode() == 200){ Log.d("123456","get方式提交參數成功"); return true; } return false; } }
咱們來看看activity
package application.weiyuan.com.lihuoming_27; import android.app.Activity; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.text.TextUtils; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import application.weiyuan.com.lihuoming_27.bussiness.VideoService; public class MainActivity extends Activity { private Button btn_main_post; private Button btn_main_get; private EditText et_main_length; private EditText et_main_title; private ExecutorService executorService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initListener(); } private void initListener() { btn_main_get.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { executorService = Executors.newCachedThreadPool(); executorService.execute(new Runnable() { @Override public void run() { String title = et_main_title.getText().toString(); String timeLength = et_main_length.getText().toString(); if(TextUtils.isEmpty(timeLength) || TextUtils.isEmpty(title)){ runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this,"標題時間長度不爲空",Toast.LENGTH_LONG).show(); return; } }); } String url = "http://10.12.8.13:8080/lihuoming_27/ShowServlet"; Map<String,String> map = new HashMap<String, String>(); map.put("title",title); map.put("timeLength",timeLength); try { boolean flag = VideoService.submitByGet(url, map); if(flag){ runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this,"Get提交參數成功",Toast.LENGTH_LONG).show(); return; } }); } } catch (final IOException e) { e.printStackTrace(); runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this,"Get提交參數失敗"+e.toString(),Toast.LENGTH_LONG).show(); return; } }); } } }); } }); btn_main_post.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { executorService = Executors.newCachedThreadPool(); executorService.execute(new Runnable() { @Override public void run() { String title = et_main_title.getText().toString(); String timeLength = et_main_length.getText().toString(); if(TextUtils.isEmpty(timeLength) || TextUtils.isEmpty(title)){ runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this,"標題時間長度不爲空",Toast.LENGTH_LONG).show(); return; } }); } String url = "http://10.12.8.13:8080/lihuoming_27/ShowServlet"; Map<String,String> map = new HashMap<String, String>(); map.put("title",title); map.put("timeLength",timeLength); try { boolean flag = VideoService.submitByPost(url, map); if(flag){ runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this,"post提交參數成功",Toast.LENGTH_LONG).show(); return; } }); } } catch (final IOException e) { e.printStackTrace(); runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this,"post提交參數失敗"+e.toString(),Toast.LENGTH_LONG).show(); return; } }); } } }); } }); } private void initView() { et_main_length = (EditText) findViewById(R.id.et_main_length); et_main_title = (EditText) findViewById(R.id.et_main_title); btn_main_get = (Button) findViewById(R.id.btn_main_get); btn_main_post = (Button) findViewById(R.id.btn_main_post); } }
咱們來看看xml文件
<?xml version="1.0" encoding="utf-8"?> <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" tools:context="application.weiyuan.com.lihuoming_27.MainActivity"> <TextView android:textSize="25sp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="視頻名稱" /> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="25sp" android:id="@+id/et_main_title"/> <TextView android:textSize="25sp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="視頻長度" /> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="25sp" android:id="@+id/et_main_length"/> <Button android:textSize="25sp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="get方式提交" android:id="@+id/btn_main_get"/> <Button android:textSize="25sp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="post方式提交" android:id="@+id/btn_main_post"/> </LinearLayout>