项目经验
用过滤器判断用户是否登录,然后将用户id 用threadlocal类的set 方法 放在线程副本中,然后在要用到的时候取出来,然后我把set方法写在doFilter后面, 后面要取的时候这么取不出来,不知道是取不到还是set进去,
然后发现整个线程先走dofilter,要将set方法写到doFilter前面才能设置进去,要不然后面get不到,
doFilter
一.chain.doFilter作用
1.一般filter都是一个链,web.xml 里面配置了几个就有几个。一个一个的连在一起
request -> filter1 -> filter2 ->filter3 -> …. -> request resource.
2.chain.doFilter将请求转发给过滤器链下一个filter , 如果没有filter那就是你请求的资源
@Order(1) 确定顺序
@WebFilter(filterName = "first" , urlPatterns = "/*")
@Order(1)
public class FirstFilter implements Filter {
在进行修改的时候要先进行回显, 由于id是long类型且用雪花算法生成的19位的数字,long类型在js中只能回显17,不够的用0补,然后前后端数据就不一样了,修改好的数据传给后端update就失败了,这时就要用对象映射器,继承jackson包的objectMapper类,并在webMvcConfig类进行注册消息转换器
小bug给用户端的菜品展示没有没有口味,所以要构造一个dishDto类,将口味类加进去
在前端
用户权限管理
一个管理员用户,前端<el-button 组件 > 会判断用户id是否为1,来确定是否是管理员,确定是否展示禁用,启用按钮
静态资源映射
1.继承WebMvcConfigurationSupport
2.添加@Configuration注解
@Slf4j
@Configuration
@EnableSwagger2
@EnableKnife4j
public class WebMvcConfig extends WebMvcConfigurationSupport {
/**
* 静态资源映射
* ("classpath:/backend/"); 其中的/ 代表的是target
* @param registry
*/
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
log.info("静态资源映射.......");
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");
}
}
返回结果类
导入返回结果类,就是通用的结果类,将结果封装到结果中
package com.itheima.reggie.common;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
@Data
@ApiModel(value = "返回统一对象")
public class R<T> implements Serializable {
@ApiModelProperty(value = "编码")
private Integer code; //编码:1成功,0和其它数字为失败
@ApiModelProperty(value = "错误信息")
private String msg; //错误信息
@ApiModelProperty(value = "数据")
private T data; //数据
@ApiModelProperty(value = "数据")
private Map map = new HashMap(); //动态数据
public static <T> R<T> success(T object) {
R<T> r = new R<T>();
r.data = object;
r.code = 1;
return r;
}
public static <T> R<T> error(String msg) {
R r = new R();
r.msg = msg;
r.code = 0;
return r;
}
public R<T> add(String key, Object value) {
this.map.put(key, value);
return this;
}
}
用户登录
用户登出
删除 用户session
完善用户登录功能
在过滤器类上加@WebFilter(filterName = “LoginCheckFilter”, urlPatterns = “/*”)注解
启动类增加 @ServletComponentScan
package com.itheima.reggie;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Slf4j
@SpringBootApplication
@ServletComponentScan
@EnableCaching
public class ReggieApplication {
public static void main(String[] args) {
SpringApplication.run(ReggieApplication.class,args);
log.info("项目启动成功......");
}
}
package com.itheima.reggie.filter;
import com.alibaba.fastjson.JSON;
import com.itheima.reggie.common.BaseContext;
import com.itheima.reggie.common.R;
import com.itheima.reggie.entity.Employee;
import com.itheima.reggie.entity.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.AntPathMatcher;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter(filterName = "LoginCheckFilter", urlPatterns = "/*")
@Slf4j
public class LoginCheckFilter implements Filter {
private final static AntPathMatcher PATH_MATCHER = new AntPathMatcher();
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
log.info("过滤器拦截到的请求: {}", httpServletRequest.getRequestURI());
//不需要拦截的路径
String[] urls = new String[]{
"/employee/login",
"/employee/logout",
"/backend/**",
"/front/**",
"/user/login",
"/user/sendMsg",
"/doc.html",
"/webjars/**",
"/swagger-resources",
"/v2/api-docs"
};
boolean check = check(urls, httpServletRequest.getRequestURI());
if (check) {
log.info("放行的请求:{}", httpServletRequest.getRequestURI());
filterChain.doFilter(servletRequest, servletResponse);
return;
}
//后端用户登录状态
Employee employee = (Employee) httpServletRequest.getSession().getAttribute("employee");
Long empId = employee.getId();
if (employee != null) {
// BaseContext.setCurrentId(empId);方法一定要写在 filterChain.doFilter(servletRequest, servletResponse);
BaseContext.setCurrentId(empId);
filterChain.doFilter(servletRequest, servletResponse);
// BaseContext.setCurrentId(empId);
log.info("得到的用户id为 {} " + empId);
return;
}
//前端用户登录状态
User user = (User) httpServletRequest.getSession().getAttribute("user");
Long userId = employee.getId();
if (user != null) {
// BaseContext.setCurrentId(empId);方法一定要写在 filterChain.doFilter(servletRequest, servletResponse);
BaseContext.setCurrentId(userId);
filterChain.doFilter(servletRequest, servletResponse);
// BaseContext.setCurrentId(empId);
return;
}
log.info("没有用户登录");
httpServletResponse.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
return;
}
private boolean check(String[] urls, String requestUrl) {
for (String url : urls) {
boolean match = PATH_MATCHER.match(url, requestUrl);
if (match) {
return true;
}
}
return false;
}
}
全局异常处理
在添加时添加的名称是一样
@ControllerAdvice(annotations = {RestController.class, Controller.class}) 通知拦截那些controller
@ResponseBody 以json数据返回
@ExceptionHandler(SQLIntegrityConstraintViolationException.class) 捕获异常
package com.itheima.reggie.common;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.sql.SQLIntegrityConstraintViolationException;
/**
* 全局异常处理器
*/
@ControllerAdvice(annotations = {RestController.class, Controller.class})
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {
/**
* 不重复字段 重复异常
* @param ex
* @return
*/
@ExceptionHandler(SQLIntegrityConstraintViolationException.class)
public R<String> exceptionHandler(SQLIntegrityConstraintViolationException ex){
String message = ex.getMessage();
if (message.contains("Duplicate entry")){
String[] split = message.split(" ");
String s = split[2]+"已经存在";
log.error(s);
return R.error(s);
}
return R.error("未知错误");
}
/**
* 自定义异常类抛出
* @param ex
* @return
*/
@ExceptionHandler(CustomException.class)
public R<String> customException(CustomException ex){
String message = ex.getMessage();
log.error(message);
return R.error(message);
}
}
分页
package com.itheima.reggie.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* mybatisPlus进行分页 注册
*/
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mybatisPlusInterceptor;
}
}
/**
* 分页查询
* @param page
* @param pageSize
* @param name
* @return
*/
@GetMapping("/page")
public R<Page> page(long page ,long pageSize ,String name){
log.info("分页请求数据 page={} pageSize={} name={}",page,pageSize,name);
Page pageInfo = new Page(page,pageSize);
LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.like(StringUtils.isNotEmpty(name),Employee::getName,name);
queryWrapper.orderByDesc(Employee::getUpdateTime);
//会将查询出来的结果自动封装到 pageInfo中
employeeService.page(pageInfo,queryWrapper);
return R.success(pageInfo);
}
package com.itheima.reggie.common;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
/**
* 对象映射器:基于jackson将Java对象转为json,或者将json转为Java对象
* 将JSON解析为Java对象的过程称为 [从JSON反序列化Java对象]
* 从Java对象生成JSON的过程称为 [序列化Java对象到JSON]
*/
public class JacksonObjectMapper extends ObjectMapper {
public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
public JacksonObjectMapper() {
super();
//收到未知属性时不报异常
this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);
//反序列化时,属性不存在的兼容处理
this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
SimpleModule simpleModule = new SimpleModule()
.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)))
.addSerializer(BigInteger.class, ToStringSerializer.instance)
.addSerializer(Long.class, ToStringSerializer.instance)
.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
//注册功能模块 例如,可以添加自定义序列化器和反序列化器
this.registerModule(simpleModule);
}
}
对象映射器
1.继承json包中objectMapper类
2.WebMvcConfig中配置 拓展消息转换器
package com.itheima.reggie.common;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
/**
* 对象映射器:基于jackson将Java对象转为json,或者将json转为Java对象
* 将JSON解析为Java对象的过程称为 [从JSON反序列化Java对象]
* 从Java对象生成JSON的过程称为 [序列化Java对象到JSON]
*/
public class JacksonObjectMapper extends ObjectMapper {
public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
public JacksonObjectMapper() {
super();
//收到未知属性时不报异常
this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);
//反序列化时,属性不存在的兼容处理
this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
SimpleModule simpleModule = new SimpleModule()
.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)))
.addSerializer(BigInteger.class, ToStringSerializer.instance)
.addSerializer(Long.class, ToStringSerializer.instance)
.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
//注册功能模块 例如,可以添加自定义序列化器和反序列化器
this.registerModule(simpleModule);
}
}
/**
* 扩展mvc框架消息转换器
* @param converters
*/
@Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
log.info("扩展消息转换器启动");
MappingJackson2HttpMessageConverter messageConverter=new MappingJackson2HttpMessageConverter();
messageConverter.setObjectMapper(new JacksonObjectMapper());
converters.add(0,messageConverter);
}
公共字段自动填充
在实体类中加入@TableField注解
package com.itheima.reggie.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String username;
private String name;
private String password;
private String phone;
private String sex;
private String idNumber;
private Integer status;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
@TableField(fill = FieldFill.INSERT)
private Long createUser;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updateUser;
}
实现MetaObjectHandler
package com.itheima.reggie.common;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* 自定义元数据对象处理器
*/
@Component
@Slf4j
public class MyMetaObjecthandler implements MetaObjectHandler {
/**
* 插入操作,自动填充
* @param metaObject
*/
@Override
public void insertFill(MetaObject metaObject) {
log.info("公共字段自动填充[insert]...");
log.info(metaObject.toString());
metaObject.setValue("createTime", LocalDateTime.now());
metaObject.setValue("updateTime",LocalDateTime.now());
metaObject.setValue("createUser",BaseContext.getCurrentId());
metaObject.setValue("updateUser",BaseContext.getCurrentId());
System.out.println(BaseContext.getCurrentId());
}
/**
* 更新操作,自动填充
* @param metaObject
*/
@Override
public void updateFill(MetaObject metaObject) {
log.info("公共字段自动填充[update]...");
log.info(metaObject.toString());
long id = Thread.currentThread().getId();
log.info("线程id为:{}",id);
metaObject.setValue("updateTime",LocalDateTime.now());
metaObject.setValue("updateUser",BaseContext.getCurrentId());
}
}
文件的上传与下载
package com.itheima.reggie.controller;
import com.itheima.reggie.common.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.UUID;
@RestController
@Slf4j
@RequestMapping("/common")
public class CommonController {
@Value("${reggie.path}")
private String basePath;
/**
* 文件上传到服务器并保存到磁盘 就使用了一个MultipartFile file参数
* @param file
* @return
*/
@PostMapping("/upload")
public R<String> upload(MultipartFile file) {
String fileOriginalFilename = file.getOriginalFilename();
String suffix = fileOriginalFilename.substring(fileOriginalFilename.lastIndexOf("."));
String fileName = UUID.randomUUID() + suffix;
File dir = new File(basePath);
if (!dir.exists()) {
dir.mkdirs();
}
try {
file.transferTo(new File(basePath + fileName));
} catch (IOException e) {
}
return R.success(fileName);
}
/**
* 文件下载 谁创建某个流谁关闭 只有响应
* @param name
* @param response
* @throws IOException
*/
@GetMapping("/download")
public void download(String name, HttpServletResponse response) throws IOException {
InputStream fileInputStream = new FileInputStream(basePath + name);
response.setContentType("image/jpeg");
ServletOutputStream outputStream = response.getOutputStream();
byte[] bytes = new byte[1024];
int len = 0;
while ((len = fileInputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, len);
outputStream.flush();
}
fileInputStream.close();
}
}
//浏览器接收到响应信息之后,默认情况下,直接在显示窗口中打开响应信息;即使打不开,也会调用应用程序打开;只有实在打不开,才会激活文件下载窗口。
//可以设置响应头信息,使浏览器接收到响应信息之后,直接激活文件下载窗口,即使能打开也打不开
response.addHeader("Content-Disposition","attachment;filename=mystudentList.xls");
attachment 附件
10.1.3 表单的编码格式只能用:multipart/form-data
<form action="workbench/activity/fileUpload.do" method="post" enctype="multipart/form-data">
<input type="file" name="myFile"><br>
<input type="text" name="userName"><br>
<input type="submit" value="提交">
</form>
根据HTTP协议的规定,浏览器每次向后台提交参数,都会对参数进行统一编码;默认采用的编码格式是entype= "urlencoded"
,这种编码格式只能对文本数据进行编码;
浏览器每次向后台提交参数,都会首先把所有的参数转换成字符串,然后对这些数据统一进行urlencoded编码;对服务器传来的数据也通过这种方式进行解码 以前的提交的参数传输可以这么做,现在要传输文件了(传输二进制)就不能用这种编码方式
文件上传的表单编码格式只能用multipart/form-data:enctype="multipart/form-data" 功能:只是阻止默认行为
必须配置这个类 接受到文件上传请求后自动调用这个类
springboot默认有这个类
配置文件上传解析器 id:必须是multipartResolver 要不然会找不到
查询菜品列表和套餐列表分别是type=1或type=2在 CategoryController 分别查询出来
前端菜品展示需要DishFlavor,所以返回的类型需要有DishFlavor
package com.itheima.reggie.dto;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishFlavor;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
public class DishDto extends Dish {
private List<DishFlavor> flavors = new ArrayList<>();
private String categoryName;
private Integer copies;
}
/**
* 返回菜品列表
* @param dish
* @return
*/
@GetMapping("/list")
public R<List<DishDto>> list(Dish dish) {
List<DishDto> dishDtoList = null;
String key = "dish_" + dish.getCategoryId() + "status_" + dish.getStatus();
dishDtoList = (List<DishDto>) redisTemplate.opsForValue().get(key);
redis实现缓存验证码缓存用户信息
redis实现缓存菜品
springChace
cacheable类似查询
Cacheput类似添加
cacheEvict类似删除
Nginx
不知道目标服务器的地址 ,适用于管理多台服务器,其他服务器在内网,就一个反向代理服务器提供一个端口和外网
负载均衡器
mysql主从复制
实现读写分离
server:
port: 8080
spring:
application:
#可选 应用名称
name: reggie_take_out
shardingsphere:
datasource:
names:
master,slave
# 主数据源
master:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.30.128:3306/reggie?characterEncoding=utf-8
username: root
password: root
# 从数据源
slave:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.30.129:3306/reggie?characterEncoding=utf-8
username: root
password: root
masterslave:
# 读写分离配置
load-balance-algorithm-type: round_robin #轮询
# 最终的数据源名称
name: dataSource
# 主库数据源名称
master-data-source-name: master
# 从库数据源名称列表,多个逗号分隔
slave-data-source-names: slave
props:
sql:
show: true #开启SQL显示,默认false
main:
allow-bean-definition-overriding: true
redis:
host: 192.168.30.128
port: 6379
password: 123321
database: 0
mybatis-plus:
configuration:
#在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
id-type: ASSIGN_ID
reggie:
#反斜杠 创建路径
path: /usr/local/img/
德鲁伊的数据源和sharingJDBC的数据源冲突,我们配置允许数据源覆盖即可
在yml配置文件中配置
swagger
@Slf4j
@Configuration
@EnableSwagger2
@EnableKnife4j
public class WebMvcConfig extends WebMvcConfigurationSupport {
@Bean
public Docket createRestApi() {
// 文档类型
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.itheima.reggie.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("瑞吉外卖")
.version("1.0")
.description("瑞吉外卖接口文档")
.build();
}
/**
* 静态资源映射
* ("classpath:/backend/"); 其中的/ 代表的是target
* @param registry
*/
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
log.info("静态资源映射.......");
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");
}
//不需要拦截的路径
String[] urls = new String[]{
"/employee/login",
"/employee/logout",
"/backend/**",
"/front/**",
"/user/login",
"/user/sendMsg",
"/doc.html",
"/webjars/**",
"/swagger-resources",
"/v2/api-docs"
};