1.前台页面

  1. <%@ page language="java" pageEncoding="utf-8" isELIgnored="false"%>
  2. <%
  3. String path = request.getContextPath();
  4. %>
  5. <%@ taglib prefix="s" uri="/struts-tags"%>
  6. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  7. <html>
  8. <head>
  9. <title>Basic DataGrid - jQuery EasyUI Demo</title>
  10. <script type="text/javascript" src="easyui/jquery.min.js"></script>
  11. <script type="text/javascript" src="easyui/jquery.easyui.min.js"></script>
  12. <script type="text/javascript" src="easyui/locale/easyui-lang-zh_CN.js"></script>
  13. <link rel="stylesheet" href="easyui/themes/default/easyui.css"
  14. type="text/css" charset="utf-8"></link>
  15. <link rel="stylesheet" href="easyui/themes/icon.css" type="text/css"
  16. charset="utf-8"></link>
  17. </head>
  18. <script type="text/javascript">
  19. function doSearch(value,name){ //用户输入用户名,点击搜素,触发此函数
  20. $("#tt").datagrid({
  21. title:'searchBox',
  22. iconCls:'icon-ok',
  23. width:600,
  24. pageSize:10,
  25. pageList:[5,10,15,20],
  26. nowrap:true,
  27. striped:true,
  28. collapsible:true,
  29. toolbar:"#easyui_toolbar",
  30. url:'searchByUsernameAction.action?searchValue='+value, //触发此action,带上参数searcValue
  31. loadMsg:'数据加载中......',
  32. fitColumns:true,//允许表格自动缩放,以适应父容器
  33. sortName:'userId',
  34. sortOrder:'asc',
  35. remoteSort:false,
  36. columns : [ [ {
  37. field : 'userId',
  38. width : 150,
  39. title : '用户id'
  40. }, {
  41. field : 'name',
  42. width : 150,
  43. title : '用户名'
  44. }, {
  45. field : 'password',
  46. width : 230,
  47. align : 'right',
  48. title : '密码'
  49. } ] ],
  50. pagination : true,
  51. rownumbers : true
  52. })
  53. }
  54. </script>
  55. <body>
  56. <div class="easyui-panel" title="DataGrid with searching box"
  57. icon="icon-save" style="width: 600px; height: 420px;"
  58. collapsible="true" minimizable="true" maximizable=true closable="true">
  59. <div class="easyui-layout" fit="true"  >
  60. <div  id="easyui_toolbar" region="north" border="false"
  61. style="border-bottom: 1px solid #ddd; height: 32px; padding: 2px 5px; background: #fafafa;">
  62. <div style="float: left;">
  63. <a href="#" class="easyui-linkbutton" plain="true" icon="icon-add">新增</a>
  64. </div>
  65. <div class="datagrid-btn-separator"></div>
  66. <div style="float: left;">
  67. <a href="#" class="easyui-linkbutton" plain="true" icon="icon-save">编辑</a>
  68. </div>
  69. <div class="datagrid-btn-separator"></div>
  70. <div style="float: left;">
  71. <a href="#" class="easyui-linkbutton" plain="true"
  72. icon="icon-remove">删除</a>
  73. </div>
  74. <div id="tb" style="float: right;">
  75. <input id="ss" class="easyui-searchbox"
  76. searcher="doSearch" prompt="请输入用户名"
  77. style="width: 130px; vertical-align: middle;"></input>
  78. </div>
  79. </div>
  80. <div region="center" border="false">
  81. <table id="tt"></table>
  82. </div>
  83. </div>
  84. </div>
  85. <script>
  86. $('#tt').datagrid({
  87. title:'searchBox',
  88. iconCls:'icon-ok',
  89. width:600,
  90. pageSize:10,
  91. pageList:[5,10,15,20],
  92. nowrap:true,
  93. striped:true,
  94. collapsible:true,
  95. toolbar:"#easyui_toolbar",
  96. //url : './datagrid/userData.json',
  97. url:'getAllUserAction.action', //搜索前,触发此action请求所有用户信息
  98. loadMsg:'数据加载中......',
  99. fitColumns:true,//允许表格自动缩放,以适应父容器
  100. sortName:'userId',
  101. sortOrder:'asc',
  102. remoteSort:false,
  103. columns : [ [ {
  104. field : 'userId',
  105. width : 150,
  106. title : '用户id'
  107. }, {
  108. field : 'name',
  109. width : 150,
  110. title : '用户名'
  111. }, {
  112. field : 'password',
  113. width : 230,
  114. align : 'right',
  115. title : '密码'
  116. } ] ],
  117. pagination : true,
  118. rownumbers : true
  119. });
  120. </script>
  121. </body>
  122. </html>

