一、搭建简单的web服务器

首先简单看一下web工程目录及其包的构建:

导入jar包

业务层接口:BussinessService.java
package com.xbmu.service;import java.util.List;
import com.xbmu.bean.Bid;
import com.xbmu.bean.Item;
import com.xbmu.bean.Kind;
import com.xbmu.business.BidBean;
import com.xbmu.business.ItemBean;
import com.xbmu.business.KindBean;
import com.xbmu.exception.AuctionException;
/*** 业务层接口(主要声明一些主要的功能)* @author Administrator**/
public interface BussinessService{/*** 根据赢取者查询物品* @param winerId 赢取者的ID* @return 赢取者获得的全部物品*/List<ItemBean> getItemByWiner(Integer winerId)throws AuctionException;/*** 查询流拍的全部物品* @return 全部流拍物品*/List<ItemBean> getFailItems()throws AuctionException;/*** 根据用户名,密码验证登录是否成功* @param username 登录的用户名* @param pass 登录的密码* @return 登录成功返回用户ID,否则返回-1*/int validLogin(String username , String pass)throws AuctionException;/*** 查询用户的全部出价* @param userId 竞价用户的ID* @return 用户的全部出价*/List<BidBean> getBidByUser(Integer userId)throws AuctionException;/*** 根据用户查找目前仍在拍卖中的全部物品* @param userId 所属者的ID* @return 属于当前用户的、处于拍卖中的全部物品。*/List<ItemBean> getItemsByOwner(Integer userId)throws AuctionException;/*** 查询全部种类* @return 系统中全部全部种类*/List<KindBean> getAllKind() throws AuctionException;/*** 添加物品* @param item 新增的物品* @param avail 有效天数* @param kindId 物品种类ID* @param userId 添加者的ID* @return 新增物品的主键*/int addItem(Item item, int avail , int kindId , Integer userId)throws AuctionException;/*** 添加种类* @param kind 新增的种类* @return 新增种类的主键*/int addKind(Kind kind) throws AuctionException;/*** 根据产品分类,获取处于拍卖中的全部物品* @param kindId 种类id;* @return 该类的全部产品*/List<ItemBean> getItemsByKind(int kindId) throws AuctionException;/*** 根据种类id获取种类名* @param kindId 种类id;* @return 该种类的名称*/String getKind(int kindId) throws AuctionException;/*** 根据物品id,获取物品* @param itemId 物品id;* @return 指定id对应的物品*/ItemBean getItem(int itemId) throws AuctionException;/*** 增加新的竞价,并对竞价用户发邮件通知* @param itemId 物品id;* @param bid 竞价* @param userId 竞价用户的ID* @return 返回新增竞价记录的ID*/int addBid(int itemId , Bid bid ,Integer userId)throws AuctionException;/*** 根据时间来修改物品的赢取者*/void updateWiner()throws AuctionException;
}

完成登录功能模块:

BussinessServiceImpl.java
package com.xbmu.service.impl;import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;import com.xbmu.bean.Bid;
import com.xbmu.bean.Item;
import com.xbmu.bean.Kind;
import com.xbmu.bean.User;
import com.xbmu.business.BidBean;
import com.xbmu.business.ItemBean;
import com.xbmu.business.KindBean;
import com.xbmu.dao.AuctionUserDao;
import com.xbmu.dao.ItemDao;
import com.xbmu.dao.impl.AuctionUserDaoImpl;
import com.xbmu.dao.impl.ItemDaoImpl;
import com.xbmu.exception.AuctionException;
import com.xbmu.service.BussinessService;public class BussinessServiceImpl implements BussinessService {//---------------------用户----------------------------private AuctionUserDao userDao = new AuctionUserDaoImpl();/*** 根据用户名,密码验证登录是否成功* @param username 登录的用户名* @param pass 登录的密码* @return 登录成功返回用户ID,否则返回-1*/public int validLogin(String username, String pass) throws AuctionException {User user = userDao.findUserByNameAndPass(username, pass);if(user!=null){return user.getUser_id();}return -1;}//...
}

AuctionUserDao.java

package com.xbmu.dao;import com.xbmu.bean.User;/*** 数据访问层,用户接口* @author Administrator**/
public interface AuctionUserDao {/*** 验证用户登录* @param username 用户名* @param pass 用户密码* @return 验证成功,返回一个用户;否则返回null*/User findUserByNameAndPass(String username, String pass);
}

AuctionUserDaoImpl.java

package com.xbmu.dao.impl;import java.sql.SQLException;
import java.util.List;import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;import com.xbmu.bean.User;
import com.xbmu.dao.AuctionUserDao;
import com.xbmu.util.DBCPUtil;public class AuctionUserDaoImpl implements AuctionUserDao {private QueryRunner qr = new QueryRunner(DBCPUtil.getDataSource());public User findUserByNameAndPass(String username, String pass) {String sql = "select * from auction_user where username=? and userpass=?";try {List<User> userList = qr.query(sql, new BeanListHandler<User>(User.class), username,pass);if (userList.size() == 1){return (User)userList.get(0);}return null;} catch (SQLException e) {throw new RuntimeException(e);}}}

LoginServlet.java

