版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
【移動(dòng)應(yīng)用開發(fā)技術(shù)】Android中如何使用json實(shí)現(xiàn)服務(wù)器與客戶端數(shù)據(jù)的交互功能
/**
*
查詢遠(yuǎn)程服務(wù)器的工具
*
*/
public
class
QueryUtils
{
//private
static
final
String
TAG
=
"CommonUtils";
private
static
QueryUtils
instance;
private
SharedPreferences
sp;
private
QueryUtils(Context
context){
sp
=
context.getSharedPreferences(Constant.CONFIG,
Context.MODE_PRIVATE);
}
public
static
QueryUtils
getInstance(Context
context){
if
(instance
==
null)
{
synchronized
(QueryUtils.class)
{
if
(instance
==
null)
{
instance
=
new
QueryUtils(context);
}
}
}
return
instance;
}
/**
*
請(qǐng)求服務(wù)器得到返回值
*
*
@param
keyword
*
@return
*
@throws
Exception
*/
public
String
queryServer(String
keyword,
String
reqType,
String
servlet)
throws
Exception
{
String
returnValue
=
null;
//
使用Map封裝請(qǐng)求參數(shù)
Map<String,
String>
map
=
new
HashMap<String,
String>();
map.put("reqType",
reqType);
map.put("localIP",
sp.getString(Constant.NETIP,
""));
if
(!TextUtils.isEmpty(keyword))
{
map.put("keyword",
keyword);
}
String
url
=
"http://"
+
sp.getString(Constant.NETURL,
"")
+
"/ymerp/"
+
servlet;
returnValue
=
postRequest(url,
map);
return
returnValue;
}
}
/**
*
請(qǐng)求遠(yuǎn)程服務(wù)器,并封裝參數(shù)信息
*
@param
url
*
@param
rawParams
*
@return
*
@throws
Exception
*/
public
static
String
postRequest(String
url,
Map<String,
String>
rawParams)
throws
Exception
{
//
創(chuàng)建HttpPost對(duì)象。
HttpPost
post
=
new
HttpPost(url);
//
如果傳遞參數(shù)個(gè)數(shù)比較多的話可以對(duì)傳遞的參數(shù)進(jìn)行封裝
List<NameValuePair>
params
=
new
ArrayList<NameValuePair>();
for
(String
key
:
rawParams.keySet())
{
//
封裝請(qǐng)求參數(shù)
params.add(new
BasicNameValuePair(key,
rawParams.get(key)));
}
//Logger.i(TAG,
"params>"
+
params);
//
設(shè)置請(qǐng)求參數(shù)
post.setEntity(new
UrlEncodedFormEntity(params,
"UTF-8"));
HttpParams
httpParameters
=
new
BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParameters,
3000);
HttpConnectionParams.setSoTimeout(httpParameters,
15000);
DefaultHttpClient
httpClient
=
new
DefaultHttpClient(httpParameters);
//
發(fā)送POST請(qǐng)求
HttpResponse
httpResponse
=
httpClient.execute(post);
//
如果服務(wù)器成功地返回響應(yīng)
String
result
=
null;
if
(httpResponse.getStatusLine().getStatusCode()
==
200)
{
//
獲取服務(wù)器響應(yīng)字符串
result
=
EntityUtils.toString(httpResponse.getEntity(),
"UTF-8");
Logger.i(TAG,
"result>"
+
result);
}
return
result;
}/**
*
使用這個(gè)需要注意,一切都必須與服務(wù)器上的字段一一對(duì)應(yīng),大小寫一致
為了保持一致,所有的實(shí)體都必須小寫,遠(yuǎn)程數(shù)據(jù)庫(kù)上的字段也得小寫
*
*
@author
chen.lin
*
*/
@SuppressWarnings({
"unchecked",
"deprecation"
})
public
class
BaseManager
{
private
static
BaseManager
instance;
private
QueryUtils
queryUtils;
private
SharedPreferences
sp;
private
Context
context;
private
BaseManager(Context
context)
{
this.context
=
context;
queryUtils
=
QueryUtils.getInstance(context);
sp
=
context.getSharedPreferences(Constant.CONFIG,
Context.MODE_PRIVATE);
}
public
static
BaseManager
getInstance(Context
context)
{
if
(instance
==
null){
synchronized
(BaseManager.class)
{
if
(instance
==
null)
{
instance
=
new
BaseManager(context);
}
}
}
return
instance;
}
private
static
Map<String,
List<?>>
LISTCACHE;//
static
{
//
16M,如果不足<16M(模擬器)
//
32M,真機(jī)
if
(MemoryManager.hasAcailMemory())
{
LISTCACHE
=
new
HashMap<String,
List<?>>();
}
else
{
LISTCACHE
=
new
SoftMap<String,
List<?>>();
}
}
private
static
Map<String,
Object>
DOCCACHE;//
static
{
//
16M,如果不足<16M(模擬器)
//
32M,真機(jī)
if
(MemoryManager.hasAcailMemory())
{
DOCCACHE
=
new
HashMap<String,
Object>();
}
else
{
DOCCACHE
=
new
SoftMap<String,
Object>();
}
}
public
<T>
List<T>
queryListByCache(Class<T>
clazz,
String
key,
String
reqType,
String
servlet)
throws
Exception
{
List<T>
list
=
null;
//
一旦創(chuàng)建過,重用
//
判斷是否創(chuàng)建了——曾經(jīng)創(chuàng)建過的界面需要存儲(chǔ)
if
(LISTCACHE
!=
null
&&
LISTCACHE.containsKey(key))
{
//
創(chuàng)建了,重用
list
=
(List<T>)
LISTCACHE.get(key);
if
(list
==
null
||
list.isEmpty())
{
//
有時(shí)候查詢
的數(shù)據(jù)過大,viewcache中放置不了那么多數(shù)據(jù),就會(huì)被垃圾回收站回收,得重新查詢遠(yuǎn)程數(shù)據(jù)庫(kù)
list
=
getListFromServer(clazz,
key,
reqType,
servlet);
LISTCACHE.put(key,
list);
}
}
else
{
//
否則,創(chuàng)建
list
=
getListFromServer(clazz,
key,
reqType,
servlet);
LISTCACHE.put(key,
list);
}
return
list;
}
public
<T>
List<T>
getListFromServer(Class<T>
clazz,
String
keyword,
String
reqType,
String
servlet)
throws
Exception
{
List<T>
list
=
new
ArrayList<T>();
String
returnValue
=
queryUtils.queryServer(keyword,
reqType,
servlet);
if
(!TextUtils.isEmpty(returnValue))
{
Gson
gson
=
new
Gson();
JsonParser
jsonParser
=
new
JsonParser();
JsonArray
jsonArray
=
jsonParser.parse(returnValue).getAsJsonArray();
if
(jsonArray
!=
null)
{
T
t
=
null;
//
循環(huán)記錄數(shù)(多少條)
for
(JsonElement
json
:
jsonArray)
{
if
(json
!=
null)
{
t
=
gson.fromJson(json,
clazz);
list.add(t);
}
}
}
}
return
list;
}
public
<T>
T
queryDocByCache(Class<T>
clazz,
String
key,
String
reqType,
String
servlet)
throws
Exception
{
T
t
=
null;
//
一旦創(chuàng)建過,重用
//
判斷是否創(chuàng)建了——曾經(jīng)創(chuàng)建過的界面需要存儲(chǔ)
if
(DOCCACHE
!=
null
&&
DOCCACHE.containsKey(key))
{
//
創(chuàng)建了,重用
t
=
(T)
DOCCACHE.get(key);
if
(t
==
null)
{
//
有時(shí)候查詢
的數(shù)據(jù)過大,viewcache中放置不了那么多數(shù)據(jù),就會(huì)被垃圾回收站回收,得重新查詢遠(yuǎn)程數(shù)據(jù)庫(kù)
t
=
getDocFromServer(clazz,
key,
reqType,
servlet);
DOCCACHE.put(key,
t);
}
}
else
{
//
否則,創(chuàng)建
t
=
getDocFromServer(clazz,
key,
reqType,
servlet);
DOCCACHE.put(key,
t);
}
return
t;
}
public
<T>
T
getDocFromServer(Class<T>
clazz,
String
keyword,
String
reqType,
String
servlet)
throws
Exception
{
String
returnValue
=
queryUtils.queryServer(keyword,
reqType,
servlet);
if
(!TextUtils.isEmpty(returnValue))
{
Gson
gson
=
new
Gson();
T
t
=
gson.fromJson(returnValue,
clazz);
return
t;
}
return
null;
}
/**
*
查詢判斷客戶是否已經(jīng)添加
*
*
@param
keyword
*
@param
dialog
*
@return
*
@throws
Exception
*/
public
boolean
isAccountExist(String
keyword)
throws
Exception
{
String
returnValue
=
queryUtils.queryServer(keyword,
"queryaccountExist",
"AccountDocumentServlet");
if
(!TextUtils.isEmpty(returnValue)
&&
"true".equals(returnValue.trim()))
{
return
true;
}
return
false;
}
/**
*
更新服務(wù)器上的數(shù)據(jù)
*
@param
context
*
@param
params
*
@param
servlet
*
@return
*
@throws
Exception
*/
public
void
updateServer(final
RequestParams
params,
String
servlet)
{
AsyncHttpClient
client
=
new
AsyncHttpClient();
String
url
=
"http://"
+
sp.getString(Constant.NETURL,
"")
+
"/ymerp/"
+
servlet;
client.post(url,
params,
new
AsyncHttpResponseHandler()
{
@Override
public
void
onSuccess(int
statusCode,
Header[]
headers,
byte[]
responseBody)
{
try
{
String
returnValue
=
new
String(responseBody);
JSONObject
jsonObject
=
new
JSONObject(returnValue);
if
("success".equalsIgnoreCase(jsonObject.getString("result")))
{
if
(params.has("sendread"))
{
Logger.i("update",
"更新成功!");
}else
{
Toast.makeText(context,
"更新成功!",
Toast.LENGTH_SHORT).show();
}
}else
{
if
(params.has("sendread"))
{
Logger.i("update",
"更新失敗!");
}else
{
Toast.makeText(context,
"更新失?。?,
Toast.LENGTH_SHORT).show();
}
}
}
catch
(JSONException
e)
{
e.printStackTrace();
Toast.makeText(context,
"json格式數(shù)據(jù)有誤!",
Toast.LENGTH_SHORT).show();
}
}
@Override
public
void
onFailure(int
statusCode,
Header[]
headers,
byte[]
responseBody,
Throwable
error)
{
Toast.makeText(context,
"網(wǎng)絡(luò)錯(cuò)誤!錯(cuò)誤信息:"
+
error.getMessage(),
Toast.LENGTH_SHORT).show();
}
});
}
}public
class
SearchActivity
extends
CommonActivity
implements
OnClickListener
{
private
BaseManager
mManager;
private
ListView
mListView
;
private
Button
mBtnQuery;
private
QueryAccountAdapter
mAdapter;
@Override
protected
void
onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.search);
//
初始化組件
initView();
//
進(jìn)出動(dòng)畫效果
overridePendingTransition(R.anim.push_bottom_in,
R.anim.push_bottom_out);
}
}
private
void
initView()
{
mManager
=
BaseManager.getInstance(this);
mListView
=
(ListView)
findViewById(R.id.lv_search);
mButton
=
(Button)findViewById(R.id.bt_query);
mButton.setOnClickListener(this);
mAdapter
=
new
QueryAccountAdapter(this,
mAccounts);
mListView.setAdapter(mAdapter);
}
@Override
public
void
onClick(View
v)
{
if(v
==
mBtnQuery){
mAccounts
=
mManager.getListFromServer(Account.class,
query,
"queryAccountByKey",
"QueryServlet");
}
}
}/**
*
客戶信息
*
*
@author
chen.lin
*
@createtime
20150217
*/
public
class
Account
implements
Serializable
{
/**
*
*/
private
static
final
long
serialVersionUID
=
1L;
private
String
id;
private
String
sname;//
客戶名稱
private
String
scode;//
客戶編碼
private
String
contact;//
聯(lián)系人
private
String
idcontact;//
聯(lián)系人id
private
String
emtype;//
客戶分類
private
String
xsly;//
客戶來源
private
String
xsbh;//
線索編號(hào)
private
String
xs;//
線索名稱
private
String
idlead;//
線索id
private
String
leadscode;
private
String
idzh;//
相關(guān)展會(huì)
private
String
srcpath;//
來源途徑
private
String
emindustry;//
行業(yè)
private
String
idarea;
//
行政區(qū)域
private
String
saddress;//
客戶地址
private
String
shdz;//
收貨地址
private
String
cclx;//
乘車路線
private
String
spostcode;//
郵編
private
String
stel;//
手機(jī)
private
String
telcode;//
電話號(hào)碼
private
String
sfax;//
傳真
private
String
semail;//
郵箱
private
String
swebsite;//
站點(diǎn)主頁(yè)
private
String
iddep;//
負(fù)責(zé)人部門
private
String
idowner;//
負(fù)責(zé)人
private
String
created;//
新建時(shí)間
private
String
createdby;//
新建人
private
String
updated;//
編輯時(shí)間
private
String
updatedby;//
編輯人
public
String
getIdcontact()
{
return
idcontact;
}
public
void
setIdcontact(String
idcontact)
{
this.idcontact
=
idcontact;
}
public
String
getContact()
{
return
contact;
}
public
void
setContact(String
contact)
{
this.contact
=
contact;
}
public
String
getIdlead()
{
return
idlead;
}
public
void
setIdlead(String
idlead)
{
this.idlead
=
idlead;
}
public
String
getLeadscode()
{
return
leadscode;
}
public
void
setLeadscode(String
leadscode)
{
this.leadscode
=
leadscode;
}
public
String
getTelcode()
{
return
telcode;
}
public
void
setTelcode(String
telcode)
{
this.telcode
=
telcode;
}
public
String
getId()
{
return
id;
}
public
void
setId(String
id)
{
this.id
=
id;
}
public
String
getSname()
{
return
sname;
}
public
void
setSname(String
sname)
{
this.sname
=
sname;
}
public
String
getScode()
{
return
scode;
}
public
void
setScode(String
scode)
{
this.scode
=
scode;
}
public
String
getEmtype()
{
return
emtype;
}
public
void
setEmtype(String
emtype)
{
this.emtype
=
emtype;
}
public
String
getXsly()
{
return
xsly;
}
public
void
setXsly(String
xsly)
{
this.xsly
=
xsly;
}
public
String
getXsbh()
{
return
xsbh;
}
public
void
setXsbh(String
xsbh)
{
this.xsbh
=
xsbh;
}
public
String
getXs()
{
return
xs;
}
public
void
setXs(String
xs)
{
this.xs
=
xs;
}
public
String
getIdzh()
{
return
idzh;
}
public
void
setIdzh(String
idzh)
{
this.idzh
=
idzh;
}
public
String
getSrcpath()
{
return
srcpath;
}
public
void
setSrcpath(String
srcpath)
{
this.srcpath
=
srcpath;
}
public
String
getEmindustry()
{
return
emindustry;
}
public
void
setEmindustry(String
emindustry)
{
this.emindustry
=
emindustry;
}
public
String
getIdarea()
{
return
idarea;
}
public
void
setIdarea(String
idarea)
{
this.idarea
=
idarea;
}
public
String
getSaddress()
{
return
saddress;
}
public
void
setSaddress(String
saddress)
{
this.saddress
=
saddress;
}
public
String
getShdz()
{
return
shdz;
}
public
void
setShdz(String
shdz)
{
this.shdz
=
shdz;
}
public
String
getCclx()
{
return
cclx;
}
public
void
setCclx(String
cclx)
{
this.cclx
=
cclx;
}
public
String
getSpostcode()
{
return
spostcode;
}
public
void
setSpostcode(String
spostcode)
{
this.spostcode
=
spostcode;
}
public
String
getStel()
{
return
stel;
}
public
void
setStel(String
stel)
{
this.stel
=
stel;
}
public
String
getSfax()
{
return
sfax;
}
public
void
setSfax(String
sfax)
{
this.sfax
=
sfax;
}
public
String
getSemail()
{
return
semail;
}
public
void
setSemail(String
semail)
{
this.semail
=
semail;
}
public
String
getSwebsite()
{
return
swebsite;
}
public
void
setSwebsite(String
swebsite)
{
this.swebsite
=
swebsite;
}
public
String
getIddep()
{
return
iddep;
}
public
void
setIddep(String
iddep)
{
this.iddep
=
iddep;
}
public
String
getIdowner()
{
return
idowner;
}
public
void
setIdowner(String
idowner)
{
this.idowner
=
idowner;
}
public
String
getCreated()
{
return
created;
}
public
void
setCreated(String
created)
{
this.created
=
created;
}
public
String
getCreatedby()
{
return
createdby;
}
public
void
setCreatedby(String
createdby)
{
this.createdby
=
createdby;
}
public
String
getUpdated()
{
return
updated;
}
public
void
setUpdated(String
updated)
{
this.updated
=
updated;
}
public
String
getUpdatedby()
{
return
updatedby;
}
public
void
setUpdatedby(String
updatedby)
{
this.updatedby
=
updatedby;
}
public
Account(String
id,
String
sname,
String
scode,
String
idowner)
{
this.id
=
id;
this.sname
=
sname;
this.scode
=
scode;
this.idowner
=
idowner;
}
public
Account(String
id,
String
sname,
String
scode,
String
emtype,
String
xsly,
String
xsbh,
String
xs,
String
idzh,
String
srcpath,
String
emindustry,
String
idarea,
String
saddress,
String
shdz,
String
cclx,
String
spostcode,
String
stel,
String
sfax,
String
semail,
String
swebsite,
String
iddep,
String
idowner,
String
created,
String
createdby,
String
updated,
String
updatedby)
{
this.id
=
id;
this.sname
=
sname;
this.scode
=
scode;
this.emtype
=
emtype;
this.xsly
=
xsly;
this.xsbh
=
xsbh;
this.xs
=
xs;
this.idzh
=
idzh;
this.srcpath
=
srcpath;
this.emindustry
=
emindustry;
this.idarea
=
idarea;
this.saddress
=
saddress;
this.shdz
=
shdz;
this.cclx
=
cclx;
this.spostcode
=
spostcode;
this.stel
=
stel;
this.sfax
=
sfax;
this.semail
=
semail;
this.swebsite
=
swebsite;
this.iddep
=
iddep;
this.idowner
=
idowner;
this.created
=
created;
this.createdby
=
createdby;
this.updated
=
updated;
this.updatedby
=
updatedby;
}
public
Account()
{
super();
}
}/**
*
*
@author
chen.lin
*/
public
class
QueryServlet
extends
HttpServlet
{
@Override
protected
void
doGet(HttpServletRequest
request,
HttpServletResponse
response)
throws
ServletException,
IOException
{
processRequest(request,
response);
}
@Override
protected
void
doPost(HttpServletRequest
request,
HttpServletResponse
response)
throws
ServletException,
IOException
{
response.setContentType("text/html;charset=utf-8");
response.setCharacterEncoding("UTF-8");
request.setCharacterEncoding("UTF-8");
PrintWriter
out
=
response.getWriter();
String
reqType
=
request.getParameter("reqType");
String
localIP
=
request.getParameter("localIP");
EJBClientLocal.setServerip(localIP);
/**
*
根據(jù)關(guān)鍵字查詢服務(wù)單
*/
if
(reqType
!=
null
&&
"queryAccountByKey".equalsIgnoreCase(reqType))
{
//
根據(jù)查詢關(guān)鍵字查找對(duì)應(yīng)用戶列表
String
keyword
=
request.getParameter("keyword");
System.out.println("keyword
:"
+
keyword);
try
{
List<JSONObject>
list
=
EJBClientLocal.getMetaCRMIntegratedSessionBeanLocal().queryAccountByKey(keyword);
System.out.println("
queryAccountByKey
list:"
+
list);
if
(list
!=
null)
{
JSONArray
json
=
JSONArray.fromObject(list);
//
輸出響應(yīng)
out.println(json.toString());
out.flush();
}
}
catch
(Exception
ex)
{
System.out.println("queryAccountByKey
error:"
+
ex.getMessage());
}
}
}
@Override
public
String
getServletInfo()
{
return
"Short
description";
}
}@Stateless
public
class
MetaCRMIntegratedSessionBean
implements
MetaCRMIntegratedSessionBeanRemote,
MetaCRMIntegratedSessionBeanLocal
{
@Resource
SessionContext
ctx;
@PersistenceContext(unitName
=
"meta_crm_ejbPU")
private
EntityManager
em;
private
DBMSqlServer2005
dbm
=
null;
private
Statement
statement
=
null;
private
PreparedStatement
pStatement
=
null;
SimpleDateFormat
yyyymmdd
=
new
SimpleDateFormat("yyyy-MM-dd");
@AroundInvoke
public
Object
log(InvocationContext
ctx)
throws
Exception
{
String
className
=
ctx.getTarget().getClass().getName();
String
mothodName
=
ctx.getMethod().getName();
String
target
=
className
+
"."
+
mothodName
+
"()";
System.out.println("開始調(diào)用
"
+
target
+
"方法");
long
start
=
System.currentTimeMillis();
try
{
Object
localObject1
=
ceed();
long
time;
return
localObject1;
}
catch
(Exception
e)
{
return
null;
}
finally
{
long
time
=
System.currentTimeMillis()
-
start;
System.out.print(t
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 醫(yī)院消毒供應(yīng)中心工作總結(jié)
- 幼兒園邀請(qǐng)專家入園診斷活動(dòng)方案
- 述職報(bào)告的寫法
- 參觀心得體會(huì)
- 健康博覽會(huì)宣傳策劃方案
- 冬季防滑防溺水安全教育主題班會(huì)
- 納稅計(jì)繳與申報(bào)(第四版)課件9.6 不征稅收入、免稅收入與扣除項(xiàng)目(上)
- 懷化學(xué)院《體育與健康課程標(biāo)準(zhǔn)和教材研究》2023-2024學(xué)年第一學(xué)期期末試卷
- 懷化學(xué)院《器樂演奏》2022-2023學(xué)年第一學(xué)期期末試卷
- 2024個(gè)人加盟合同加盟合同樣本
- 壓力管道材料等級(jí)表
- 三年級(jí)數(shù)學(xué)上冊(cè) 加號(hào)、減號(hào)的來源課外拓素材 冀教版 素材
- 《狼和小羊》PPT課件.ppt
- 神明—EZflame火焰檢測(cè)系統(tǒng)
- 新《固廢法》解讀(專業(yè)版)
- 個(gè)人簡(jiǎn)歷求職簡(jiǎn)歷課件.ppt
- 副神經(jīng)節(jié)瘤圖文.ppt
- 業(yè)務(wù)流程繪制方法IDEF和IDEFPPT課件
- (完整版)垃圾自動(dòng)分揀機(jī)構(gòu)PLC控制畢業(yè)設(shè)計(jì).doc
- 小學(xué)四年級(jí)音樂課程標(biāo)準(zhǔn)
- 我的一次教研經(jīng)歷
評(píng)論
0/150
提交評(píng)論