
2021.1.27 更新
已更新新版本部落格,更新内容很多,是以新開了一篇部落格,戳這裡。
1 概述
使用spring boot作為後端架構與Android端配合mysql進行基本的互動,包含了最基本的增删查改功能.
2 開發環境
- Win
- IDEA 2019.2
- Tomcat 9.0.27
- MySQL 8.0.17
- Spring Boot 2.2.1
- JDK 8
3 後端
3.1 建立一個Spring Boot項目
參考這裡.
3.2 實體類
建立User類作為實體類:
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
用的其實是3.1連結中的代碼,裡面有詳細的解釋.
3.3 持久層
建立UserRepository實作增删查改:
@Repository
public interface UserRepository extends CrudRepository<User,Integer>
{
@Query(value = "select * from user where name = ?1",nativeQuery = true)
public List<User> findByName(String name);
@Modifying
@Query(value = "delete from user where name = ?1",nativeQuery = true)
public int deleteByName(String name);
}
由于CrudRepository中已經包含了"增"與"改",是以按需要實作自己的"查"與"删"即可.
CrudRepository的api很簡單,官方文檔在這裡.
- "增"使用
即可,參數為實體類save
- "删"使用
,通過主鍵删除,若不想通過主鍵删除可以自己編寫sql,像上面一樣deleteById
- "查"使用
或findAll
,自定義查找的話需要自己編寫SQLfindById
- "改"也可使用
,注意需要設定主鍵save
@Query
用于設定SQL語句,
nativeQuery
表示使用原生SQL.
3.4 業務層
建立一個MainService.java:
@Transactional
@Service
public class MainService {
@Autowired
private UserRepository userRepository;
public Iterable<User> getAllUsers()
{
return userRepository.findAll();
}
public List<User> findByName(String name)
{
return userRepository.findByName(name);
}
public boolean add(String name)
{
User user = new User();
user.setName(name);
userRepository.save(user);
return true;
}
public boolean modify(Integer id,String name)
{
User user = new User();
user.setName(name);
user.setId(id);
userRepository.save(user);
return true;
}
public boolean deleteByName(String name)
{
return userRepository.deleteByName(name) != 0;
}
}
-
:傳回所有行,getAllUsers()
類型Iterable<E>
-
:根據name傳回所有name相同的行findByName()
-
直接使用了add
,由于save
傳回的是實體類,原本的代碼是這樣寫的:save
return userRepository.save(user) != null;
但是文檔說了不會為null,是以隻能強制傳回true了.
-
使用了id與name作為參數,建立一個user,将其作為setter的參數,然後交給savemodify
-
使用了自定義的删除函數,傳回的是int,在UserRepository中這個int代表SQL影響的行數,删除成功則行數不為0,删除失敗,或者沒有這行資料則行數為0.是以将傳回值與0進行比較deleteByName
3.5 控制層
@Controller
@RequestMapping(path = "/demo")
public class MainController {
@Autowired
private MainService mainService;
@GetMapping(path = "/getAll")
public @ResponseBody Iterable<User> getAllUsers()
{
return mainService.getAllUsers();
}
@PostMapping(path = "/get")
public @ResponseBody List<User> findByName(String name)
{
return mainService.findByName(name);
}
@PostMapping(path = "/add")
public @ResponseBody boolean add(@RequestParam String name)
{
return mainService.add(name);
}
@PostMapping(path = "/modify")
public @ResponseBody boolean modify(@RequestParam Integer id,@RequestParam String name)
{
return mainService.modify(id,name);
}
@PostMapping(path = "/delete")
public @ResponseBody boolean deleteByName(@RequestParam String name)
{
return mainService.deleteByName(name);
}
}
Controller主要就是幾個注解,除了getAllUsers使用Get外,其他的都是用Post.另外就是路徑設定,直接在path中設定即可.
後端的話到這裡就基本完成了,剩下的打包部署操作就不說了,需要的可以參考這裡.
4 Android端
什麼建立工程之類的就不說了.
貼上部分MainActivity,完整代碼見文末:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
register.setOnClickListener(v ->{new Thread(()-> {
OkHttpClient okHttpClient = new OkHttpClient();
String name = ((EditText) findViewById(R.id.name)).getText().toString();
FormBody formBody = new FormBody.Builder().add("name", name).build();
Request request = new Request.Builder()
.url(Constant.ADD)
.post(formBody)
.build();
try (Response response = okHttpClient.newCall(request).execute()) {
Looper.prepare();
if (Boolean.parseBoolean(response.body().string()))
{
Toast.makeText(this, "注冊成功", Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(this, "注冊失敗", Toast.LENGTH_SHORT).show();
}
Looper.loop();
}
//...
}).start();});
login.setOnClickListener(v ->{new Thread(()-> {
OkHttpClient okHttpClient = new OkHttpClient();
String name = ((EditText) findViewById(R.id.name)).getText().toString();
FormBody formBody = new FormBody.Builder().add("name", name).build();
Request request = new Request.Builder()
.url(Constant.GET)
.post(formBody)
.build();
try (Response response = okHttpClient.newCall(request).execute()) {
List<User> users = JSONArray.parseArray(response.body().string(),User.class);
Looper.prepare();
if(users.size() == 0)
{
Toast.makeText(this,"登入失敗",Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(this,"登入成功",Toast.LENGTH_SHORT).show();
}
Looper.loop();
}
//...
}).start();});
delete.setOnClickListener(v ->{new Thread(()-> {
OkHttpClient okHttpClient = new OkHttpClient();
String name = ((EditText) findViewById(R.id.name)).getText().toString();
FormBody formBody = new FormBody.Builder().add("name", name).build();
Request request = new Request.Builder()
.url(Constant.DELETE)
.post(formBody)
.build();
try (Response response = okHttpClient.newCall(request).execute()) {
Looper.prepare();
if (Boolean.parseBoolean(response.body().string()))
{
Toast.makeText(this, "删除成功", Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(this, "删除失敗", Toast.LENGTH_SHORT).show();
}
Looper.loop();
}
//...
}).start();});
modify.setOnClickListener(v ->{new Thread(()-> {
OkHttpClient okHttpClient = new OkHttpClient();
String name = ((EditText) findViewById(R.id.name)).getText().toString();
String id = ((EditText)findViewById(R.id.id)).getText().toString();
FormBody formBody = new FormBody.Builder()
.add("name", name)
.add("id",id)
.build();
Request request = new Request.Builder()
.url(Constant.MODIFY)
.post(formBody)
.build();
try (Response response = okHttpClient.newCall(request).execute()) {
Looper.prepare();
if (Boolean.parseBoolean(response.body().string()))
{
Toast.makeText(this, "修改成功", Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(this, "修改失敗", Toast.LENGTH_SHORT).show();
}
Looper.loop();
}
//...
}).start();});
}
}
下面分别進行CRUD操作.
4.1 增
OkHttpClient okHttpClient = new OkHttpClient();
String name = ((EditText) findViewById(R.id.name)).getText().toString();
FormBody formBody = new FormBody.Builder().add("name", name).build();
Request request = new Request.Builder()
.url(Constant.ADD)
.post(formBody)
.build();
try (Response response = okHttpClient.newCall(request).execute()) {
Looper.prepare();
if (Boolean.parseBoolean(response.body().string()))
{
Toast.makeText(this, "注冊成功", Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(this, "注冊失敗", Toast.LENGTH_SHORT).show();
}
Looper.loop();
} catch (IOException e) {
e.printStackTrace();
}
使用OkHttp,通過
FormBody
設定參數,然後建立
Request
通過
OkHttpClient
發送.
由于後端"增"的方法傳回的是一個true,是以這裡将
response.body().string()
轉換成
boolean
判斷是否操作成功.
稍微提一下,
Looper.prepare();
Looper.loop();
這兩行可以在非UI線程中使用
Toast
.
4.2 删
OkHttpClient okHttpClient = new OkHttpClient();
String name = ((EditText) findViewById(R.id.name)).getText().toString();
FormBody formBody = new FormBody.Builder().add("name", name).build();
Request request = new Request.Builder()
.url(Constant.DELETE)
.post(formBody)
.build();
try (Response response = okHttpClient.newCall(request).execute()) {
Looper.prepare();
if (Boolean.parseBoolean(response.body().string()))
{
Toast.makeText(this, "删除成功", Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(this, "删除失敗", Toast.LENGTH_SHORT).show();
}
Looper.loop();
} catch (IOException e) {
e.printStackTrace();
}
删這部分也是差不多的,就是改一下url,然後....然後沒有了....好像很簡單的樣子?2333333
4.3 查
OkHttpClient okHttpClient = new OkHttpClient();
String name = ((EditText) findViewById(R.id.name)).getText().toString();
FormBody formBody = new FormBody.Builder().add("name", name).build();
Request request = new Request.Builder()
.url(Constant.GET)
.post(formBody)
.build();
try (Response response = okHttpClient.newCall(request).execute()) {
List<User> users = JSONArray.parseArray(response.body().string(),User.class);
Looper.prepare();
if(users.size() == 0)
{
Toast.makeText(this,"登入失敗",Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(this,"登入成功",Toast.LENGTH_SHORT).show();
}
Looper.loop();
} catch (IOException e) {
e.printStackTrace();
}
查這裡注意一下後端傳回的是
List
,這裡借助阿裡的
fastjson
List
List<User> users = JSONArray.parseArray(response.body().string(),User.class);
然後判斷有沒有的話就判斷長度是否為0即可.
4.4 改
OkHttpClient okHttpClient = new OkHttpClient();
String name = ((EditText) findViewById(R.id.name)).getText().toString();
String id = ((EditText)findViewById(R.id.id)).getText().toString();
FormBody formBody = new FormBody.Builder()
.add("name", name)
.add("id",id)
.build();
Request request = new Request.Builder()
.url(Constant.MODIFY)
.post(formBody)
.build();
try (Response response = okHttpClient.newCall(request).execute()) {
Looper.prepare();
if (Boolean.parseBoolean(response.body().string()))
{
Toast.makeText(this, "修改成功", Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(this, "修改失敗", Toast.LENGTH_SHORT).show();
}
Looper.loop();
} catch (IOException e) {
e.printStackTrace();
}
改的話隻需一個額外的ID參數,在FormBody中add一個即可,不難.
4.5 UI
UI不詳細說了,就幾個簡單的Button,具體可以看代碼中的xml檔案.
4.6 依賴與其他
注意一下依賴,還有設定java8.
compileOptions{
sourceCompatibility=1.8
targetCompatibility=1.8
}
dependencies{
implementation 'com.squareup.okhttp3:okhttp:x.x.x'
implementation 'com.alibaba:fastjson:x.x.x'
}
- OkHttp最新版本戳這裡檢視
- fastjson最新版本戳這裡檢視
4.7 網絡權限
這個筆者之前的文章有說,主要就是
AndroidManifest.xml
中的權限設定,請看這裡.
5 測試
原始資料庫:
注冊一個:
看看資料庫:
測試登入:
試試登入一個不存在的:
修改:
最後是删除:
删除一個不存在的會删除失敗.
6 源碼
- Github
- 碼雲
- CODE.CHINA
如果覺得文章好看,歡迎點贊。
同時歡迎關注微信公衆号:氷泠之路。