首先默认已经装了Tomcat了,这方面的教程网上一大堆。
两数求和
移动端输入两个数,点击按钮,在web端计算结果并返回,最后在页面弹出
Web端:
web项目名:WebProject_war
只写了个Servlet进行逻辑的运算,Servlet名为:Servlet
package com.Servlet;
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;
/**
* Servlet implementation class Servlet
*/
@WebServlet("/Servlet")
public class Servlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public Servlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
// TODO Auto-generated method stub
//避免使用super.doPost(request,response)
PrintWriter out = response.getWriter();
String n1 = request.getParameter("n1").trim();
String n2 = request.getParameter("n2").trim();
if(n1!=null && n2 != null && !"".equals(n1) && !"".equals(n2)) {
int a = Integer.parseInt(n1);
int b = Integer.parseInt(n2);
out.print(Integer.toString(a+b));
out.flush();
out.close();
}
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
接着导出改项目的war包,不管是IDEA还是Eclipse导出War包的博客有很多,这里不在讲了。
导出后,将war包放在tomcat根目录下的webapps文件夹下。并且在根目录的bin文件夹中点击startup.bat启动tomcat。
移动端:
新建项目TomcatTest
编写一个简单的页面,有两个输入框和一个按钮。
activtiy_main.xml 代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:padding="10dp"
android:orientation="vertical">
<EditText
android:id="@+id/shuju1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="input n1"/>
<EditText
android:id="@+id/shuju2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="input n2"/>
<Button
android:id="@+id/sum"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="Sum"/>
</LinearLayout>
然后是MainActivity.java的代码:
package com.example.tomcattest;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
public class MainActivity extends AppCompatActivity {
private EditText shuju1;
private EditText shuju2;
String n1,n2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.sum);
shuju1 = (EditText) findViewById(R.id.shuju1);
shuju2 = (EditText) findViewById(R.id.shuju2);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
// Log.d("MainActivity","Start");
final String URL="http://10.0.2.2:8080/WebProject_war/Servlet";//根据自己的项目需要修改
new Thread(new Runnable() {
public void run()
{
String msg = "";
n1 = shuju1.getText().toString();//获取输入框的值
n2 = shuju2.getText().toString();
try {
// Log.d("MainActivity","Continue");
URL url = new URL(URL);//生成一个URL实例,指向我们刚才设定的地址URL
/*
openConnection()方法只是创建了一个HttpURLConnection实例,
并不是真正连接,在连接之前可以设置一些属性
*/
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST"); //设置请求方式为post
conn.setReadTimeout(5000);//设置超时信息
conn.setConnectTimeout(5000);//设置超时信息
conn.setDoInput(true);//设置输入流,允许输入
conn.setDoOutput(true);//设置输出流,允许输出
conn.setUseCaches(false);//设置POST请求方式不能够使用缓存
/*
定义我们要传给servlet的参数,格式好像一定要xxx=xxx,代表键值对,
如果有多组,要加一个&, //如“cmd1=version&cmd2=value”
*/
String data = "n1=" + n1 + "&n2=" + n2;
// System.out.println("shuju" +" " + n1 +" "+n2);
/*
获取输出流,其实在这之前还应该有一个操作:conn.connect();
意思为建立HttpURLConnection连接,只不过//getOutputStream()方法会隐含
进行连接,所以不调用connect()也可以建立连接
*/
OutputStream out = conn.getOutputStream();
//把data里的数据以字节的形式写入out流中
out.write(data.getBytes());
//刷新,将数据缓冲区中的数据全部输出,并清空缓冲区
out.flush();
//关闭输出流并释放与流相关的资源
out.close();
/*
这里是将conn.getInputStream中的数据包装在字符流的缓冲流reader中
这里值得一说的是:无论是post还是get,http请求实际上直到HttpURLConnection
的getInputStream()这个函数
里面才正式发出去,同时getInputStream返回的值就是servlet返回的数据
*/
BufferedReader reader = new BufferedReader(new InputStreamReader(
conn.getInputStream()));
String line = null;
if ((line = reader.readLine()) != null) {
/*
如果数据比较多的话要把if换成while,循环体代码也要小改一下,
由于我当时只是测试,就没改
*/
msg = line;
}
Looper.prepare();//为了在子线程中使用Toast
Toast.makeText(MainActivity.this, "The answer is " +
msg, Toast.LENGTH_SHORT).show();
Looper.loop();
conn.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
最后在AndroidManifest.xml中声明网页权限,并且允许使用未加密网络
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.tomcattest">
<uses-permission android:name="android.permission.INTERNET"/>
<application
....
android:usesCleartextTraffic="true">
....
</application>
</manifest>
关于URL="http://10.0.2.2:8080/WebProject_war/Servlet"
中链接的写法,就是你的ip:端口/项目名/访问文件
在一般的JavaWeb程序开发中,我们通常使用localhost或者127.0.0.1来访问本机的Web服务,但是如果我们在Android模拟器中也采用同样的地址来访问,Android模拟器将无法正常访问到我们的服务,这是为什么呢?
我们可以这样来理解:Android的底层是Linux kernel,包括Android本身就是一个操作系统,因此,这时我们在模拟器的浏览器中输入的localhost或127.0.0.1所代表的是Android模拟器(Android虚拟机),而不是你的电脑,明白了吗?这就是为什么你在模拟器中使用localhost时会报“Web
page not available”的原因。
那到底要如何才能访问到本地电脑上的Web应用呢?在Android中,默认将我们本地电脑的地址映射为10.0.2.2,因此,只需要将原先的localhost或者127.0.0.1换成10.0.2.2,就可以在模拟器上访问本地计算机上的Web资源了。
这样,一个简单的求和计算机就生成了。
账户登录与注册
数据库用的MySQL ,数据库名为login,表名为user_table,字段如上图所示,其实这里演示只需要user和pwd两个属性就够了。
web后端:
用Eclipse写的
项目名为LoginTest,结构如下
这里主要是访问LoginCheckServlet,里面实现登录和注册的逻辑,而具体实现在Dao下。
接着导出改项目的war包,不管是IDEA还是Eclipse导出War包的博客有很多,这里不在讲了。
导出后,将war包放在tomcat根目录下的webapps文件夹下。并且在根目录的bin文件夹中点击startup.bat启动tomcat。
代码如有需要,去github自取。
android前端:
项目名LoginTest
页面两个输入框两个按钮,activity_main.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:padding="13dp"
android:orientation="vertical">
<EditText
android:id="@+id/admin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="账户"/>
<EditText
android:id="@+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="密码"
android:inputType="textPassword"/>
<Button
android:id="@+id/regist"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="注册"/>
<Button
android:id="@+id/login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="登录"/>
</LinearLayout>
然后在MainActivity.java中实现具体逻辑
package com.example.logintest;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private EditText admin;
private EditText password;
private Button login;
private Button regist;
final String URL_LOGIN ="http://10.0.2.2:8080/LoginTest/loginCheckServlet";//根据自己的项目需要修改
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
admin = (EditText)findViewById(R.id.admin);
password = (EditText) findViewById(R.id.password);
login = (Button) findViewById(R.id.login);
regist = (Button) findViewById(R.id.regist);
login.setOnClickListener(this);
regist.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.login:
Log.d("Main","Start");
new Thread(new Runnable() {
@Override
public void run() {
String ad = admin.getText().toString();
String pw = password.getText().toString();
String flag = "";
try {
Log.d("Main","Continue");
URL url =new URL(URL_LOGIN);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST"); //设置请求方式为post
conn.setReadTimeout(5000);//设置超时信息
conn.setConnectTimeout(5000);//设置超时信息
conn.setDoInput(true);//设置输入流,允许输入
conn.setDoOutput(true);//设置输出流,允许输出
conn.setUseCaches(false);//设置POST请求方式不能够使用缓存
String data = "admin=" + ad + "&password=" + pw + "&flag=login";
OutputStream out = conn.getOutputStream();
out.write(data.getBytes());
out.flush();
out.close();
BufferedReader reader = new BufferedReader(new InputStreamReader(
conn.getInputStream()));
String line = null;
if ((line = reader.readLine()) != null) {
/*
如果数据比较多的话要把if换成while,循环体代码也要小改一下,
由于我当时只是测试,就没改
*/
flag = line;
}
} catch (IOException e) {
e.printStackTrace();
}
String msg = "";
if(flag.equals("true")) msg = "登录成功";
else msg = "失败";
Log.d("Main",msg);
Looper.prepare();
Toast.makeText(MainActivity.this, msg,
Toast.LENGTH_SHORT).show();
Looper.loop();
}
}).start();
break;
case R.id.regist:
new Thread(new Runnable() {
@Override
public void run() {
String ad = admin.getText().toString();
String pw = password.getText().toString();
String flag = "";
try {
URL url =new URL(URL_LOGIN);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST"); //设置请求方式为post
conn.setReadTimeout(5000);//设置超时信息
conn.setConnectTimeout(5000);//设置超时信息
conn.setDoInput(true);//设置输入流,允许输入
conn.setDoOutput(true);//设置输出流,允许输出
conn.setUseCaches(false);//设置POST请求方式不能够使用缓存
String data = "admin=" + ad + "&password=" + pw + "&flag=regist";
OutputStream out = conn.getOutputStream();
out.write(data.getBytes());
out.flush();
out.close();
BufferedReader reader = new BufferedReader(new InputStreamReader(
conn.getInputStream()));
String line = null;
if ((line = reader.readLine()) != null) {
/*
如果数据比较多的话要把if换成while,循环体代码也要小改一下,
由于我当时只是测试,就没改
*/
flag = line;
}
} catch (IOException e) {
e.printStackTrace();
}
String msg = "";
if(flag.equals("true")) msg = "注册成功";
else msg = "注册失败";
Looper.prepare();
Toast.makeText(MainActivity.this, msg,
Toast.LENGTH_SHORT).show();
Looper.loop();
}
}).start();
break;
default:
}
}
}
最后在AndroidManifest.xml中声明网页权限,并且允许使用未加密网络
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.tomcattest">
<uses-permission android:name="android.permission.INTERNET"/>
<application
....
android:usesCleartextTraffic="true">
....
</application>
</manifest>
关于URL="http://10.0.2.2:8080/WebProject_war/Servlet"
中链接的写法,就是你的ip:端口/项目名/访问文件
在一般的JavaWeb程序开发中,我们通常使用localhost或者127.0.0.1来访问本机的Web服务,但是如果我们在Android模拟器中也采用同样的地址来访问,Android模拟器将无法正常访问到我们的服务,这是为什么呢?
我们可以这样来理解:Android的底层是Linux kernel,包括Android本身就是一个操作系统,因此,这时我们在模拟器的浏览器中输入的localhost或127.0.0.1所代表的是Android模拟器(Android虚拟机),而不是你的电脑,明白了吗?这就是为什么你在模拟器中使用localhost时会报“Web
page not available”的原因。
那到底要如何才能访问到本地电脑上的Web应用呢?在Android中,默认将我们本地电脑的地址映射为10.0.2.2,因此,只需要将原先的localhost或者127.0.0.1换成10.0.2.2,就可以在模拟器上访问本地计算机上的Web资源了。