SpringBoot2核心功能 --- Web开发

一、SpringMVC自动配置概览

Spring Boot provides auto-configuration for Spring MVC that works well with most applications.(大多场景我们都无需自定义配置)

The auto-configuration adds the following features on top of Spring’s defaults:

  • Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.

        内容协商视图解析器和 BeanName 视图解析器

  • Support for serving static resources, including support for WebJars (covered later in this document)).

        静态资源(包括webjars)

  • Automatic registration of Converter, GenericConverter, and Formatter beans.

        自动注册 Converter, GenericConverter, Formatter

  • Support for HttpMessageConverters (covered later in this document).

        支持 HttpMessageConverters (后来我们配合内容协商理解原理)

  • Automatic registration of MessageCodesResolver (covered later in this document).

        自动注册 MessageCodesResolver (国际化用)

  • Static index.html support.

        静态 index.html 页支持

  • Custom Favicon support (covered later in this document).

        自定义 Favicon

  • Automatic use of a ConfigurableWebBindinglnitializer bean (covered later in this document).

        自动使用 ConfigurableWebBindinglnitializer(DataBinder负责将请求数据绑定到JavaBean上)

If you want to keep those Spring Boot MVC customizations and make more MVC customizations (interceptors, formatters, view controllers, and other features), you can add your own @Configuration class of type WebMvcConfigurer but without @EnableWebMvc

不用@EnableWebMvc注解。使用 @Configuration + WebMvcConfigurer 自定义规则

If you want to provide custom instances of RequestMappingHandlerMapping , RequestMappingHandlerAdapter , or ExceptionHandlerExceptionResolver , and still keep the Spring Boot MVC customizations, you can declare a bean of type WebMvcRegistrations and use it to provide custom instances of those components.

声明 WebMvcRegistrations 改变默认底层组件

If you want to take complete control of Spring MVC, you can add your own Configuration annotated with @EnableWebMvc , or alternatively add your own Configuration -annotated DelegatingWebMvcConfigunation as described in theJavadoc of @EnableWebMvc .

使用 @EnableWebMvc + @Configuration + DelegatingWebMvcConfiguration 全面接管 SpringMVC

 

 

二、简单功能分析

2.1、静态资源访问

2.1.1、静态资源目录

静态资源放在类路径下: called /static

                                                   /public

                                                   /resources

                                                   /META-INF/resources

SpringBoot2核心功能 --- Web开发_第1张图片

访问 : 当前项目根路径/ + 静态资源名