package com.xbmu.web.controller;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;
import org.json.JSONException;
import org.json.JSONObject;
import com.xbmu.service.BussinessService;
import com.xbmu.service.impl.BussinessServiceImpl;/*** Servlet3.0以后出现了注解。因此Servlet配置方式就有了两种: * 1、在web.xml文件中配置。* 2、通过注解配置。*      比如:@WebServlet(urlPatterns="/android/login.jsp")配置后,客户端就可以通过访问此路径访问该servlet*/
@WebServlet(urlPatterns = "/android/login.jsp")
public class LoginServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {//获取模式请求参数。android:表示客户端请求地址,web:表示后台请求地址String mode = request.getParameter("mode");if("android".equals(mode)){Integer userId = validateLogin(request);try {JSONObject jsonObject = new JSONObject();//把验证的userId封装成JSONObjectjsonObject.put("userId", userId);//输出响应response.getWriter().println(jsonObject.toString());} catch (JSONException e) {e.printStackTrace();}}else if("web".equals(mode)){Integer userId = validateLogin(request);//转发到首页request.getRequestDispatcher("/manage/index.jsp").forward(request, response);}}/*** 验证用户登录* @param request* @return 登录成功,返回用户id*/private Integer validateLogin(HttpServletRequest request) {String username = request.getParameter("username");String password = request.getParameter("password");//获取业务逻辑对象BussinessService service = new BussinessServiceImpl();//验证用户登录Integer userId = service.validLogin(username, password);if (userId > 0) {//将用户ID放入HTTP session中,方便以后程序跟踪用户的登录状态request.getSession(true).setAttribute("userId", userId);}return userId;}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}}
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登录页面</title>
</head>
<body><div align="center"><h2>欢迎您,使用电子拍卖系统</h2><form action="${pageContext.request.contextPath}/servlet/LoginServlet?mode=web" method="post">用户账号:<input type="text" name="username" /><br/> 用户密码:<input type="password" name="password" /><br/> <input type="submit" value="登录" /></form></div>
</body>
</html>

请求地址:
服务端:登录界面:http://localhost:8080/AuctionServer/manage/login.jsp  登录表单action="http://localhost:8080/AuctionServer/servlet/LoginServlet?mode=web"
客户端:登录访问地址:http://localhost:8080/AuctionServer/android/login.jsp?mode=android(http://localhost:8080/AuctionServer/servlet/LoginServlet?mode=android)

二、客户端开发:

搭建开发环境,创建项目:

一、登录模块:

登录流程图:

FutureTask类介绍:

FutureTask是一种可以取消的异步的计算任务。它的计算是通过Callable实现的,它等价于可以携带结果的Runnable,并且有三个状态:等待、运行和完成。
完成包括所有计算以任意的方式结束,包括正常结束、取消和异常。
Future有个get方法而获取结果只有在计算完成时获取,否则会一直阻塞直到任务转入完成状态,然后会返回结果或者抛出异常。
FutureTask有下面几个重要的方法:
1.get()
阻塞一直等待执行完成拿到结果
2.get(int timeout, TimeUnit timeUnit)
阻塞一直等待执行完成拿到结果,如果在超时时间内,没有拿到抛出异常
3.isCancelled()
是否被取消
4.isDone()
是否已经完成
5.cancel(boolean mayInterruptIfRunning)
试图取消正在执行的任务
访问网络的工具类HttpUtil.java
package com.xbmu.auction.util;import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
/*** 访问网络的工具类,采用了Apache 下的HttpClient类* @author Administrator**/
public class HttpUtil
{// 创建HttpClient对象public static HttpClient httpClient = new DefaultHttpClient();public static final String BASE_URL ="http://10.0.2.2:8080/AuctionServer/android/";/**** @param url 发送请求的URL* @return 服务器响应字符串* @throws Exception*/public static String getRequest(final String url)throws Exception{FutureTask<String> task = new FutureTask<String>(new Callable<String>(){@Overridepublic String call() throws Exception{// 创建HttpGet对象。HttpGet get = new HttpGet(url);// 发送GET请求HttpResponse httpResponse = httpClient.execute(get);// 如果服务器成功地返回响应if (httpResponse.getStatusLine().getStatusCode() == 200){// 获取服务器响应字符串String result = EntityUtils.toString(httpResponse.getEntity());return result;}return null;}});new Thread(task).start();return task.get();}/*** @param url 发送请求的URL* @param params 请求参数* @return 服务器响应字符串* @throws Exception*/public static String postRequest(final String url, final Map<String ,String> rawParams)throws Exception{FutureTask<String> task = new FutureTask<String>(new Callable<String>(){@Overridepublic String call() throws Exception{// 创建HttpPost对象。HttpPost post = new HttpPost(url);// 如果传递参数个数比较多的话可以对传递的参数进行封装List<NameValuePair> params = new ArrayList<NameValuePair>();for(String key : rawParams.keySet()){//封装请求参数params.add(new BasicNameValuePair(key , rawParams.get(key)));}// 设置请求参数post.setEntity(new UrlEncodedFormEntity(params, "utf-8"));// 发送POST请求HttpResponse httpResponse = httpClient.execute(post);// 如果服务器成功地返回响应if (httpResponse.getStatusLine().getStatusCode() == 200){// 获取服务器响应字符串String result = EntityUtils.toString(httpResponse.getEntity());return result;}return null;}});new Thread(task).start();return task.get();}
}

LoginActivity.java

package com.xbmu.auction;import java.util.HashMap;
import java.util.Map;
import org.json.JSONObject;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import com.xbmu.auction.util.DialogUtil;
import com.xbmu.auction.util.HttpUtil;
/*** 登录界面的Activity* @author Administrator**/
public class LoginActivity extends Activity {private EditText etUser;private EditText etPwd;private Button btnLogin;private Button btnCancel;private String username;private String password;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_login);etUser = (EditText) findViewById(R.id.et_user);etPwd = (EditText) findViewById(R.id.et_pwd);btnLogin = (Button) findViewById(R.id.btn_Login);btnCancel = (Button) findViewById(R.id.btn_Cancel);btnLogin.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {//1.校验用户信息if(validate()){//2.如果信息正确,登录应用if(loginPro()){//3.登录成功,启动主ActivityIntent intent = new Intent(LoginActivity.this, AuctionClientActivity.class);startActivity(intent);//结束该Activityfinish();}else{DialogUtil.showDialog(LoginActivity.this, "用户名或者密码错误,请重新输入!", false);}}}});}/**用于登录信息验证成功后,登录程序*/protected boolean loginPro() {try {JSONObject jsonObject = query(username,password);//如果userId > 0if(jsonObject.getInt("userId") > 0){return true;}} catch (Exception e) {DialogUtil.showDialog(this, "服务器响应异常,请稍后再试!", false);e.printStackTrace();}return false;}/*** 发送请求的方法* @param username* @param password* @return* @throws Exception */private JSONObject query(String username, String password) throws Exception {//使用Map封装请求参数Map<String, String> map = new HashMap<String, String>();map.put("username", username);map.put("password", password);//发送请求的URLString url = HttpUtil.BASE_URL+"login.jsp"+"?mode=android";System.out.println(HttpUtil.postRequest(url, map));//发送请求return new JSONObject(HttpUtil.postRequest(url, map));}/**对用户输入的用户名、密码进行校验*/protected boolean validate() {username = etUser.getText().toString().trim();password = etPwd.getText().toString().trim();if(TextUtils.isEmpty(username)){DialogUtil.showDialog(this, "用户账号是必填项", false);return false;}if(TextUtils.isEmpty(password)){DialogUtil.showDialog(this, "用户密码是必填项", false);return false;}return true;}
}
登录界面使用了表格布局,我们这里简单介绍下表格布局的常用属性:
android:shrinkColumns:设置允许被收缩的列的列序号。多个序列号之间用逗号隔开。
android:stretchColumns:设置允许被拉伸的列的列序号。多个序列号之间用逗号隔开。
android:collapseColumns:设置需要被隐藏的列的列序号。多个序列号之间用逗号隔开。

activity_login.xml

<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="300dp"android:layout_height="match_parent"android:layout_gravity="center_horizontal"android:stretchColumns="1"><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:contentDescription="@string/hello"android:scaleType="fitCenter"android:src="@drawable/logo" /><TextViewandroid:id="@+id/TextView"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:padding="@dimen/title_padding"android:text="@string/welcome"android:textSize="@dimen/label_font_size" /><!-- 输入用户名的行 --><TableRow><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/user_name"android:textSize="@dimen/label_font_size" /><EditTextandroid:id="@+id/et_user"android:layout_width="match_parent"android:layout_height="wrap_content"android:inputType="text" /></TableRow><!-- 输入密码的行 --><TableRow><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/user_pass"android:textSize="@dimen/label_font_size" /><EditTextandroid:id="@+id/et_pwd"android:layout_width="match_parent"android:layout_height="wrap_content"android:inputType="textPassword"android:text="" /></TableRow><!-- 定义登录、取消按钮的行 --><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:orientation="horizontal" ><Buttonandroid:id="@+id/btn_Login"android:layout_width="0dp"android:layout_weight="1"android:layout_height="wrap_content"android:text="@string/login" /><Buttonandroid:id="@+id/btn_Cancel"android:layout_width="0dp"android:layout_weight="1"android:layout_height="wrap_content"android:text="@string/cancel" /></LinearLayout></TableLayout>

DialogUtil.java

package com.xbmu.auction.util;import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.view.View;import com.xbmu.auction.AuctionClientActivity;
/*** 项目要用到许多对话框,这里封装一个对话框的工具类。便于显示对话框* @author Administrator**/
public class DialogUtil {/*** 定义一个显示消息的对话框* * @param context 上下文* @param msg 对话框显示的描述信息* @param goHome 标记,为true表示登录成功,为false登录失败*/public static void showDialog(final Context context, String msg,boolean goHome) {//创建一个AlertDialog.Builder对象AlertDialog.Builder builder = new AlertDialog.Builder(context);builder.setMessage(msg);builder.setCancelable(false);if (goHome) {//登录成功,跳转到AuctionClientActivity(也就是应用程序的主界面)界面builder.setPositiveButton("确定", new OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {Intent intent = new Intent(context,AuctionClientActivity.class);intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);context.startActivity(intent);}});} else {builder.setPositiveButton("确定", null);}builder.create().show();}/*** 定义一个显示指定组件(布局)的对话框* @param context* @param view*/public static void showDialog(Context context, View view) {new AlertDialog.Builder(context).setView(view).setCancelable(false).setPositiveButton("确定", null).create().show();}
}

AuctionClientActivity.java

package com.xbmu.auction;import android.app.Activity;
import android.os.Bundle;
/*** 应用程序主界面* @author Administrator**/
public class AuctionClientActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}
}