2.strust.xml的配置

  1. <package name="easyui" extends="struts-default">
  2. <action name="getAllUserAction" class="com.ssh.action.UserAction"
  3. method="getAllUser">
  4. </action>
  5. <action name="userVerifyAction" class="com.ssh.action.UserAction"
  6. method="verify">
  7. </action>
  8. <action name="delUserAction" class="com.ssh.action.UserAction"
  9. method="delUser">
  10. </action>
  11. <action name="userAddAction" class="com.ssh.action.UserAction"
  12. method="add">
  13. </action>
  14. <action name="searchByUsernameAction" class="com.ssh.action.UserAction"
  15. method="searchByUsername">
  16. </action>
  17. </package>

3.action类

  1. <span style="font-size:12px;">package com.ssh.action;
  2. import java.io.PrintWriter;
  3. import java.util.List;
  4. import java.util.Map;
  5. import javax.servlet.http.HttpServletResponse;
  6. import com.opensymphony.xwork2.ActionContext;
  7. import com.opensymphony.xwork2.ActionSupport;
  8. import com.ssh.bean.TUser;
  9. import com.ssh.service.UserService;
  10. import com.ssh.serviceImp.ViewLogServiceImp;
  11. import net.sf.json.JSONObject;
  12. import org.apache.struts2.ServletActionContext;
  13. @SuppressWarnings("serial")
  14. public class UserAction extends ActionSupport{
  15. // static Logger log = Logger.getLogger(TUser.class);
  16. private JSONObject jsonObj;
  17. private String rows;//
  18. private String page;
  19. private TUser tuser;
  20. private String tableName;
  21. private String fieldName;
  22. private String parameter;
  23. private UserService userService;
  24. private String num;// 删除时循环的次数;
  25. private String ids;//要删除的用户id号
  26. private String searchValue;
  27. //
  28. private ViewLogServiceImp viewLogService;
  29. // 测试用的变量
  30. String userId;
  31. String name;
  32. String password;
  33. //
  34. public void getAllUser() throws Exception {
  35. // log.info("查询所有学生信息!");
  36. System.out.println("getAllUser方法" + "page=" + page + "  rows=" + rows);
  37. List list = userService.getUserList(page, rows);
  38. for (int i = 0; i < list.size(); i++) {
  39. System.out.println(((TUser) list.get(i)).getName() + "*");
  40. }
  41. int size = userService.getUserTotal();
  42. System.out.println("UserAction:Total=" + size + ",page=" + list.size());
  43. try {
  44. toBeJson(list, size);
  45. } catch (Exception e) {
  46. e.printStackTrace();
  47. }
  48. }
  49. /*
  50. * public void add() throws Exception { tuser=new TUser();
  51. * tuser.setUserId(15); tuser.setName("aaaaa"); tuser.setPassword("xxxx");
  52. */
  53. public void add(String userId, String name, String password)
  54. throws Exception {
  55. System.out
  56. .println("add方法:   " + userId + "  " + name + "  " + password);
  57. userService.saveUser(userId, name, password);
  58. }
  59. public void add() throws Exception {
  60. System.out.println("不带参数的add方法:   " + tuser.getUserId() + "  "
  61. + tuser.getName() + "  " + tuser.getPassword());
  62. userService.saveUser((tuser.getUserId()).toString(), tuser.getName(),
  63. tuser.getPassword());
  64. TUser tu=getTUser();
  65. userService.saveRecord(tu, "add user");
  66. }
  67. // 添加时,验证是否已经存在数据库
  68. public void verify() throws Exception {
  69. System.out.println("UserAction:verfiy: " + tableName + " " + fieldName
  70. + "  " + parameter);
  71. String s = userService.queryByUnique(tableName, fieldName, parameter);
  72. // 将验证结果返回到页面,1代表已经存在数据库中,0代表没有
  73. System.out.println("s=" + s);
  74. HttpServletResponse response = ServletActionContext.getResponse();
  75. response.setContentType("text/html;Charset=utf-8");
  76. PrintWriter out = response.getWriter();
  77. out.print(s);
  78. out.flush();
  79. out.close();
  80. }
  81. // 删除
  82. public void delUser(String ids) throws Exception {
  83. System.out.println("delUser方法:   " + ids);
  84. userService.delUser(ids);
  85. TUser tu=getTUser();
  86. userService.saveRecord(tu, "delete user");
  87. }
  88. public void delUser()throws Exception{
  89. System.out.println("不带参数delUser方法: "+ids);
  90. userService.delUser(ids);
  91. }
  92. public void searchByUsername()throws Exception{
  93. List list=userService.searchByUsername(page,rows,searchValue);
  94. int size=userService.getSearchByUsernameTotal(searchValue);
  95. toBeJson(list,size);
  96. }
  97. // 转化WieJson格式
  98. @SuppressWarnings({ "rawtypes", "unchecked" })
  99. public void toBeJson(List list, int total) throws Exception {
  100. try {
  101. HttpServletResponse response = ServletActionContext.getResponse();
  102. // ???????????????
  103. // JSONObject jobj = new JSONObject();
  104. // System.out.println("UserAction.toBeJson()4");
  105. // jobj.accumulate("total", total);// total代表一共有多少数据
  106. // System.out.println("UserAction.toBeJson()1");
  107. // jobj.accumulate("rows", list);// rows是代表显示的页的数据
  108. // System.out.println("UserAction.toBeJson()3");
  109. // response.setCharacterEncoding("utf-8");// 指定为utf-8
  110. // System.out.println("UserAction.toBeJson()2" + jobj.toString());
  111. String sb = "{";
  112. sb += "\"total\":" + total;
  113. sb += ",\"rows\":[";
  114. for (TUser po : (List<TUser>) list) {
  115. sb += "{";
  116. sb += "\"name\":\"" + po.getName();
  117. sb += "\",\"password\":\"" + po.getPassword();
  118. sb += "\",\"userId\":" + po.getUserId();
  119. sb += "},";
  120. }
  121. if (sb.endsWith(","))
  122. sb = sb.substring(0, sb.length() - 1);
  123. sb += "]}";
  124. // System.out.println("UserAction.toBeJson()" + sb);
  125. response.getWriter().write(sb);// 转化为JSON格式
  126. // log.info(sb);
  127. } catch (Exception e) {
  128. e.printStackTrace();
  129. }
  130. }
  131. //根据session来获取当前用户的信息
  132. @SuppressWarnings("rawtypes")
  133. public TUser getTUser()
  134. {
  135. ActionContext ctx=ActionContext.getContext();
  136. Map session=ctx.getSession();
  137. TUser tu=(TUser)session.get("LOGINED_USER");
  138. System.out.println("UserAction中:getTUser方法:"+tu.getUserId()+"  "+tu.getName());
  139. return tu;
  140. }
  141. public JSONObject getJsonObj() {
  142. return jsonObj;
  143. }
  144. public void setJsonObj(JSONObject jsonObj) {
  145. this.jsonObj = jsonObj;
  146. }
  147. public String getRows() {
  148. return rows;
  149. }
  150. public void setRows(String rows) {
  151. this.rows = rows;
  152. }
  153. public String getPage() {
  154. return page;
  155. }
  156. public void setPage(String page) {
  157. this.page = page;
  158. }
  159. public TUser getTuser() {
  160. return tuser;
  161. }
  162. public void setTuser(TUser tuser) {
  163. this.tuser = tuser;
  164. }
  165. public String getTableName() {
  166. return tableName;
  167. }
  168. public void setTableName(String tableName) {
  169. this.tableName = tableName;
  170. }
  171. public String getFieldName() {
  172. return fieldName;
  173. }
  174. public void setFieldName(String fieldName) {
  175. this.fieldName = fieldName;
  176. }
  177. public String getParameter() {
  178. return parameter;
  179. }
  180. public void setParameter(String parameter) {
  181. this.parameter = parameter;
  182. }
  183. public UserService getUserService() {
  184. return userService;
  185. }
  186. public void setUserService(UserService userService) {
  187. this.userService = userService;
  188. }
  189. public String getNum() {
  190. return num;
  191. }
  192. public void setNum(String num) {
  193. this.num = num;
  194. }
  195. public String getIds() {
  196. return ids;
  197. }
  198. public void setIds(String ids) {
  199. this.ids = ids;
  200. }
  201. public String getUserId() {
  202. return userId;
  203. }
  204. public void setUserId(String userId) {
  205. this.userId = userId;
  206. }
  207. public String getName() {
  208. return name;
  209. }
  210. public void setName(String name) {
  211. this.name = name;
  212. }
  213. public String getPassword() {
  214. return password;
  215. }
  216. public void setPassword(String password) {
  217. this.password = password;
  218. }
  219. public ViewLogServiceImp getViewLogService() {
  220. return viewLogService;
  221. }
  222. public void setViewLogService(ViewLogServiceImp viewLogService) {
  223. this.viewLogService = viewLogService;
  224. }
  225. public String getSearchValue() {
  226. return searchValue;
  227. }
  228. public void setSearchValue(String searchValue) {
  229. this.searchValue = searchValue;
  230. }
  231. }</span>

