复习
- spring-boot的使用
- 特征
- 独立的应用程序
- 内嵌式的tomcat、jetty或undertow
- 提供starter依赖,简化构建配置
- 自动配置
- 提供生产级功能,比如:运行指标、健康检查、外化配置
- 绝不使用代码生成与xml
- 原理
- starter依赖
- 简化依赖(依赖传递)
- 自动配置
- 外化配置(将散落在不同的配置文件中的配置,集中到外部的配置文件application.yml中)
- 命名约定(官方:spring-boot-starter-xxx 民间:xxx-spring-boot-starter)
- spring-boot-maven插件
- 运行 mvn spring-boot:run
- 打包 mvn clean package (fatjar) java -jar xxxx.jar
- parent —> spring-boot-starter-parent —> spring-boot-dependencies (依赖版本)
- starter依赖
- 自动配置
- @EnableAutoConfiguration 启动自动配置
- spring-boot在启动时,扫描starter依赖根目录下的META-INF/spring.factories,得到自动配置类的路径
- 自动配置类,@Configuration标记为配置类 @Bean 提供了集成到spring所需要的bean,实现自动配置
- 自动配置类关联一个配置属性类@EnableConfigurationProperties(配置类),可以将配置类的属性用于自动配置
- 配置属性类 @ConfigurationProperties(prefix=”配置前缀”) application.yml中配置项格式就是 配置前缀.属性名;将外化配置文件中的配置读入到该属性类,用于自动配置
- 集成springmvc+mybatis spring-boot三板斧
- 加依赖 starter依赖
- 修改配置文件 application.yml
- 加注解
作业
- 学生管理(增删改查)
- 学生姓名 学号 性别 年龄 专业 入学时间 咨询老师 班级
- 学生注册 / 学生毕业 / 学生分页查询
建表规范
- 学生表,有哪些字段?需求
- 隐性的需求 举例: 用户表的 最后一次登录时间
- 字段命名,英文,下划线分词,见名知意,不要用缩写,不要用拼音
- 字段数据类型的选择
- 关联关系
- 1:1 任意,甚至双边
- 1:m/ m:1 存在多的一方
- m:n 中间表
- 主键,使用int,自增
- 给表和字段加注释
- 有默认字段 raw_add_time记录新增时间 raw_update_time记录更新时间
drop database if exists edu_56;create database edu_56;drop table if exists edu_student;create table edu_student(student_id int auto_increment primary key,student_name varchar(64) not null comment '学生姓名',student_no varchar(20) not null comment '学号',gender char(1) null comment 'M 男 | F 女 | U 未填写',age tinyint null comment '年龄',major varchar(64) not null comment '专业',register_time datetime not null comment '入学时间',counselor varchar(64) not null comment '咨询师',class_name varchar(64) not null comment '班级',raw_add_time datetime not null default CURRENT_TIMESTAMP comment '记录添加时间',raw_update_time datetime not null DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP comment '记录更新时间')engine=innodbDEFAULT CHARSET = utf8COMMENT ='学生信息表';
关联关系存储
要理解数据库是二维表
一对多、多对一,将关联关系存在多的一方
多对多,将关联关系存成另一张中间表
数据库引擎选择innodb,使用业务无关的自增主键
MyISAM一旦出现系统宕机或者进程崩溃情况容易造成存储数据损坏。此外,频繁读写的InnoDB表,一定要使用具有自增/顺序特征的整型作为显式主键。MySQL :使用业务无关的自增主键,详见下文
控制单表数据量
控制列数量
单表字段数上限控制在20到50之内.字段少而精可以提高并发,IO更高效 (优化InnoDB表BLOB列的存储效率)
原因是存储引擎的API工作时需要在服务器层和存储引擎层之间通过行缓冲格式拷贝数据,然后在服务器层将缓冲内容解码成各个列,这个转换过程的代价是非常高的。如果列太多而实际使用的列又很少的话,有可能会导致CPU占用过高。
平衡范式与冗余
禁止在数据库里存图片和文件
禁止在数据库中使用varbinary、blob、text存储图片和文件.
数据库完整性要求
字段选择合适的数据类型
IP字段
如果是使用的IPV4,则使用int存储不使用char(15).
在MySQL中提供了INER_ATONO()和INET_NTOA()函数来对IP和数字之间进行转换. 前者提供IP到数字的转换后者提供数字到IP的转换.
insert into table column(ipvalues(INET_ATONO('127.0.0.1')) ;
如业务需求需要存储IPV6,可采用varchar(40)类型.
手机字段
如果考虑到varchar占用空间大影响查询性能,请使用bigint来存储手机号码.
- 不要使用
int,因为int类型的最大长度不能超过11位 - 如果手机号码中含有地区码,则用
varchar
枚举类型可以使用ENUM,ENUM的内部存储机制是采用TINYINT或SMALLINT(并非CHAR/VARCHAR)。enum,set和tinyint类型使用
注意:ENUM类型扩展性较差,如果新增枚举值,需要修改表字段定义,而且在执行ddl时会对性能有影响金额字段
对于金额字段,统一采用decimal(17,0)类型,金额以“分”为单位保存.时间字段
时间字段优先考虑datetime.精确浮点数字段必须使用decimal替代float和double
MySQL中的数值类型(不包括整型)IEEE754浮点数:单精度(float)、双精度(double和real)、 定点数(decimal和numeric).float,double等非标准类型,在DB中保存的是近似值,而decimal则以字符串的形式保存数值
写代码的注意点
- 实体类与form对象必须区分开,字段不一定一致,考虑参数能少让用户传就少传(能够从系统获取,session中获取,其他字段解析出来比如身份证可以解析性别生日)
- 套路
- 打日志
- 参数校验,通用解析校验结果方法,ControllerBase
c. 调用service(业务校验),参数适配 BeanUtils<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency>
d. 异常处理(通过全局异常处理器实现)
e. 返回结果 Result(便捷方法)
demo56.zip
javamvc.zip
Restful风格
REST
- 实体通过网址URL来表示: /product/1 @PathVariable
- 通过HTTP协议的请求方法,表达对一个资源的操作
- GET 查询 @GetMapping
- POST 新增 @PostMapping
- PUT 更新
- DELETE 删除

传参
- formData传参
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script><script>$(function () {$.ajax({url:"/test1",type: 'post',dataType:'json',data:{'username':'zhangsan','password':'abc123'},success:function(resp){console.log(resp)}});});</script>

后端用对象接受 ```java @PostMapping(“test1”) public Result doTest(TestForm testForm){
}log.info("TestForm:{}",testForm);return Result.success();
2. payload 方式前端:```javascript<script>$(function () {$.ajax({url:"/test2",type: 'post',dataType:'json',data:JSON.stringify({'username':'zhangsan','password':'abc123'}),contentType:'application/json;charset=utf-8',success:function(resp){console.log(resp)}});});</script>

后端接收
@PostMapping("test2")public Result doTest2(@RequestBody TestForm testForm){log.info("TestForm:{}",testForm);return Result.success();}
注意点:
- @RequestBody 只能有一个
- Get/Delete请求不能用@RequestBody
- @RequestBody
- @RequestParam
- @PathVaraible
@SpringBootApplication
核心注解 SpringBootConfiguration + EnableAutoConfiguration + ComponentScan ```java
@SpringBootConfiguration 标记为springboot配置类,即为spring的配置类,意味着可以在Application类里写@Bean注册bean @EnableAutoConfiguration 启动自动配置 @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) 包扫描 public @interface SpringBootApplication {
@AliasFor(annotation = EnableAutoConfiguration.class)Class<?>[] exclude() default {};@AliasFor(annotation = EnableAutoConfiguration.class)String[] excludeName() default {};//指定扫描包路径,不指定时,默认为当前类所在的路径@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")String[] scanBasePackages() default {};@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")Class<?>[] scanBasePackageClasses() default {};@AliasFor(annotation = ComponentScan.class, attribute = "nameGenerator")Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;@AliasFor(annotation = Configuration.class)boolean proxyBeanMethods() default true;
}
<a name="i4EFL"></a># Spring-Boot的一些约定- 配置文件- XXXApplication必须直接放在根包下- resources- static 静态资源 前端渲染(浏览器执行)- template 模板 后端渲染(jvm)<a name="sxsgT"></a># 集成mybatisplus1. 导入依赖```xml<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.2.0</version></dependency>
修改配置
mybatis-plus:type-aliases-package: com.woniuxy.boot.mybatisplusdemo.entityconfiguration:map-underscore-to-camel-case: truelog-impl: org.apache.ibatis.logging.slf4j.Slf4jImplmapper-locations: classpath*:mappers/**/*.xml
加注解 @MapperScan
代码生成器
加依赖
<!-- mybatis-plus代码生成器 --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.2.0</version><scope>test</scope></dependency><dependency><groupId>org.apache.velocity</groupId><artifactId>velocity-engine-core</artifactId><version>2.1</version><scope>test</scope></dependency>
代码 ```java package com.woniuxy.boot.mybatisplusdemo;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException; import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.generator.AutoGenerator; import com.baomidou.mybatisplus.generator.InjectionConfig; import com.baomidou.mybatisplus.generator.config.*; import com.baomidou.mybatisplus.generator.config.po.TableInfo; import com.baomidou.mybatisplus.generator.config.rules.DateType; import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
import java.util.ArrayList; import java.util.List; import java.util.Scanner;
public class MybatisPlusGenerator {
/*** <p>* 读取控制台内容* </p>*/public static String scanner(String tip) {Scanner scanner = new Scanner(System.in);StringBuilder help = new StringBuilder();help.append("请输入" + tip + ":");System.out.println(help.toString());if (scanner.hasNext()) {String ipt = scanner.next();if (StringUtils.isNotEmpty(ipt)) {return ipt;}}throw new MybatisPlusException("请输入正确的" + tip + "!");}public static void main(String[] args) {// 代码生成器AutoGenerator mpg = new AutoGenerator();// 全局配置GlobalConfig gc = new GlobalConfig();String projectPath = System.getProperty("user.dir");gc.setOutputDir(projectPath + "/src/main/java");gc.setAuthor("Lucas");gc.setOpen(false);gc.setDateType(DateType.ONLY_DATE);// gc.setSwagger2(true); 实体属性 Swagger2 注解mpg.setGlobalConfig(gc);// 数据源配置DataSourceConfig dsc = new DataSourceConfig();//①数据源dsc.setUrl("jdbc:mysql://localhost:3306/edu_56?useUnicode=true&useSSL=false&characterEncoding=utf8");// dsc.setSchemaName("public");dsc.setDriverName("com.mysql.jdbc.Driver");dsc.setUsername("root");dsc.setPassword("root123");mpg.setDataSource(dsc);// 包配置PackageConfig pc = new PackageConfig();//② 包,留意parent设置为上一级,moduleName最后一级pc.setParent("com.woniuxy.boot");pc.setModuleName("mybatisplusdemo");pc.setController("controller");pc.setService("service");pc.setServiceImpl("service.impl");pc.setMapper("mapper");pc.setXml("mappers");pc.setEntity("entity");mpg.setPackageInfo(pc);// 自定义配置InjectionConfig cfg = new InjectionConfig() {@Overridepublic void initMap() {// to do nothing}};// 如果模板引擎是 freemarker
// String templatePath = “/templates/mapper.xml.ftl”; // 如果模板引擎是 velocity String templatePath = “/templates/mapper.xml.vm”;
// 自定义输出配置List<FileOutConfig> focList = new ArrayList<>();// 自定义配置会被优先输出focList.add(new FileOutConfig(templatePath) {@Overridepublic String outputFile(TableInfo tableInfo) {// 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!return projectPath + "/src/main/resources/mappers" +"/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;}});/*cfg.setFileCreate(new IFileCreate() {@Overridepublic boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) {// 判断自定义文件夹是否需要创建checkDir("调用默认方法创建的目录");return false;}});*/cfg.setFileOutConfigList(focList);mpg.setCfg(cfg);// 配置模板TemplateConfig templateConfig = new TemplateConfig();// 配置自定义输出模板//指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
// templateConfig.setEntity(“templates/entity2.java”); // templateConfig.setService(); // templateConfig.setController();
templateConfig.setXml(null);mpg.setTemplate(templateConfig);// 策略配置StrategyConfig strategy = new StrategyConfig();strategy.setNaming(NamingStrategy.underline_to_camel);strategy.setColumnNaming(NamingStrategy.underline_to_camel);
// strategy.setSuperEntityClass(“com.baomidou.ant.common.BaseEntity”); strategy.setEntityLombokModel(true); strategy.setRestControllerStyle(true); // 公共父类 // strategy.setSuperControllerClass(“com.baomidou.ant.common.BaseController”); // 写于父类中的公共字段 // strategy.setSuperEntityColumns(“id”); strategy.setInclude(scanner(“表名,多个英文逗号分割”).split(“,”)); strategy.setControllerMappingHyphenStyle(true);
//③ 表前缀strategy.setTablePrefix("edu");mpg.setStrategy(strategy);mpg.setTemplateEngine(new VelocityTemplateEngine());mpg.execute();}
}
1. 运行1. 插件使用```javapackage com.woniuxy.boot.mybatisplusdemo.config;import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;import org.mybatis.spring.annotation.MapperScan;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class MybatisPlusConfig {// 旧版@Beanpublic PaginationInterceptor paginationInterceptor() {PaginationInterceptor paginationInterceptor = new PaginationInterceptor();// 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false// paginationInterceptor.setOverflow(false);// 设置最大单页限制数量,默认 500 条,-1 不受限制// paginationInterceptor.setLimit(500);// 开启 count 的 join 优化,只针对部分 left joinpaginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));return paginationInterceptor;}}
分层架构

集成Thymeleaf


c.jsp就是一个后端模板
jsp因为本身的性能以及安全问题,已经被弃用,新兴的后端模板引擎替换了jsp
后端模板引擎
- 老牌:Velocity、Freemarker
- 新兴:Thymeleaf、Mustache、Groovy
Thymeleaf核心理念:自然模板
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency>
spring:datasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/edu_56username: rootpassword: root123thymeleaf:cache: false
<!DOCTYPE html><!--命名空间--><html lang="en" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8"><title>Title</title></head><body>hello thymeleaf<div>hello <span th:text="${username}">游客</span><span th:if="${age >18}">年轻小伙</span><span th:unless="${age >18}">小朋友</span><ul><li th:each="s : ${students}"><span th:text="${s}">小王</span></li></ul></div></body></html>
https://www.cnblogs.com/jnba/p/10832878.html
日志框架
作业
需求分析
在线教育网站参考:https://demo.edu.roncoos.com/
介绍及技术架构:https://demo.edu.roncoos.com/blog/article/1266656581010952194
讲师协议,约定了分成:https://demo.edu.roncoos.com/apply
- 设计课程course、章chapter、*节lesson,产出建表sql
- 实现一个课程分页搜索,支持根据课程类别,收费方式进行搜索,spring-boot+mybatis-plus