原理: 静态映射 /** 

请求进来,先去找 Controller 看能不能处理。不能处理的所有请求又都交给静态资源处理器。静态资源也找不到则响应404页面

改变默认的静态资源路径:

SpringBoot2核心功能 --- Web开发_第2张图片

spring:
  resources:
    static-locations: [classpath:/haha/]

 

2.1.2、静态资源访问前缀

默认无前缀

自定义前缀:

spring:
  mvc:
    static-path-pattern: /res/**

当前项目 + static-path-pattern + 静态资源名 = 静态资源文件夹下找

 

2.1.3、webjar

自动映射 /webjars/**

WebJars - Web Libraries in Jars


    org.webjars
    jquery
    3.5.1

访问地址:http://localhost:8080/webjars/jquery/3.5.1/jquery.js 后面地址要按照依赖里面的包路径

 

2.2、欢迎页支持

静态资源路径下 index.html

可以配置静态资源路径

但是不可以配置静态资源的访问前缀。否则导致 index.html 不能被默认访问

SpringBoot2核心功能 --- Web开发_第3张图片

spring:
#  mvc:
#    static-path-pattern: /res/**   这个会导致welcome page功能失效

  resources:
    static-locations: [classpath:/haha/]

使用 controller 处理 /index

 

2.3、自定义 Favicon

自定义页面小图标

favicon.ico 放在静态资源目录下即可。

SpringBoot2核心功能 --- Web开发_第4张图片

spring:
#  mvc:
#    static-path-pattern: /res/**   这个会导致 Favicon 功能失效

 

 

三、请求参数处理

3.1、请求映射

rest使用与原理:

@xxxMapping;

Rest风格支持(使用HTTP请求方式动词来表示对资源的操作

以前:/getUser   获取用户  /deleteUser 删除用户   /editUser  修改用户   /saveUser 保存用户

现在: /user GET-获取用户 DELETE-删除用户 PUT-修改用户 POST-保存用户 




    
    首页


index.html

核心Filter;HiddenHttpMethodFilter

用法: 表单method=post,隐藏域 _method=put

SpringBoot中手动开启

    @RequestMapping(value = "/user",method = RequestMethod.GET)
    public String getUser(){
        return "GET-张三";
    }

    @RequestMapping(value = "/user",method = RequestMethod.POST)
    public String saveUser(){
        return "POST-张三";
    }


    @RequestMapping(value = "/user",method = RequestMethod.PUT)
    public String putUser(){
        return "PUT-张三";
    }

    @RequestMapping(value = "/user",method = RequestMethod.DELETE)
    public String deleteUser(){
        return "DELETE-张三";
    }

    //查看源码可以发现默认是false,需要手动开启 
	@Bean
	@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
	@ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", name = "enabled", matchIfMissing = false)
	public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
		return new OrderedHiddenHttpMethodFilter();
	}

 Rest使用客户端工具

  • 如PostMan直接发送Put、delete等方式请求,无需Filter。
spring:
  mvc:
    hiddenmethod:
      filter:
        enabled: true   #开启页面表单的Rest功能

Rest原理(表单提交要使用REST的时候)

  • 表单提交会带上_method=PUT
  • 请求过来被HiddenHttpMethodFilter拦截

       1、求是否正常,并且是POST

       2、获取到_method的值。

       3、兼容以下请求;PUT.DELETE.PATCH

       4、原生request(post),包装模式requesWrapper重写了getMethod方法,返回的是传入的值。

       5、过滤器链放行的时候用wrapper。以后的方法调用getMethod是调用requesWrapper的。 

 扩展:如何把_method 这个名字换成我们自己喜欢的。

    //自定义filter
    @Bean
    public HiddenHttpMethodFilter hiddenHttpMethodFilter(){
        HiddenHttpMethodFilter methodFilter = new HiddenHttpMethodFilter();
        methodFilter.setMethodParam("_m");
        return methodFilter;
    }

 

3.2、普通参数与基本注解

3.2.1、注解

@PathVariable、@RequestHeader、@ModelAttribute、@RequestParam、@MatrixVariable、@CookieValue、@RequestBody

测试基本注解:
    car/{id}/owner/{username}
  • @PathVariable(路径变量)
  • @RequestHeader(获取请求头)
  • @RequestParam(获取请求参数)
  • @CookieValue(获取cookie值)
  • @RequestBody(获取请求体[POST])
  • @RequestAttribute(获取request域属性)
  • @MatrixVariable(矩阵变量)
/cars/{path}?xxx=xxx&aaa=ccc queryString 查询字符串。@RequestParam;
/cars/sell;low=34;brand=byd,audi,yd ;矩阵变量
页面开发,cookie禁用了,session里面的内容怎么使用; session.set(a,b)---> jsessionid ---> cookie ----> 每次发请求携带。 url重写:/abc;jsesssionid=xxxx 把cookie的值使用矩阵变量的方式进行传递. /boss/1/2 /boss/1;age=20/2;age=20 @MatrixVariable(矩阵变量) @MatrixVariable(矩阵变量) @MatrixVariable(矩阵变量)/boss/{bossId}/{empId}
测试@RequestBody获取数据
用户名:
邮箱:
  1. 矩阵变量需要在SpringBoot中手动开启
  2. 根据RFC3986的规范,矩阵变量应当绑定在路径变量中!
  3. 若是有多个矩阵变量,应当使用英文符号;进行分隔。
  4. 若是一个矩阵变量有多个值,应当使用英文符号,进行分隔,或之命名多个重复的key即可。
  5. 如:/cars/sell;low=34;brand=byd,audi,yd
@RestController
public class ParameterTestController {
    //  car/2/owner/zhangsan
    @GetMapping("/car/{id}/owner/{username}")
    public Map getCar(@PathVariable("id") Integer id,
                                     @PathVariable("username") String name,
                                     @PathVariable Map pv,
                                     @RequestHeader("User-Agent") String userAgent,
                                     @RequestHeader Map header,
                                     @RequestParam("age") Integer age,
                                     @RequestParam("inters") List inters,
                                     @RequestParam Map params,
                                     @CookieValue("_ga") String _ga,
                                     @CookieValue("_ga") Cookie cookie){


        Map map = new HashMap<>();

//        map.put("id",id);
//        map.put("name",name);
//        map.put("pv",pv);
//        map.put("userAgent",userAgent);
//        map.put("headers",header);
        map.put("age",age);
        map.put("inters",inters);
        map.put("params",params);
        map.put("_ga",_ga);
        System.out.println(cookie.getName()+"===>"+cookie.getValue());
        return map;
    }


    @PostMapping("/save")
    public Map postMethod(@RequestBody String content){
        Map map = new HashMap<>();
        map.put("content",content);
        return map;
    }

    //1、语法: 请求路径:/cars/sell;low=34;brand=byd,audi,yd
    //2、SpringBoot默认是禁用了矩阵变量的功能
    //      手动开启:原理。对于路径的处理。UrlPathHelper进行解析。
    //              removeSemicolonContent(移除分号内容)支持矩阵变量的
    //3、矩阵变量必须有url路径变量才能被解析
    @GetMapping("/cars/{path}")
    public Map carsSell(@MatrixVariable("low") Integer low,
                        @MatrixVariable("brand") List brand,
                        @PathVariable("path") String path){
        Map map = new HashMap<>();

        map.put("low",low);
        map.put("brand",brand);
        map.put("path",path);
        return map;
    }

    // /boss/1;age=20/2;age=10

    @GetMapping("/boss/{bossId}/{empId}")
    public Map boss(@MatrixVariable(value = "age",pathVar = "bossId") Integer bossAge,
                    @MatrixVariable(value = "age",pathVar = "empId") Integer empAge){
        Map map = new HashMap<>();

        map.put("bossAge",bossAge);
        map.put("empAge",empAge);
        return map;

    }
}

 

3.2.2、Servlet API

WebRequest、ServletRequest、MultipartRequest、 HttpSession、javax.servlet.http.PushBuilder、Principal、InputStream、Reader、HttpMethod、Locale、TimeZone、ZoneId

ServletRequestMethodArgumentResolver 以上的部分参

@Override
	public boolean supportsParameter(MethodParameter parameter) {
		Class paramType = parameter.getParameterType();
		return (WebRequest.class.isAssignableFrom(paramType) ||
				ServletRequest.class.isAssignableFrom(paramType) ||
				MultipartRequest.class.isAssignableFrom(paramType) ||
				HttpSession.class.isAssignableFrom(paramType) ||
				(pushBuilder != null && pushBuilder.isAssignableFrom(paramType)) ||
				Principal.class.isAssignableFrom(paramType) ||
				InputStream.class.isAssignableFrom(paramType) ||
				Reader.class.isAssignableFrom(paramType) ||
				HttpMethod.class == paramType ||
				Locale.class == paramType ||
				TimeZone.class == paramType ||
				ZoneId.class == paramType);
	}

 

3.2.3、复杂参数

MapModel(map、model里面的数据会被放在request的请求域 request.setAttribute)、Errors/BindingResult、RedirectAttributes( 重定向携带数据)ServletResponse(response)、SessionStatus、UriComponentsBuilder、ServletUriComponentsBuilder

Map map,  Model model, HttpServletRequest request 都是可以给request域中放数据,
request.getAttribute();

Map、Model类型的参数,会返回 mavContainer.getModel();---> BindingAwareModelMap 是Model 也是Map

mavContainer.getModel(); 获取到值的

SpringBoot2核心功能 --- Web开发_第5张图片

SpringBoot2核心功能 --- Web开发_第6张图片

SpringBoot2核心功能 --- Web开发_第7张图片

 

3.2.4、自定义对象参数

可以自动类型转换与格式化,可以级联封装。

测试封装POJO;
姓名:
年龄:
生日:
宠物:
/**
 *     姓名:  
* 年龄:
* 生日:
* 宠物姓名:
* 宠物年龄: */ @Data public class Person { private String userName; private Integer age; private Date birth; private Pet pet; } @Data public class Pet { private String name; private String age; } result

 

 

