1该项目主要实现Android客户端以get的方式或者post的方式向java web服务器提交参数
Android客户端通过get方式或者post方式将参数提交给后台服务器,后台服务器对收到的参数进行规制校验之后,一般把数据都存储在数据库中。
现在 准备向服务器提交下面的两个参数:
1、 key videoTitle :value
2、 key videoTimeLength:value
准备将视频的名称和时间长度提交到后台服务器
java web后台的框架如上图所示
1 客户端向服务器提交参数,就会存在中文乱码的问题
向前面23 、24、55视频中讲解的中的服务器向客户端返回字符串、返回xml数据、返回json数据,客户端的编码方式都必须和服务器jsp页面中的编码方式一样,否则客户端显示的时候客户端会出现乱码
同理:客户端向服务器提交参数的时候,服务器的获得的字符串的编码方式必须和客户端的编码方式一样,否则服务器获得参数就会存在乱码问题。
客户端向服务器提交中文参数:解决乱码问题可以有下面的方式进行解决:
1、客户端指定上传参数的编码方式:
可以使用URLEncoder类指定客户端的编码方式
2、服务器按照客户端指定的编码方式编码
这里需要注意的是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
1、 该类的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 子类除了可以重写父类的方法之外,当然可以增加新的函数实现新的功能,所以本质上继承的主要目的是修改父类的功能和实现父类功能的扩展。
相当的经典。
3、 将封装之后的request对象wrapper传递给servlet,servlet本身获得wrapper对象就是一个封装的request对象,servlet调用wrapper对象的getPramas()获得的参数就是解决了中文乱码的。
4、 本质上就是过滤器对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);
}
}
我们来分析下代码:
1、第一MyRequestWapper必须继承HttpServletRequestWrapper;
2、HttpServletRequestWrapper类也是对request类的封装类,实现了request对象的所有操作方法;
3、MyRequestWapper类的作用是对request对象的封装,所有构造函数中需要传人被封装的request对象,将request对象传输给父类HttpServletRequestWrapper使用super(request)就是传递给父类HttpServletRequestWrapper;
所有通过构造函数传递进来的request对象有两个作用:
(1)使用super(request)就是传递给父类HttpServletRequestWrapper,HttpServletRequestWrapper实现对request对象中函数的封装处理;
(2)request传递给MyRequestWapper调用,使用正确的编码对getParameter进行处理
4、HttpServletRequestWrapper对象实现了request对象的所有方法,当然也实现了request的getParameter(),现在子类MyRequestWapper要对HttpServletRequestWrapper父类的getParameter()方法进行重写使用正确的字符串编码。在外面调用者调用的时候调用的是子类MyRequestWapper重写的方法getParameter,而不是父类HttpServletRequestWrapper的方法getParameter。
上面就是继承的作用:
1、子类除了可以重写父类的方法之外修改原来的功能入上面的getParameter;
2、子类可以增加新的函数实现新的功能,实现父类功能的扩展。
接下来看看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>