文章目录
需求分析
用例分析
数据库设计
一共设计了3张表
s_user: 存储用户信息
s_homework: 存储教师发布的作业
s_student_homework: 存储学生提交的作业
为了查询方便,没有设置外键约束
开发技术
开发平台:windows 10
开发工具:Intellij IDEA 2019.3.3
JDK:Java 8
Maven:maven-3.6.3
服务器:tomcat 7.0
数据库:MySQL 8.0
数据源:Druid1.1.6
Spring Boot:1.5.6.RELEASE
ORM框架:MyBatis+通用Mapper
实现过程
- 项目目录
搭建IDEA+springboot项目
- File –> New –> Project
- Spring Initializer –> 选择SDK–>Next
- 创建项目的文件结构以及jdk的版本 –> Next
- 选择项目所需要的依赖
使用mysql创建数据库
sql语句如下:
CREATE DATABASE `school` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */;
CREATE TABLE `s_user` (
`account` char(8) NOT NULL,
`password` char(18) NOT NULL,
`name` varchar(20) NOT NULL,
`type` int NOT NULL,
PRIMARY KEY (`account`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
CREATE TABLE `s_homework` (
`id` bigint NOT NULL AUTO_INCREMENT,
`title` varchar(20) DEFAULT NULL,
`content` text,
`score` int NOT NULL,
`techerid` char(8) NOT NULL,
`create_time` timestamp NOT NULL,
`update_time` timestamp NULL DEFAULT NULL,
`teacher_name` char(8) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
CREATE TABLE `s_student_homework` (
`id` bigint NOT NULL AUTO_INCREMENT,
`student_id` char(8) DEFAULT NULL,
`homework_id` bigint NOT NULL,
`homework_title` varchar(45) NOT NULL,
`homework_content` text,
`score` int DEFAULT NULL,
`comment` char(150) DEFAULT NULL,
`create_time` timestamp NOT NULL,
`update_time` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
使用mybatis generator 自动生成代码:
- 创建application.yml配置文件,配置datasource和mybatis
server:
port: 8080
spring:
datasource:
name: test
url: jdbc:mysql://127.0.0.1:3306/school
#serverTimezone: UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
username: root
password: 123456
# 使用druid数据源
#type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
filters: stat
maxActive: 20
initialSize: 1
maxWait: 60000
minIdle: 1
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: select 'x'
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxOpenPreparedStatements: 20
## 该配置节点为独立的节点,有很多同学容易将这个配置放在spring的节点下,导致配置无法被识别
mybatis:
mapper-locations: classpath:mapping/*.xml #注意:一定要对应mapper映射xml文件的所在路径
type-aliases-package: com.winter.model # 注意:对应实体类的路径
- 在pom.xml中添加generator 插件
<!-- mybatis generator 自动生成代码插件 -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
<configuration>
<configurationFile>${basedir}/src/main/resources/generator/generatorConfig.xml</configurationFile>
<overwrite>true</overwrite>
<verbose>true</verbose>
</configuration>
</plugin>
- 创建pom.xml中generator 插件所对应的配置文件 generatorConfig.xml
设置数据库驱动
设置数据库连接
设置生成模型的包名和位置
设置生成映射文件的包名和位置
设置DAO的包名和位置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!-- 数据库驱动:选择你的本地硬盘上面的数据库驱动包-->
<classPathEntry location="E:/developer/mybatis-generator-core-1.3.2/lib/mysql-connector-java-5.1.25-bin.jar"/>
<context id="DB2Tables" targetRuntime="MyBatis3">
<commentGenerator>
<property name="suppressDate" value="true"/>
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!--数据库链接URL,用户名、密码 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://127.0.0.1/mytest" userId="root" password="root">
</jdbcConnection>
<javaTypeResolver>
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<!-- 生成模型的包名和位置-->
<javaModelGenerator targetPackage="com.winter.model" targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!-- 生成映射文件的包名和位置-->
<sqlMapGenerator targetPackage="mapping" targetProject="src/main/resources">
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>
<!-- 生成DAO的包名和位置-->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.winter.mapper" targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<!-- 要生成的表 tableName是数据库中的表名或视图名 domainObjectName是实体类名-->
<table tableName="s_user" domainObjectName="User" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
<table tableName="s_student_homework" domainObjectName="StudentHomework" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
<table tableName="s_homework" domainObjectName="Homework" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
</context>
</generatorConfiguration>
- 点击run-Edit Configurations
- 添加配置
- 运行generator
对应generatorConfig.xml中的配置,每张表对应生成模型、映射文件、DAO
- 在springboot启动类中吧mapper的路径加进来
@MapperScan : mapper接口扫描注解
重复运行时模型和DAO文件会重写,映射文件文件不会,将导致项目运行时会出错
解决办法:重新运行之前先删除mapper.xml文件
我们还需要一些特殊的sql语句,可以自己添加
比如实现:select * from s_homework
HomeworkMapper.java 中添加如下代码
List<Homework> selectAll();
HomeworkMapper.xml
<select id="selectAll" resultMap="ResultMapWithBLOBs" parameterType="java.lang.Long" >
select
<include refid="Base_Column_List" />
,
<include refid="Blob_Column_List" />
from s_homework
order by create_time DESC
</select>
编写Service
遵循单一责任原则和接口分离原则
- UserService
package com.winter.service; import com.winter.model.User; /** * Created by wjq */ public interface UserService { int addUser(User user); User selectUser(String account); }
- UserHomeworkServiceImpl
package com.winter.service; import com.winter.mapper.UserMapper; import com.winter.model.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service(value = "userService") public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper;//这里会报错,但是并不会影响 @Override public User selectUser(String account) { return userMapper.selectByPrimaryKey(account); } @Override public int addUser(User user) { return userMapper.insertSelective(user); } }
- HomeworkService
package com.winter.service; import com.winter.model.Homework; import java.util.List; /** * @author:Jingqi Wu * @date: 2020/4/23 */ public interface HomeworkService { /** * 老师发布作业 * @param homework * @return */ int addHomework(Homework homework); /** * This is the method to be used to list down all homework * @return */ List<Homework> selectAll(); List<Homework> selectByTeacherId(String teacherId); List<Homework> selectByTeacherName(String teacherName); Homework selectByPK(Long id); }
- HomeworkServiceImpl
package com.winter.service; import com.winter.mapper.HomeworkMapper; import com.winter.model.Homework; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; /** * @author:Jingqi Wu * @date: 2020/6/16 */ @Service(value = "homeworkService") public class HomeworkServiceImpl implements HomeworkService { @Autowired HomeworkMapper homeworkMapper; /** * 老师发布作业 * * @param homework * @return */ @Override public int addHomework(Homework homework) { return homeworkMapper.insert(homework); } /** * This is the method to be used to list down all homework * * @return */ @Override public List<Homework> selectAll() { return homeworkMapper.selectAll(); } @Override public List<Homework> selectByTeacherId(String teacherId) { return homeworkMapper.selectByTeacherId(teacherId); } @Override public List<Homework> selectByTeacherName(String teacherName) { return homeworkMapper.selectByTeacherName(teacherName); } @Override public Homework selectByPK(Long id) { return homeworkMapper.selectByPrimaryKey(id); } }
- StudentHomeworkService
package com.winter.service; import com.winter.model.StudentHomework; import java.util.List; /** * @author:Jingqi Wu * @date: 2020/6/16 */ public interface StudentHomeworkService { /** * 学生提交作业 * @param studentHomework * @return */ int addStudentHomework(StudentHomework studentHomework); /** * @return */ int updateStudentHomework(StudentHomework studentHomework); /** * This is the method to be used to list down all * students' homework * @param homeworkId * @return */ List<StudentHomework> selectByHomeworkId(Long homeworkId); /** * This is the method to be used to search the student's homework * * @param id * @return */ StudentHomework selectByP(Long id); /** * 目前是通过studentid,homeworkid查询 * @param studentHomework * @return */ StudentHomework selectByDoublekey(StudentHomework studentHomework); }
- StudentHomeworkServiceImpl
package com.winter.service; import com.winter.mapper.StudentHomeworkMapper; import com.winter.model.StudentHomework; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; /** * @author:Jingqi Wu * @date: 2020/6/16 */ @Service(value = "studentHomeworkService") public class StudentHomeworkServiceImpl implements StudentHomeworkService { @Autowired private StudentHomeworkMapper studentHomeworkMapper; /** * 学生提交作业 * * @param studentHomework * @return */ @Override public int addStudentHomework(StudentHomework studentHomework) { return studentHomeworkMapper.insert(studentHomework); } /** * This is the method to be used to list down all * students' homework * * @param homeworkId * @return */ @Override public List<StudentHomework> selectByHomeworkId(Long homeworkId) { return studentHomeworkMapper.selectByHomeworkId(homeworkId) ; } /** * 目前是通过studentid,homeworkid查询 * * @param studentHomework * @return */ @Override public StudentHomework selectByDoublekey(StudentHomework studentHomework) { return studentHomeworkMapper.selectByDoublekey(studentHomework); } /** * This is the method to be used to search the student's homework * * @return */ @Override public StudentHomework selectByP(Long id) { return studentHomeworkMapper.selectByPrimaryKey(id); } /** * @param studentHomework * @return */ @Override public int updateStudentHomework(StudentHomework studentHomework) { return studentHomeworkMapper.updateByPrimaryKeySelective(studentHomework); } }
编写Controller
UserController
package com.winter.controller;
import com.winter.model.Homework;
import com.winter.model.StudentHomework;
import com.winter.model.User;
import com.winter.service.HomeworkService;
import com.winter.service.StudentHomeworkService;
import com.winter.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Controller
@RequestMapping(value = "/user")
public class UserController {
@Autowired
private UserService userService;
@Autowired
private HomeworkService homeworkService;
@Autowired
private StudentHomeworkService studentHomeworkService;
private User user;
private ModelAndView mv = new ModelAndView();
private Date date = new Date();
/**
* 用户注册
* @return
*/
@RequestMapping(value = "/register", produces = {"application/json;charset=UTF-8"})
public String register() {
return "register";
}
/**
* 用户登录
* @return
*/
@RequestMapping(value = "/login", produces = {"application/json;charset=UTF-8"})
public String login() {
return "login";
}
/**
* 添加用户
* @param user
* @return
*/
//@ResponseBody
@RequestMapping(value = "/add", produces = {"application/json;charset=UTF-8"})
public String addUser(User user) {
userService.addUser(user);
return "redirect:/user/login";
}
/**
* 登录验证
* @param account
* @param password
* @return
*/
@RequestMapping(value = "/verify", produces = {"application/json;charset=UTF-8"})
public String selectUser(@RequestParam("account") String account,
@RequestParam("password") String password) {
user = userService.selectUser(account);
System.out.println(user.getPassword().equals(password));
if (user.getPassword().equals(password)) {
if (user.getType() == 0) {
mv.setViewName("student");
return "redirect:student";
} else if (user.getType() == 1) {
return "redirect:teacher";
}
}
return "redirect:login";
}
/**
* 教师版首页显示教师发布的作业
* @return
*/
@RequestMapping(value = "/teacher", produces = {"application/json;charset=UTF-8"})
public ModelAndView teacher() {
List<Homework> list = new ArrayList<>();
list = homeworkService.selectByTeacherId(user.getAccount());
mv.setViewName("teacher");
mv.addObject("name",user.getName());
mv.addObject("list", list);
return mv;
}
/**
* 学生版首页显示所有教师发布的作业
* @return
*/
@RequestMapping(value = "/student", produces = {"application/json;charset=UTF-8"})
public ModelAndView student() {
List<Homework> list = new ArrayList<>();
list = homeworkService.selectAll();
mv.setViewName("student");
mv.addObject("name",user.getName());
mv.addObject("list", list);
return mv;
}
/**
* 教师查看学生提交的作业列表
* @param hid
* @return
*/
@RequestMapping(value = "/selectsh", produces = {"application/json;charset=UTF-8"})
public ModelAndView selectsh(@RequestParam("homeworkId") Long hid) {
List<StudentHomework> list = new ArrayList<>();
list = studentHomeworkService.selectByHomeworkId(hid);
mv.setViewName("studentHomeworks");
mv.addObject("name",user.getName());
mv.addObject("homeworkId",hid);
mv.addObject("list", list);
return mv;
}
/**
* 学生选择作业
* @param studentHomework
* @return
*/
@RequestMapping(value = "/selectmh", produces = {"application/json;charset=UTF-8"})
public ModelAndView selectmh(StudentHomework studentHomework) {
studentHomework.setStudentId(user.getAccount());
System.out.println(studentHomework.getStudentId());
StudentHomework sh = studentHomeworkService.selectByDoublekey(studentHomework);
Homework homework = homeworkService.selectByPK(studentHomework.getHomeworkId());
List<StudentHomework> list = new ArrayList<>();
if(sh != null) {
list.add(sh);
}
mv.addObject("homework",homework);
mv.setViewName("addStudentHomework");
mv.addObject("studentId", user.getAccount());
mv.addObject("name",user.getName());
mv.addObject("homeworkId", studentHomework.getHomeworkId());
mv.addObject("list", list);
return mv;
}
/**
* 根据教师姓名查询作业
* @param teacherName
* @return
*/
@RequestMapping(value = "/searchHomework", produces = {"application/json;charset=UTF-8"})
public ModelAndView searchHomework(@RequestParam("teacherName") String teacherName) {
List<Homework> list = new ArrayList<>();
list = homeworkService.selectByTeacherName(teacherName);
mv.setViewName("student");
mv.addObject("list", list);
mv.addObject("name",user.getName());
return mv;
}
/**
* 跳转到学生修改作业页
* @param id
* @return
*/
@RequestMapping(value = "/modify", produces = {"application/json;charset=UTF-8"})
public ModelAndView modify_mh(@RequestParam("id") Long id) {
StudentHomework studentHomework = studentHomeworkService.selectByP(id);
mv.setViewName("modify");
mv.addObject("studentHomework", studentHomework);
mv.addObject("name",user.getName());
return mv;
}
/**
* 学生提交作业
* @param studentHomework
* @return
*/
@RequestMapping(value = "/addStudentHomework", produces = {"application/json;charset=UTF-8"})
public String addStudentHomework(StudentHomework studentHomework) {
studentHomework.setCreateTime(date);
studentHomeworkService.addStudentHomework(studentHomework);
return "redirect:student";
}
/**
* 学生修改已提交的作业
* @param studentHomework
* @return
*/
@RequestMapping(value = "/updateStudentHomework", produces = {"application/json;charset=UTF-8"})
public String updateStudentHomework(StudentHomework studentHomework) {
studentHomework.setUpdateTime(date);
studentHomeworkService.updateStudentHomework(studentHomework);
return "redirect:student";
}
/**
* 教师发布作业
* @param homework
* @return
*/
@RequestMapping(value = "/addHomework", produces = {"application/json;charset=UTF-8"})
public String addHomework(Homework homework) {
homework.setTecherid(user.getAccount());
homework.setTeacherName(user.getName());
homework.setCreateTime(date);
homeworkService.addHomework(homework);
return "redirect:teacher";
}
/**
* 教师根据studentId和homeworkId查询学生作业
* @param studentHomework
* @return
*/
@RequestMapping(value = "/searchStudentHomework", produces = {"application/json;charset=UTF-8"})
public ModelAndView searchsh(StudentHomework studentHomework) {
StudentHomework list = studentHomeworkService.selectByDoublekey(studentHomework);
mv.setViewName("studentHomeworks");
mv.addObject("list", list);
mv.addObject("name",user.getName());
return mv;
}
/**
* 跳转到教师批改业,显示学生作业详情
* @param id
* @return
*/
@RequestMapping(value = "/review", produces = {"application/json;charset=UTF-8"})
public ModelAndView review(@RequestParam("id") Long id) {
StudentHomework list = studentHomeworkService.selectByP(id);
mv.setViewName("review");
mv.addObject("studentHomework", list);
mv.addObject("name",user.getName());
return mv;
}
/**
* 教师提交评价
* @param studentHomework
* @return
*/
@RequestMapping(value = "/addreview", produces = {"application/json;charset=UTF-8"})
public String addReview(StudentHomework studentHomework) {
studentHomeworkService.updateStudentHomework(studentHomework);
return "redirect:selectsh?homeworkId="+studentHomework.getHomeworkId();
}
}
源码
https://github.com/BeJane/ssm-demo-homeworkMIS
交互设计及运行截图
- 教师/学生注册:http://localhost:8080/user/register
老师进行注册
同学进行注册
- 教师/学生登录: http://localhost:8080/user/login
注册成功跳转到登录页面,李四老师使用刚注册的账号进行登录
学生进行登录
- 教师发布作业:http://localhost:8080/user/teacher
登录成功后进入教师首页,可以看到教师自己以往发布的作业,也可以发布新的作业,发布新 作业可以设置作业题目、作业内容、作业分值
发布成功后可以在已发布作业列表的第一行找到新发布的作业
点击列表最后一列的查看,可以看到学生提交作业情况 - 老师查看/查找学生作业:http://localhost:8080/user/selectsh?homeworkId=1
在输入框输入学号后点击查询,可以查找特定学生的学号
比如:输入12345
点击查看可以进行作业批改 - 教师批改作业:http://localhost:8080/user/review?id=1
- 点击每个页面左上角的“注销”退出登录
- 学生查看/查找教师发布的作业:http://localhost:8080/user/student
学生登录成功进入学生版首页,可以看到所有教师发布的作业,越晚发布排在前面
在输入框输入教师姓名,然后点击查询可以查找该老师发布的作业
比如输入李德之
- 学生提交作业
点击查看,如果学生未提交该作业,则可进行提交
如果学生已提交过该作业,则可以查看相应作业的提交情况以及老师的评分和评语
点击修改可以修改作业内容,修改时间会被记录 - 学生修改作业:http://localhost:8080/user/modify?id=1
知识点总结
Spring的3个阶段
第一阶段:XML配置,在Spring1.x时代,使用Spring开发满眼都是xml配置的Bean,随着项目的扩大,我们需要把xml配置文件分放到不同的配置文件里,那时候需要频繁的在开发的类和配置文件之间切换。
第二阶段:注解配置,在Spring2.x时代,Spring提供声明Bean的注解,大大减少了配置量。应用的基本配置用xml,业务配置用注解。
第三阶段:Java配置,从Spring3.x到现在,Spring提供了Java配置,使用Java配置可以让你更理解你所配置的Bean。
Spring Boot:使用“习惯优于配置”的理念让你的项目快速运行起来。使用Spring Boot很容易创建一个独立运行、准生产级别的基于Spring框架的项目,使用Spring Boot你可以不用或者只需要很少的Spring配置。
下面就来使用Spring Boot一步步搭建一个前后端分离的应用开发框架,并且以后不断的去完善这个框架,往里面添加功能。后面以实战为主,不会介绍太多概念,取而代之的是详细的操作。
springboot工作原理
一个典型的springboot应用
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@SpringBootApplication
@SpringBootApplication是一个复合annotation。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
...
}
其中最重要的三个annotation是@SpringBootConfiguration,@EnableAutoConfiguration和@ComponentScan。
所以以下 的springboot启动类也可以启动。
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
@SpringBootConfiguration和@Configuration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration
@SpringBootConfiguration本质上是一个@Configuration。
启动类标注了@SpringBootConfiguration之后,本身其实也是一个ioc容器的配置类。
@EnableAutoConfiguration
spring框架提供了各种名字以@Enable开头的annotation定义,比如@EnableScheduling、@EnableCaching、@EnableMBeanExport等,@EnableAutoConfiguration就是借助@Import的支持,收集和注册特定场景相关的bean定义:
@EnableScheduling是通过@Import将spring调度框架相关的bean定义都加载到ioc容器。
@EnableMBeanExport是通过@Import将JMX相关的bean定义都加载到ioc容器
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration
@EnableAutoConfiguration作为一个复合annotation,其中最关键的要属@Import(AutoConfigurationImportSelector.class),借助AutoConfigurationImportSelector,@EnableAutoConfiguration可以帮助springboot应用将所有符合条件的@Configuration配置都加载到当前springboot创建并使用的ioc容器,就跟一只八爪鱼一样。
AutoConfigurationImportSelector借助spring框架原有的一个工具类SpringFactoriesLoader的支持,@EnableAutoConfiguration可以智能地完成自动配置。
SpringFactoriesLoader主要功能是从指定的配置文件META-INF/spring.factories加载配置,spring.factories是一个典型的Java properties文件,配置的格式为key=value形式,只不过key和value都是Java类型的完整类型。
SpringFactoriesLoader在@EnableAutoConfiguration的场景中,更多的是提供了一种配置查找的功能支持,即根据@EnableAutoConfiguration的完整类名org.springframework.boot.autoconfigure.EnableAutoConfiguration作为查找的key,获取对应的一组@Configuration类:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=/
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,/
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,/
所以,@EnableAutoConfiguration的自动配置就是从classpath中搜寻所有META-INF/spring.factories配置文件,并将其中org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的配置项通过反射实例化为对应的标注了@Configuration的JavaConfig形式的ioc容器配置类,然后汇总为一个并加载到ioc容器。
@ComponentScan
@ComponentScan的功能其实就是自动扫描并加载符合条件的组件或bean定义,最终将这些bean定义加载到容器中。
Mybatis工作原理
mybatis应用程序通过SqlSessionFactoryBuilder从mybatis-config.xml配置文件(也可以用Java文件配置的方式,需要添加@Configuration)来构建SqlSessionFactory(SqlSessionFactory是线程安全的);
然后,SqlSessionFactory的实例直接开启一个SqlSession,再通过SqlSession实例获得Mapper对象并运行Mapper映射的SQL语句,完成对数据库的CRUD和事务提交,之后关闭SqlSession。
说明:SqlSession是单线程对象,因为它是非线程安全的,是持久化操作的独享对象,类似jdbc中的Connection,底层就封装了jdbc连接。
详细流程如下:
1、加载mybatis全局配置文件(数据源、mapper映射文件等),解析配置文件,MyBatis基于XML配置文件生成Configuration,和一个个MappedStatement(包括了参数映射配置、动态SQL语句、结果映射配置),其对应着<select | update | delete | insert>标签项。
2、SqlSessionFactoryBuilder通过Configuration对象生成SqlSessionFactory,用来开启SqlSession。
3、SqlSession对象完成和数据库的交互:
a、用户程序调用mybatis接口层api(即Mapper接口中的方法)
b、SqlSession通过调用api的Statement ID找到对应的MappedStatement对象
c、通过Executor(负责动态SQL的生成和查询缓存的维护)将MappedStatement对象进行解析,sql参数转化、动态sql拼接,生成jdbc Statement对象
d、JDBC执行sql。
e、借助MappedStatement中的结果映射关系,将返回结果转化成HashMap、JavaBean等存储结构并返回。
Thymeleaf
Thymeleaf是一种用于Web和独立环境的现代服务器端的Java模板引擎
常见用法
- herf
<a th:href="@{'review?id='+${entries['id']}}" >查看</a>
- value
<input type="hidden" name="homeworkId" value="" th:value="*{homeworkId}">
- 列表遍历
<tr th:each="entries:${list}" th:style="'background-color:'+'#F2F2F2'" > <td th:text="${entries['id']}"></td> <td th:text="${entries['studentId']}"></td> </tr>
- 格式化日期时间
<td th:text="${#dates.format(studentHomework['updateTime'], 'yyyy-MM-dd HH:mm')}"></td>
- 判断列表是否为空
<div th:if="${#lists.isEmpty(list)}">
</div>
<div th:if="${not #lists.isEmpty(list)}">
</div>
参考资料
spring boot整合mybatis: https://blog.csdn.net/Winter_chen001/article/details/77249029
springboot工作原理:https://blog.csdn.net/Chen_Victor/article/details/81262233
Mybatis工作原理:https://blog.csdn.net/u014745069/article/details/80788127