58sql军规
tinyint(1byte) smallint(2byte:65536) mediumint(3byte) int bigint(8byte)
Decimal==numeric
Date日期 datetime日期+时间
Spring配置繁琐,太多xml,Annotation配置,让人眼花缭乱;
Spring Boot采用Java config方式对Spring配置;其二,不用配置tomcat,包括静态资源处理,,视图解析器,注解扫描等
Spring boot小结
父pom里定义的一些版本
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger2artifactId>
<version>2.9.2version>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.3.0version>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-generatorartifactId>
<version>3.3.0version>
dependency>
<dependency>
<groupId>org.apache.velocitygroupId>
<artifactId>velocity-engine-coreartifactId>
<version>2.1version>
dependency>
创建common包放自己写的类(下有config/exception/util三个包)
在utils下创建mysqlGenerator类(自动生成)(要修改父包名等等)
public class mysqlGenerator {
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(); // 代码生成器
DataSourceConfig dsc = new DataSourceConfig(); // 数据源配置
dsc.setDbType(DbType.MYSQL); //数据库类型
//dsc.setSchemaName("public");数据库schemaName
dsc.setUrl("jdbc:mysql://127.0.0.1:3306/graduation?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("root");
mpg.setDataSource(dsc);
PackageConfig pc = new PackageConfig(); // 包配置
pc.setParent("com.xxw.graduation"); //父包名。如果为空,将下面子包名必须写全部, 否则就只需写子包名
pc.setModuleName(scanner("模块名")); //父包模块名
mpg.setPackageInfo(pc);
GlobalConfig gc = new GlobalConfig(); // 全局配置
String projectPath = System.getProperty("user.dir");
String pre = pc.getModuleName().substring(0,1).toUpperCase() + pc.getModuleName().substring(1); //类前缀
gc.setOutputDir(projectPath + "/src/main/java");
gc.setFileOverride(true); //第一次吧第二次覆盖掉
gc.setOpen(false); //是否打开输出目录
gc.setEnableCache(false); //是否在xml中加二级缓存配置
gc.setAuthor("xxw"); //作者名字
gc.setActiveRecord(true); //开启AR,与分页有关
gc.setBaseResultMap(true); //开启baseResultMap,xmlde resultMap是否生成
gc.setBaseColumnList(true); //开启生成基础列,在xml中
gc.setDateType(DateType.ONLY_DATE); //datatype指定(only_date只使用Java.util.date代替/sql_pack使用java.sql包下的/time_pack使用java.time下的)
gc.setEntityName("%s"); //实体命名方式
gc.setMapperName("%sMapper"); //mapper命名方式gc.setMapperName(pre+"%sMapper");这个会加上输入的模块名
gc.setXmlName("%sMapper"); //mapper xml命名方式gc.setXmlName(pre+"%sMapper");
gc.setServiceName("%sService"); //service命名方式gc.setServiceName(pre+"%sService");
gc.setServiceImplName("%sServiceImpl");//serviceImpl命名方式gc.setServiceImplName(pre+"%sServiceImpl");
gc.setControllerName("%sController");//controller命名方式gc.setControllerName(pre+"%sController");
gc.setIdType(IdType.AUTO); //主键策略:自动增加
gc.setSwagger2(true); //实体属性 Swagger2 注解
mpg.setGlobalConfig(gc);
InjectionConfig cfg = new InjectionConfig() { // 自定义配置
@Override
public void initMap() {
// to do nothing
}
};
// 如果模板引擎是 velocity
String templatePath = "/templates/mapper.xml.vm";
// 自定义输出配置
List<FileOutConfig> focList = new ArrayList<>();
// 自定义配置会被优先输出
focList.add(new FileOutConfig(templatePath) {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
return projectPath + "/src/main/resources/mapper/" + pc.getModuleName()
+ "/"+ tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
}
});
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
// 配置模板
TemplateConfig templateConfig = new TemplateConfig();
templateConfig.setXml(null);
mpg.setTemplate(templateConfig);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
//下划线转驼峰s
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.setSuperMapperClass("com.baomidou.mybatisplus.core.mapper.BaseMapper");
// strategy.setSuperControllerClass("com.baomidou.ant.common.BaseController");
// 写于父类中的公共字段
// strategy.setSuperEntityColumns("id");
strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
strategy.setControllerMappingHyphenStyle(true);
// 表前面字段(生成时弃掉)
strategy.setTablePrefix("xxw_");
strategy.setEntityTableFieldAnnotationEnable(true);
mpg.setStrategy(strategy);
// mpg.setTemplateEngine(new VelocityTemplateEngine());
mpg.execute();
// 输入 xxw_user,xxw_sort,xxw_label,xxw_friend,xxw_comment,xxw_collect,xxw_article_sort,xxw_article_label,xxw_article
}
}
@MapperScan("com.xxw.test.personWeb.mapper")
配置文件内容(第一个是application.yml)
#设置配置文件的加载(dev开发/prod生产/test测试环境)
spring:
profiles:
active: dev
jackson:
# 时区设置(中国北京为8时区,以及格式设置)
date-format: yyyy-MM-dd HH-mm-ss
time-zone: GMT+8
#mybatis-plus总体配置
mybatis-plus:
global-config:
db-config:
#默认数据库表下滑线命名
table-underline: true
#逻辑删除配置(1为已删除,0为未删除)---------实体类字段前加入 @TableLogic!!!!
logic-not-delete-value: 0
logic-delete-value: 1
# 全局主键策略(auto主键自增/uuid全局唯一(所有机器同一时空唯一)/id_work数值类型/id_work_str字符串类型/input自定义;与数据库一致)
id-type: auto
configuration:
#驼峰命名法(默认开启,容易出错:字段nickName,实体类getNickName()“报错:找不到nick-name字段”)最好关闭,这里数据库设计还行,就不关了
map-underscore-to-camel-case: true
# 这个配置会将执行的sql打印出来,在开发或测试的时候可以用
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#如果查询结果中包含空值的列,则 MyBatis 在映射的时候,不会映射这个字段
call-setters-on-nulls: true
这个是dev开发环境配置
server:
port: ????
spring:
datasource:
username: root
password: root
url: jdbc:mysql://127.0.0.1:3306/graduation?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
driver-class-name: com.mysql.cj.jdbc.Driver
在resources下创建logback-spring.xml文件配置日志(lockback日志)
要先在idea下载Grep Console插件
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<!-- 从高到地低 OFF 、 FATAL 、 ERROR 、 WARN 、 INFO 、 DEBUG 、 TRACE 、 ALL -->
<!-- 日志输出规则 根据当前ROOT 级别,日志输出时,级别高于root默认的级别时 会输出 -->
<!-- 以下 每个配置的 filter 是过滤掉输出文件里面,会出现高级别文件,依然出现低级别的日志信息,通过filter 过滤只记录本级别的日志-->
<contextName>logback</contextName>
<!-- 定义日志文件 输入位置 -->
<!-- 巨坑!!!windows复制目录是\而这里要/ -->
<property name="logPath" value="C:/Users/Administrator/Desktop/GraduationProject/log"/>
<!-- 日志最大的历史 30天,这个参数要看你基于哪一种滚动策略【基于天,单位为天,月同理】本文件设置的多事基于天滚动策略 -->
<property name="maxHistory" value="30"/>
<!-- 日志输出格式【控制台】 -->
<!-- 我这里不要线程的消息 | %boldGreen(%thread) -->
<property name="logPatternConsoleLog" value="%date{yyyy-MM-dd HH:mm:ss} | %highlight(%-5level) | %boldYellow(%logger) | %msg%n"/>
<!-- 日志输出格式【日志文件】 | %thread -->
<property name="logPattern" value="%date{yyyy-MM-dd HH:mm:ss} | %-5level | %logger | %msg%n"/>
<!-- 日志输出编码格式 -->
<property name="logCharset" value="UTF-8"/>
<!--配置控制台的输出-->
<appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${logPatternConsoleLog}</pattern>
<charset>${logCharset}</charset>
</encoder>
</appender>
<!--配置文件输出:error-->
<appender name="fileErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${logPath}/log_error.log</file>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch> <!-- 这里被坑过一次(deny与accept写反了) -->
<onMismatch>DENY</onMismatch>
</filter>
<encoder>
<pattern>${logPattern}</pattern>
<charset>${logCharset}</charset>
</encoder>
<!--滚动策略:每天一个日志文件-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--路径-->
<fileNamePattern>${logPath}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!-- 可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件假设设置每个月滚动,且<maxHistory>是30,
则只保存最近30天的文件,删除之前的旧文件。注意,删除旧文件是,那些为了归档而创建的目录也会被删除-->
<maxHistory>${maxHistory}</maxHistory>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>50MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
</appender>
<!--配置文件输出:warn-->
<appender name="fileWarnLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${logPath}/log_warn.log</file>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>WARN</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder>
<pattern>${logPattern}</pattern>
<charset>${logCharset}</charset>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${logPath}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxHistory>${maxHistory}</maxHistory>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>50MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
</appender>
<!--配置文件输出:info-->
<appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${logPath}/log_info.log</file>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder>
<pattern>${logPattern}</pattern>
<charset>${logCharset}</charset>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${logPath}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxHistory>${maxHistory}</maxHistory>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>50MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
</appender>
<springProfile name="dev">
<!--可以输出项目中debug日志,包括mybatis是sql日志-->
<logger name="com.xxw" level="INFO"/>
<root level="INFO">
<appender-ref ref="consoleLog"/> <!--控制台-->
<!-- <appender-ref ref="fileErrorLog"/>-->
<!-- <appender-ref ref="fileWarnLog"/>-->
<!-- <appender-ref ref="fileInfoLog"/>-->
</root>
</springProfile>
<springProfile name="prod">
<logger name="com.xxw" level="INFO"/>
<root level="INFO">
<appender-ref ref="fileErrorLog"/> <!--error文件-->
<appender-ref ref="fileWarnLog"/> <!--warn文件-->
<appender-ref ref="fileInfoLog"/> <!--info文件 -->
</root>
</springProfile>
</configuration>
一:创建enum枚举(先创建类,改class为enum)
@Getter
public enum ResultCodeEnum {
SUCCESS(true,200, "成功!"),
FAIL(false,400,"失败!"),
PARAM_ERROR(false,4001,"参数出错"),
FILE_UPLOAD_ERROR(false,4002,"文件上传失败"),
EXCEL_DATA_IMPORT_ERROR(false,4003,"excel表上传失败"),
BAD_SQL_GRAMMAR(false,4004,"sql语法出现错误"),
JSON_PARSE_ERROR(false,4005,"json数据读取(解析)出错"),
UNKNOWN_ERROR(false,100000, "未知错误!");
private Boolean success;//响应是否成功
private Integer code;//返回码
private String message;//返回信息
ResultCodeEnum(Boolean success, Integer code, String message) {
this.success = success;
this.code = code;
this.message = message;
}
}
二:全局统一返回结果集类
@Data
public class Result {
private Boolean success;//是否成功
private Integer code;//返回码
private String message;//返回信息
//返回的数据
private Map<String,Object> data = new HashMap<String, Object>();
private Result(){}
//注意静态方法可以直接使用类名去调用(省略了new对象)
public static Result ok(){
Result result =new Result();
result.setSuccess(ResultCodeEnum.SUCCESS.getSuccess());
result.setCode(ResultCodeEnum.SUCCESS.getCode());
result.setMessage(ResultCodeEnum.SUCCESS.getMessage());
return result;
}
public static Result error(){
Result result =new Result();
result.setSuccess(ResultCodeEnum.UNKNOWN_ERROR.getSuccess());
result.setCode(ResultCodeEnum.UNKNOWN_ERROR.getCode());
result.setMessage(ResultCodeEnum.UNKNOWN_ERROR.getMessage());
return result;
}
public Result data(Map<String,Object> map){
this.setData(map);
return this;
}
public Result data(String key,Object value){
this.data.put(key,value);
return this;
}
// 自定义--> 例如:return Result.ok().message("获取数据成功").data(list)
public Result message(String message){
this.setMessage(message);
return this;
}
public Result code(Integer code){
this.setCode(code);
return this;
}
public Result success(Boolean success){
this.setSuccess(success);
return this;
}
// 异常处理使用枚举数据的方法
public static Result setResult(ResultCodeEnum resultCodeEnum){
Result result=new Result();
result.setSuccess(resultCodeEnum.getSuccess());
result.setCode(resultCodeEnum.getCode());
result.setMessage(resultCodeEnum.getMessage());
return result;
}
}
一: 自定义异常类
@Data
public class XxwException extends RuntimeException{
private Integer code;
@Override
public String toString() {
return "XxwException{" +"code=" + code +", message=" + this.getMessage() +'}';
}
二:全局异常处理类
@ControllerAdvice // 全局异常处理/全局数据绑定/全局数据预处理(三个主要作用)
@Slf4j //log.error(e.getMessage());日志记录器(记录异常message)
public class GlobalExceptionHandler {
//全局的对应方法
@ExceptionHandler(Exception.class) //出现exception异常,自动调用error方法
@ResponseBody //异常返回给前端也是json形式
public Result error(Exception e){
// e.printStackTrace(); //后端输出异常堆栈信息
log.error(ExceptionUtil.getMessage(e));
return Result.error();
}
@ExceptionHandler(BadSqlGrammarException.class) //sql语法出现错误
@ResponseBody
public Result error(BadSqlGrammarException e){
log.error(ExceptionUtil.getMessage(e)); //出错:log.error(e.getMessage())不输出详细堆栈错误信息
//return Result.error().code(4001).message("sql语法出现错误");
return Result.setResult(ResultCodeEnum.BAD_SQL_GRAMMAR);
}
@ExceptionHandler(HttpMessageNotReadableException.class) //json数据读取(解析)出错
@ResponseBody
public Result error(HttpMessageNotReadableException e){
log.error(ExceptionUtil.getMessage(e));
return Result.setResult(ResultCodeEnum.JSON_PARSE_ERROR);
}
//自定义异常(运行时)(例如上传参数为出现错误时,抛这个)
@ExceptionHandler(XxwException.class)
@ResponseBody
public Result error(XxwException e){
log.error(ExceptionUtil.getMessage(e));
return Result.error().message(e.getMessage()).code(e.getCode());
}
}
后端搭建基本完成
Vue.js是前端一个比较火的MVVM框架, 是一套构建用户界面的渐进式框架
Vue 只关注视图层, 采用自底向上增量开发的设计
Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件
首先安装好node.js,它包括了npm。然后,再利用npm安装淘宝镜像的cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org
cnpm install cnpm -g
cnpm install vue
cnpm install -g vue-cli (vue -V检查版本)
vue ui 终端打开vue脚手架
(默认选)Babel-----Linter/Formatter(加上) //Router-----使用配置文件(插件将有各自的配置文件)
vue-cli-plugin-elment
改默认配置(import on demand按需导入)axios