文章目錄
需求分析
用例分析
數據庫設計
一共設計了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