四、数据响应与内容协商

SpringBoot2核心功能 --- Web开发_第8张图片

  

4.1、响应JSON

1、jackson.jar+@ResponseBody

        
            org.springframework.boot
            spring-boot-starter-web
        
web场景自动引入了json场景
    
      org.springframework.boot
      spring-boot-starter-json
      2.3.4.RELEASE
      compile
    

SpringBoot2核心功能 --- Web开发_第9张图片

给前端自动返回json数据;

 

2、SpringMVC到底支持哪些返回值

ModelAndView
Model
View
ResponseEntity 
ResponseBodyEmitter
StreamingResponseBody
HttpEntity
HttpHeaders
Callable
DeferredResult
ListenableFuture
CompletionStage
WebAsyncTask
有 @ModelAttribute 且为对象类型的
@ResponseBody 注解 ---> RequestResponseBodyMethodProcessor;

 

4.2、内容协商

根据客户端接收能力不同,返回不同媒体类型的数据。

 

4.2.1、引入xml依赖

 
            com.fasterxml.jackson.dataformat
            jackson-dataformat-xml

 

4.2.2、postman分别测试返回json和xml

只需要改变请求头中Accept字段。Http协议中规定的,告诉服务器本客户端可以接收的数据类型。

SpringBoot2核心功能 --- Web开发_第10张图片

 

