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错误和指定内容。

四、表单数据校验(请求参数的合法性校验)

使用JSR303的校验框架实现,SpringBoot提供JSR-303的支持,他就是Spring-boot-starter-validation,它包括了很多校验规则只需要在模型类中通过注解指定校验规则,在controller方法上开启校验。

JSR 303是Java规范的一部分,它定义了Java Bean验证的标准规范,即Bean Validation。

在Java应用程序中,使用Bean Validation可以对对象的属性进行验证,确保其满足特定的约束条件。通过在Java Bean类的字段上添加注解,可以定义验证规则和约束条件。

以下是一些常用的JSR 303注解:

  • @NotNull:字段的值不能为null。
  • @Size:字段的长度必须在指定的最小值和最大值之间。
  • @Min:字段的值必须大于或等于指定的最小值。
  • @Max:字段的值必须小于或等于指定的最大值。
  • @Email:字段必须是一个有效的电子邮件地址。
  • @Pattern:字段的值必须匹配指定的正则表达式模式。

使用Bean Validation的好处包括:

  1. 代码简洁:通过添加注解,可以轻松地定义验证规则和约束条件,而不需要编写大量的验证逻辑。
  2. 可读性强:通过在字段上添加注解,可以清晰地表达字段的验证规则,使代码更易读和理解。
  3. 可复用性高:通过定义自定义的约束注解和验证器,可以重复使用验证逻辑,提高代码的可重用性。
  4. 标准化:JSR 303提供了一个标准规范,使得在不同的Java应用程序中可以使用相同的验证方法和工具。

要在Java应用程序中使用JSR 303,需要添加相应的依赖,例如Hibernate Validator,并在需要验证的Java Bean类上添加合适的注解。然后,可以使用验证器对对象进行验证,并根据验证结果进行相应的处理。

五、开发成果

效果图 1:

每个公司都可以针对自己旗下的课程进行编辑发布,一个公司可以发布多门课程。

 实现了课程的编辑删除,条件查询,分页查询。

 实现了章节和小节的添加,删除,查询,上移,下移。

 教师信息的添加,编辑,删除,查询。