拿了一个比较完整的springbootMVC的框架以及源码进行了相应的学习
SpringBootMVC的结构解读:
对于SpringBoot来说一个高内聚低耦合的框架必须要遵守一个能够承受得住较大量开发的逻辑难度,有些开发者是单人开发,所面临的主要开发问题是如何记住自己写过的每一个功能,并且某些功能与功能之间也可能出现一些功能上的重合,可能需要调用很多相同的函数或者是根本就是相似的写法或者功能,如何去组织这些功能之间的耦合性与内聚性达到一种比较和谐的平衡关系,这就需要有一套管理代码调用的机制MVC,在一般的开发者面前这个机制也许是用来管理代码的,更有深层次的解读。
View层:用于接受用户提交请求的代码,也就是在我们所开发的项目中的所用到的Controller层,这一层负责将前端开发者用到的服务整合并将接口暴露出来用于接受前端开发者的请求与传入的参数并对其进行一定的提取和整合,接着将前端请求逻辑上进行对服务层的接口进行调用。
Service层:系统的业务逻辑主要在这里完成。用户的请求在View层得到处理后调用Service层的函数来实现具体的操作并将后端数据库的操作进行调用,从而实现整个逻辑层。
Dao层:Service层的逻辑实现过程中会对数据库进行操作,Dao层就是实现了一系列对数据库操作的函数和类。
这三层都会以接口或者抽象方式将自己的所提供的函数暴露出来,上层对下层的调用通过接口来实现,底层才是上层逻辑或者要求的服务的真正提供者。
在这三层之外,对于数据库的操作,也就是Dao这一层,我们将数据库返回出来的关系也可以抽象成一个实体类,于是Dao层中对数据库进行操作过程中传出的参数,会直接由SpringBoot中对注解以及封装的接口将其自动封装为自己之前定义好的实体类,也就是entity,如果我们使用传统的mybatis生成结构的话,会出现比较传统的xml注入的情况,于是也就有了对应的Dao层对于xml的映射关系,对于这层关系来说,每一个Dao操作的类,都会对应在Mapper.xml中找到对应自己接口名的id,在规定好传入参数和穿出参数后,就可以进行合理的映射,每当有服务层的服务去调用Dao层对数据库调用的接口时,Dao的接口在注解的封装下就会自动去映射其对应的Mapper.xml中所调用接口的xml标签,对应找到标签以后会在标签内所写的结构化的sql语言的注入到数据库中,从而实现对应的数据库的操作。
SpringBoot注解解读:
对于一般的使用上面来说,如果不用mybatis的话我是这么使用的:
首先我们从entity层开始写起,这一层在一般情况下不需要注解,因为只是一个实体类。
写好对应的entity实体类时候我们开始对Dao数据库层进行操作,Dao中首先需要Mapper将这个接口与对应的XML对应上,然后按照我的习惯,会直接对对应的接口进行数据库操作的注入,直接在接口上方用@Insert或者@Delete等来注入比如:
public interface PaperMaitainDao{
@Insert("INSERT INTO paper_maitain (tea_id,paper_id,qulid_id) VALUES (#{teaId}, #{paperId},#{qualifId})")
boolen insertPaperMaitain(PaperMaitain paperMaitian);
//PaperMaitain是在entity中的实体类
}
做好这一层的逻辑构成了,我们开始更上一层的服务层在这里我们需要注册一个服务接口@Service
然后注入对应要使用的Dao的接口服务,一般使用到@Resource或者@Autowired
然后我们就可以写对应的服务接口了
@Service
public class TeacherService{
@Resource
private PaperMaintainDao paperMaintainDao;
public Boolean createPaperMaintain(PaperMaintain paperMaintain){
try {
return paperMaintainDao.insertPaperMaintain(paperMaintain);
} catch (Exception e){
e.printStackTrace();
}
return false;
}
}
我们的服务就此写好后,接下来就是将一系列的服务操作与前端对接风部分了Controller层
首先先声明这个对应的Controller使用@RestController
然后对应我们要在路由上面进行对应起来,@RequestMapping(value = “/teacher”)这一个总的接口会在root/teacher上面开启
@RestController
@RequestMapping(value = "/teacher")
public class TeacherController {
@Resource
private TeacherService teacherService;
//这里是直接调用服务层,引入资源
//做一个在/teacher下的路由映射,访问这个接口需要root/teacher/createPaperMaintain
@RequestMapping(value = "/createPaperMaintain")
@ResponseBody
public Result createPaperMaintains(@RequestBody Map<String, Object> request){
int teaId = (int) request.get("tea_id");
String paperId = (String) request.get("paper_id");
Integer qualifId = (Integer) request.get("qualif_id");
PaperMaintain paperMaintain = new PaperMaintain();
paperMaintain.setPaperId(paperId);
paperMaintain.setQualifId(qualifId);
paperMaintain.setTeaId(teaId);
return Result.succ(teacherService.createPaperMaintain(paperMaintain));
}
}
关于应对前端传入的数组问题
前端传入的数组对于java来说其实是一个单独的ArrayList,所以可以单独用这个来接受,因此,就会有下面的操作
1.如果前端直接传输的是一个数组,则在Controller的接口层面就直接(@RequestBody ArrayList<数组中json在实体类对应的类型> request)
2.直接在实体类中定义对应的接收的实体类,然后定义前端要专递数据的类型
比如下面这个实体类:
public class StudentCourseUpdaterCollection {
private Integer courseId;
private List<StudentCourseUpdater> studentCourseUpdaters;
public Integer getCourseId() {
return courseId;
}
public void setCourseId(Integer courseId) {
this.courseId = courseId;
}
public List<StudentCourseUpdater> getStudentCourseUpdaters() {
return studentCourseUpdaters;
}
public void setStudentCourseUpdaters(List<StudentCourseUpdater> studentCourseUpdaters) {
this.studentCourseUpdaters = studentCourseUpdaters;
}
}
然后后端的接收的接口是这样的:
@RequestMapping(value = "/updateStuCourseByKey")
@ResponseBody
public Result updateStuCourseByKey(@RequestBody StudentCourseUpdaterCollection studentCourseUpdaterCollection){
ArrayList<Integer> ids= new ArrayList<Integer>();
//System.out.println(studentCourseUpdaterCollection.getCourseId());
for( StudentCourseUpdater studentCourseUpdater: studentCourseUpdaterCollection.getStudentCourseUpdaters() ){
try {
if(teacherService.updateStuCourseByKey(studentCourseUpdater)==0){
ids.add(studentCourseUpdater.getStuId());
}
}catch (Exception e) {
ids.add(studentCourseUpdater.getStuId());
//System.out.println(studentCourseUpdater.getStuId());
}
//System.out.println(studentCourseUpdater.getScore());
}
if(ids.size()==0){
return Result.succ("操作成功");
}else {
String msg="";
for (int id:ids){
msg+=id+",";
}
return Result.fail("操作失败!"+"失败id:"+msg);
}
}
前端在传递参数的时候也要按照对应的格式来
{
"courseId":480120,
"studentCourseUpdaters":[
{
"stuId":201656788,
"courseId":80120,
"score":79
}
]
}
以上是一个比较粗略的一个springboot从整体到局部的一个解析,也是这一周将之前学到的知识参与实践的操作。