4.2.3、开启浏览器参数方式内容协商功能

为了方便内容协商,开启基于请求参数的内容协商功能。

spring:
    contentnegotiation:
      favor-parameter: true  #开启请求参数内容协商模式

发请求: http://localhost:8080/test/person?format=json

               http://localhost:8080/test/person?format=xml

SpringBoot2核心功能 --- Web开发_第11张图片

确定客户端接收什么样的内容类型;

1、Parameter策略优先确定是要返回json数据(获取请求头中的format的值)

2、最终进行内容协商返回给客户端json即可。

 

 

五、视图解析与模板引擎

视图解析:SpringBoot默认不支持 JSP,需要引入第三方模板引擎技术实现页面渲染

5.1、视图解析

SpringBoot2核心功能 --- Web开发_第12张图片

视图解析原理流程:

1、目标方法处理的过程中,所有数据都会被放在 ModelAndViewContainer 里面。包括数据和视图地址

2、方法的参数是一个自定义类型对象(从请求参数中确定的),把他重新放在 ModelAndViewContainer

3、任何目标方法执行完成以后都会返回 ModelAndView(数据和视图地址)。

4、processDispatchResult 处理派发结果(页面改如何响应)

SpringBoot2核心功能 --- Web开发_第13张图片

 视图解析:

  • 返回值以 forward: 开始: new InternalResourceView(forwardUrl); --> 转发request.getRequestDispatcher(path).forward(request, response);
  • 返回值以 redirect: 开始: new RedirectView() --》 render就是重定向
  • 返回值是普通字符串: new ThymeleafView()--->

 

5.2、模板引擎-Thymeleaf

5.2.1、thymeleaf简介

Thymeleaf is a modern server-side Java template engine for both web and standalone environments, capable of processing HTML, XML, JavaScript, CSS and even plain text.

现代化、服务端Java模板引擎

 

5.2.2、基本语法

1、表达式

表达式名字

语法

用途

变量取值

${...}

获取请求域、session域、对象等值

选择变量

*{...}

获取上下文对象值

消息

#{...}

获取国际化等值

链接

@{...}

生成链接

片段表达式

~{...}

jsp:include 作用,引入公共页面片段

 

2、字面量

文本值: 'one text' , 'Another one!'

数字: 0 , 34 , 3.0 , 12.3 ...

布尔值: true , false

空值: null

变量: one,two,.... 变量不能有空格

 

3、文本操作

字符串拼接: +

变量替换: |The name is ${name}|

 

4、数学运算

运算符: + , - , * , / , %

 

5、布尔运算

运算符: and , or

一元运算: ! , not

 

6、比较运算

比较: > , < , >= , <= ( gt , lt , ge , le )等式: == , != ( eq , ne )

 

7、条件运算

If-then: (if) ? (then)

If-then-else: (if) ? (then) : (else)

Default: (value) ?: (defaultvalue)

 

8、特殊操作

无操作: _

 

5.2.3、设置属性值-th:attr

