Springboot 复习
1.安装依赖
<!--继承 springboot项目,项目只能单一继承-->
<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.7.2</version>
</parent>
<dependencies>
<!-- 子项目中的依赖,如果在父项目中定义了,就可以不指定版本,如果指定,按指定的版本使用-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--热部署-->
<!-- 分布式(一个项目拆分成多个小项目) 集群(相同的下项目或模块 部署在不同的机器上)-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
<!--打包 一般在项目完成之后才会使用,所以一般不写 -->
<properties>
<!--打包跳过单元测试-->
<skipTests>true</skipTests>
</properties>
<build>
<!--打包插件-->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<!--启动入口-->
<configuration>
<mainClass>com.zking.Start</mainClass>
</configuration>
</plugin>
</plugins>
</build>
2.启动类配置
/*
@SpringBootApplication springboot 注解
启动类需要位于父包 ,在启动时会扫描本项目及子项目
如 com.zking子目录 com.zking.a com.zking.b 里面的注解会扫描到
com.zking.a.b扫描不到
*/
@SpringBootApplication
//过滤器只要在配置类中声明就行
//@ServletComponentScan("com.zking.filter")
public class Start {
public static void main(String[] args) {
SpringApplication.run(Start.class);
}
}
- yaml 和 properties 文件没有区别,yaml 中的: 就相当于properties中的 ' . '
3.过滤器的使用
- 过滤器需要加在配置类中才能生效
- 配置类: @configuration、@ComponentScan、@Bean
方式一 (继承Filter)
注意:一定要在配置类中加 @ServletComponentScan // 扫描servlet组件,过滤器才能生效
@WebFilter("/*")
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("进入过滤器");
filterChain.doFilter(servletRequest,servletResponse);
}
}
方式二 (@Bean方式)
第二种方式,通过自定义FilterConfig配置类,进行过滤器的组件扫描(推荐)
创建一个config文件夹,创建FilterConfig配置类
package com.zking.config;
@Configuration //这是一个配置类
public class FilterConfig {
// @Bean("m") // 在IOC容器中创建组件,等同于xml中的bean组件,可以设置Bean的名字,有时候需要
@Bean
public FilterRegistrationBean<MyFilter> my() {
FilterRegistrationBean fr = new FilterRegistrationBean();
fr.setFilter(new MyFilter());// 设置过滤器类
fr.addUrlPatterns("/*"); // 要过滤的地址,多个用,逗号隔开
fr.setOrder(1); //设置过滤器执行的顺序 ,小数字优先
return fr;
}
}
4.拦截器的配置
- 编写拦截器,继承 HandlerInterceptor
package com.zking.interceptor;
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("进入拦截器 1");
return true;
}
}
- 配置拦截器,在Springmvc中进行配置,继承 WebMvcConfigurer
package com.zking.config;
@Configuration
public class WebmvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 添加拦截器1
registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").order(1);
// 添加拦截器2
registry.addInterceptor(new MyInterceptor2()).addPathPatterns("/**").order(2);
}
}
过滤器与拦截器的执行顺序
- 先执行过滤器,再执行拦截器,相同的过滤器或者拦截器执行顺序由order决定,order越小先执行
5.过滤器与拦截器的区别
IOC容器结构图
- 通俗理解过滤器和拦截器
过滤器:
从一堆含有铁块的石堆中过滤出铁块
拦截器:
治安管理,在一组队伍中要拦截人群进行筛选,女生走左边,男生走右边,不难不难拦截下来询问原因。
拦截器可以进行拦截,也可以阻断程序的运行,过滤器有的东西拦截器都有,功能比过滤器强
区别:
①:拦截器是基于java的反射机制的,而过滤器是基于函数的回调。 ②:拦截器不依赖于servlet容器,而过滤器依赖于servlet容器。 ③:拦截器只对action请求起作用,而过滤器则可以对几乎所有的请求起作用。 ④:拦截器可以访问action上下文、值、栈里面的对象,而过滤器不可以。 ⑤:在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。 ⑥:拦截器可以获取IOC容器中的各个bean,而过滤器不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。
6.异常处理
1.方法一:全局异常处理(推荐)
- springboot静态资源路径: 从resource开始
package com.zking.config;
/*
* RestControllerAdvice :返回结果都是json
* ControllerAdvice :返回结果都是页面,会走视图解析器,定义string类型跳指定页面
* */
@RestControllerAdvice
public class MyException{
@ExceptionHandler(NullPointerException.class)
public Map<String ,Object> ex1(NullPointerException ex) {
ex.printStackTrace();
Map<String ,Object> map = new LinkedHashMap<>();
map.put("code",500); // 自定义状态码
map.put("msg","服务器出现空指针异常");
return map;
}
@ExceptionHandler(Exception.class)
public Map<String ,Object> ex2(Exception ex) {
ex.printStackTrace();
Map<String ,Object> map = new LinkedHashMap<>();
map.put("code1",500); // 自定义状态码
map.put("msg","服务器出现未知异常");
return map;
}
}
测试
@RestController
public class TestController {
@RequestMapping("err1")
public void b() {
String s=null;
System.out.println(s.equals(""));
}
@RequestMapping("err2")
public void c() {
System.out.println(1/0);
}
}
方法二:跳页面异常处理(不推荐,但可能用到)
-
产品上线,报错的时候可以直接跳页面提示用户
-
页面要放到static静态资源中,静态资源不会被拦截器拦截
-
package com.zking.config;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.ErrorPageRegistrar;
import org.springframework.boot.web.server.ErrorPageRegistry;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
@Configuration
public class ErrorPageCongfig implements ErrorPageRegistrar {
@Override
public void registerErrorPages(ErrorPageRegistry registry) {
registry.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/err/404.html"));
registry.addErrorPages(new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/err/500.html"));
}
}
小提示
- springboot中项目访问路径的修改
server:
port: 8080
servlet:
context-path: / # 项目访问路径