由于之前那篇文章是在大学期间好多东西都不太懂的时候写的,放到现在再来看总感觉到处都是问题(或者说已经看不懂啦)。但是看到每天上涨的那点阅读量,想了想还是把这个再用相对正常的方式再重写一遍吧。
为了省事本项目的服务端采用SpringBoot + MybatisPlus开发,要是Java水平还不够的小伙伴就自己再稍微努力努力 (°∀°)ノ
一、服务端
首先对SpringBoot提一嘴,这玩意是用来简化Spring应用的初始搭建以及开发过程的。
创建好工程之后在pom文件中导入相关依赖,用到的大概有mysql、druid、mybatis。mybatis-plus、fastjson、lombok等。
随后对配置信息进行设置,这里采用yml文件的格式。
server:
port: 80
spring:
#数据库相关配置
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/db1?serverTimezone=UTC
username: root
password: 1234
#设置数据源为druid
type: com.alibaba.druid.pool.DruidDataSource
cache:
redis:
time-to-live: 1800000
mybatis-plus:
global-config:
db-config:
id-type: assign_id
configuration:
#在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
随后就是紧张刺激(并不)的代码开发啦。
由于本项目只是为了实现Android访问MySQL数据库,就只是模拟实现了一个用户登录功能。
先准备好MySQL中的数据:
对应好实体类中的User类:
@Data
public class User {
private Integer id;
private String userId;
private String userName;
private String password;
private String phoneNumber;
private String sex;
private String personalSignature;
}
由于使用了MybatisPlus,所以数据层会显的非常简单:
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
业务层接口:
public interface UserService extends IService<User> {
Result<User> login(String userId, String password);
}
业务层实现:
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public Result<User> login(String userId, String password) {
// 1、校验参数
if (StringUtils.isBlank(userId) || StringUtils.isBlank(password)) {
return Result.error("请输入账号和密码");
}
// 2、构造查询条件
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getUserId, userId);
queryWrapper.eq(User::getPassword, password);
User user = userMapper.selectOne(queryWrapper);
// 3、判断查询结果
if (user != null) {
return Result.success(user);
} else {
return Result.error("账号或密码错误");
}
}
}
表现层:
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/login")
public Result<User> login(@RequestBody Map<String, String> userInfo) {
log.info("用户登录");
String userId = userInfo.get("userId");
String password = userInfo.get("password");
return userService.login(userId, password);
}
}
其中的Result为通用的返回结果类,包含了状态码、错误信息以及返回数据等内容。
至此,服务端的开发就告一段落。运行启动类,进行调试。
二、Android端
创建完工程后简单的写两个页面,一个用于登录,一个用于展示信息。
对页面控件进行初始化完成后,给按钮添加一个点击事件:
btn_login.setOnClickListener(v -> {
String id = et_id.getText().toString();
String pwd = et_pwd.getText().toString();
// 判断用户输入账号和密码是否为空
if (StringUtil.isNotEmpty(id) && StringUtil.isNotEmpty(pwd)){
loginTest(id, pwd);
}else {
ToastUtil.showShort( LoginActivity.this, "请输入账号和密码");
}
});
具体实现思路是:使用OkHttp向服务端发送请求,将服务端返回的JSON数据用GSON进行解析,从而将在数据库中获取到的信息进行展示。具体实现如下:
private void loginTest(String id, String pwd) {
new Thread(() -> {
try {
// 创建OKHttp客户端
OkHttpClient client = new OkHttpClient();
// 构造消息体(不是JSON格式)
RequestBody requestBody = new FormBody.Builder()
.add("userId", id)
.add("password", pwd)
.build();
// 发送post请求
Request request = new Request.Builder()
.url("http://server.natappfree.cc:39945/user/login")
.post(requestBody)
.build();
// 获取响应
Response response = client.newCall(request).execute();
String userInfo = response.body().string();
// 利用GSON将返回的JSON格式数据转化为对象
Gson gson = new Gson();
Result result = gson.fromJson(userInfo, Result.class);
// 判断返回结果,确认登录是否成功
if (result == null) {
ToastUtil.showShortInThread(LoginActivity.this, "登录失败");
return;
}
if (result.getCode() == 1 && result.getData() != null) {
String userStr = result.getData().toString();
User user = gson.fromJson(userStr, User.class);
Intent intent = new Intent(LoginActivity.this, UserInfoActivity.class);
intent.putExtra("User", user);
startActivity(intent);
} else {
ToastUtil.showShortInThread(LoginActivity.this, result.getMsg());
return;
}
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
其中的请求地址使用了NATAPP内网穿透工具将本地的端口进行映射,使得外网也可以访问。(免费隧道每次启动时地址会发生变化)
启动项目:
登录页面
输入正确的账号密码信息,点击登录,并没有反应。检查服务器后发现报了一个异常:
2023-02-22 17:42:58.922 WARN 9424 --- [p-nio-80-exec-5] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported]
经排查发现,在服务端接收参数时使用了@RequestBody注解,表示我们接收的是一个JSON格式的数据,但是OkHttp发送的数据并不是JSON数据,因此在这里报了异常。那么只要在接收参数时直接用两个变量接收即可解决这个问题,修改UserController中的代码:
@PostMapping("/login")
public Result<User> login(String userId, String password) {
log.info("用户登录");
return userService.login(userId, password);
}
重启服务,后再次尝试登陆:
访问成功,撒花✿ヽ(°▽°)ノ✿