设置单个值

设置多个值

以上两个的代替写法 th:xxxx


所有h5兼容的标签写法

Tutorial: Using Thymeleaf

 

5.2.4、迭代


        Onions
        2.41
        yes

  Onions
  2.41
  yes

 

5.2.5、条件运算

view

User is an administrator

User is a manager

User is some other thing

 

5.2.6、属性优先级

SpringBoot2核心功能 --- Web开发_第14张图片

 

5.3、thymeleaf使用

1、引入Starter

        
            org.springframework.boot
            spring-boot-starter-thymeleaf
        

2、自动配置好了thymeleaf

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(ThymeleafProperties.class)
@ConditionalOnClass({ TemplateMode.class, SpringTemplateEngine.class })
@AutoConfigureAfter({ WebMvcAutoConfiguration.class, WebFluxAutoConfiguration.class })
public class ThymeleafAutoConfiguration { }

自动配好的策略

  • 1、所有thymeleaf的配置值都在 ThymeleafProperties
  • 2、配置好了 SpringTemplateEngine
  • 3、配好了 ThymeleafViewResolver
  • 4、我们只需要直接开发页面
	public static final String DEFAULT_PREFIX = "classpath:/templates/";

	public static final String DEFAULT_SUFFIX = ".html";  //xxx.html

3、页面开发




    
    Title


哈哈

去百度
去百度2

@Controller
public class ViewTestController {

    @GetMapping("/haha")
    public String haha(Model model) {

        model.addAttribute("msg", "hello,thymeleaf");
        model.addAttribute("link", "http://www.baidu.com");
        return "success";
    }
}

 

5.4、构建后台管理系统

1、项目创建

选择需要引入的配置:

thymeleaf、web-starter、devtools、lombok

 

5.4.2、静态资源处理

自动配置好,我们只需要把所有静态资源放到 static 文件夹下

 

3、路径构建

th:action="@{/login}"

    

 

4、模板抽取

th:insert

th:replace

th:include

 

5、页面跳转

    @PostMapping("/login")
    public String main(User user, HttpSession session, Model model){

        if(StringUtils.hasLength(user.getUserName()) && "123456".equals(user.getPassword())){
            //把登陆成功的用户保存起来
            session.setAttribute("loginUser",user);
            //登录成功重定向到main.html;  重定向防止表单重复提交
            return "redirect:/main.html";
        }else {
            model.addAttribute("msg","账号密码错误");
            //回到登录页面
            return "login";
        }

    }

 

6、数据渲染

    @GetMapping("/dynamic_table")
    public String dynamic_table(Model model){
        //表格内容的遍历
        List users = Arrays.asList(new User("zhangsan", "123456"),
                new User("lisi", "123444"),
                new User("haha", "aaaaa"),
                new User("hehe ", "aaddd"));
        model.addAttribute("users",users);

        return "table/dynamic_table";
    }
        
# 用户名 密码
Trident Internet [[${user.password}]]

 

 

六、拦截器

6.1、HandlerInterceptor 接口