res/values/strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources><string name="action_settings">Settings</string><string name="app_name">电子拍卖</string><string name="welcome">欢迎使用电子拍卖系统</string><string name="hello_world">Hello world!</string><string name="user_name">用户账号:</string><string name="user_pass">用户密码</string><string name="login">登录</string><string name="cancel">取消</string><string name="hello">Hello World, Login!</string></resources>

res/values/dimens.xml

<resources><!-- Default screen margins, per the Android Design guidelines. --><dimen name="title_padding">10dp</dimen><dimen name="label_font_size">20dp</dimen></resources>

记得在清单文件中加入访问网络的权限:

<uses-permission android:name="android.permission.INTERNET"/>

运行效果:(记得先开启服务器)

二、进入主页面

auction_list.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:orientation="vertical" ><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:padding="@dimen/title_padding"android:text="@string/welcome"android:textSize="@dimen/label_font_size" /><ListViewandroid:id="@+id/auction_list"android:layout_width="match_parent"android:layout_height="match_parent"android:entries="@array/auction_list" /></LinearLayout>

AuctionListFragment.java
package com.xbmu.auction.view;import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import com.xbmu.auction.Callbacks;
import com.xbmu.auction.R;/*** 自定义的Fragment,该Fragment种显示一个ListView,每个ListView条目代表一个系统功能* * @author Administrator* */
public class AuctionListFragment extends Fragment {ListView auctionList;private Callbacks mCallbacks;   /**重写该方法,该方法返回的View将作为Fragment显示的组件*/@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){View rootView = inflater.inflate(R.layout.auction_list,container, false);auctionList = (ListView) rootView.findViewById(R.id.auction_list);// 为ListView的列表项的单击事件绑定事件监听器auctionList.setOnItemClickListener(new OnItemClickListener(){@Overridepublic void onItemClick(AdapterView<?> parent, View view,int position, long id){mCallbacks.onItemSelected(position , null);}});return rootView;}  /**当该Fragment被添加、显示到Activity时,回调该方法*/@Overridepublic void onAttach(Activity activity){super.onAttach(activity);// 如果Activity没有实现Callbacks接口,抛出异常if (!(activity instanceof Callbacks)){throw new IllegalStateException("AuctionListFragment所在的Activity必须实现Callbacks接口!");}// 把该Activity当成Callbacks对象mCallbacks = (Callbacks) activity;}/**当该Fragment从它所属的Activity中被删除时回调该方法*/@Overridepublic void onDetach(){super.onDetach();// 将mCallbacks赋为null。mCallbacks = null;}/*** 设置:激活条目点击* @param activateOnItemClick*/public void setActivateOnItemClick(boolean activateOnItemClick){   //设置ListView的选择行为。该属性支持如下属性值/** none:不显示任何选中项* singleChoice:允许单选*/auctionList.setChoiceMode(activateOnItemClick ? ListView.CHOICE_MODE_SINGLE: ListView.CHOICE_MODE_NONE);}
}
Callbacks.java
package com.xbmu.auction;import android.os.Bundle;/*** 定义一个回调接口,里面定义一些回调方法。用于优化代码* @author Administrator**/
public interface Callbacks {/*** 单个条目被选中,调用该方法。* @param id* @param bundle*/public void onItemSelected(Integer id,Bundle bundle);
}

