UD在线学习网站开发日记(一)
一、为什么会出现跨域问题?解决跨域问题的方法?
首先了解一下同源策略(SOP),它是由Netscape公司在1995年引入浏览器的。同源策略是浏览器中最基本最重要的安全功能,如果缺少了同源策略,我们的浏览器就会很容易受到XSS、CSFR等攻击。而所谓的同源策略是指:协议+域名+端口三者相同。
因此,当我们请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。
1、通过JSONP跨域
通过 script 标签的 src 属性进行跨域请求,如果服务端要响应内容则首先读取请求参数 callback 的值,callback 是一个回调函数的名称,服务端读取 callback 的值后将响应 内容通过调用 callback 函数的方式告诉请求方。
核心思想:网页通过添加一个script元素,向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。
2、添加响应头
cors是跨域资源共享,是一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其它 origin(域,协议和端口),使得浏览器允许这些 origin 访问加载自己的资源。服务端设置了Access-Control-Allow-Origin就开启了CORS,所以这种方式只要后端实现了CORS,就解决跨域问题。
//允许白名单域名进行跨域调用
config.addAllowedOrigin("*");
//允许跨域发送 cookie
config.setAllowCredentials(true);
//放行全部原始头信息
config.addAllowedHeader("*");
//允许所有请求方法跨域调用
config.addAllowedMethod("*");
package com.xuecheng.system.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
/**
* @description 跨域过虑器
* @author Mr.M
* @date 2022/9/7 11:04
* @version 1.0
*/
@Configuration
public class GlobalCorsConfig {
/**
* 允许跨域调用的过滤器
*/
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
//允许白名单域名进行跨域调用
config.addAllowedOrigin("*");
//允许跨越发送 cookie
config.setAllowCredentials(true);
//放行全部原始头信息
config.addAllowedHeader("*");
//允许所有请求方法跨域调用
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new
UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
此配置类实现了跨域过虑器,在响应头添加 Access-Control-Allow-Origin。
3.Nginx反向代理解决跨域
由于服务端之间没有跨域,浏览器通过 nginx 去访问跨域地址。利用了服务器和服务器之间通信不受浏览器的同源策略的限制
二、MybatisPlus相关问题
1、MybatisPlus代码生成器工具
它的好处是只需要设置好相关配置,就可以对某一张数据表一键生成,实体类,控制层,业务层,和持久层的基本代码,不需要我们再一个个的手动创建。
通常他是需要对6个部分进行设置。
1.数据库配置
2、全局配置
指定输出目录,作者名,是否开启swagger模式,时间策略
3、包配置
路径配置,Entity、Controller、Service、Mapper的名称设置
4、模板配置
设置模板路径
5、注入配置
自定义配置模板
6、策略配置
对Entity、Controller、Service、Mapper进行配置。
2、分页插件的底层原理
使用MybatisPlus的步骤:
1、构造分页拦截器
@Configuration
@MapperScan("com.UD.content.mapper")
public class MybatisPlusConfig {
/**
* 定义分页拦截器
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
2.构造分页构造器(current,size)
3、构造条件构造器QueryWrapper
4、执行QueryWrapper
5、获得数据
@Test
void testSelectPage() {
//当前页码
int current = 2;
//每页条数
int size = 2;
//构建 分页构造器
IPage<User> page = new Page(current, size);
//构建 条件构造器
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.lt("age",23);
//执行查询
userMapper.selectPage(page, wrapper);
//它会自动完成 数据的封装 并把查询出来的数据 存储到page对象的一个属性中
// setRecords 把数据存到 Records 里面了
// 总条数 总页数 --page也有封装
//获取page的 Records属性
List<User> records = page.getRecords();//当前页数据
long total = page.getTotal();//总条数
long pages = page.getPages();//总页数
System.out.println("当前数据总共有:"+total);
System.out.println("共"+pages+"页");
System.out.println("当前页数据:"+records);
}
底层实现:
Mybatis使用的是PageHelper。MybatisPlus使用的是IPage。
对于Mybatis的PageHelper,内部原理是将传入的当前页码和每页条数赋值给Page对象,保存到ThreadLocal中,然后在Mybatis的拦截器里获取分页参数,根据指定的数据库类型进行sql语句的拼接,期间用到了Limit。
Mybatis-plus分页插件使用的是IPage进行分页。IPage内部原理是基于拦截器的,拦截器会通过反射获取该方法的参数从而判断 是否存在IPage对象的实现类。如果不存在则不进行分页,存在则将该参数赋值给IPage对象,然后进行拼接sql的处理完成分页操作。
3、树型表的标记字段是什么?如何查询MySQL树型表?
树型表的标记字段是parentid即父节点的id
查询Mysql树形表的方法:
1)当层级固定的时候可以使用表的自连接进行查询。
2)灵活地查询方法是通过mysql递归的方法进行查询(with recursive实现)。
4、Mybatis的ResultType和ResultMap的区别?
resultType:如果查询出来的字段名字和类型能跟某一类中的属性能一 一对应好就使用ResultType。
resultMap:如果查询出来的字段名字和某类中的属性名字不能完美对应上,则需要使用ResultMap,然后进行手动完成字段匹配。
5、#{}和¥{}有什么区别?
#{}是占位符,在最后的sql语句中会显示问号。可以防止sql注入
${}用于动态拼接sql中的字符串,可能导致sql注入。
三、UD系统处理异常
自定义了一个统一的异常处理器去捕获并处理异常,可以针对某个异常类型进行单独处理。
使用控制器增加注解@ControllerAdvice和异常处理注解@ExceptionHandler来实现
1)处理自定义异常
程序在校验过程中抛出自定义异常,被异常处理器捕获后统一封装成异常类对象,记录日之后,响应给前端。
2)处理未知异常
程序在运行过程中抛出系统异常,被异常处理器捕获后封装成异常类对象,记录日志后,返回500错误和指定内容。