/**
 * 登录检查
 * 1、配置好拦截器要拦截哪些请求
 * 2、把这些配置放在容器中
 */
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {

    /**
     * 目标方法执行之前
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        String requestURI = request.getRequestURI();
        log.info("preHandle拦截的请求路径是{}",requestURI);

        //登录检查逻辑
        HttpSession session = request.getSession();

        Object loginUser = session.getAttribute("loginUser");

        if(loginUser != null){
            //放行
            return true;
        }

        //拦截住。未登录。跳转到登录页
        request.setAttribute("msg","请先登录");
//        re.sendRedirect("/");
        request.getRequestDispatcher("/").forward(request,response);
        return false;
    }

    /**
     * 目标方法执行完成以后
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.info("postHandle执行{}",modelAndView);
    }

    /**
     * 页面渲染以后
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info("afterCompletion执行异常{}",ex);
    }
}

 

6.2、配置拦截器

/**
 * 1、编写一个拦截器实现HandlerInterceptor接口
 * 2、拦截器注册到容器中(实现WebMvcConfigurer的addInterceptors)
 * 3、指定拦截规则【如果是拦截所有,静态资源也会被拦截】
 */
@Configuration
public class AdminWebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/**")  //所有请求都被拦截包括静态资源
                .excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**","/js/**"); //放行的请求
    }
}

 

6.3、拦截器原理

1、根据当前请求,找到HandlerExecutionChain【可以处理请求的handler以及handler的所有 拦截器】

2、先来顺序执行 所有拦截器的 preHandle方法

  • 如果当前拦截器prehandler返回为true。则执行下一个拦截器的preHandle
  • 如果当前拦截器返回为false。直接 倒序执行所有已经执行了的拦截器的 afterCompletion;

3、如果任何一个拦截器返回false。直接跳出不执行目标方法

4、所有拦截器都返回True。执行目标方法

5、倒序执行所有拦截器的postHandle方法。

6、前面的步骤有任何异常都会直接倒序触发 afterCompletion

7、页面成功渲染完成以后,也会倒序触发 afterCompletion

SpringBoot2核心功能 --- Web开发_第15张图片

SpringBoot2核心功能 --- Web开发_第16张图片

 

 

七、文件上传

7.1、页面表单


    

 

7.2、文件上传代码

    /**
     * MultipartFile 自动封装上传过来的文件
     * @param email
     * @param username
     * @param headerImg
     * @param photos
     * @return
     */
    @PostMapping("/upload")
    public String upload(@RequestParam("email") String email,
                         @RequestParam("username") String username,
                         @RequestPart("headerImg") MultipartFile headerImg,
                         @RequestPart("photos") MultipartFile[] photos) throws IOException {

        log.info("上传的信息:email={},username={},headerImg={},photos={}",
                email,username,headerImg.getSize(),photos.length);

        if(!headerImg.isEmpty()){
            //保存到文件服务器,OSS服务器
            String originalFilename = headerImg.getOriginalFilename();
            headerImg.transferTo(new File("H:\\cache\\"+originalFilename));
        }

        if(photos.length > 0){
            for (MultipartFile photo : photos) {
                if(!photo.isEmpty()){
                    String originalFilename = photo.getOriginalFilename();
                    photo.transferTo(new File("H:\\cache\\"+originalFilename));
                }
            }
        }


        return "main";
    }

 

 

八、异常处理 - 错误处理

1、默认规则

  • 默认情况下,Spring Boot提供/error处理所有错误的映射
  • 对于机器客户端,它将生成JSON响应,其中包含错误,HTTP状态和异常消息的详细信息。对于浏览器客户端,响应一个“ whitelabel”错误视图,以HTML格式呈现相同的数据

SpringBoot2核心功能 --- Web开发_第17张图片

SpringBoot2核心功能 --- Web开发_第18张图片

  • 要对其进行自定义,添加View解析为error
  • 要完全替换默认行为,可以实现 ErrorController 并注册该类型的Bean定义,或添加ErrorAttributes类型的组件以使用现有机制但替换其内容。
  • error/下的4xx,5xx页面会被自动解析;

SpringBoot2核心功能 --- Web开发_第19张图片

 

2、定制错误处理逻辑

  • 自定义错误页

               error/404.html error/5xx.html;有精确的错误状态码页面就匹配精确,没有就找 4xx.html;如果都没有就触发白页

  • @ControllerAdvice+@ExceptionHandler处理全局异常;底层是 ExceptionHandlerExceptionResolver 支持的
  • @ResponseStatus+自定义异常 ;底层是 ResponseStatusExceptionResolver ,把responsestatus注解的信息底层调用 response.sendError(statusCode, resolvedReason);tomcat发送的/error
  • Spring底层的异常,如 参数类型转换异常;DefaultHandlerExceptionResolver 处理框架底层的异常。
  • 自定义实现 HandlerExceptionResolver 处理异常;可以作为默认的全局异常处理规则
  • ErrorViewResolver 实现自定义处理异常;

        esponse.sendError 。error请求就会转给controller

        你的异常没有任何人能处理。tomcat底层 response.sendError。error请求就会转给controller

        basicErrorController 要去的页面地址是 ErrorViewResolver

 

 

九、Web原生组件注入(Servlet、Filter、Listener)

9.1、使用Servlet API

@ServletComponentScan(basePackages = "com.ssm.boot") :指定原生Servlet组件都放在哪里

@ServletComponentScan(basePackages = "com.ssm.boot")
@SpringBootApplication
public class SpringBoot05WebAdminApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringBoot05WebAdminApplication.class, args);
	}
}