将Fragment添加到Activity中有如下两种方法:
1、在布局文件中使用<fragment />元素添加到Fragment,<fragment />元素的android:name属性指定Fragment的实现类。
2、在java代码中通过FragmentTransaction对象的add()方法来添加Fragment

activity_main.xml

<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="horizontal" ><!--添加一个自定义的Fragment  --><fragmentandroid:name="com.xbmu.auction.view.AuctionListFragment"android:id="@+id/auction_list"android:layout_width="match_parent"android:layout_height="match_parent"/>
</LinearLayout>
Activity获取它包含的Fragment:调用Activity关联的FragmentManager的findFragmentById(int id)或findFragmentByTag(String tag)方法即可获取指定的Fragment

AuctionClientActivity.java

package com.xbmu.auction;import android.app.Activity;
import android.app.FragmentManager;
import android.content.Intent;
import android.os.Bundle;
import com.xbmu.auction.activity.ChooseKind;
import com.xbmu.auction.activity.ManageItem;
import com.xbmu.auction.activity.ManageKind;
import com.xbmu.auction.activity.ViewBid;
import com.xbmu.auction.activity.ViewItem;
import com.xbmu.auction.view.AuctionListFragment;
/*** 应用程序主界面* @author Administrator**/
public class AuctionClientActivity extends Activity implements Callbacks{@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);FragmentManager fm = getFragmentManager();AuctionListFragment auctionList = (AuctionListFragment) fm.findFragmentById(R.id.auction_list);auctionList.setActivateOnItemClick(true);}@Overridepublic void onItemSelected(Integer id, Bundle bundle) {Intent intent = null;switch ((int)id) {// 查看竞得物品case 0:// 启动ViewItem Activityintent = new Intent(this, ViewItem.class);// action属性为请求的Servlet地址。intent.putExtra("action", "viewSucc.jsp");startActivity(intent);break;// 浏览流拍物品case 1:// 启动ViewItem Activityintent = new Intent(this, ViewItem.class);// action属性为请求的Servlet的URL。intent.putExtra("action", "viewFail.jsp");startActivity(intent);break;// 管理物品种类case 2:// 启动ManageKind Activityintent = new Intent(this, ManageKind.class);startActivity(intent);break;// 管理物品case 3:// 启动ManageItem Activityintent = new Intent(this, ManageItem.class);startActivity(intent);break;// 浏览拍卖物品(选择物品种类)case 4:// 启动ChooseKind Activityintent = new Intent(this, ChooseKind.class);startActivity(intent);break;// 查看自己的竞标case 5:// 启动ViewBid Activityintent = new Intent(this, ViewBid.class);startActivity(intent);break;}}
}

提示:

在界面布局文件中使用<fragment />元素添加Fragment时,可以为<fragment />元素指定android:id或android:tag属性,这两个属性都可用于标识该Fragment,接下来Activity将可通过findFragmentById(int id)或findFragmentByTag(String tag)来获取该Fragment。
FragmentActivity.java
package com.xbmu.auction;import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.widget.LinearLayout;public abstract class FragmentActivity extends Activity{private static final int ROOT_CONTAINER_ID = 0x90001;@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);LinearLayout layout = new LinearLayout(this);setContentView(layout);layout.setId(ROOT_CONTAINER_ID);getFragmentManager().beginTransaction().replace(ROOT_CONTAINER_ID , getFragment()).commit();}protected abstract Fragment getFragment();
}

