特点:
-
依赖管理 父项目用来做依赖管理:利用maven的依赖传递原则 其他都不用写明版本号 可以在当前项目里面重写配置,利用的是 maven的 就近依赖原则
-
自动配置 导入Tomcat依赖后
-
自动配好Web常见功能,如:字符编码问题
-
默认的包结构,用于注解扫描
-
-
主程序所在包(启动类所在包)及其下面的所有子包里面的组件都会被默认扫描进来
-
所以无需以前的包扫描配置
-
如果想要改变扫描路径,
-
@SpringBootApplication(scanBasePackages="com.atguigu")或者@ComponentScan 指定扫描路径
-
各种配置拥有默认值
-
-
-
配置文件的值最终会绑定到对应的类上,这些类会在容器中创建对象。所以用到这些值的时候,SpringBoot底层会拿到这些类的对象,提取出值,之后绑定,关于如何绑定,要讨论
-
-
按需加载所有自动配置项
-
-
非常多的starter
-
引入了哪些场景这个场景的自动配置才会开启,例如:web场景就只有web
-
SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure 包里面
-
自动配置,spring-boot-autoconfigure。包里源码标红,表示依赖的其它的包未导入,导入其依赖的包即可使用
-
-
@SpringBootApplication
标识启动类。有下三个重要注解标识
1.@SpringBootConfiguration
@Configuration。代表当前是一个配置类
2.@ComponentScan
指定扫描哪些,Spring注解;
3.@EnableAutoConfiguration
该注解有两个注解进行标识
AutoConfigurationPackage是导入你自己创建的Bean,比如controller啥的,下面的Import是导入第三方的组件,比如DispatcherServlet啥的。
所以说本项目中的 类的优先级高于自动配置starter中的bean创建
1.@AutoConfigurationPackage
自动配置包?指定了默认的包规则
2.@Import(AutoConfigurationImportSelector.class)
有选择的导入
@ConditionalOnBean(Value)
标注在类和方法上。作用,如果ioc容器中有value值的Bean才能将其标注的方法或者类生效
@ConditionalOnMissingBean(value)
标注在类和方法上,作用与上一个相反,如果ioc容器中没有value值的Bean才能将其标注的方法或者类生效
@ImportResource(value="classpath:")
作用在类上,将配置文件导入。
@EanalbeConfigurationProperties({Car.class})
作用在配置类上,作用1.开启Car这个类的配置绑定功能(可以实现类属性绑定yml自定义值)。2.把Car这个组件加入ioc容器
类属性绑定yml中的自定义值
1. @Component + @ConfigurationProperties(prefix="自定义前缀")
只有在容器中的组件,才会拥有SpringBoot提供的强大功能,所以要加上@Component注解
2. @EnableConfigurationProperties(类.class) + @ConfigurationProperties(prefix)
@EnableConfigurationProperties 一定要写在配置类
定制化mvc
1、使用Servlet API
@ServletComponentScan(basePackages = "com.atguigu.admin") :指定原生Servlet组件都放在那里
请求不发送到DispatchServlet,不经过dispatcher方法,不过拦截器
拦截器是DispatcherServlet类中dodispatch()方法中的,这里DispatcherServlet的没走,走的是我们定义 的Servlet,所以拦截器就不会生效.
Servlet 是规范之一,只是框架在底层帮我们实现了
原生不经过那一系列框架,效率会更高
原因很简单,就是springmvc底层实际上就是一个大型的servlet, 而他的urlpatterns为 / 。所以当请求/.my时
会精确匹配到自定义的servlet, 不会经过spring.
@WebServlet(urlPatterns = "/my"):效果:直接响应,没有经过Spring的拦截器?
@WebFilter(urlPatterns={"/css/*","/images/*"})
@WebListener
东西太多看别个博客吧。
https://blog.csdn.net/weixin_41924879/article/details/101175659
2、使用RegistrationBean
ServletRegistrationBean`, `FilterRegistrationBean`, and `ServletListenerRegistrationBean
//filter用于字符过滤,listener用于初始化作用域数据,interceptor用于拦截请求
扩展:DispatchServlet 如何注册进来
-
容器中自动配置了 DispatcherServlet 属性绑定到 WebMvcProperties;对应的配置文件配置项是 spring.mvc。
-
通过 ServletRegistrationBean<DispatcherServlet> 把 DispatcherServlet 配置进来。
-
-
老师这里错了吧,dispatcherServlet是用@Bean标签注册到了容器中
-
这个注册类应该是将dispatcherservlet封装注册到tomcat服务器的Servletcontext全局作用域中
-
Servlet是要被ServletContext管理才能生效的,DispatcherServletRegistrationBean的作用就是把这个servlet交给ServletContext管理
-
-
默认映射的是 / 路径。
拦截器是在请求发过来的时候交给Spring去拦截的(dispatcherServlet)
3、定制化
-
编写自定义的配置类 xxxConfiguration;+ @Bean替换、增加容器中默认组件;视图解析器
-
最常用:Web应用 编写一个配置类实现 WebMvcConfigurer 即可定制化web功能;+ @Bean给容器中再扩展一些组件
@EnableWebMvc
@ EnableWebMvc+ 实现 WebMvcConfigurer —— @Bean 可以全面接管SpringMVC,所有规则全部自己重新配置; 实现定制和扩展功能
拦截器原理
拦截器(Interceptor)和过滤器(Filter)的执行顺序 过滤前-拦截前-Action处理-拦截后-过滤后
拦截器(Interceptor)使用 interceptor 的执行顺序大致为:
请求到达 DispatcherServlet DispatcherServlet 发送至 Interceptor ,执行 preHandle 请求达到 Controller 请求结束后,postHandle 执行
过滤器,拦截器这种类似的都是责任链模式。
1、根据当前请求,找到HandlerExecutionChain【可以处理请求的handler以及handler的所有 拦截器(拦截器链)】
2、先来顺序执行 所有拦截器的 preHandle方法
-
1、如果当前拦截器prehandle()返回为true。则执行下一个拦截器的preHandle()
-
2、如果当前拦截器返回为false。直接 倒序执行所有已经执行了的拦截器的 afterCompletion()方法;
3、如果任何一个拦截器返回false。直接跳出不执行目标方法
4、所有拦截器都返回True。执行目标方法
5、倒序执行所有拦截器的postHandle()方法。
6、前面的步骤有任何异常都会直接倒序触发 afterCompletion
7、页面成功渲染完成以后,也会倒序触发 afterCompletion
preHandle顺序执行,postHandle和afterCompletion都是逆序执行,afterCompletion会在preHandle返回false/任何异常发生时/渲染视图完成后执行。
图解拦截器原理:
1、实现HandlerInterceptor 接口
/**
* 登录检查
* 1、配置好拦截器要拦截哪些请求
* 2、把这些配置放在容器中
*/
-
preHandle
用来拦截处理器的执行,preHandle方法将在Controller处理之前调用的。SpringMVC里可以同时存在多个interceptor,它们基于链式方式调用,每个interceptor都根据其声明顺序依次执行。这种链式结构可以中断,当方法返回false时整个请求就结束了。
方法的返回值是布尔类型,方法如果返回false,那后面的interceptor和Controller都不会执行(通常都会响应一个自定义的 Http 错误码给客户端)。如果返回值为true,则接着调用下一个interceptor的preHandle方法。如果当前是最后一个interceptor,接下来就会直接调用Controller的处理方法。
-
postHandle:
postHandle 会在Controller方法调用之后,但是在DispatcherServlet 渲染视图之前调用。因此我们可以在这个阶段,对将要返回给客户端的ModelAndView进行操作。
-
afterCompletion:
afterCompletion在当前interceptor的preHandle方法返回true时才执行。该方法会在整个请求处理完成后被调用,就是DispatcherServlet渲染视图完成以后,主要是用来进行资源清理工作。需要注意的是,afterCompletion在interceptor链式结构中以相反的顺序执行,也就是说先申明的interceptor返回会后调用。
2、配置拦截器
把这些配置放在容器中。
/**
* 1、编写一个拦截器实现HandlerInterceptor接口
* 2、拦截器注册到容器中(实现WebMvcConfigurer的addInterceptors)
* 3、指定拦截规则【如果是拦截所有,静态资源也会被拦截】
4、/*只代表当前目录下,/**同时还包含了子文件夹(类路径又是什么意思 )
*/
文件上传
1、页面表单
<!-- method="post" enctype="multipart/form-data" 文件上传表单的固定写法。
enctype就是encodetype就是编码类型的意思。multipart/form-data是指表单数据中由多部分构成
既有文本数据,又有文件等二进制数据 -->
<form method="post" action="/upload" enctype="multipart/form-data">
<input type="file" name="file"><br>
<input type="submit" value="提交">
</form>
2、文件上传代码
/**
* MultipartFile 自动封装上传过来的文件
//各位记得设置上传最大空间值,放的图片太大会有异常
*/
3、文件上传自动配置类
在配置文件中可设置文件上传大小
//文件上传大小配置。单个文件,整个请求
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=100MB
异常
1、默认规则
-
默认情况下,Spring Boot提供
/error
处理所有错误的映射 -
对于机器客户端,它将生成JSON响应,其中包含错误,HTTP状态和异常消息的详细信息。
-
对于浏览器客户端,响应一个“ whitelabel”错误视图,以HTML格式呈现相同的数据
-
要对其进行自定义,添加View解析为error
替换调mvc组件error(也就是白页)
-
要完全替换默认行为,可以实现
ErrorController
并注册该类型的Bean定义,或添加ErrorAttributes类型的组件
以使用现有机制但替换其内容。 -
error/下的4xx,5xx页面会被自动解析;
2、定制错误处理逻辑
-
1、自定义错误页
-
-
error/404.html error/5xx.html;有精确的错误状态码页面就匹配精确,没有就找 4xx.html;如果都没有就触发白页
-
-
2、@ControllerAdvice+@ExceptionHandler 处理全局异常;底层是 ExceptionHandlerExceptionResolver 支持的,因为标了@ExceptionHandler注解
/**
* 处理整个web controller的异常
*/
-
3、@ResponseStatus+自定义异常 ;底层是 ResponseStatusExceptionResolver 解析器处理,因为标了@ResponseStatus注解,把responsestatus注解的信息,底层调用 response.sendError(statusCode, resolvedReason);然后还是下面的流程,没有解析器可以解析,然后tomcat发送的/error到mvc,找4xx,5xx页面
//设置状态码 和异常信息 程序执行到这里时主要将注解中的信息获得
-
4、自定义实现 HandlerExceptionResolver 处理异常;把优先级调高(一旦出现异常优先被其处理),可以作为默认的全局异常处理规则
-
ErrorViewResolver 实现自定义处理异常;
-
-
主动调用response.sendError() 。error请求就会转给controller,如果没有4叉叉这些页面,就会调用BeanNameViewResolver解析器,返回error白页(为mvc的错误页面,组件View)
-
你的异常没有任何人能处理。tomcat底层调用 response.sendError()。error请求就会转给controller,如果没有4叉叉这些页面,就会调用Tomcat自己的错误页面
-
以上都是由basicErrorController 控制器处理,要去的页面地址是 ErrorViewResolver解析器解析 ;
-
@PathVariable(rest风格)、@RequestHeader、@RequestParam、@CookieValue、@RequestBody、@RequestAttribute(用来请求域中取数据,然后请求转发)、@ModelAttribute、@MatrixVariable(矩阵变量)
整合mybatis
1、纯配置模式
-
全局配置文件
-
SqlSessionFactory: 自动配置好了
-
SqlSession:自动配置了 SqlSessionTemplate 组合了SqlSession
-
@Import(AutoConfiguredMapperScannerRegistrar.class);
-
Mapper: 只要我们写的操作MyBatis的接口标注了 @Mapper 就会被自动扫描
可以修改配置文件中 mybatis 开始的所有配置;
# 第一种方式:纯配置模式
# 配置mybatis规则
yml:-------------------------------------------
mybatis:
// config-location: classpath:mybatis/mybatis-config.xml #全局配置文件位置
mapper-locations: classpath:mybatis/mapper/*.xml #sql映射文件位置
configuration:
map-underscore-to-camel-case: true
全局配置文件和在yml中使用configuration配置,二者只能选其一 推荐在yml中
可以不写全局配置文件,所有全局配置文件的配置信息都放在configuration配置项中即可
Mapper接口--->绑定Xml
接口----------------------------------------------
@Mapper
public interface AccountMapper {
public Account getAcct(Long id);
}
SQL实现的xml----------------------------------------------------
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.admin.mapper.AccountMapper">
<!-- public Account getAcct(Long id); -->
<select id="getAcct" resultType="com.atguigu.admin.bean.Account">
select * from account_tbl where id=#{id}
</select>
</mapper>
mybatis使用规则:
-
导入mybatis官方starter
-
编写mapper接口。标注@Mapper注解
-
编写sql映射文件并绑定mapper接口
-
在application.yaml中指定Mapper配置文件的位置,以及指定全局配置文件的信息 (建议不写全局配置文件,直接配置在mybatis.configuration)
2、纯注解模式
//这个方式讲mybatis的时候就提了,1.不适合复杂查询 2.写死了sql语句
//主要是因为注解只适合小型的sql语句,而公司里的语句都非常长,用xml配置会更清晰
3、推荐混合模式
//一般都混合使用,简单的sql语句就通过注解写在方法上
最佳实战:
-
引入mybatis-starter依赖
-
配置application.yaml中,指定mapper-location位置即可
-
编写Mapper接口并标注@Mapper注解
-
简单方法直接注解方式
-
复杂方法编写mapper.xml进行绑定映射
-
在程序启动类上面标注@MapperScan("com.atguigu.admin.mapper") 简化,其他的接口就可以不用标注@Mapper注解。
整合 MyBatis-Plus
优点:数据层: mapper的CRUD不用写了
-
只需要我们的Mapper继承 BaseMapper 就可以拥有crud能力,因为BaseMapper声明了许多方法。如果不够用,那就映射xml文件。
public interface UserMapper extends BaseMapper<User> {}
优点:业务层: Service 的CRUD也不用写了
/**
* service的接口继承顶级service接口---IService
*/
public interface UserService extends IService<User> {
}
service的实现类继承ServiceImpl----它是顶级接口IService的实现类,所以我们就可以直接用方法了。
如果不够用,那就自己加在接口中UserService,然后再来UserServiceImpl实现。
3、CRUD功能
//控制器方法
//使用分页还需要的配置,分页拦截器