springboot基本配置、异常配置、拦截器配置、过滤器配置

557 阅读3分钟

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越小先执行

过滤器与拦截器的执行顺序.png

5.过滤器与拦截器的区别

IOC容器结构图

IOC容器结构图.png

  • 通俗理解过滤器和拦截器

过滤器:

从一堆含有铁块的石堆中过滤出铁块

拦截器:

治安管理,在一组队伍中要拦截人群进行筛选,女生走左边,男生走右边,不难不难拦截下来询问原因。

拦截器可以进行拦截,也可以阻断程序的运行,过滤器有的东西拦截器都有,功能比过滤器强

区别:

①:拦截器是基于java的反射机制的,而过滤器是基于函数的回调。 ②:拦截器不依赖于servlet容器,而过滤器依赖于servlet容器。 ③:拦截器只对action请求起作用,而过滤器则可以对几乎所有的请求起作用。 ④:拦截器可以访问action上下文、值、栈里面的对象,而过滤器不可以。 ⑤:在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。 ⑥:拦截器可以获取IOC容器中的各个bean,而过滤器不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。

6.异常处理

1.方法一:全局异常处理(推荐)

  • springboot静态资源路径: 从resource开始
package com.zking.config;
​
/*
* RestControllerAdvice  :返回结果都是json
* ControllerAdvice      :返回结果都是页面,会走视图解析器,定义string类型跳指定页面
* */
@RestControllerAdvicepublic 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);
    }
}

err1-全局异常处理.png

err2-全局异常处理.png

方法二:跳页面异常处理(不推荐,但可能用到)

  • 产品上线,报错的时候可以直接跳页面提示用户

  • 页面要放到static静态资源中,静态资源不会被拦截器拦截

  • 静态资源static.png

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"));
    }
}

小提示

  1. springboot中项目访问路径的修改
server:
  port: 8080
  servlet:
    context-path: /  # 项目访问路径