ViewItem.java

package com.xbmu.auction.activity;import android.app.Fragment;import com.xbmu.auction.FragmentActivity;/*** 浏览流拍物品* @author Administrator*/
public class ViewItem extends FragmentActivity {@Overrideprotected Fragment getFragment() {// TODO Auto-generated method stubreturn null;}
}

其中ChooseKind.java、ManageItem.java、ManageKind.java、ViewBid.java这几个文件暂时性和ViewItem的内容差不多。
res/values/array.xml
<?xml version="1.0" encoding="utf-8"?>
<resources><string-array name="auction_list"><item>查看竞得物品</item><item>浏览流拍物品</item><item>管理物品种类</item><item>管理物品</item><item>浏览拍卖物品</item><item>查看自己的竞标</item></string-array>
</resources>

res/values/strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources><string name="action_settings">Settings</string><string name="app_name">电子拍卖</string><string name="welcome">欢迎使用电子拍卖系统</string><string name="hello_world">Hello world!</string><string name="user_name">用户账号:</string><string name="user_pass">用户密码</string><string name="login">登录</string><string name="cancel">取消</string><string name="hello">Hello World, Login!</string><string name="manage_kind">系统的所有物品种类</string><string name="manage_item">你当前的拍卖物品</string><string name="view_bid">你参与竞标的物品</string><string name="choose_kind">请选择一个物品的种类</string></resources>

在清单文件中注册:
<activityandroid:name=".AuctionClientActivity"android:label="@string/app_name" ></activity><activityandroid:name="com.xbmu.auction.activity.ViewItem"android:label="@string/app_name" ></activity><activityandroid:name="com.xbmu.auction.activity.ManageKind"android:label="@string/manage_kind" ></activity><activityandroid:name="com.xbmu.auction.activity.ManageItem"android:label="@string/manage_item" ></activity><activityandroid:name="com.xbmu.auction.activity.ViewBid"android:label="@string/view_bid" ></activity><activityandroid:name="com.xbmu.auction.activity.ChooseKind"android:label="@string/choose_kind" ></activity>

运行效果:

三、实现主页面各个功能:

3.1:浏览流拍物品:

在服务器上写浏览流拍物品功能:
BussinessServiceImpl.java
package com.xbmu.service.impl;import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.xbmu.bean.Bid;
import com.xbmu.bean.Item;
import com.xbmu.bean.Kind;
import com.xbmu.bean.User;
import com.xbmu.business.BidBean;
import com.xbmu.business.ItemBean;
import com.xbmu.business.KindBean;
import com.xbmu.dao.AuctionUserDao;
import com.xbmu.dao.ItemDao;
import com.xbmu.dao.KindDao;
import com.xbmu.dao.impl.AuctionUserDaoImpl;
import com.xbmu.dao.impl.ItemDaoImpl;
import com.xbmu.dao.impl.KindDaoImpl;
import com.xbmu.exception.AuctionException;
import com.xbmu.service.BussinessService;public class BussinessServiceImpl implements BussinessService {//...// ---------------------物品----------------------------private ItemDao itemDao = new ItemDaoImpl();/*** 查询流拍的全部物品* * @return 全部流拍物品*/public List<ItemBean> getFailItems() throws AuctionException {try {List<Item> items = itemDao.findItemByState(3);List<ItemBean> result = new ArrayList<ItemBean>();for (Iterator<Item> it = items.iterator(); it.hasNext();) {ItemBean ib = new ItemBean();initItem(ib, it.next());result.add(ib);}return result;} catch (Exception e) {throw new AuctionException("查询流拍物品出现异常,请重试");}}//..../*** 将一个Item PO转换成ItemBean的VO* @param ib  ItemBean的VO* @param item Item的PO*/private void initItem(ItemBean ib, Item item) {ib.setId(item.getItem_id());ib.setName(item.getItem_name());ib.setDesc(item.getItem_desc());ib.setRemark(item.getItem_remark());if (item.getKind() != null)ib.setKind(item.getKind().getKind_name());if (item.getOwner() != null)ib.setOwner(item.getOwner().getUsername());if (item.getWiner() != null)ib.setWiner(item.getWiner().getUsername());ib.setAddTime(item.getAddtime());ib.setEndTime(item.getEndtime());if (item.getItemState() != null)ib.setState(item.getItemState().getState_name());ib.setInitPrice(item.getInit_price());ib.setMaxPrice(item.getMax_price());}}

ItemDao.java
package com.xbmu.dao;import java.util.List;
import com.xbmu.bean.Item;
/*** 物品接口* @author Administrator**/
public interface ItemDao{/*** 根据物品状态查找物品* @param stateId 状态Id;* @return 该状态下的全部物品*/List<Item> findItemByState(Integer stateId);
}

ItemDaoImpl.java

package com.xbmu.dao.impl;import java.sql.SQLException;
import java.util.List;import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;import com.xbmu.bean.Item;
import com.xbmu.bean.Kind;
import com.xbmu.bean.User;
import com.xbmu.dao.ItemDao;
import com.xbmu.util.DBCPUtil;public class ItemDaoImpl implements ItemDao {QueryRunner qr = new QueryRunner(DBCPUtil.getDataSource());/*** 根据物品状态查找物品* @param stateId 状态id;* @return 该状态下的全部物品*/public List<Item> findItemByState(Integer stateId) {try {String sql = "select * from item where state_id = ?";List<Item> itemList  = qr.query(sql, new BeanListHandler<Item>(Item.class),stateId);//遍历物品,设置种类,赢取者,拥有者的属性。for (Item item : itemList) {//设置种类String kindSql = "select * from kind where kind_id = (select kind_id from item where state_id=?)";Kind kind = qr.query(kindSql, new BeanHandler<Kind>(Kind.class), stateId);item.setKind(kind);//设置拥有者用户String ownerSql = "select * from auction_user where user_id = (select owner_id from item where state_id=?)";User owner = qr.query(ownerSql, new BeanHandler<User>(User.class), stateId);item.setOwner(owner);//设置赢取者用户String winerSql = "select * from auction_user where user_id = (select winer_id from item where state_id=?)";User winer = qr.query(winerSql, new BeanHandler<User>(User.class), stateId);item.setWiner(winer);System.out.println(item.toString());}return itemList;} catch (SQLException e) {throw new RuntimeException(e);}}//...
}

ViewFailServlet.java
package com.xbmu.web.controller;import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONArray;
import com.xbmu.business.ItemBean;
import com.xbmu.service.BussinessService;
import com.xbmu.service.impl.BussinessServiceImpl;/*** 查看流拍物品的Servlet* * @author Administrator* */
@WebServlet(urlPatterns = "/android/viewFail.jsp")
public class ViewFailServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {//获取请求参数,这个参数标记的是返回的json数据,用于提供给客户端String mode = request.getParameter("mode");// 获取业务逻辑对象BussinessService service = new BussinessServiceImpl();// 查询所有流拍的物品List<ItemBean> items = service.getFailItems();if("android".equals(mode)){//返回json数据提供给客户端JSONArray jsonArray = new JSONArray(items);response.getWriter().println(jsonArray.toString());}else if("web".equals(mode)){//将数据保存在request域中,显示在服务端界面上request.setAttribute("items", items);request.getRequestDispatcher("/manage/viewFail.jsp").forward(request, response);}}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}}

运行效果:
返回json对象:

在客户端上写浏览流拍物品功能:
view_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:orientation="vertical" ><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="@dimen/sub_title_margin"android:gravity="center"android:orientation="horizontal" ><TextViewandroid:id="@+id/view_titile"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/view_succ"android:textSize="@dimen/label_font_size" /><!-- 定义返回按钮 --><Buttonandroid:id="@+id/bn_home"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="@dimen/label_font_size"android:background="@drawable/home" /></LinearLayout><!-- 查看物品列表的ListView --><ListViewandroid:id="@+id/succList"android:layout_width="match_parent"android:layout_height="match_parent" /></LinearLayout>
res/drawable/tv_bg.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"><stroke android:color="#888"android:width="2dp"/><!-- 设置圆角矩形 --><corners android:radius="2dp" /> <solid android:color="#fff"/>
</shape>

res/values/styles.xml

 <style name="tv_show"><item name="android:textColor">#000</item><item name="android:textSize">20sp</item><item name="android:padding">4dp</item><item name="android:background">@drawable/tv_bg</item></style>

ViewItemFragment.java

package com.xbmu.auction.fragment;import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import com.xbmu.auction.R;
import com.xbmu.auction.adapter.JSONArrayAdapter;
import com.xbmu.auction.listener.HomeListener;
import com.xbmu.auction.util.DialogUtil;
import com.xbmu.auction.util.HttpUtil;
public class ViewItemFragment extends Fragment
{Button bnHome;ListView succList;TextView viewTitle;@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){View rootView = inflater.inflate(R.layout.view_item, container , false);// 获取界面上的返回按钮bnHome = (Button) rootView.findViewById(R.id.bn_home);succList = (ListView) rootView.findViewById(R.id.succList);viewTitle = (TextView) rootView.findViewById(R.id.view_titile);// 为返回按钮的单击事件绑定事件监听器bnHome.setOnClickListener(new HomeListener(getActivity()));//Bundle.getArguments():如果有的话,当fragment初始化的时候,返回提供的参数。String action = getArguments().getString("action");// 定义发送请求的URLString url = HttpUtil.BASE_URL + action+"?mode=android";// 如果是查看流拍物品,修改标题if (action.equals("viewFail.jsp")){viewTitle.setText(R.string.view_fail);}try{// 向指定URL发送请求,并把服务器响应转换成JSONArray对象JSONArray jsonArray = new JSONArray(HttpUtil.getRequest(url));  // 将JSONArray包装成AdapterJSONArrayAdapter adapter = new JSONArrayAdapter(getActivity(), jsonArray, "name", true); succList.setAdapter(adapter);}catch (Exception e){DialogUtil.showDialog(getActivity(), "服务器响应异常,请稍后再试!", false);e.printStackTrace();}succList.setOnItemClickListener(new OnItemClickListener(){@Overridepublic void onItemClick(AdapterView<?> parent, View view,int position, long id){// 查看指定物品的详细情况。viewItemDetail(position);}});return rootView;}private void viewItemDetail(int position){// 加载detail.xml界面布局代表的视图View detailView = getActivity().getLayoutInflater().inflate(R.layout.detail, null);// 获取detail.xml界面布局中的文本框TextView itemName = (TextView) detailView.findViewById(R.id.itemName);TextView itemKind = (TextView) detailView.findViewById(R.id.itemKind);TextView maxPrice = (TextView) detailView.findViewById(R.id.maxPrice);TextView itemRemark = (TextView) detailView.findViewById(R.id.itemRemark);// 获取被单击的列表项JSONObject jsonObj = (JSONObject) succList.getAdapter().getItem(position);try{// 通过文本框显示物品详情itemName.setText(jsonObj.getString("name"));itemKind.setText(jsonObj.getString("kind"));maxPrice.setText(jsonObj.getString("maxPrice"));itemRemark.setText(jsonObj.getString("desc"));}catch (JSONException e){e.printStackTrace();}DialogUtil.showDialog(getActivity(), detailView);}
}

detail.xml
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:stretchColumns="1" ><TableRow><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/item_name"android:textSize="@dimen/label_font_size" /><TextViewandroid:id="@+id/itemName"style="@style/tv_show"android:layout_width="match_parent"android:layout_height="wrap_content" /></TableRow><TableRow><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/item_kind"android:textSize="@dimen/label_font_size" /><TextViewandroid:id="@+id/itemKind"style="@style/tv_show"android:layout_width="match_parent"android:layout_height="wrap_content" /></TableRow><TableRow><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/win_price"android:textSize="@dimen/label_font_size" /><TextViewandroid:id="@+id/maxPrice"style="@style/tv_show"android:layout_width="match_parent"android:layout_height="wrap_content" /></TableRow><TableRow><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/remark"android:textSize="@dimen/label_font_size" /><TextViewandroid:id="@+id/itemRemark"style="@style/tv_show"android:layout_width="match_parent"android:layout_height="wrap_content" /></TableRow></TableLayout>

HomeListener.java

package com.xbmu.auction.listener;import com.xbmu.auction.AuctionClientActivity;
import android.app.Activity;
import android.content.Intent;
import android.view.View;
import android.view.View.OnClickListener;public class HomeListener implements OnClickListener
{private Activity activity;public HomeListener(Activity activity){this.activity = activity;}@Overridepublic void onClick(View source){Intent i = new Intent(activity , AuctionClientActivity.class);i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);activity.startActivity(i);}
}

JSONArrayAdapter.java

package com.xbmu.auction.adapter;import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONException;
import com.xbmu.auction.R;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
public class JSONArrayAdapter extends BaseAdapter
{private Context ctx;// 定义需要包装的JSONArray对象private JSONArray jsonArray;// 定义列表项显示JSONObject对象的哪个属性private String property;private boolean hasIcon;public JSONArrayAdapter(Context ctx, JSONArray jsonArray, String property, boolean hasIcon){this.ctx = ctx;this.jsonArray = jsonArray;this.property = property;this.hasIcon = hasIcon;}@Overridepublic int getCount(){return jsonArray.length();}@Overridepublic Object getItem(int position){return jsonArray.optJSONObject(position);}@Overridepublic long getItemId(int position){try{// 返回物品的IDreturn ((JSONObject)getItem(position)).getInt("id");}catch (JSONException e){e.printStackTrace();}return 0;}@Overridepublic View getView(int position, View convertView, ViewGroup parent){// 定义一个线性布局管理器LinearLayout linear = new LinearLayout(ctx);// 设置为水平的线性布局管理器linear.setOrientation(0);// 创建一个ImageViewImageView iv = new ImageView(ctx);iv.setPadding(10, 0, 20, 0);iv.setImageResource(R.drawable.item);// 将图片添加到LinearLayout中linear.addView(iv);// 创建一个TextViewTextView tv = new TextView(ctx);try{// 获取JSONArray数组元素的property属性String itemName = ((JSONObject)getItem(position)).getString(property);// 设置TextView所显示的内容tv.setText(itemName);}catch (JSONException e){e.printStackTrace();}tv.setTextSize(20);if (hasIcon){// 将TextView添加到LinearLayout中linear.addView(tv);return linear;}else{return tv;}}
}

ViewItem.java

package com.xbmu.auction.activity;import android.app.Fragment;
import android.os.Bundle;
import com.xbmu.auction.FragmentActivity;
import com.xbmu.auction.fragment.ViewItemFragment;/*** 浏览流拍物品* * @author Administrator*/
public class ViewItem extends FragmentActivity {// 重写getFragment()方法,该Activity显示该方法返回的Fragment@Overrideprotected Fragment getFragment() {/*** 思路:Activity向Fragment传递数据:在Activity中创建Bundle数据包,* 并调用Fragment的setArguments(Bundle bundle) 方法即可将Bundle数据包传给Fragment。*/ViewItemFragment fragment = new ViewItemFragment();// 携带数据的数据包对象Bundle arguments = new Bundle();// 向数据包对象中装数据arguments.putString("action", getIntent().getStringExtra("action"));//将Bundle数据包传给Fragmentfragment.setArguments(arguments);return fragment;}
}

res/values/strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources><string name="action_settings">Settings</string><string name="app_name">电子拍卖</string><string name="welcome">欢迎使用电子拍卖系统</string><string name="hello_world">Hello world!</string><string name="user_name">用户账号:</string><string name="user_pass">用户密码</string><string name="login">登录</string><string name="cancel">取消</string><string name="hello">Hello World, Login!</string><string name="manage_kind">系统的所有物品种类</string><string name="manage_item">你当前的拍卖物品</string><string name="view_bid">你参与竞标的物品</string><string name="choose_kind">请选择一个物品的种类</string><string name="view_succ">浏览竞得物品</string><string name="view_fail">浏览流拍物品</string><string name="item_list">当前种类的物品</string><string name="item_name">物品名:</string><string name="item_kind">物品种类:</string><string name="item_desc">物品描述:</string><string name="win_price">赢取价格:</string><string name="max_price">最高竞价:</string><string name="remark">物品备注:</string></resources>

res/vaalues/dimens.xml

<resources><!-- Default screen margins, per the Android Design guidelines. --><dimen name="title_padding">10dp</dimen><dimen name="label_font_size">20dp</dimen><dimen name="sub_title_margin">20dp</dimen></resources>

运行效果:

电子拍卖系统开发第二天相关推荐

  1. 电子拍卖系统开发第一天

    电子拍卖系统开发: 功能流程图: 数据库设计: 说明: 物品表(item).物品种类表(kind).物品状态表(state).竞价历史表(bid).用户表(auction_user) 表之间的关系: ...

  2. 电子拍卖系统开发第四天

    今天主要整理了一下服务端代码.前面一直遇到一个问题?管理人员既能在后台web上可以管理物品等功能,可以实现物品种类的添加,查询,物品的添加及其浏览等一些功能.一直想将管理人员操作这些功能的界面写的也比 ...

  3. 电子拍卖系统毕业设计

    技术:Java.JSP等 摘要: 随着Internet的日益普及和电子商务的发展,网上拍卖迅速成为一种非常活跃的C2C电子商务模式.文中详细介绍了JSP技术以及分析了基于JSP建立网上拍卖系统的技术手 ...

  4. Xamarin ios C#苹果应用开发第二讲配置环境和编写代码

    Xamarin ios C#苹果应用开发第二讲配置环境和编写代码 Xamarin ios C#苹果应用开发第二讲配置环境和编写代码 观看地址://v.youku.com/v_show/id_XNzE1 ...

  5. 组队开发第二周第一次会议

    会议时间:组队开发第二周  星期一    开始时间晚上9:30-10:20 会议地点:学一食堂 二楼 到会人员:李志岩 孙存良 王亚蕊 安帅 薛禄坤 张新宇 会议内容概要: 会议主要完成了两项工作: ...

  6. 锁具行业电子工程师岗位职责_赏金猎人招募电子产品开发工程师产品结构工程师...

    "赏金猎人"专栏6期来啦! 这个专栏,可以让产业需求被更广大的社区看见 让社区更多有技能.有解决方案的小伙伴参与进来 最终促进科技在传统产业中的应用落地 专栏里面发布的猎人需求 只 ...

  7. 主从式网络的优点_贸泽电子原创开发板大赛【创意奖作品】物联网开发板做成主从机形式,是创意还是多此一举?...

    没有创意,竞赛还有什么意义? 作为汇集了国内工程师中的一批顶尖高手的设计大赛,本届贸泽电子原创开发板大赛自然少不了"最佳创意奖",今天,就让我们来看看工程师大开脑洞的获奖作品有何稀 ...

  8. 【微信开发第二章】SpringBoot实现微信公众号普通消息和模板消息回复

    前言 在进行微信公众号业务开发的时候,微信公众号的消息回复是非常重要的一环,而微信公众号消息回复分为:普通消息自动回复和模板消息回复.该篇文章会先使用微信测试工具过一遍流程,再使用代码进行实现,并且每 ...

  9. Agv、Rgv 车辆控制调度系统开发第二篇

    系列文章目录 Agv.Rgv 车辆控制调度系统开发第二篇(理论片) 文章目录 系列文章目录 前言 一.什么是调度系统? 问题 二.问题分析 1.寻找路线 2.避碰算法 3.移车算法 4.解锁算法 总结 ...

最新文章

  1. 36 岁开发者应聘被拒,这 3 位 50 岁程序员的生存秘籍送给你!
  2. python自学入门教程-Python学习教程(一)自学资源分享
  3. CGAN生成cifar10, cifar100, mnist, fashion_mnist,STL10,Anime图片(pytorch)
  4. 会计转行从事IT,如何在一年时间内全职学习?
  5. 什么时候应该避免写代码注释?
  6. spring基于注释的配置_基于注释的Spring MVC Web应用程序入门
  7. linux03-学习记录
  8. mysql 复制 错误_Mysql复制错误error
  9. 弹框插件self(动效兼容到IE9,功能兼容IE6)
  10. 【Node】—系统模块
  11. archlinux安装gnome-shell主题
  12. 计算机应用技术课程本科,《计算机应用技术I》课程教学大纲(共本科29级用)().doc...
  13. Atitit nlp重要节点 v3 目录 1. 语法分析重点 节点余额365个 1 2. nlp词性表 2 2.1. 词语分类13类 2 2.2. 副词 约20个 3 2.3. 代词30个 3 2
  14. 【三维装箱】基于matlab粒子群算法求解三维装箱优化问题【含Matlab源码 950期】
  15. 机器学习笔记 - 基于最简单的编码器/解码器架构SegNet进行语义分割
  16. 地方时太阳时html源码,地方时、区时和世界时
  17. 使用Python-OpenCV将图片批量转换为jpg格式
  18. jquery mysql实现加入购物车_jquery-实现加入购物车效果
  19. 与孤独世界的博弈——诺贝尔奖得主约翰·纳什的传奇一生
  20. org.hibernate.StaleStateException: Batch update returned unexpected row cou...

热门文章

  1. 【生成报名号+缴费成功】不代表考研报名成功!
  2. 单片机汇编伪指令DATA和EQU的区别
  3. 小米手机录音删除了怎么恢复?可自动备份的录音便签
  4. Android Studio的Logcat/Run/Terminal/Build等窗口没有了怎么调出
  5. 百度以5000万“祭杀”的王劲是谁?他错了吗?
  6. 【微信小游戏】排行榜概念篇
  7. 基于Wemos D1避障WiFi小车及智能垃圾桶设计
  8. 每日经典算法题(十三) 逆推算法(平方根相关)
  9. Flask异步渲染管理后台局部页面
  10. Leetcode 860. 柠檬水找零(贪心) 记录反思