android與java web互動完成簡單的登入和註冊
阿新 • • 發佈:2018-12-21
本文的知識點包括android客戶端的網路程式設計、訊息機制、IO流、多執行緒和java web伺服器端的servlet、資料庫操作、javabean技術、工具類和測試類的使用。
客戶端
執行效果圖
佈局檔案
activity_main.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="com.ningxiaojian.clientlogindemo.MainActivity"> <EditText android:id="@+id/et_username" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="請輸入登入賬號"/> <EditText android:id="@+id/et_password" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="請輸入登入密碼"/> <Button android:id="@+id/bt_login" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="登入" android:onClick="login"/> <Button android:id="@+id/bt_register" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="註冊" android:onClick="register"/> </LinearLayout>
程式主入口
MainActivity
package com.ningxiaojian.clientlogindemo; import android.annotation.SuppressLint; import android.os.Handler; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.EditText; import android.widget.Toast; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; public class MainActivity extends AppCompatActivity { private EditText username; private EditText password; private String usernameStr; private String passwordStr; private final int LOGINSUCCESS=0; private final int LOGINNOTFOUND=1; private final int LOGINEXCEPT=2; private final int REGISTERSUCCESS=3; private final int REGISTERNOTFOUND=4; private final int REGISTEREXCEPT=5; @SuppressLint("HandlerLeak") Handler handler=new Handler(){//訊息機制,用來在子執行緒中更新UI @Override public void handleMessage(Message msg) { switch (msg.what){//具體訊息,具體顯示 case LOGINSUCCESS: Toast.makeText(getApplicationContext(),(String)msg.obj,Toast.LENGTH_LONG).show(); break; case LOGINNOTFOUND: Toast.makeText(getApplicationContext(),(String)msg.obj,Toast.LENGTH_LONG).show(); break; case LOGINEXCEPT: Toast.makeText(getApplicationContext(),(String)msg.obj,Toast.LENGTH_LONG).show(); break; case REGISTERSUCCESS: Toast.makeText(getApplicationContext(),(String)msg.obj,Toast.LENGTH_LONG).show(); break; case REGISTERNOTFOUND: Toast.makeText(getApplicationContext(),(String)msg.obj,Toast.LENGTH_LONG).show(); break; case REGISTEREXCEPT: Toast.makeText(getApplicationContext(),(String)msg.obj,Toast.LENGTH_LONG).show(); break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //找到我們需要的控制元件 username = (EditText) findViewById(R.id.et_username); password = (EditText) findViewById(R.id.et_password); } //登入按鈕的點選事件,也可以用set監聽器的方法,不過這種方法簡單 public void login(View v){ //獲取編輯框內的內容 usernameStr = username.getText().toString().trim(); passwordStr = password.getText().toString().trim(); //判斷是否輸入為空(在這裡就不再進行正則表示式判斷了) if(usernameStr.equals("") || passwordStr.equals("")){ Toast.makeText(MainActivity.this,"使用者名稱或密碼不能為空",Toast.LENGTH_SHORT).show(); }//進行登入操作(聯網操作要新增許可權) else { //聯網操作要開子執行緒,在主執行緒不能更新UI new Thread(){ private HttpURLConnection connection; @Override public void run() { try { //封裝成傳輸資料的鍵值對,無論get還是post,傳輸中文時都要進行url編碼(RULEncoder) // 如果是在瀏覽器端的話,它會自動進行幫我們轉碼,不用我們進行手動設定 String data2= "username="+ URLEncoder.encode(usernameStr,"utf-8")+"&password="+ URLEncoder.encode(passwordStr,"utf-8")+"&sign="+URLEncoder.encode("1","utf-8"); connection=HttpConnectionUtils.getConnection(data2); int code = connection.getResponseCode(); if(code==200){ InputStream inputStream = connection.getInputStream(); String str = StreamChangeStrUtils.toChange(inputStream);//寫個工具類流轉換成字串 Message message = Message.obtain();//更新UI就要向訊息機制傳送訊息 message.what=LOGINSUCCESS;//用來標誌是哪個訊息 message.obj=str;//訊息主體 handler.sendMessage(message); } else { Message message = Message.obtain(); message.what=LOGINNOTFOUND; message.obj="註冊異常...請稍後再試"; handler.sendMessage(message); } } catch (Exception e) {//會丟擲很多個異常,這裡抓一個大的異常 e.printStackTrace(); Message message = Message.obtain(); message.what=LOGINEXCEPT; message.obj="伺服器異常...請稍後再試"; handler.sendMessage(message); } } }.start();//不要忘記開執行緒 } } //註冊按鈕的點選事件 public void register(View v){ usernameStr = username.getText().toString().trim(); passwordStr = password.getText().toString().trim(); if(usernameStr.equals("") || passwordStr.equals("")){ Toast.makeText(MainActivity.this,"使用者名稱或密碼不能為空",Toast.LENGTH_SHORT).show(); } else { new Thread(){ HttpURLConnection connection=null; @Override public void run() { try { String data= "username="+ URLEncoder.encode(usernameStr,"utf-8")+"&password="+ URLEncoder.encode(passwordStr,"utf-8")+"&sign="+URLEncoder.encode("2","utf-8"); connection=HttpConnectionUtils.getConnection(data); int code = connection.getResponseCode(); if(code==200){ InputStream inputStream = connection.getInputStream(); String str = StreamChangeStrUtils.toChange(inputStream); Message message = Message.obtain(); message.obj=str; message.what=REGISTERSUCCESS; handler.sendMessage(message); } else { Message message = Message.obtain(); message.what=REGISTERNOTFOUND; message.obj="註冊異常...請稍後再試"; handler.sendMessage(message); } } catch (Exception e) { e.printStackTrace(); Message message = Message.obtain(); message.what=REGISTEREXCEPT; message.obj="伺服器異常...請稍後再試"; handler.sendMessage(message); } } }.start();//不要忘記開執行緒 } } }
流轉換成字串的工具類
StreamChangeStrUtils
package com.ningxiaojian.clientlogindemo; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; /** * 流轉換成字串的工具類 */ public class StreamChangeStrUtils { public static String toChange(InputStream inputStream) throws Exception { ByteArrayOutputStream bos = new ByteArrayOutputStream();//陣列流,在流的內部有個緩衝區,可以進行轉換成位元組 //下面是屬於io流的知識,在此不再贅述 byte b[]=new byte[1024]; int len=-1; while ((len=inputStream.read(b))!=-1){ bos.write(b,0,len); } inputStream.close();//關閉流,陣列流會自動關閉,關閉是否都可以 String str = new String(bos.toByteArray()); //伺服器預設返回的是gbk,如果要在android端解決亂碼,可以在此設定為gbk,一般提倡的是伺服器解決 // 讓伺服器給我們返回utf-8,因為在android本地預設的是utf-8 return str; } }
聯網工具類
HttpConnectionUtils
package com.ningxiaojian.clientlogindemo;
import android.os.Message;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
import java.net.URLEncoder;
/**
* 獲取聯網連線
* Created by Justin on 2018/4/16.
*/
public class HttpConnectionUtils {
public static HttpURLConnection getConnection(String data) throws Exception {
//通過URL物件獲取聯網物件
URL url= new URL("http://192.168.1.104:8080/AndroidLoginDemo/LoginServlet");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");//設定post請求
connection.setReadTimeout(5000);//設定5s的響應時間
connection.setDoOutput(true);//允許輸出
connection.setDoInput(true);//允許輸入
//設定請求頭,以鍵值對的方式傳輸(以下這兩點在GET請求中不用設定)
connection.setRequestProperty("Content-Type","application/x-www-form-urlencoded ");
connection.setRequestProperty("Content-Length",data.length()+"");//設定請求體的長度
OutputStream outputStream = connection.getOutputStream();
outputStream.write(data.getBytes());//進行傳輸操作
//判斷服務端返回的響應碼,這裡是http協議的內容
return connection;
}
}
聯網操作一定要在
AndroidManifest.xml加上許可權
<uses-permission android:name="android.permission.INTERNET"/> 伺服器端(Tomcat) 首先去mysql建立一個數據庫,表結構如下 因為使用到mysql,所以要把jdbc的驅動類新增到webcontent->web-inf->lib中 mysql-connector-java-5.1.45-bin.jar 在eclipse建立以下包名 com.ningxiaojian.dao:dao層介面 com.ningxiaojian.dao.impl:dao層介面的實現 com.ningxiaojian.domain:javabean物件 com.ningxiaojian.service:邏輯層的介面 com.ningxiaojian.service.impl:邏輯層的實現 com.ningxiaojian.web.control:存放servlet com.ningxiaojian.utils:存放工具類 com.ninxiaojian.test:存放測試類 建立java物件 User.java
package com.ningxiaojian.domain;
/**
*
*設定一個javabean物件,用來封裝dao層取出的資料
* @author Justin
*
*/
public class User {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
dao層介面
UserDao.java
package com.ningxiaojian.dao;
import java.util.List;
import com.ningxiaojian.domain.User;
public interface UserDao {
//找到所有元素,用來驗證登入資訊
public List<User> findAll();
//插入元素,用來註冊
public void insertElement(User people);
}
dao層實現類
UserDaoImpl.java
package com.ningxiaojian.dao.impl;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.ningxiaojian.dao.UserDao;
import com.ningxiaojian.domain.User;
import com.ningxiaojian.utils.JDBCUtils;
public class UserDaoImpl implements UserDao {
Connection connection=null;
PreparedStatement ps=null;
ResultSet rs=null;
/**
* dao層,從資料庫裡面取出資料
*/
@Override
public List<User> findAll() {
List<User> list=null;
try {
//通過工具類獲得連線
connection = JDBCUtils.getConnetion();
//通過連線物件獲取操作資料庫的物件
String sql="SELECT * FROM user;";//查詢sql語句
ps=connection.prepareStatement(sql);
//返回查詢結果集
rs=ps.executeQuery();
//遍歷rs,並封裝資料
list=new ArrayList<User>();
while(rs.next()) {
User user=new User();
user.setUsername(rs.getString(2));//索引從1開始,id引數不用取
user.setPassword(rs.getString(3));
list.add(user);
}
} catch (Exception e) {
e.printStackTrace();
}
finally{
JDBCUtils.close(connection, ps, rs);//關閉連線
}
return list;
}
@Override
public void insertElement(User people) {
try {
connection=JDBCUtils.getConnetion();
String sql="INSERT INTO user(username,password) VALUES(?,?);";//插入語句
ps=connection.prepareStatement(sql);
ps.setString(1,people.getUsername());//使用prepareStatement可以防止sql注入
ps.setString(2,people.getPassword());
//執行更新語句
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}
finally {
JDBCUtils.close(connection, ps, rs);
}
}
}
jdbc工具類
JDBCUtils.java
package com.ningxiaojian.utils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* 因為要多次用到以下的步驟,所以寫一個工具類來操作jdbc
* @author Justin
*在這裡不要導錯包,import com.mysql.jdbc.PreparedStatement;是錯的
*/
public class JDBCUtils {
/**
* 獲得jdbc連線
*/
static Connection connection=null;
public static Connection getConnetion() throws Exception {
//載入jdbc驅動
Class.forName("com.mysql.jdbc.Driver");
//建立連線資料庫的路徑
String url = "jdbc:mysql://localhost/android_login?user=root&password=12345";
//通過url獲得與資料庫的連線
connection = DriverManager.getConnection(url);
return connection;
}
public static void close(Connection connection,PreparedStatement ps,ResultSet rs) {
//一定要確保關閉連線,以下關閉步驟是參照官方文件的,有權威性
if(rs!=null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(ps!=null) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection!=null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
測試dao層方法的test類(僅作測試作用)
TestDao.java
package com.ninxiaojian.test;
import java.util.List;
import org.junit.jupiter.api.Test;
import com.ningxiaojian.dao.UserDao;
import com.ningxiaojian.dao.impl.UserDaoImpl;
import com.ningxiaojian.domain.User;
class TestDao {
/**
* 測試類,測試dao層那兩個方法是否查詢和插入正確
*/
@Test
void testFindAll() {
UserDao dao=new UserDaoImpl();
List<User> list = dao.findAll();
for(int i=0;i<list.size();i++) {//遍歷list
User user=list.get(i);
System.out.println("username:"+user.getUsername());
System.out.println("password:"+user.getPassword());
}
}
@Test
void testInsertElement() {
UserDao dao=new UserDaoImpl();
User people=new User();
people.setUsername("hhhhh");
people.setPassword("66666");
dao.insertElement(people);
}
}
servlet類
LoginServlet.java
package com.ningxiaojian.web.control;
import java.io.IOException;
import java.io.PrintWriter;
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 com.ningxiaojian.domain.User;
import com.ningxiaojian.service.UserService;
import com.ningxiaojian.service.impl.UserServiceImpl;
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");//解決請求亂碼(post)
response.setCharacterEncoding("UTF-8");//解決響應亂碼,下面要以字元流輸出(若位元組流輸出則要再次編碼)
String username=request.getParameter("username");
String password=request.getParameter("password");
String sign=request.getParameter("sign");
PrintWriter out=response.getWriter();
//把傳來的資料封裝進javabean中
User user=new User();
user.setUsername(username);
user.setPassword(password);
UserService service=new UserServiceImpl();
if("1".equals(sign)) {//登入操作(設定了一個標記)
String loginInfo=service.checkLogin(user);
out.print(loginInfo);
}
else if("2".equals(sign)) {//註冊操作
String registerInfo=service.register(user);
out.print(registerInfo);
}
System.out.println(username);//在控制檯輸出
System.out.println(password);
System.out.println(sign);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
service介面層
UserService.java
package com.ningxiaojian.service;
import com.ningxiaojian.domain.User;
public interface UserService {
//查驗登入
public String checkLogin(User user);
//註冊使用者
public String register(User user);
}
service實現層,服務端的主要邏輯
UserServiceImpl.java
package com.ningxiaojian.service.impl;
import java.util.List;
import com.ningxiaojian.dao.UserDao;
import com.ningxiaojian.dao.impl.UserDaoImpl;
import com.ningxiaojian.domain.User;
import com.ningxiaojian.service.UserService;
public class UserServiceImpl implements UserService {
UserDao dao=new UserDaoImpl();
/*
* 主要的邏輯實現
*/
@Override
public String checkLogin(User user) {
List<User> list = dao.findAll();
for(int i=0;i<list.size();i++) {//遍歷集合
User user2=list.get(i);
if(user2.getUsername().equals(user.getUsername()) && user2.getPassword().equals(user.getPassword())) {
return "登入成功";
}
}
return "登入失敗,密碼輸入錯誤";
}
@Override
public String register(User user) {
List<User> list = dao.findAll();
for(int i=0;i<list.size();i++) {
User user2=list.get(i);
if(user2.getUsername().equals(user.getUsername())) {
return "註冊失敗,該使用者名稱已存在!";
}
}
dao.insertElement(user);
return "註冊成功";
}
}
以上就是全部的程式碼,每句程式碼都會有詳細的解釋