2.实现层,查询数据库

  1. package com.ssh.serviceImp;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import javax.servlet.http.HttpSession;
  5. //import org.hibernate.criterion.DetachedCriteria;
  6. import org.apache.struts2.ServletActionContext;
  7. import org.springframework.orm.hibernate3.HibernateTemplate;
  8. import com.ssh.bean.TAdminLog;
  9. import com.ssh.bean.TUser;
  10. import com.ssh.service.UserService;
  11. public class UserServiceImp implements UserService {
  12. HibernateTemplate ht;
  13. public HibernateTemplate getHt() {
  14. return ht;
  15. }
  16. public void setHt(HibernateTemplate ht) {
  17. this.ht = ht;
  18. }
  19. @SuppressWarnings("unchecked")
  20. @Override
  21. public List<TUser> getTUser(String username, String password) {
  22. // TODO Auto-generated method stub
  23. StringBuffer sql = new StringBuffer("from TUser where name='");
  24. sql.append(username + "' and password='" + password + "'");
  25. return ht.find(sql.toString());
  26. }
  27. //
  28. @SuppressWarnings("rawtypes")
  29. public List getUserList(String page, String rows) {
  30. int currentPage = Integer
  31. .parseInt((page == null) || (page == "0") ? "1" : page);
  32. int pageSize = Integer.parseInt((rows == null) || rows == "0" ? "1"
  33. : rows);
  34. System.out.println("currentPage=" + currentPage + "  pageSize="
  35. + pageSize);
  36. /*
  37. * DetachedCriteria criteria=DetachedCriteria.forClass(TUser.class);
  38. * List list=ht.findByCriteria(criteria, currentPage*pageSize,
  39. * pageSize);
  40. */
  41. StringBuffer sql = new StringBuffer("from TUser where userId>=");
  42. sql.append((currentPage - 1) * pageSize + 1);
  43. sql.append(" and userId <=");
  44. sql.append(currentPage * pageSize);
  45. List list = ht.find(sql.toString());
  46. return list;
  47. }
  48. @SuppressWarnings("rawtypes")
  49. public int getUserTotal() throws Exception {
  50. List list = ht.find("from TUser");
  51. return list.size();
  52. }
  53. // 新增用户信息
  54. public void saveUser(String userId, String name, String password)
  55. throws Exception {
  56. System.out.println("UserServiceImp:" + name);
  57. TUser tuser = new TUser();
  58. tuser.setUserId(Integer.parseInt(userId));
  59. tuser.setName(name);
  60. tuser.setPassword(password);
  61. ht.save(tuser);
  62. HttpSession session = ServletActionContext.getRequest().getSession();
  63. TUser tu = new TUser();
  64. String uid = (String) session.getAttribute("userId");
  65. String na = (String) session.getAttribute("username");
  66. String ps = (String) session.getAttribute("password");
  67. tu.setUserId(Integer.parseInt(uid));
  68. tu.setName(na);
  69. tu.setPassword(ps);
  70. saveRecord(tu, "save user");
  71. }
  72. // 删除用户
  73. @SuppressWarnings("rawtypes")
  74. public void delUser(String ids) throws Exception {
  75. int id = Integer.parseInt(ids);
  76. StringBuffer sql = new StringBuffer(
  77. "delete TUer user where user.userId = ");
  78. sql.append(id);
  79. System.out.println(sql);
  80. // ht.delete(sql);
  81. // TUser tuser = (TUser) (ht.find("from TUser where userId = " + ids));
  82. TUser tuser = new TUser();
  83. List list = ht.find("from TUser where userId = " + ids);
  84. if (list.size() > 0) {
  85. tuser = (TUser) list.get(0);
  86. }
  87. System.out.println("***" + tuser.getName());
  88. ht.delete(tuser);
  89. HttpSession session = ServletActionContext.getRequest().getSession();
  90. TUser tu = new TUser();
  91. String uid = (String) session.getAttribute("userId");
  92. String na = (String) session.getAttribute("username");
  93. String ps = (String) session.getAttribute("password");
  94. tu.setUserId(Integer.parseInt(uid));
  95. tu.setName(na);
  96. tu.setPassword(ps);
  97. System.out.println("delUser:userId:");
  98. System.out.println(uid);
  99. saveRecord(tu, "delUser user");
  100. }
  101. // 判断是否具有唯一性
  102. @SuppressWarnings("rawtypes")
  103. public String queryByUnique(String tableName, String fieldName,
  104. String parameter) throws Exception {
  105. System.out.println("tableName:" + tableName + " fieldName:" + fieldName
  106. + " parameter:" + parameter);
  107. StringBuffer sql = new StringBuffer("from " + tableName + " where "
  108. + fieldName + " = " + parameter);
  109. System.out.println(sql.toString());
  110. List list = null;
  111. try {
  112. list = ht.find(sql.toString());
  113. if (list != null) {
  114. System.out.println("***1" + list.toString());
  115. // System.out.println(((TUser) list.get(0)).getName());
  116. } else {
  117. System.out.println("***2");
  118. }
  119. } catch (Exception e) {
  120. e.printStackTrace();
  121. }
  122. /*
  123. * if (list != null) { //System.out.println(((TUser)
  124. * list.get(0)).getName());
  125. *
  126. * } else { System.out.println("***"); }
  127. */
  128. if (list == null || list.size() != 0) {
  129. return "1";
  130. } else {
  131. return "0";// 代表数据库里没有这条数据;
  132. }
  133. }
  134. @Override
  135. public void saveRecord(TUser tuser, String record) throws Exception {
  136. // TODO Auto-generated method stub
  137. TAdminLog tAdminLog = new TAdminLog(tuser, record);
  138. ht.save(tAdminLog);
  139. }
  140. @Override
  141. public List searchByUsername(String page, String rows, String searchValue)
  142. throws Exception {
  143. // TODO Auto-generated method stub
  144. System.out.println("page="+page);
  145. System.out.println("rows="+rows);
  146. System.out.println("searchValue="+searchValue);
  147. StringBuffer sql = new StringBuffer("from TUser t where t.name ='");
  148. sql.append(searchValue);
  149. sql.append("'");//注意要加单引号
  150. System.out.println("searchByUsername:"+sql);
  151. List list = ht.find(sql.toString());
  152. int currentPage = Integer
  153. .parseInt((page == null) || (page == "0") ? "1" : page);
  154. int currentRows = Integer
  155. .parseInt((rows == null) || (rows == "0") ? "1" : rows);
  156. int number = (currentPage - 1) * currentRows;
  157. List li = new ArrayList();
  158. for (int i = number; i < (number + currentRows)
  159. && i < (list.size()); i++) {
  160. li.add(list.get(i));
  161. }
  162. return li;
  163. }
  164. @Override
  165. public int getSearchByUsernameTotal(String searchValue) throws Exception {
  166. // TODO Auto-generated method stub
  167. StringBuffer sql = new StringBuffer("from TUser t where t.name ='");
  168. sql.append(searchValue);
  169. sql.append("'");
  170. List list = ht.find(sql.toString());
  171. if (list.size() == 0) {
  172. return 0;
  173. } else {
  174. return list.size();
  175. }
  176. }
  177. }