@WebServlet(urlPatterns = "/my"):效果:直接响应,没有经过Spring的拦截器

@WebServlet(urlPatterns = "/my")
public class MyServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("6666");
    }
}

@WebFilter(urlPatterns={"/css/*","/images/*"})

@Slf4j
//拦截多个路径
@WebFilter(urlPatterns={"/css/*","/images/*"})
public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("MyFilter初始化完成");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        log.info("MyFilter工作");
        chain.doFilter(request,response);
    }

    @Override
    public void destroy() {
        log.info("MyFilter销毁");
    }
}

@WebListener

@Slf4j
public class MyServletContextListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        log.info("MyServletContextListener监听到项目初始化完成");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        log.info("MyServletContextListener监听到项目销毁");
    }
}

扩展:DispatchServlet 如何注册进来

  • 容器中自动配置了 DispatcherServlet 属性绑定到 WebMvcProperties;对应的配置文件配置项是 spring.mvc。
  • 通过 ServletRegistrationBean 把 DispatcherServlet 配置进来。
  • 默认映射的是 / 路径。

SpringBoot2核心功能 --- Web开发_第20张图片

Tomcat-Servlet;

多个Servlet都能处理到同一层路径,精确优选原则

A: /my/

B: /my/1

 

9.2、使用RegistrationBean

推荐使用这种方式

ServletRegistrationBean

FilterRegistrationBean

ServletListenerRegistrationBean

@Configuration
public class MyRegistConfig {

    @Bean
    public ServletRegistrationBean myServlet(){
        MyServlet myServlet = new MyServlet();

        return new ServletRegistrationBean(myServlet,"/my","/my02");
    }


    @Bean
    public FilterRegistrationBean myFilter(){

        MyFilter myFilter = new MyFilter();
//        return new FilterRegistrationBean(myFilter,myServlet());
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(myFilter);
        filterRegistrationBean.setUrlPatterns(Arrays.asList("/my","/css/*"));
        return filterRegistrationBean;
    }

    @Bean
    public ServletListenerRegistrationBean myListener(){
        MySwervletContextListener mySwervletContextListener = new MySwervletContextListener();
        return new ServletListenerRegistrationBean(mySwervletContextListener);
    }
}

 

 

十、嵌入式Servlet容器

10.1、切换嵌入式Servlet容器

默认支持的webServer:

Tomcat、Hetty、Undertow 

ServletWebServerApplicationContext 容器启动寻找 ServletWebServerFactory 并引导创建服务器

切换服务器:


    org.springframework.boot
    spring-boot-starter-web
    
        
            org.springframework.boot
            spring-boot-starter-tomcat
        
    

 

10.2、定制Servlet容器

  • 实现 WebServerFactoryCustomizer

        把配置文件的值和ServletWebServerFactory 进行绑定

  • 修改配置文件 server.xxx
  • 直接自定义 ConfigurableServletWebServerFactory

xxxxxCustomizer:定制化器,可以改变xxxx的默认规则

import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.stereotype.Component;

@Component
public class CustomizationBean implements WebServerFactoryCustomizer {

    @Override
    public void customize(ConfigurableServletWebServerFactory server) {
        server.setPort(9000);
    }

}

 

 

十一、定制化原理

11.1、定制化的常见方式

  • 修改配置文件;
  • xxxxxCustomizer;
  • 编写自定义的配置类 xxxConfiguration;+ @Bean替换、增加容器中默认组件;视图解析器
  • Web应用 编写一个配置类实现 WebMvcConfigurer 即可定制化web功能;+ @Bean给容器中再扩展一些组件
@Configuration
public class AdminWebConfig implements WebMvcConfigurer
  • @EnableWebMvc + WebMvcConfigurer —— @Bean 可以全面接管SpringMVC,所有规则全部自己重新配置; 实现定制和扩展功能

 

11.2、原理分析套路

场景starter - xxxxAutoConfiguration - 导入xxx组件 - 绑定xxxProperties -- 绑定配置文件项

你可能感兴趣的:(SSM框架,spring,java,spring,boot)