3.10
手机端新课程添加功能实现
设计思想:
本功能旨在实现一个手机端的课程添加界面,主要包含以下验证逻辑:
- 课程名称唯一性验证
- 教师姓名合法性验证(限定9位特定教师)
- 上课地点格式验证(必须以特定教学楼前缀开头)
- 数据持久化到远程数据库
采用MVVM架构设计,前端使用Android原生开发,后端使用Spring Boot提供RESTful API,数据库使用MySQL。
源程序代码:
- Android前端代码
activity_add_course.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:orientation="vertical"
android:padding="16dp">
<EditText
android:id="@+id/etCourseName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="课程名称"/>
<EditText
android:id="@+id/etTeacher"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="任课教师"/>
<EditText
android:id="@+id/etLocation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="上课地点"/>
<Button
android:id="@+id/btnSave"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="保存"/>
</LinearLayout>
AddCourseActivity.kt
class AddCourseActivity : AppCompatActivity() {
private lateinit var binding: ActivityAddCourseBinding
private val viewModel: CourseViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityAddCourseBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.btnSave.setOnClickListener {
val courseName = binding.etCourseName.text.toString()
val teacher = binding.etTeacher.text.toString()
val location = binding.etLocation.text.toString()
if (validateInput(courseName, teacher, location)) {
viewModel.addCourse(courseName, teacher, location)
}
}
viewModel.result.observe(this) { result ->
when (result) {
is Result.Success -> {
Toast.makeText(this, "课程添加成功", Toast.LENGTH_SHORT).show()
finish()
}
is Result.Error -> {
Toast.makeText(this, result.message, Toast.LENGTH_SHORT).show()
}
}
}
}
private fun validateInput(courseName: String, teacher: String, location: String): Boolean {
if (courseName.isEmpty()) {
Toast.makeText(this, "课程名称不能为空", Toast.LENGTH_SHORT).show()
return false
}
val validTeachers = listOf("王建民", "刘立嘉", "刘丹", "杨子光", "张云霞", "武永亮", "高飞", "孙静", "黄荣峰")
if (!validTeachers.contains(teacher)) {
Toast.makeText(this, "教师不在允许名单中", Toast.LENGTH_SHORT).show()
return false
}
val validPrefixes = listOf("一教", "二教", "三教", "基教")
if (!validPrefixes.any { location.startsWith(it) }) {
Toast.makeText(this, "上课地点必须以一教、二教、三教或基教开头", Toast.LENGTH_SHORT).show()
return false
}
return true
}
}
- 后端Spring Boot代码
CourseController.java
@RestController
@RequestMapping("/api/courses")
public class CourseController {
@Autowired
private CourseService courseService;
@PostMapping
public ResponseEntity<?> addCourse(@RequestBody CourseDto courseDto) {
try {
Course course = courseService.addCourse(courseDto);
return ResponseEntity.ok(course);
} catch (DuplicateCourseException e) {
return ResponseEntity.badRequest().body(e.getMessage());
}
}
}
CourseService.java
@Service
public class CourseService {
@Autowired
private CourseRepository courseRepository;
public Course addCourse(CourseDto courseDto) throws DuplicateCourseException {
if (courseRepository.existsByCourseName(courseDto.getCourseName())) {
throw new DuplicateCourseException("课程名称重复,重新录入");
}
Course course = new Course();
course.setCourseName(courseDto.getCourseName());
course.setTeacher(courseDto.getTeacher());
course.setLocation(courseDto.getLocation());
return courseRepository.save(course);
}
}
3. 数据库表结构
CREATE TABLE courses (
id INT AUTO_INCREMENT PRIMARY KEY,
course_name VARCHAR(100) NOT NULL UNIQUE,
teacher VARCHAR(50) NOT NULL,
location VARCHAR(100) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
- 输入验证失败 :当教师姓名不在允许名单中时提示错误
- 地点验证失败 :当地点不以指定前缀开头时提示错误
- 课程重复 :当课程名称已存在时提示错误
- 添加成功 :所有验证通过后成功添加课程
编程总结分析
实现难点
- 输入验证逻辑 :需要在客户端和服务端都实现验证逻辑,确保数据一致性
- 网络请求处理 :Android端需要正确处理网络请求和响应,包括错误情况
- 用户体验 :在验证失败时给出明确的错误提示
解决方案:
- 采用前后端双重验证机制,确保数据有效性
- 使用Kotlin协程处理网络请求,避免主线程阻塞
- 设计清晰的错误提示信息,帮助用户理解问题
改进方向:
-
增加自动补全功能,帮助用户输入教师姓名和地点
-
实现离线缓存功能,在网络不可用时暂存数据
-
添加更多课程相关信息,如上课时间、学分等
PSP0级时间记录日志
| 任务 | 开始时间 | 结束时间 | 耗时 | 备注 |
|---|---|---|---|---|
| 需求分析 | 10:00 | 10:30 | 30min | 明确功能需求 |
| UI设计 | 10:30 | 11:00 | 30min | 设计界面布局 |
| Android编码 | 11:00 | 12:30 | 90min | 实现前端逻辑 |
| 后端API开发 | 14:00 | 15:30 | 90min | 实现RESTful API |
| 数据库设计 | 15:30 | 16:00 | 30min | 设计表结构 |
| 联调测试 | 16:00 | 17:30 | 90min | 前后端联调 |
| 文档撰写 | 17:30 | 18:00 | 30min | 编写博客和记录 |
| 总计 | 5h |
通过本次开发,我掌握了手机端表单验证的实现方法,以及如何设计前后端分离的应用架构。在未来的开发中,我会更加注重用户体验和代码的可维护性。

浙公网安备 33010602011771号