easyui Datagrid+searchbox 实现搜索功能的更多相关文章

  1. JS实现EasyUI ,Datagrid,合并单元格功能

    为了实现datagrid的合并单元格效果,datagrid的数据加载方式肯定是要写在JS文件内部的. 一:在JS内部添加Datagrid数据加载方法如下: $("#id").dat ...

  2. easyui datagrid toolbar 添加搜索框

    最近用到了就研究了下,效果  把列名稍加转换放入menubtton,对于单项搜索来说还是非常方便的 var fields =  $('#tt').datagrid('getColumnFields') ...

  3. easyUI分页实现加搜索功能

    前台页面: js代码: ps:pagination为true时会在table下面加上easyUI的分页. load函数会将查询值传给datagrid并传给后台重新加载. DAO.xml为: 后台代码实 ...

  4. 关于EasyUI datagrid editor combogrid搜索框的实现

    首先需要datagrid editor对combogrid的扩展,这个是别人实现的: $.extend($.fn.datagrid.defaults.editors, { combogrid: { i ...

  5. Easyui DataGrid DateRange Filter 漂亮实用的日期区间段筛选功能

    自定义扩展Jquery easyui datagrid filter组件实现对日期类型区间段的筛选功能.显示效果如一下 是不是非常实用 引用的jquery 组件是 Date Range Picker ...

  6. 第二百一十节,jQuery EasyUI,SearchBox(搜索框)组件

    jQuery EasyUI,SearchBox(搜索框)组件 学习要点: 1.加载方式 2.属性列表 3.方法列表 本节课重点了解 EasyUI 中 SearchBox(搜索框)组件的使用方法,这个组 ...

  7. easyui datagrid client搜索、分页、排序

    easyui datagrid的排序默认是server端排序.能够用sorter实现client排序[2].client分页可用filter实现[3].client搜索相同能够用filter实现. 不 ...

  8. 完美实现保存和加载easyui datagrid自定义调整列宽位置隐藏属性功能

    需求&场景 例表查询是业务系统中使用最多也是最基础功能,但也是调整最平凡,不同的用户对数据的要求也不一样,所以在系统正式使用后,做为开发恨不得坐在业务边上,根据他们的要求进行调整,需要调整最多 ...

  9. EasyUI DataGrid 实现单行/多行编辑功能

    要实现 EasyUI DataGrid 的可编辑很简单,在需要编辑的列添加 editor [编辑器]就可以了. 单行编辑 // 初始化数据列表 function initDatagrid() { $( ...

随机推荐

  1. Python学习笔记——与爬虫相关的网络知识

    1 关于URL URL(Uniform / Universal Resource Locator):统一资源定位符,用于完整地描述Internet上网页和其他资源的地址的一种标识方法 URL是爬虫的入 ...

  2. AP_应付模组在月结的处理

    2014-06-04 Created By BaoXinjian 1. 完成所有交易及检查Interface      (1). Invoice and Credits      (2). Prepa ...

  3. AP_建立银行信息总行、分行、账户(设定)

    2014-06-04 Created By BaoXinjian

  4. mysql 再查询结果的基础上查询(子查询)

    SELECT A.wx_name, A.wx_litpic, B . * FROM ( SELECT uid, COUNT( * ) AS daticishu FROM statements , ) ...

  5. MySQL索引经验

    在数据库表中,使用索引可以大大提高查询速度. 假如我们创建了一个testIndex表:create TABLE testIndex(i_testID INT NOT NULL,vc_Name VARC ...

  6. 【转】sql server存储过程中SELECT 与 SET 对变量赋值的区别

    转自:http://www.cnblogs.com/micheng11/archive/2008/07/08/1237905.html SQL Server 中对已经定义的变量赋值的方式用两种,分别是 ...

  7. 《ZedBoard各种资料网址备份记录》

    转载来自于:http://http//www.eefocus.com/crazybingo/blog/2013-02/289101_ab4c8.html 1. Xilinx FPGA相关连接 1) X ...

  8. MSSQLid清零

    truncate table [cellphone2016].[dbo].[tp_phone_9]

  9. cocos2d-x 父节点和子节点执行不同动作

    Test6::Test6() { CCSprite* sp1 = CCSprite::create(s_pPathSister1); CCSprite* sp11 = CCSprite::create ...

  10. 五、String在Java中是传“引用”

    这个是Java的经典问题.许多类似的问题在stackoverflow被提问,有很多不正确或不完备的答案.如果不想太多你会认为这个问题比较简单.( The question is simple if y ...