黎活明8天快速掌握android视频教程--27_网络通信之通过GET和POST方式提交参数给web应用
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>
黎活明8天快速掌握android视频教程--27_网络通信之通过GET和POST方式提交参数给web应用的更多相关文章
- 黎活明8天快速掌握android视频教程--25_网络通信之资讯客户端
1 该项目的主要功能是:后台通过xml或者json格式返回后台的视频资讯,然后Android客户端界面显示出来 首先后台新建立一个java web后台 采用mvc的框架 所以的servlet都放在se ...
- 黎活明8天快速掌握android视频教程--24_网络通信之网页源码查看器
1 该项目的主要功能就是从将后台的html网页在Android的界面上显示出来 后台就是建立一个java web工程在工程尚建立一个html或者jsp文件就可以了,这里主要看Android客户端的程序 ...
- 黎活明8天快速掌握android视频教程--23_网络通信之网络图片查看器
1.首先新建立一个java web项目的工程.使用的是myeclipe开发软件 图片的下载路径是http://192.168.1.103:8080/lihuoming_23/3.png 当前手机和电脑 ...
- 黎活明8天快速掌握android视频教程--22_访问通信录中的联系人和添加联系人
Android系统中联系人的通讯录的contentProvide是一个单独的apk,显示在界面的contact也是一个独立的apk,联系人apk通过contentProvide访问底层的数据库. 现在 ...
- 黎活明8天快速掌握android视频教程--21_监听ContentProvider中数据的变化
采用ContentProvider除了可以让其他应用访问当前的app的数据之外,还有可以实现当app的数据发送变化的时候,通知注册了数据变化通知的调用者 其他所有的代码都和第20讲的一样,不同的地方看 ...
- 黎活明8天快速掌握android视频教程--20_采用ContentProvider对外共享数据
1.内容提供者是让当前的app的数据可以让其他应用访问,其他应该可以通过内容提供者访问当前app的数据库 contentProvider的主要目的是提供一个开发的接口,让其他的应该能够访问当前应用的数 ...
- 黎活明8天快速掌握android视频教程--19_采用ListView实现数据列表显示
1.首先整个程序也是采用mvc的框架 DbOpenHelper 类 package dB; import android.content.Context; import android.databas ...
- 黎活明8天快速掌握android视频教程--17_创建数据库与完成数据添删改查
1.我们首先来看下整个项目 项目也是采用mvc的框架 package dB; import android.content.Context; import android.database.sqlit ...
- 黎活明8天快速掌握android视频教程--16_采用SharedPreferences保存用户偏好设置参数
SharedPreferences保存的数据是xml格式,也是存在数据保存的下面四种权限: 我们来看看 我们来看看具体的业务操作类: /** * 文件名:SharedPrecences.java * ...
随机推荐
- [批处理教程之Shell]001.文本处理
在计算机科学中,Shell俗称壳(用来区别于核),是指“提供使用者使用界面”的软件(命令解析器).它类似于DOS下的command和后来的cmd.exe.它接收用户命令,然后调用相应的应用程序. 同时 ...
- 关于Backus-Naur Form巴克斯诺尔范式和扩展巴克斯范式的知识点和相关词语中英文对照
巴克斯诺尔范式的相关词语中英文对照和知识点 syntax 语法 强调的是编程语言的组形式,例如一个句子中会包含表达式.陈述还有各种单元等等 semantics 语义 强调的是这个编程语言的实际含义,例 ...
- vue-cli4 + TS构建新项目
1. 如果你之前没有安装vue-cli,可以通过如下命令进行安装: npm install -g @vue/cli yarn global add @vue/cli 2. 创建vue项目 vue cr ...
- docker重启提示已存在一个容器的问题处理
一.问题:在vmware虚拟机中测试以docker方式安装的prometheus,当重启虚拟机后,再次运行prometheus的执行文件,提示已有名称为prometheus的容器存在. 二.处理过程 ...
- 从0开始探究vue-双向绑定原理
理解 vue是一个非常优秀的框架,其优秀的双向绑定原理,mvvm模型,组件,路由解析器等,非常的灵活方便,也使开发者能够着重于数据处理,让开发者更清晰的设计自己的业务. 双向绑定,就是数据变化的时候, ...
- Linux (九)服务器环境搭建
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一.行为守则 1.拍摄快照 Linux系统操作非常复杂,搭建开发环境时全部使用命令完成安装过程.而在Li ...
- Java实现 LeetCode 529 扫雷游戏(DFS)
529. 扫雷游戏 让我们一起来玩扫雷游戏! 给定一个代表游戏板的二维字符矩阵. 'M' 代表一个未挖出的地雷,'E' 代表一个未挖出的空方块,'B' 代表没有相邻(上,下,左,右,和所有4个对角线) ...
- Java实现 蓝桥杯VIP 算法提高 排队打水问题
算法提高 排队打水问题 时间限制:1.0s 内存限制:256.0MB 问题描述 有n个人排队到r个水龙头去打水,他们装满水桶的时间t1.t2----tn为整数且各不相等,应如何安排他们的打水顺序才能使 ...
- [转] Ubuntu的apt-get 设置代理的方法
点击阅读原文 新立得软件管理器这种图形化的代理设置很明了,这里介绍下终端命令行的网络代理设置,这样大家就可以通过代理进行apt-get了. 方法一: 如果只是想临时使用http代理,可以在使用apt- ...
- Uint47 calculator【map数组+快速积+各种取余公式】
Uint47 calculator 题目链接(点击) In the distant space, there is a technologically advanced planet. One day ...