05、Web开发 - 图605、Web开发 - 图705、Web开发 - 图8

1、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 ConfigurableWebBindingInitializer bean (covered later in this document).
    • 自动使用 ConfigurableWebBindingInitializer ,(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 DelegatingWebMvcConfiguration as described in the Javadoc of @EnableWebMvc.
使用 @EnableWebMvc+@Configuration+DelegatingWebMvcConfiguration 全面接管SpringMVC

2、简单功能分析

2.1、静态资源访问

1、静态资源目录

只要静态资源放在类路径下: called /static (or /public or /resources or /META-INF/resources
访问 : 当前项目根路径/ + 静态资源名

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

改变默认的静态资源路径
spring: mvc: static-path-pattern: /res/** resources: static-locations: [classpath:/haha/]

2、静态资源访问前缀

默认无前缀
spring: mvc: static-path-pattern: /res/**
当前项目 + static-path-pattern + 静态资源名 = 静态资源文件夹下找

3、webjar

自动映射 /webjars/**
https://www.webjars.org/
org.webjars jquery 3.5.1
访问地址:http://localhost:8080/webjars/jquery/3.5.1/jquery.js 后面地址要按照依赖里面的包路径

2.2、欢迎页支持

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

spring: # mvc: # static-path-pattern: /res/** 这个会导致welcome page功能失效 resources: static-locations: [classpath:/haha/]

  • controller能处理/index

2.3、自定义 Favicon

favicon.ico 放在静态资源目录下即可。
spring: # mvc: # static-path-pattern: /res/** 这个会导致 Favicon 功能失效

2.4、静态资源配置原理

  • SpringBoot启动默认加载 xxxAutoConfiguration 类(自动配置类)
  • SpringMVC功能的自动配置类 WebMvcAutoConfiguration,生效

@Configuration(proxyBeanMethods = false) @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class }) @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class }) public class WebMvcAutoConfiguration {}

  • 给容器中配了什么。

    @Configuration(proxyBeanMethods = false) @Import(EnableWebMvcConfiguration.class) @EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class }) @Order(0) public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {}

  • 配置文件的相关属性和xxx进行了绑定。WebMvcProperties==spring.mvc、ResourceProperties==spring.resources

1、配置类只有一个有参构造器

  1. //有参构造器所有参数的值都会从容器中确定 //ResourceProperties resourceProperties;获取和spring.resources绑定的所有的值的对象 //WebMvcProperties mvcProperties 获取和spring.mvc绑定的所有的值的对象 //ListableBeanFactory beanFactory Spring的beanFactory //HttpMessageConverters 找到所有的HttpMessageConverters //ResourceHandlerRegistrationCustomizer 找到 资源处理器的自定义器。========= //DispatcherServletPath //ServletRegistrationBean 给应用注册Servlet、Filter.... public WebMvcAutoConfigurationAdapter(ResourceProperties resourceProperties, WebMvcProperties mvcProperties, ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider, ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider, ObjectProvider<DispatcherServletPath> dispatcherServletPath, ObjectProvider<ServletRegistrationBean<?>> servletRegistrations) { this.resourceProperties = resourceProperties; this.mvcProperties = mvcProperties; this.beanFactory = beanFactory; this.messageConvertersProvider = messageConvertersProvider; this.resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizerProvider.getIfAvailable(); this.dispatcherServletPath = dispatcherServletPath; this.servletRegistrations = servletRegistrations; }

2、资源处理的默认规则

@Override public void addResourceHandlers(ResourceHandlerRegistry registry) { if (!this.resourceProperties.isAddMappings()) { logger.debug(“Default resource handling disabled”); return; } Duration cachePeriod = this.resourceProperties.getCache().getPeriod(); CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl(); //webjars的规则 if (!registry.hasMappingForPattern(“/webjars/“)) { customizeResourceHandlerRegistration(registry.addResourceHandler(“/webjars/“) .addResourceLocations(“classpath:/META-INF/resources/webjars/“) .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl)); } // String staticPathPattern = this.mvcProperties.getStaticPathPattern(); if (!registry.hasMappingForPattern(staticPathPattern)) { customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern) .addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations())) .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl)); } }
spring: # mvc: # static-path-pattern: /res/ resources: add-mappings: false 禁用所有静态资源规则
@ConfigurationProperties(prefix = “spring.resources”, ignoreUnknownFields = false) public class ResourceProperties { private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { “classpath:/META-INF/resources/“, “classpath:/resources/“, “classpath:/static/“, “classpath:/public/“ }; /
Locations of static resources. Defaults to classpath:[/META-INF/resources/, /resources/, /static/, /public/]. */ private String[] staticLocations = CLASSPATH_RESOURCE_LOCATIONS;

3、欢迎页的处理规则

  1. HandlerMapping:处理器映射。保存了每一个Handler能处理哪些请求。 @Bean public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext, FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) { WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping( new TemplateAvailabilityProviders(applicationContext), applicationContext, getWelcomePage(), this.mvcProperties.getStaticPathPattern()); welcomePageHandlerMapping.setInterceptors(getInterceptors(mvcConversionService, mvcResourceUrlProvider)); welcomePageHandlerMapping.setCorsConfigurations(getCorsConfigurations()); return welcomePageHandlerMapping; } WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders, ApplicationContext applicationContext, Optional<Resource> welcomePage, String staticPathPattern) { if (welcomePage.isPresent() && "/**".equals(staticPathPattern)) { //要用欢迎页功能,必须是/** logger.info("Adding welcome page: " + welcomePage.get()); setRootViewName("forward:index.html"); } else if (welcomeTemplateExists(templateAvailabilityProviders, applicationContext)) { // 调用Controller /index logger.info("Adding welcome page template: index"); setRootViewName("index"); } }

4、favicon

3、请求参数处理

0、请求映射

1、rest使用与原理

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

    • 以前:/getUser 获取用户 /deleteUser 删除用户 /editUser 修改用户 /saveUser 保存用户
    • 现在: /user GET-获取用户 DELETE-删除用户 PUT-修改用户 POST-保存用户
    • 核心Filter;HiddenHttpMethodFilter
      • 用法: 表单method=post,隐藏域 _method=put
      • SpringBoot中手动开启
    • 扩展:如何把_method 这个名字换成我们自己喜欢的。

      @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-张三”; } @Bean @ConditionalOnMissingBean(HiddenHttpMethodFilter.class) @ConditionalOnProperty(prefix = “spring.mvc.hiddenmethod.filter”, name = “enabled”, matchIfMissing = false) public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() { return new OrderedHiddenHttpMethodFilter(); } //自定义filter @Bean public HiddenHttpMethodFilter hiddenHttpMethodFilter(){ HiddenHttpMethodFilter methodFilter = new HiddenHttpMethodFilter(); methodFilter.setMethodParam(“_m”); return methodFilter; }
      Rest原理(表单提交要使用REST的时候)

  • 表单提交会带上_method=PUT

  • 请求过来被HiddenHttpMethodFilter拦截
    • 请求是否正常,并且是POST
      • 获取到_method的值。
      • 兼容以下请求;PUT.DELETE.PATCH
      • 原生request(post),包装模式requesWrapper重写了getMethod方法,返回的是传入的值。
      • 过滤器链放行的时候用wrapper。以后的方法调用getMethod是调用requesWrapper的。

Rest使用客户端工具,

  • 如PostMan直接发送Put、delete等方式请求,无需Filter。

spring: mvc: hiddenmethod: filter: enabled: true #开启页面表单的Rest功能

2、请求映射原理

05、Web开发 - 图9
SpringMVC功能分析都从 org.springframework.web.servlet.DispatcherServlet-》doDispatch()

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try { ModelAndView mv = null; Exception dispatchException = null; try { processedRequest = checkMultipart(request); multipartRequestParsed = (processedRequest != request); // 找到当前请求使用哪个Handler(Controller的方法)处理 mappedHandler = getHandler(processedRequest); //HandlerMapping:处理器映射。/xxx->>xxxx
05、Web开发 - 图10
RequestMappingHandlerMapping:保存了所有@RequestMapping 和handler的映射规则。
05、Web开发 - 图11
所有的请求映射都在HandlerMapping中。

  • SpringBoot自动配置欢迎页的 WelcomePageHandlerMapping 。访问 /能访问到index.html;
  • SpringBoot自动配置了默认 的 RequestMappingHandlerMapping
  • 请求进来,挨个尝试所有的HandlerMapping看是否有请求信息。
    • 如果有就找到这个请求对应的handler
    • 如果没有就是下一个 HandlerMapping
  • 我们需要一些自定义的映射处理,我们也可以自己给容器中放HandlerMapping。自定义 HandlerMapping

    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { if (this.handlerMappings != null) { for (HandlerMapping mapping : this.handlerMappings) { HandlerExecutionChain handler = mapping.getHandler(request); if (handler != null) { return handler; } } } return null; }

1、普通参数与基本注解

1.1、注解:

@PathVariable、@RequestHeader、@ModelAttribute、@RequestParam、@MatrixVariable、@CookieValue、@RequestBody
@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; } }

1.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); }

1.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(); 获取到值的
05、Web开发 - 图12

05、Web开发 - 图13

05、Web开发 - 图14

1.4、自定义对象参数:

可以自动类型转换与格式化,可以级联封装。
/* 姓名:
年龄:
生日:
宠物姓名:
宠物年龄: */ @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

2、POJO封装过程

  • ServletModelAttributeMethodProcessor

3、参数处理原理

  • HandlerMapping中找到能处理请求的Handler(Controller.method())
  • 为当前Handler 找一个适配器 HandlerAdapter; RequestMappingHandlerAdapter
  • 适配器执行目标方法并确定方法参数的每一个值

1、HandlerAdapter

05、Web开发 - 图15
0 - 支持方法上标注@RequestMapping
1 - 支持函数式编程的
xxxxxx

2、执行目标方法

// Actually invoke the handler. //DispatcherServlet — doDispatch mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
mav = invokeHandlerMethod(request, response, handlerMethod); //执行目标方法 //ServletInvocableHandlerMethod Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs); //获取方法的参数值 Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);

3、参数解析器-HandlerMethodArgumentResolver

确定将要执行的目标方法的每一个参数的值是什么;
SpringMVC目标方法能写多少种参数类型。取决于参数解析器。
05、Web开发 - 图16
05、Web开发 - 图17

  • 当前解析器是否支持解析这种参数
  • 支持就调用 resolveArgument

4、返回值处理器

05、Web开发 - 图18

5、如何确定目标方法每一个参数的值

============InvocableHandlerMethod========================== protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object… providedArgs) throws Exception { MethodParameter[] parameters = getMethodParameters(); if (ObjectUtils.isEmpty(parameters)) { return EMPTY_ARGS; } Object[] args = new Object[parameters.length]; for (int i = 0; i < parameters.length; i++) { MethodParameter parameter = parameters[i]; parameter.initParameterNameDiscovery(this.parameterNameDiscoverer); args[i] = findProvidedArgument(parameter, providedArgs); if (args[i] != null) { continue; } if (!this.resolvers.supportsParameter(parameter)) { throw new IllegalStateException(formatArgumentError(parameter, “No suitable resolver”)); } try { args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory); } catch (Exception ex) { // Leave stack trace for later, exception may actually be resolved and handled… if (logger.isDebugEnabled()) { String exMsg = ex.getMessage(); if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) { logger.debug(formatArgumentError(parameter, exMsg)); } } throw ex; } } return args; }

5.1、挨个判断所有参数解析器那个支持解析这个参数

  1. @Nullable private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) { HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter); if (result == null) { for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) { if (resolver.supportsParameter(parameter)) { result = resolver; this.argumentResolverCache.put(parameter, result); break; } } } return result; }

5.2、解析这个参数的值

调用各自 HandlerMethodArgumentResolver 的 resolveArgument 方法即可

5.3、自定义类型参数 封装POJO

ServletModelAttributeMethodProcessor 这个参数处理器支持
是否为简单类型。
public static boolean isSimpleValueType(Class<?> type) { return (Void.class != type && void.class != type && (ClassUtils.isPrimitiveOrWrapper(type) || Enum.class.isAssignableFrom(type) || CharSequence.class.isAssignableFrom(type) || Number.class.isAssignableFrom(type) || Date.class.isAssignableFrom(type) || Temporal.class.isAssignableFrom(type) || URI.class == type || URL.class == type || Locale.class == type || Class.class == type)); }
@Override @Nullable public final Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception { Assert.state(mavContainer != null, “ModelAttributeMethodProcessor requires ModelAndViewContainer”); Assert.state(binderFactory != null, “ModelAttributeMethodProcessor requires WebDataBinderFactory”); String name = ModelFactory.getNameForParameter(parameter); ModelAttribute ann = parameter.getParameterAnnotation(ModelAttribute.class); if (ann != null) { mavContainer.setBinding(name, ann.binding()); } Object attribute = null; BindingResult bindingResult = null; if (mavContainer.containsAttribute(name)) { attribute = mavContainer.getModel().get(name); } else { // Create attribute instance try { attribute = createAttribute(name, parameter, binderFactory, webRequest); } catch (BindException ex) { if (isBindExceptionRequired(parameter)) { // No BindingResult parameter -> fail with BindException throw ex; } // Otherwise, expose null/empty value and associated BindingResult if (parameter.getParameterType() == Optional.class) { attribute = Optional.empty(); } bindingResult = ex.getBindingResult(); } } if (bindingResult == null) { // Bean property binding and validation; // skipped in case of binding failure on construction. WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name); if (binder.getTarget() != null) { if (!mavContainer.isBindingDisabled(name)) { bindRequestParameters(binder, webRequest); } validateIfApplicable(binder, parameter); if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) { throw new BindException(binder.getBindingResult()); } } // Value type adaptation, also covering java.util.Optional if (!parameter.getParameterType().isInstance(attribute)) { attribute = binder.convertIfNecessary(binder.getTarget(), parameter.getParameterType(), parameter); } bindingResult = binder.getBindingResult(); } // Add resolved attribute and BindingResult at the end of the model Map bindingResultModel = bindingResult.getModel(); mavContainer.removeAttributes(bindingResultModel); mavContainer.addAllAttributes(bindingResultModel); return attribute; }
WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name);
WebDataBinder :web数据绑定器,将请求参数的值绑定到指定的JavaBean里面
WebDataBinder 利用它里面的 Converters 将请求数据转成指定的数据类型。再次封装到JavaBean中
GenericConversionService:在设置每一个值的时候,找它里面的所有converter那个可以将这个数据类型(request带来参数的字符串)转换到指定的类型(JavaBean — Integer)
byte — > file
@FunctionalInterfacepublic interface Converter

05、Web开发 - 图19

05、Web开发 - 图20

未来我们可以给WebDataBinder里面放自己的Converter;
private static final class StringToNumber implements Converter

自定义 Converter
//1、WebMvcConfigurer定制化SpringMVC的功能 @Bean public WebMvcConfigurer webMvcConfigurer(){ return new WebMvcConfigurer() { @Override public void configurePathMatch(PathMatchConfigurer configurer) { UrlPathHelper urlPathHelper = new UrlPathHelper(); // 不移除;后面的内容。矩阵变量功能就可以生效 urlPathHelper.setRemoveSemicolonContent(false); configurer.setUrlPathHelper(urlPathHelper); } @Override public void addFormatters(FormatterRegistry registry) { registry.addConverter(new Converter() { @Override public Pet convert(String source) { // 啊猫,3 if(!StringUtils.isEmpty(source)){ Pet pet = new Pet(); String[] split = source.split(“,”); pet.setName(split[0]); pet.setAge(Integer.parseInt(split[1])); return pet; } return null; } }); } }; }

6、目标方法执行完成

将所有的数据都放在 ModelAndViewContainer;包含要去的页面地址View。还包含Model数据。
05、Web开发 - 图21

7、处理派发结果

processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);

InternalResourceView: @Override protected void renderMergedOutputModel( Map model, HttpServletRequest request, HttpServletResponse response) throws Exception { // Expose the model object as request attributes. exposeModelAsRequestAttributes(model, request); // Expose helpers as request attributes, if any. exposeHelpers(request); // Determine the path for the request dispatcher. String dispatcherPath = prepareForRendering(request, response); // Obtain a RequestDispatcher for the target resource (typically a JSP). RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath); if (rd == null) { throw new ServletException(“Could not get RequestDispatcher for [“ + getUrl() + “]: Check that the corresponding file exists within your web application archive!”); } // If already included or response already committed, perform include, else forward. if (useInclude(request, response)) { response.setContentType(getContentType()); if (logger.isDebugEnabled()) { logger.debug(“Including [“ + getUrl() + “]”); } rd.include(request, response); } else { // Note: The forwarded resource is supposed to determine the content type itself. if (logger.isDebugEnabled()) { logger.debug(“Forwarding to [“ + getUrl() + “]”); } rd.forward(request, response); } }
暴露模型作为请求域属性 // Expose the model object as request attributes. exposeModelAsRequestAttributes(model, request);
protected void exposeModelAsRequestAttributes(Map model, HttpServletRequest request) throws Exception { //model中的所有数据遍历挨个放在请求域中 model.forEach((name, value) -> { if (value != null) { request.setAttribute(name, value); } else { request.removeAttribute(name); } }); }

4、数据响应与内容协商

1、响应JSON

1.1、jackson.jar+@ResponseBody

  1. <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> web场景自动引入了json场景 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-json</artifactId> <version>2.3.4.RELEASE</version> <scope>compile</scope> </dependency>

05、Web开发 - 图22

给前端自动返回json数据;

1、返回值解析器

05、Web开发 - 图23
try { this.returnValueHandlers.handleReturnValue( returnValue, getReturnValueType(returnValue), mavContainer, webRequest); }
@Override public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType); if (handler == null) { throw new IllegalArgumentException(“Unknown return value type: “ + returnType.getParameterType().getName()); } handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest); }
RequestResponseBodyMethodProcessor @Override public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException { mavContainer.setRequestHandled(true); ServletServerHttpRequest inputMessage = createInputMessage(webRequest); ServletServerHttpResponse outputMessage = createOutputMessage(webRequest); // Try even with null return value. ResponseBodyAdvice could get involved. // 使用消息转换器进行写出操作 writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage); }

2、返回值解析器原理

05、Web开发 - 图24

  • 1、返回值处理器判断是否支持这种类型返回值 supportsReturnType
  • 2、返回值处理器调用 handleReturnValue 进行处理
  • 3、RequestResponseBodyMethodProcessor 可以处理返回值标了@ResponseBody 注解的。
      1. 利用 MessageConverters 进行处理 将数据写为json
        • 1、内容协商(浏览器默认会以请求头的方式告诉服务器他能接受什么样的内容类型)
        • 2、服务器最终根据自己自身的能力,决定服务器能生产出什么样内容类型的数据,
        • 3、SpringMVC会挨个遍历所有容器底层的 HttpMessageConverter ,看谁能处理?
          • 1、得到MappingJackson2HttpMessageConverter可以将对象写为json
          • 2、利用MappingJackson2HttpMessageConverter将对象转为json再写出去。

05、Web开发 - 图25

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

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

1.3、HTTPMessageConverter原理

1、MessageConverter规范

05、Web开发 - 图26
HttpMessageConverter: 看是否支持将 此 Class类型的对象,转为MediaType类型的数据。
例子:Person对象转为JSON。或者 JSON转为Person

2、默认的MessageConverter

05、Web开发 - 图27
0 - 只支持Byte类型的
1 - String
2 - String
3 - Resource
4 - ResourceRegion
5 - DOMSource.class \ SAXSource.class) \ StAXSource.class \StreamSource.class \Source.class
6 - MultiValueMap
7 - true
8 - true
9 - 支持注解方式xml处理的。

最终 MappingJackson2HttpMessageConverter 把对象转为JSON(利用底层的jackson的objectMapper转换的)
05、Web开发 - 图28

2、内容协商

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

1、引入xml依赖

com.fasterxml.jackson.dataformat jackson-dataformat-xml ### 2、postman分别测试返回json和xml 只需要改变请求头中Accept字段。Http协议中规定的,告诉服务器本客户端可以接收的数据类型。
05、Web开发 - 图29 ### 3、开启浏览器参数方式内容协商功能 为了方便内容协商,开启基于请求参数的内容协商功能。
spring: contentnegotiation: favor-parameter: true #开启请求参数内容协商模式
发请求: http://localhost:8080/test/person?format=json
http://localhost:8080/test/person?format=xml 05、Web开发 - 图30
确定客户端接收什么样的内容类型;
1、Parameter策略优先确定是要返回json数据(获取请求头中的format的值)
05、Web开发 - 图31
2、最终进行内容协商返回给客户端json即可。 ### 4、内容协商原理 - 1、判断当前响应头中是否已经有确定的媒体类型。MediaType - 2、获取客户端(PostMan、浏览器)支持接收的内容类型。(获取客户端Accept请求头字段)【application/xml】 - contentNegotiationManager 内容协商管理器 默认使用基于请求头的策略 - 05、Web开发 - 图32 - HeaderContentNegotiationStrategy 确定客户端可以接收的内容类型 - 05、Web开发 - 图33 - 3、遍历循环所有当前系统的 MessageConverter,看谁支持操作这个对象(Person) - 4、找到支持操作Person的converter,把converter支持的媒体类型统计出来。 - 5、客户端需要【application/xml】。服务端能力【10种、json、xml】 - 05、Web开发 - 图34 - 6、进行内容协商的最佳匹配媒体类型 - 7、用 支持 将对象转为 最佳匹配媒体类型 的converter。调用它进行转化 。 05、Web开发 - 图35
导入了jackson处理xml的包,xml的converter就会自动进来
WebMvcConfigurationSupport jackson2XmlPresent = ClassUtils.isPresent(“com.fasterxml.jackson.dataformat.xml.XmlMapper”, classLoader); if (jackson2XmlPresent) { Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.xml(); if (this.applicationContext != null) { builder.applicationContext(this.applicationContext); } messageConverters.add(new MappingJackson2XmlHttpMessageConverter(builder.build())); } ### 5、自定义 MessageConverter 实现多协议数据兼容。json、xml、x-guigu
0、@ResponseBody 响应数据出去 调用 RequestResponseBodyMethodProcessor 处理
1、Processor 处理方法返回值。通过 MessageConverter 处理
2、所有 MessageConverter 合起来可以支持各种媒体类型数据的操作(读、写)
3、内容协商找到最终的 messageConverter; SpringMVC的什么功能。一个入口给容器中添加一个 WebMvcConfigurer
@Bean public WebMvcConfigurer webMvcConfigurer(){ return new WebMvcConfigurer() { @Override public void extendMessageConverters(List> converters) { } } } 05、Web开发 - 图36 05、Web开发 - 图37 有可能我们添加的自定义的功能会覆盖默认很多功能,导致一些默认的功能失效。
大家考虑,上述功能除了我们完全自定义外?SpringBoot有没有为我们提供基于配置文件的快速修改媒体类型功能?怎么配置呢?【提示:参照SpringBoot官方文档web开发内容协商章节】 # 5、视图解析与模板引擎 视图解析:SpringBoot默认不支持 JSP,需要引入第三方模板引擎技术实现页面渲染。 ## 1、视图解析 ### 1、视图解析原理流程 1、目标方法处理的过程中,所有数据都会被放在 ModelAndViewContainer 里面。包括数据和视图地址
2、方法的参数是一个自定义类型对象(从请求参数中确定的),把他重新放在 ModelAndViewContainer
3、任何目标方法执行完成以后都会返回 ModelAndView(数据和视图地址)。
4、processDispatchResult 处理派发结果(页面改如何响应) - 1、render(mv, request, response); 进行页面渲染逻辑 - 1、根据方法的String返回值得到 View 对象【定义了页面的渲染逻辑】 - 1、所有的视图解析器尝试是否能根据当前返回值得到View对象 - 2、得到了 redirect:/main.html —> Thymeleaf new RedirectView() - 3、ContentNegotiationViewResolver 里面包含了下面所有的视图解析器,内部还是利用下面所有视图解析器得到视图对象。 - 4、view.render(mv.getModelInternal(), request, response); 视图对象调用自定义的render进行页面渲染工作 - RedirectView 如何渲染【重定向到一个页面】 - 1、获取目标url地址 - 2、response.sendRedirect(encodedURL); 视图解析: - 返回值以 forward: 开始: new InternalResourceView(forwardUrl); —> 转发request.getRequestDispatcher(path).forward(request, response); - 返回值以 redirect: 开始: new RedirectView() —》 render就是重定向 - 返回值是普通字符串: new ThymeleafView()—-> 自定义视图解析器+自定义视图; 大厂学院。 05、Web开发 - 图38
05、Web开发 - 图39 05、Web开发 - 图40 05、Web开发 - 图41 ## 2、模板引擎-Thymeleaf ### 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模板引擎 ### 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、特殊操作 无操作: _ ### 3、设置属性值-th:attr 设置单个值

设置多个值
05、Web开发 - 图42 以上两个的代替写法 th:xxxx
所有h5兼容的标签写法
https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#setting-value-to-specific-attributes ### 4、迭代 Onions 2.41 yes Onions 2.41 yes ### 5、条件运算 view

User is an administrator

User is a manager

User is some other thing

### 6、属性优先级 05、Web开发 - 图43 ## 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、页面开发 <!DOCTYPE html>

哈哈

去百度
去百度2

## 4、构建后台管理系统 ### 1、项目创建 thymeleaf、web-starter、devtools、lombok ### 2、静态资源处理 自动配置好,我们只需要把所有静态资源放到 static 文件夹下 ### 3、路径构建 th:action=”@{/login}” ### 4、模板抽取 th:insert/replace/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); } } ## 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/“); //放行的请求 } } ## 3、拦截器原理 1、根据当前请求,找到HandlerExecutionChain【可以处理请求的handler以及handler的所有 拦截器】
2、先来
顺序执行 所有拦截器的 preHandle方法 - 1、如果当前拦截器prehandler返回为true。则执行下一个拦截器的preHandle - 2、如果当前拦截器返回为false。直接 倒序执行所有已经执行了的拦截器的 afterCompletion; 3、如果任何一个拦截器返回false。直接跳出不执行目标方法
4、所有拦截器都返回True。执行目标方法
5、倒序执行所有拦截器的postHandle方法。
6、前面的步骤有任何异常都会直接倒序触发 afterCompletion
7、页面成功渲染完成以后,也会倒序触发 afterCompletion 05、Web开发 - 图44 05、Web开发 - 图45 # 7、文件上传 ## 1、页面表单
## 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”; } ## 3、自动配置原理 文件上传自动配置类-MultipartAutoConfiguration-MultipartProperties - 自动配置好了 StandardServletMultipartResolver 【文件上传解析器】 - 原理步骤 - 1、请求进来使用文件上传解析器判断(isMultipart)并封装(resolveMultipart,返回MultipartHttpServletRequest)文件上传请求 - 2、参数解析器来解析请求中的文件内容封装成MultipartFile - 3、将request中文件信息封装为一个Map;MultiValueMap FileCopyUtils。实现文件流的拷贝
@PostMapping(“/upload”) public String upload(@RequestParam(“email”) String email, @RequestParam(“username”) String username, @RequestPart(“headerImg”) MultipartFile headerImg, @RequestPart(“photos”) MultipartFile[] photos)
05、Web开发 - 图46 # 8、异常处理 ## 1、错误处理 #### 1、默认规则 - 默认情况下,Spring Boot提供/error处理所有错误的映射 - 对于机器客户端,它将生成JSON响应,其中包含错误,HTTP状态和异常消息的详细信息。对于浏览器客户端,响应一个“ whitelabel”错误视图,以HTML格式呈现相同的数据 - 05、Web开发 - 图4705、Web开发 - 图48 - 要对其进行自定义,添加View解析为error
- 要完全替换默认行为,可以实现 ErrorController 并注册该类型的Bean定义,或添加ErrorAttributes类型的组件以使用现有机制但替换其内容。 - error/下的4xx,5xx页面会被自动解析; - 05、Web开发 - 图49 #### 2、定制错误处理逻辑 - 自定义错误页 - error/404.html error/5xx.html;有精确的错误状态码页面就匹配精确,没有就找 4xx.html;如果都没有就触发白页 - @ControllerAdvice+@ExceptionHandler处理全局异常;底层是
ExceptionHandlerExceptionResolver 支持的 - @ResponseStatus+自定义异常 ;底层是 ResponseStatusExceptionResolver ,把responsestatus注解的信息底层调用 response.sendError(statusCode, resolvedReason);tomcat发送的/error - Spring底层的异常,如 参数类型转换异常;DefaultHandlerExceptionResolver 处理框架底层的异常。 - response.sendError(HttpServletResponse.SC_BAD_REQUEST, ex.getMessage()); - 05、Web开发 - 图50 - 自定义实现 HandlerExceptionResolver 处理异常;可以作为默认的全局异常处理规则 - 05、Web开发 - 图51 - ErrorViewResolver实现自定义处理异常; - response.sendError 。error请求就会转给controller - 你的异常没有任何人能处理。tomcat底层 response.sendError。error请求就会转给controller - basicErrorController 要去的页面地址是 ErrorViewResolver #### 3、异常处理自动配置原理 - ErrorMvcAutoConfiguration 自动配置异常处理规则 - 容器中的组件:类型:DefaultErrorAttributes -> id:errorAttributes - public class DefaultErrorAttributes implements ErrorAttributes, HandlerExceptionResolver - DefaultErrorAttributes:定义错误页面中可以包含哪些数据。 - 05、Web开发 - 图52 - 05、Web开发 - 图53 - 容器中的组件:类型:BasicErrorController —> id:basicErrorController(json+白页 适配响应) - 处理默认 /error 路径的请求;页面响应 new ModelAndView(“error”, model); - 容器中有组件 View->id是error;(响应默认错误页) - 容器中放组件 BeanNameViewResolver(视图解析器);按照返回的视图名作为组件的id去容器中找View对象。 - 容器中的组件:类型:DefaultErrorViewResolver -> id:conventionErrorViewResolver - 如果发生错误,会以HTTP的状态码 作为视图页地址(viewName),找到真正的页面 - error/404、5xx.html 如果想要返回页面;就会找error视图【StaticView】。(默认是一个白页) 05、Web开发 - 图54写出去json
05、Web开发 - 图55 错误页 #### 4、异常处理步骤流程 1、执行目标方法,目标方法运行期间有任何异常都会被catch、而且标志当前请求结束;并且用
dispatchException
2、进入视图解析流程(页面渲染?)
processDispatchResult(processedRequest, response, mappedHandler,
mv, dispatchException);
3、
mv = processHandlerException;处理handler发生的异常,处理完成返回ModelAndView; - 1、遍历所有的 handlerExceptionResolvers,看谁能处理当前异常【HandlerExceptionResolver处理器异常解析器】 - 05、Web开发 - 图56 - 2、系统默认的 异常解析器; - 05、Web开发 - 图57 - 1、DefaultErrorAttributes先来处理异常。把异常信息保存到rrequest域,并且返回null; - 2、默认没有任何人能处理异常,所以异常会被抛出 - 1、如果没有任何人能处理最终底层就会发送 /error 请求。会被底层的BasicErrorController处理 - 2、解析错误视图;遍历所有的 ErrorViewResolver 看谁能解析。 - 05、Web开发 - 图58 - 3、默认的 DefaultErrorViewResolver ,作用是把响应状态码作为错误页的地址,error/500.html - 4、模板引擎最终响应这个页面 error/500.html # 9、Web原生组件注入(Servlet、Filter、Listener) ## 1、使用Servlet API @ServletComponentScan(basePackages = “com.atguigu.admin”) :指定原生Servlet组件都放在那里
@WebServlet(urlPatterns =
“/my”):效果:直接响应,没有经过Spring的拦截器?
@WebFilter(urlPatterns={
“/css/
,“/images/})
@WebListener
推荐可以这种方式; 扩展:DispatchServlet 如何注册进来 - 容器中自动配置了 DispatcherServlet 属性绑定到 WebMvcProperties;对应的配置文件配置项是
spring.mvc。 - 通过 ServletRegistrationBean** 把 DispatcherServlet 配置进来。 - 默认映射的是 / 路径。 05、Web开发 - 图59
Tomcat-Servlet;
多个Servlet都能处理到同一层路径,精确优选原则
A: /my/
B: /my/1 ## 2、使用RegistrationBean ServletRegistrationBean, FilterRegistrationBean, and 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); } } # 10、嵌入式Servlet容器 ## 1、切换嵌入式Servlet容器 - 默认支持的webServer - Tomcat, Jetty, or Undertow - ServletWebServerApplicationContext 容器启动寻找ServletWebServerFactory 并引导创建服务器 - 切换服务器 05、Web开发 - 图60
org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-tomcat
  • 原理
    • SpringBoot应用启动发现当前是Web应用。web场景包-导入tomcat
    • web应用会创建一个web版的ioc容器 ServletWebServerApplicationContext
    • ServletWebServerApplicationContext 启动的时候寻找 ServletWebServerFactory(Servlet 的web服务器工厂—-> Servlet 的web服务器)
    • SpringBoot底层默认有很多的WebServer工厂;TomcatServletWebServerFactory, JettyServletWebServerFactory, or UndertowServletWebServerFactory
    • 底层直接会有一个自动配置类。ServletWebServerFactoryAutoConfiguration
    • ServletWebServerFactoryAutoConfiguration导入了ServletWebServerFactoryConfiguration(配置类)
    • ServletWebServerFactoryConfiguration 配置类 根据动态判断系统中到底导入了那个Web服务器的包。(默认是web-starter导入tomcat包),容器中就有 TomcatServletWebServerFactory
    • TomcatServletWebServerFactory 创建出Tomcat服务器并启动;TomcatWebServer 的构造器拥有初始化方法initialize—-this.tomcat.start();
    • 内嵌服务器,就是手动把启动服务器的代码调用(tomcat核心jar包存在)

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,所有规则全部自己重新配置; 实现定制和扩展功能
    • 原理
    • 1、WebMvcAutoConfiguration 默认的SpringMVC的自动配置功能类。静态资源、欢迎页…..
    • 2、一旦使用 @EnableWebMvc 、。会 @Import(DelegatingWebMvcConfiguration.class)
    • 3、DelegatingWebMvcConfiguration 的 作用,只保证SpringMVC最基本的使用
      • 把所有系统中的 WebMvcConfigurer 拿过来。所有功能的定制都是这些 WebMvcConfigurer 合起来一起生效
      • 自动配置了一些非常底层的组件。RequestMappingHandlerMapping、这些组件依赖的组件都是从容器中获取
      • public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport
    • 4、WebMvcAutoConfiguration 里面的配置要能生效 必须 @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
    • 5、@EnableWebMvc 导致了 WebMvcAutoConfiguration 没有生效。
  • … …

    2、原理分析套路

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

138 人点赞

  • 05、Web开发 - 图61
  • 05、Web开发 - 图62
  • 05、Web开发 - 图63
  • 05、Web开发 - 图64
  • 05、Web开发 - 图65
  • 05、Web开发 - 图66
  • 05、Web开发 - 图67
  • 05、Web开发 - 图68
  • 05、Web开发 - 图69
  • 05、Web开发 - 图70
  • 05、Web开发 - 图71
  • 05、Web开发 - 图72
  • 05、Web开发 - 图73

尚硅谷
2020-12-23 13:33
223795
333
投诉
关注作者和知识库后续更新
已关注
05、Web开发 - 图74

尚硅谷

程序员标配,人手一套尚硅谷教程,自学一样拿1万+薪资,官网:atguigu.com/?yq
已关注

SpringBoot2核心技术与响应式编程

基于SpringBoot2.3与2.4版本
推荐阅读

03、了解自动配置原理

1、SpringBoot特点1.1、依赖管理父项目做依赖管理依赖管理 org.springframework.boot spring-boot-starter-parent<…

01、Spring与SpringBoot

1、Spring能做什么1.1、Spring的能力1.2、Spring的生态https://spring.io/projects/spring-boot覆盖了:web开发数据访问安全控制分布式消息服务移动开发批处理......1.3、Spring5重大升级1.3.1、响应式编程1.3.2、内部

02、SpringBoot2入门

1、系统要求Java 8 & 兼容java14 .Maven 3.3+idea 2019.1.21.1、maven设置 nexus-aliyun central上一篇04、配置文件下一篇06、数据访问
回复
分享到:

  • 05、Web开发 - 图7505、Web开发 - 图76逍遥子2020-12-22 23:07老师,比较有错误。2.1章节,【静态资源也找到404】应该是【静态资源也找不到404】吧回复投诉
  • 05、Web开发 - 图7705、Web开发 - 图78VMS2020-12-23 10:33的回到原文划线处标注1下面第二张图说明,map和model是一个对象,因为id都一样 都是5845回复投诉
  • 05、Web开发 - 图7905、Web开发 - 图80VMS2020-12-23 10:406、目标方法执行完成回到原文划线处对于func(Map map,Model model),如果为map或者model添加kv,那么最后map,model的kv都会保存到modelAndView里面,如下图所示,可以被后来的页面或者方法通过request对象进行获取.回复投诉
  • 05、Web开发 - 图8105、Web开发 - 图82VMS2020-12-23 16:443、页面开发回到原文划线处@{link}是将’link’添加项目根路径下回复投诉
  • 05、Web开发 - 图8305、Web开发 - 图84Accelerator2020-12-24 18:38为什么我的yaml里面spring resources static-locations是划了一条线的,提示改了之后变成spring web resources static-locations??回复投诉
  • 05、Web开发 - 图8505、Web开发 - 图86白糖。2020-12-29 12:28老师 啥子时候有完整的后台开发系统的教学回复投诉
  • 05、Web开发 - 图8705、Web开发 - 图88lee2020-12-29 14:14requesWrapper回到原文划线处requestWrapper回复投诉
  • 05、Web开发 - 图8905、Web开发 - 图90MrYue2020-12-29 15:17是否为简单类回到原文划线处isSimpleValueType回复投诉
  • 05、Web开发 - 图9105、Web开发 - 图92cloneman2020-12-30 09:41老师,再添加MessageConverters的时候,采用下面的也可以,不会覆盖,他只会在吧converters中添加自己的配置@Overridepublic void configureMessageConverters(List> converters) {converters.add(new MyMessageConverter());}在内容协商的时候,采用下面可以将自己的自定义内容协商添加到对应的ParameterContentNegotiationStrategy的mediaTypes中,并且和系统的兼容,不会覆盖掉系统自带的一些解析器spring.mvc.contentnegotiation.media-types.x-clo=application/x-clo原因:@Overridepublic void configureContentNegotiation(ContentNegotiationConfigurer configurer) {WebMvcProperties.Contentnegotiation contentnegotiation = this.mvcProperties.getContentnegotiation();configurer.favorPathExtension(contentnegotiation.isFavorPathExtension());configurer.favorParameter(contentnegotiation.isFavorParameter());if (contentnegotiation.getParameterName() != null) {configurer.parameterName(contentnegotiation.getParameterName());}// 这个里面直接拿了配置文件的,并且在下面直接添加Map mediaTypes = this.mvcProperties.getContentnegotiation().getMediaTypes();mediaTypes.forEach(configurer::mediaType);}
    if (this.favorParameter) {//获取配置文件的,直接加入ParameterContentNegotiationStrategy 中ParameterContentNegotiationStrategy strategy = new ParameterContentNegotiationStrategy(this.mediaTypes);strategy.setParameterName(this.parameterName);if (this.useRegisteredExtensionsOnly != null) {strategy.setUseRegisteredExtensionsOnly(this.useRegisteredExtensionsOnly);}else {strategy.setUseRegisteredExtensionsOnly(true); // backwards compatibility
    }strategies.add(strategy);}回复投诉
  • 05、Web开发 - 图9305、Web开发 - 图94小仓鼠01-02 09:21静态映射/**回到原文划线处拦截所有请求回复投诉
  • 05、Web开发 - 图9505、Web开发 - 图96小仓鼠01-02 09:24当前项目 + static-path-pattern + 静态资源名 = 静态资源文件夹下找回到原文划线处虚拟的,不是真是存在的文件夹回复投诉
  • 05、Web开发 - 图9705、Web开发 - 图98小仓鼠01-02 10:50静态资源配置原理回到原文划线处OrderedHiddenHttpMethodFilter 表单提交post,delete等请求回复投诉
  • 05、Web开发 - 图9905、Web开发 - 图100莫名01-02 15:29回复 @逍遥子回到原评论估计手滑了;
    越往后评论的人越少了呀回复投诉
  • 05、Web开发 - 图10105、Web开发 - 图102夏夜晚风凉01-03 15:41回复 @lee回到原评论细!回复投诉
  • 05、Web开发 - 图10305、Web开发 - 图104小仓鼠01-03 15:541.1、注解:回到原文划线处不用注解好像也可以获取参数,区别是什么?回复投诉
  • 05、Web开发 - 图10505、Web开发 - 图106MrYue01-03 19:59HandlerExceptionResolver回到原文划线处最终调用HttpServletResponseImpl的sendError方法回复投诉
  • 05、Web开发 - 图10705、Web开发 - 图108小乐01-07 09:323、如果任何一个拦截器返回false。直接跳出不执行目标方法回到原文划线处这里应该指的是preHandle方法吧回复投诉
  • 05、Web开发 - 图10905、Web开发 - 图110小仓鼠01-10 10:35改变默认的静态资源路径回到原文划线处classpath:/haha/使用数组回复投诉
  • 05、Web开发 - 图11105、Web开发 - 图112张小头01-11 15:50倒序回到原文划线处源码里是for (int i = this.interceptorIndex; i >= 0; i—),所以是倒叙回复投诉
  • 05、Web开发 - 图11305、Web开发 - 图114张小头01-11 15:51先来顺序执行回到原文划线处源码中for (int i = 0; i < this.interceptorList.size(); i++) ,所以是先来先服务回复投诉
  • 05、Web开发 - 图11505、Web开发 - 图116张小头01-11 15:52true回到原文划线处判断语句为if (!interceptor.preHandle(request, response, this.handler)) {triggerAfterCompletion(request, response, null);
    return false;
    }可以明显看到如果是false才会执行afterXXX回复投诉
  • 05、Web开发 - 图11705、Web开发 - 图118张小头01-11 15:56前面的步骤有任何异常都会直接倒序触发 afterCompletion回到原文划线处catch (Exception ex) {triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
    }catch (Throwable err) {triggerAfterCompletion(processedRequest, response, mappedHandler,
    new NestedServletException(“Handler processing failed”, err));
    }回复投诉
  • 05、Web开发 - 图11905、Web开发 - 图120张小头01-11 15:57倒序执行所有拦截器的postHandle方法。回到原文划线处05、Web开发 - 图121回复投诉
  • 05、Web开发 - 图12205、Web开发 - 图123寒城01-11 19:28但是不可以配置静态资源的访问前缀。否则导致 index.html不能被默认访问回到原文划线处好像不会哦,大家可以自己试一下回复投诉
  • 05、Web开发 - 图12405、Web开发 - 图125Striving01-13 17:19老师 啥时候有完整的后台开发系统的教学回复投诉
  • 05、Web开发 - 图12605、Web开发 - 图127罗罗爱学习01-14 10:51method=pos回到原文划线处不要忘记是post请求回复投诉
  • 05、Web开发 - 图12805、Web开发 - 图129符运龙01-15 11:05老师 啥时候有完整的后台开发系统的教学回复投诉
  • 05、Web开发 - 图13005、Web开发 - 图131白魈01-15 22:22当前项目根路径/ + 静态资源名回到原文划线处05、Web开发 - 图132回复投诉
  • 05、Web开发 - 图13305、Web开发 - 图134白魈01-15 22:28当前项目根路径/ + 静态资源名回到原文划线处05、Web开发 - 图135回复投诉
  • 05、Web开发 - 图13605、Web开发 - 图137白魈01-15 22:44静态资源访问前缀回到原文划线处以免静态资源被拦截回复投诉
  • 05、Web开发 - 图13805、Web开发 - 图13901-16 00:2105、Web开发 - 图140大佬们,这是啥问题?回复投诉
  • 05、Web开发 - 图14105、Web开发 - 图142罗罗爱学习01-18 12:24@ControllerAdvice+@ExceptionHandler处理全局异常;底层是 ExceptionHandlerExceptionResolver 支持的回到原文划线处被ExceptionHandle捕获的异常,注意此时的状态码是200回复投诉
  • 05、Web开发 - 图14305、Web开发 - 图144李致辉01-18 16:25回复 @Accelerator回到原评论划线的都是现在不推荐使用的,一般都有其他的代替了,像平常java使用的一些方法,有划线也可以用,但是最好使用新的替换的方法回复投诉
  • 05、Web开发 - 图14505、Web开发 - 图146李致辉01-18 16:2905、Web开发 - 图147这里貌似直接配个media-types就可以,不用写在java类里面,把其他的都重新写一遍spring:
    mvc:
    contentnegotiation:
    favor-parameter: true
    media-types:
    {gg: application/x-guigu}回复投诉
  • 05、Web开发 - 图14805、Web开发 - 图149李致辉01-18 16:32回复 @农回到原评论05、Web开发 - 图150放这个下面了spring:
    web:
    resources:
    static-locations:
    回复投诉
  • 05、Web开发 - 图15105、Web开发 - 图152yzxmf01-19 10:25改变默认的静态资源路径回到原文划线处目的在于以后配置的拦截器,放行固定前缀的静态资源,只拦截动态资源回复投诉
  • 05、Web开发 - 图15305、Web开发 - 图154yzxmf01-19 10:37webjar回到原文划线处了解即可回复投诉
  • 05、Web开发 - 图15505、Web开发 - 图156墨明棋妙啊01-22 08:49@MatrixVariable、回到原文划线处默认禁用
    回复投诉
  • 05、Web开发 - 图15705、Web开发 - 图158大胖子01-26 16:22先去找Controller看能不能处理。不能处理的所有请求又都交给静态资源处理器回到原文划线处*回复投诉
  • 05、Web开发 - 图15905、Web开发 - 图160大胖子01-26 16:23先去找Controller看能不能处理。不能处理的所有请求又都交给静态资源处理器回到原文划线处*回复投诉
  • 05、Web开发 - 图16105、Web开发 - 图162大胖子01-26 16:23请求进来,先去找Controller看能不能处理。不能处理的所有请求又都交给静态资源处理器。回到原文划线处重点回复投诉
  • 05、Web开发 - 图16305、Web开发 - 图164大胖子01-26 16:23请求进来,先去找Controller看能不能处理。不能处理的所有请求又都交给静态资源处理器。回到原文划线处**回复投诉
  • 05、Web开发 - 图16505、Web开发 - 图166氼哈哈01-28 16:23Favicon回到原文划线处网址前的图标回复投诉
  • 05、Web开发 - 图16705、Web开发 - 图168primrose01-28 16:39回复 @寒城回到原评论好像的确有这个问题,我也不能访问回复投诉
  • 05、Web开发 - 图16905、Web开发 - 图170灰孩子的天空02-01 10:02回复 @大胖子回到原评论确实是重点回复投诉
  • 05、Web开发 - 图17105、Web开发 - 图172灰孩子的天空02-01 10:30该评论已删除static-path-patten:/res/** 是静态资源要访问的真实路径static -location:[classpath:/haha/] 是将这些静态资源都放在指定文件夹下面 方便后面的 拦截器的操作回复投诉
  • 05、Web开发 - 图17305、Web开发 - 图174灰孩子的天空02-01 10:32回复 @小仓鼠回到原评论static-path-patten是虚拟的路径 不是真实存在的
    回复投诉
  • 05、Web开发 - 图17505、Web开发 - 图176杨熙02-01 16:14new ThymeleafView()—->回到原文划线处之后调用模板引擎的process方法进行页面渲染(用writer输出)
    回复投诉
  • 05、Web开发 - 图17705、Web开发 - 图178灰孩子的天空02-01 17:40地址回到原文划线处这是引入了jquery静态资源的一个访问路径 ,了解即可,知道访问路径即可回复投诉
  • 05、Web开发 - 图17905、Web开发 - 图180灰孩子的天空02-01 18:01支持回到原文划线处默认先去 静态资源路径下 找index 找不到则寻找index模板回复投诉
  • 05、Web开发 - 图18105、Web开发 - 图182灰孩子的天空02-01 18:04Favicon回到原文划线处2.4.2 版本文档没有了该图标解释 回复投诉
  • 05、Web开发 - 图18305、Web开发 - 图184灰孩子的天空02-01 18:09目录回到原文划线处static目录下回复投诉
  • 05、Web开发 - 图18505、Web开发 - 图186灰孩子的天空02-01 19:00资源回到原文划线处新版本 为spring.web.resources.static-locations请求路径:localhost:8080/res/a.jpga.jpg放在haha文件夹下回复投诉
  • 05、Web开发 - 图18705、Web开发 - 图188灰孩子的天空02-01 19:43WebMvcAutoConfiguration回到原文划线处在该自动配置类中,我们主要看EnableWebMvcConfiguration配置回复投诉
  • 05、Web开发 - 图18905、Web开发 - 图190灰孩子的天空02-01 19:45中回到原文划线处2.4.2版本 替换成了 WebProperties.class 前缀为spring.web回复投诉
  • 05、Web开发 - 图19105、Web开发 - 图192灰孩子的天空02-01 19:57了回到原文划线处新版本中Resources WebProperties 前缀都为spring.webWebMvcProperties 前缀为spring.mvc回复投诉
  • 05、Web开发 - 图19305、Web开发 - 图194灰孩子的天空02-02 10:08映射回到原文划线处FrameworkServlet类中的doGet调用本类中的processRequest方法后调用doService方法在其子类DispathServlet类中实现后调用doDispatch方法在其中处理请求回复投诉
  • 05、Web开发 - 图19505、Web开发 - 图196灰孩子的天空02-02 10:38原理回到原文划线处首先我们发送的每一个请求都会经过dispathServlet回复投诉
  • 05、Web开发 - 图19705、Web开发 - 图198杨熙02-02 10:40如果想要返回页面;就会找error视图【StaticView】。(默认是一个白页)回到原文划线处步骤总结回复投诉
  • 05、Web开发 - 图19905、Web开发 - 图200杨熙02-02 10:41错误页回到原文划线处上述两张图解释了为什么既能写json,又能写错误页回复投诉
  • 05、Web开发 - 图20105、Web开发 - 图202杨熙02-02 10:55dispatchException回到原文划线处用它来保存catch到的异常回复投诉
  • 05、Web开发 - 图20305、Web开发 - 图204杨熙02-02 10:56mv回到原文划线处有异常时,mv为空,异常保存在了dispatchException中回复投诉
  • 05、Web开发 - 图20505、Web开发 - 图206杨熙02-02 10:59处理器回到原文划线处指目标方法的处理器回复投诉
  • 05、Web开发 - 图20705、Web开发 - 图208hhsinchiang02-02 15:01rrequest回到原文划线处request回复投诉
  • 05、Web开发 - 图20905、Web开发 - 图210杨熙02-02 15:01作为默认的全局异常处理规则回到原文划线处使用@Order(value = Ordered.HIGHEST_PRECEDENCE)将优先级调高即可回复投诉
  • 05、Web开发 - 图21105、Web开发 - 图212杨熙02-02 15:33精确优选原则回到原文划线处因此优先来到/my路径,而不是先到/路径,因此不会走Spring流程,而是走Tomcat流程,故/my路径不会被拦截器拦截回复投诉
  • 05、Web开发 - 图21305、Web开发 - 图214杨熙02-02 15:50切换服务器回到原文划线处在pom.xml中排除tomcat依赖,再将要切换到的服务器的starter导入即可实现切换,回复投诉
  • 05、Web开发 - 图21505、Web开发 - 图216chandler02-04 19:090 - 支持方法上标注@RequestMapping回到原文划线处0={RequestMappingHandlerAdapter@5828}回复投诉
  • 05、Web开发 - 图21705、Web开发 - 图218志昊的刘02-05 09:56回复 @yzxmf回到原评论webjar就是将前端的静态资源:比如说jquery、bootstarp等资源以jar包的方式导入回复投诉
  • 05、Web开发 - 图21905、Web开发 - 图220志昊的刘02-05 09:58回复 @primrose回到原评论你配置了访问前缀之后就访问不了欢迎页了也就是访问前缀和欢迎页这两个你只能要一个,鱼和熊掌不可兼得
    回复投诉
  • 05、Web开发 - 图22105、Web开发 - 图222志昊的刘02-05 10:06回复 @灰孩子的天空回到原评论这个还要多试几下效果才能显示出来,不知道为什么,可能是缓存的原因
    回复投诉
  • 05、Web开发 - 图22305、Web开发 - 图224志昊的刘02-05 10:09回复 @罗罗爱学习回到原评论还要在yaml文件中开启,springboot才会支持rest的风格
    回复投诉
  • 05、Web开发 - 图22505、Web开发 - 图226志昊的刘02-05 10:09回复 @lee回到原评论细!回复投诉
  • 05、Web开发 - 图22705、Web开发 - 图228韩梦枫02-05 14:19回复 @lee回到原评论xixi 回复投诉
  • 05、Web开发 - 图22905、Web开发 - 图230韩梦枫02-05 14:25ServletRequestMethodArgumentResolver 以上回到原文划线处水字数回复投诉
  • 05、Web开发 - 图23105、Web开发 - 图232韩梦枫02-05 14:261.3、复杂参数:回到原文划线处接着水字数回复投诉
  • 05、Web开发 - 图23305、Web开发 - 图234韩梦枫02-05 14:34配置类只有一个有参构造器回到原文划线处水水水 接着水字数
    回复投诉
  • 05、Web开发 - 图23505、Web开发 - 图236樊广辉02-05 15:51ErrorMvcAutoConfiguration 自动配置异常处理规则回到原文划线处绑定serverproperties和webmvcproperties回复投诉
  • 05、Web开发 - 图23705、Web开发 - 图238樊广辉02-05 16:25new ModelAndView回到原文划线处要么响应一个modelandvie(页面),要么响应一个responseentity(json)回复投诉
  • 05、Web开发 - 图23905、Web开发 - 图240樊广辉02-06 13:08默认没有任何人能处理异常,所以异常会被抛出回到原文划线处交由handlerexceptionreslovercomposite,遍历其中的异常处理器处理,但默认无法处理回复投诉
  • 05、Web开发 - 图24105、Web开发 - 图242樊广辉02-06 13:20遍历所有的 ErrorViewResolver 看谁能解析回到原文划线处默认的只有一个DefaultErrorViewResolver回复投诉
  • 05、Web开发 - 图24305、Web开发 - 图244樊广辉02-06 20:54全局异常回到原文划线处通常是某些已经定义好的异常回复投诉
  • 05、Web开发 - 图24505、Web开发 - 图246樊广辉02-06 20:57(statusCode, resolvedReason回到原文划线处将状态码和错误原因组装成modelandview回复投诉
  • 05、Web开发 - 图24705、Web开发 - 图248樊广辉02-06 21:04回复 @樊广辉回到原评论数学运算异常、空指针异常等等回复投诉
  • 05、Web开发 - 图24905、Web开发 - 图250樊广辉02-07 16:55默认映射的是 / 路径回到原文划线处可以通过spring.mvc.servlet.path进行修改回复投诉
  • 05、Web开发 - 图25105、Web开发 - 图252樊广辉02-07 17:03导入tomcat回到原文划线处spring-boot-starter-web默认导入了tomcat回复投诉
  • 05、Web开发 - 图25305、Web开发 - 图254quiet02-11 20:193、如果任何一个拦截器返回false。直接跳出不执行目标方法回到原文划线处3个拦截器,当第2个拦截器出了异常,从第2个拦截器开始倒序执行afterCompletion回复投诉
  • 05、Web开发 - 图25505、Web开发 - 图256用微笑去面对所有02-16 10:36改回到原文划线处该回复投诉
  • 05、Web开发 - 图25705、Web开发 - 图258*02-20 10:03支持回到原文划线处访问webjars:1、导入依赖;2、通过/webjars/路径访问回复投诉
  • 05、Web开发 - 图25905、Web开发 - 图260对庄王者02-22 16:42过滤器链放行的时候用wrapper。以后的方法调用getMethod是调用requesWrapper的回到原文划线处后续关注:DispatcherServlet中的HandlerExecutionChain拦截器执行链(包括自定义的拦截器也会在这里)
    先执行拦截器的preHandle方法,如果返回true放行执行handlerAdapter的handle方法,也就是controller方法adapter执行完成返回ModelAndView对象执行拦截器postHandle方法然后dispatcher把mav对象交给视图解析器解析,获取View对象响应客户端
    回复投诉
  • 05、Web开发 - 图26105、Web开发 - 图262cake02-22 22:14devtools回到原文划线处devtools可以实现页面热部署(即页面修改后会立即生效,实现对属性文件的热部署。即devtools会监听classpath下的文件变动,并且会立即重启应用(发生在保存时机)回复投诉
  • 05、Web开发 - 图26305、Web开发 - 图264孙高峰02-23 09:5225集末尾,欢迎页那个,是不是因为当时有一个11000秒的缓存呢,看到视频上回复投诉
  • 05、Web开发 - 图26505、Web开发 - 图266zxh02-23 16:39回复 @寒城回到原评论一定是不能访问的,因为源码中有判断”/**”.equals(staticPathPattern)回复投诉
  • 05、Web开发 - 图26705、Web开发 - 图268    02-25 20:24Parameter策略优先确定是要返回json数据(获取请求头中的format的值)回到原文划线处最高权重直接匹配到第一个,而第一个就是json回复投诉
  • 05、Web开发 - 图26905、Web开发 - 图270    02-25 20:26回复 @    回到原评论浏览器端不传参数或者是没匹配到,就是”/“,都能匹配,然后按权重匹配回复投诉
  • 05、Web开发 - 图27105、Web开发 - 图272苏白02-26 21:31回复 @志昊的刘回到原评论你存入一个静态资源,可以先看target编译目录中有没有,没有的话使用Maven 进行clean操作,再启动服务器编译,这样就有了,访问不到应该是没有编译到静态资源回复投诉
  • 05、Web开发 - 图27305、Web开发 - 图274不想长大02-26 22:24请问自定义messageconverter输出中文乱码怎么解决
    回复投诉
  • 05、Web开发 - 图27505、Web开发 - 图276A小齐03-03 12:52源码听的好难受回复投诉
  • 05、Web开发 - 图27705、Web开发 - 图278xiongyi0103-04 11:35@FunctionalInterfacepublic interface Converter回到原文划线处只能针对form表单提交数据,不能在restfulApi下生效回复投诉
  • 05、Web开发 - 图27905、Web开发 - 图280zxh03-04 19:53并且返回null回到原文划线处默认没有能处理异常的解析器回复投诉
  • 05、Web开发 - 图28105、Web开发 - 图282zxh03-04 19:56response.sendErro回到原文划线处三种方法最后都会调用sendError()转交给controller处理回复投诉
  • 05、Web开发 - 图28305、Web开发 - 图284zxh03-04 20:55没有经过Spring的拦截器回到原文划线处根据精确优先原则,DispatcherServlet处理”/“请求,MyServlet处理”/my”请求,更精确,所以由原生的servlet(Tomcat处理),而只有由DispatcherServlet(Spring)处理的请求才会经过spring的拦截器回复投诉
  • 05、Web开发 - 图28505、Web开发 - 图286simplegq03-05 20:43挨个判断所有参数解析器那个支持解析这个参数回到原文划线处for 循环遍历所有的参数解析器,确定哪个解析器可以解析当前参数回复投诉
  • 05、Web开发 - 图28705、Web开发 - 图288simplegq03-05 20:45如何确定目标方法每一个参数的值回到原文划线处分两步:1. 确定用哪个参数解析器进行解析回复投诉
    1. 解析参数,其实最终还是从request对象中取参数的值
  • 05、Web开发 - 图28905、Web开发 - 图290simplegq03-05 20:54参数解析器-HandlerMethodArgumentResolver回到原文划线处参数解析器有很多种,supportsParameter:判断该参数解析器是否支持解析该参数
    resolveArgument:进行具体的参数解析操作,获取参数的值回复投诉
  • 05、Web开发 - 图29105、Web开发 - 图292共青坊03-06 09:51放在类路径下回到原文划线处main/resources回复投诉
  • 05、Web开发 - 图29305、Web开发 - 图294共青坊03-06 16:33注解:回到原文划线处@pathVariable 获取路径变量@RequestHeader获取请求头@RequestParam获取请求参数(一个属性有多个值可以使用?inters=bask&inters=game)@RequestBody获取表单提交内容@RequestAttribute获取request域属性(HttpServetRequest在request域中添加属性)回复投诉
  • 05、Web开发 - 图29505、Web开发 - 图296LJon03-06 22:55改变默认的静态资源路径回到原文划线处static-path-pattern: [classpath:/haha/] 会覆盖原来默认的静态资源目录 ( /static or /public or /resources or /META-INF/resources )回复投诉
  • 05、Web开发 - 图29705、Web开发 - 图298颠锅翻炒凉茶铺03-09 18:05返回值处理器回到原文划线处modelAndView、ModelMethodProcessor、ViewMethodReturnValueHandler、HttpEntityMethodProcessor回复投诉
  • 05、Web开发 - 图29905、Web开发 - 图300simplegq03-09 20:03回复 @小乐回到原评论对的,指的是preHandler回复投诉
  • 05、Web开发 - 图30105、Web开发 - 图302simplegq03-10 21:47basicErrorController 要去的页面地址是 ErrorViewResolver回到原文划线处error请求会被basicErrorController处理,里面使用了ErrorViewResolver进行解析。ErrorViewResolver 会转到一个页面或者返回json数据。回复投诉
  • 05、Web开发 - 图30305、Web开发 - 图304simplegq03-10 21:50error请求就会转给controller回到原文划线处自己调用response.error,请求也会被转发给basicErrorController进行处理。如果自己没有调用,并且异常没有任何人能够处理,tomact底层会自动调用response.sendError将请求转发给basicErrorController处理。回复投诉
  • 05、Web开发 - 图30505、Web开发 - 图306simplegq03-10 21:54@ControllerAdvice+@ExceptionHandler处理全局异常回到原文划线处处理异常方式1,使用这两个注解
    回复投诉
  • 05、Web开发 - 图30705、Web开发 - 图308simplegq03-10 21:54@ResponseStatus+自定义异常回到原文划线处方式2,使用这个注解回复投诉
  • 05、Web开发 - 图30905、Web开发 - 图310simplegq03-10 21:54自定义实现 HandlerExceptionResolver 处理异常回到原文划线处方式3:自定义处理器异常解析器
    回复投诉
  • 05、Web开发 - 图31105、Web开发 - 图312simplegq03-10 21:55ErrorViewResolver 实现自定义处理异常;回到原文划线处自定义这个使用的不多回复投诉
  • 05、Web开发 - 图31305、Web开发 - 图314simplegq03-10 21:56Spring底层的异常,如 参数类型转换异常回到原文划线处这个是Spring底层处理异常的方式。能自定义它吗?改变底层的处理方式?回复投诉
  • 05、Web开发 - 图31505、Web开发 - 图316颠锅翻炒凉茶铺03-11 11:24MessageConverter规范回到原文划线处HttpMessageConverter接口主要提供以下几个方法:(1)canRead 是否可以读(2)canWrite 是否可以写(3)read() 读数据(4)write() 写数据回复投诉
  • 05、Web开发 - 图31705、Web开发 - 图318颠锅翻炒凉茶铺03-11 11:29默认的MessageConverter回到原文划线处ByteArrayHttpMessageConverter - 只支持Byte类型的StringHttpmessageConverter - StringResourceHttpMessageConverter - ResourceResourceRegionHttpMessageConverter - ResourceRegionSourceHttpMessageConverter - DOMSource.class \ SAXSource.class) \ StAXSource.class \StreamSource.class \Source.classAllEncompassingFormHttpMessageConverter - MultiValueMapMappingJackson2HttpMessageConverter - true Jaxb2RootElementHttpMessageConverter - 支持注解方式xml处理的回复投诉
  • 05、Web开发 - 图31905、Web开发 - 图320myself03-12 11:03目标方法处理的过程中,所有数据都会被放在 ModelAndViewContainer 里面回到原文划线处通过ViewNameMethodReturnValueHandler这个handler进行处理,这个handler判断返回值是void或者是字符序列。如果是字符序列会转为String,然后将返回值放进mav中回复投诉
  • 05、Web开发 - 图32105、Web开发 - 图322myself03-12 11:21response.sendRedirect(encodedURL);回到原文划线处redirect:/main.html 通过thymeleaf创建RedirectView对象,然后该对象调用原生response的sendRedirect(url)方法回复投诉
  • 05、Web开发 - 图32305、Web开发 - 图324myself03-12 11:25request.getRequestDispatcher(path).forward(request, response);回到原文划线处servlet原生转发方法,都快忘了。。req.getRequsetDispatcher(path).forward(req,resp);回复投诉
  • 05、Web开发 - 图32505、Web开发 - 图326陈一千03-14 22:15定制化原理回到原文划线处难懂
    回复投诉
  • 05、Web开发 - 图32705、Web开发 - 图328yami03-16 19:59回复 @小仓鼠回到原评论这里配置了[classpath:/haha/],但是META/resources/下的资源依然可以访问到。回复投诉
  • 05、Web开发 - 图32905、Web开发 - 图330我要夏天03-18 14:48@RequestBody回到原文划线处用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的)回复投诉
  • 05、Web开发 - 图33105、Web开发 - 图332Re03-22 19:02静态资源回到原文划线处一般都放在static文件夹下回复投诉
  • 05、Web开发 - 图33305、Web开发 - 图334Re03-22 21:40回复 @小仓鼠回到原评论等你学微服务 Feign 方法的远程调用时,你自会收回这句话回复投诉
  • 05、Web开发 - 图33505、Web开发 - 图336سين03-31 16:20PathVariable回到原文划线处用于获取restful种的GET请求头中的内容回复投诉
  • 05、Web开发 - 图33705、Web开发 - 图338سين03-31 16:21@RequestHeader回到原文划线处用于获取http请求的header部分信息回复投诉
  • 05、Web开发 - 图33905、Web开发 - 图340toro04-01 16:51改变默认的静态资源路径回到原文划线处静态资源访问路径优先级:回复投诉
    1. META-INF/resources
    2. resources
    3. static
    4. public
  • 05、Web开发 - 图34105、Web开发 - 图342Eric沈04-01 20:54回复 @韩梦枫回到原评论让你花钱买了?回复投诉
  • 05、Web开发 - 图34305、Web开发 - 图344ChenChenChen_a04-02 10:432、静态资源处理回到原文划线处即css js image 以及第三方的静态资源功能库 比如Bootstrap JQuery 等回复投诉
  • 05、Web开发 - 图34505、Web开发 - 图346ppn04-02 19:44web应用会创建一个web版的ioc容器 ServletWebServerApplicationContext回到原文划线处先会用,再深入学原理回复投诉
  • 05、Web开发 - 图34705、Web开发 - 图348浚沐冰心04-02 20:00回复 @灰孩子的天空回到原评论你好,^-^回复投诉
  • 05、Web开发 - 图34905、Web开发 - 图350偏云04-04 16:31WebMvcAutoConfiguration回到原文划线处SpringMVC的配置主要集中在这
    回复投诉
  • 05、Web开发 - 图35105、Web开发 - 图352偏云04-04 21:31回复 @志昊的刘回到原评论05、Web开发 - 图353回复投诉
  • 05、Web开发 - 图35405、Web开发 - 图355Samson04-11 14:2105、Web开发 - 图356自定义协议 么有截图,我来补充回复投诉
  • 05、Web开发 - 图35705、Web开发 - 图358会飞的鱼04-18 16:57回复 @Re回到原评论静态资源一般包括图片、视频、js、css文件回复投诉
  • 05、Web开发 - 图35905、Web开发 - 图360大橙子04-19 16:59回到原文划线处单个是servlet的写法,** 是spring家族写法回复投诉
  • 05、Web开发 - 图36105、Web开发 - 图362大橙子04-19 17:19Tomcat-Servlet回到原文划线处配置spring.mvc.servlet.path 为dispatchSerlvet中拦截的路径配置server.servlet.context-path为上下文路径,访问的前缀回复投诉
  • 05、Web开发 - 图36305、Web开发 - 图364大橙子04-19 17:21默认映射的是 / 路径回到原文划线处配置spring.mvc.servlet.path 为dispatchSerlvet中拦截的路径配置server.servlet.context-path为上下文路径,访问的前缀回复投诉
  • 05、Web开发 - 图36505、Web开发 - 图366从容04-20 14:19补 RequestAttribute05、Web开发 - 图367回复投诉
  • 05、Web开发 - 图36805、Web开发 - 图369同情你狼04-21 09:11favicon回到原文划线处favicon.ico
    回复投诉
  • 05、Web开发 - 图37005、Web开发 - 图371sunbeam04-22 16:11lombok回到原文划线处lombok 是一个Java库回复投诉
  • 05、Web开发 - 图37205、Web开发 - 图373不器04-23 09:30回复 @zxh回到原评论1.不是bug。2.官方设计就是这样。3.老师讲错了,但是没有操作错误。3.b站弹幕真的蠢。4.不针对你,只是不会评论,只能回复你。回复投诉
  • 05、Web开发 - 图37405、Web开发 - 图375ppn04-23 19:46回复 @灰孩子的天空回到原评论是的回复投诉
  • 05、Web开发 - 图37605、Web开发 - 图377ppn04-23 19:56回复 @韩梦枫回到原评论嗯回复投诉
  • 05、Web开发 - 图37805、Web开发 - 图379sunbeam04-24 16:28Customizer回到原文划线处定制器
    回复投诉
  • 05、Web开发 - 图38005、Web开发 - 图381xuexi04-26 14:25静态资源访问前缀回到原文划线处放行对于静态资源访问的拦截回复投诉
  • 05、Web开发 - 图38205、Web开发 - 图383XD04-26 20:46include回到原文划线处不包含
    具体看https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#template-layout回复投诉
  • 05、Web开发 - 图38405、Web开发 - 图38504-28 15:47可以配置静态资源路径回到原文划线处指定静态文件所在的文件夹
    回复投诉
  • 05、Web开发 - 图38605、Web开发 - 图387黑熊噗通05-07 16:08我是神!回复投诉
  • 05、Web开发 - 图38805、Web开发 - 图389Makonike05-09 14:29HandlerMapping回到原文划线处映射每一个请求到对应的Handler回复投诉
  • 05、Web开发 - 图39005、Web开发 - 图391王哲05-11 09:32回复 @Eric沈回到原评论他可能是说他自己在水字数吧回复投诉
  • 05、Web开发 - 图39205、Web开发 - 图393张志强05-13 18:02回复 @李致辉回到原评论spring:_mvc:hiddenmethod:filter:enabled: truecontentnegotiation:favor-parameter: truemedia-types:json: “application/json”
    xml
    : “application/xml”
    gg
    : “application/x-guigu”这样配置可以不写java配置类回复投诉
  • 05、Web开发 - 图39405、Web开发 - 图395F. Finlay Xio05-17 09:52xxx回到原文划线处3-访问静态资源回复投诉
  • 05、Web开发 - 图39605、Web开发 - 图397孙朗 LangSun05-17 13:43【提示:参照SpringBoot官方文档web开发内容协商章节】回到原文划线处spring.mvc.contentnegotiation.media-types.* 应该配置文件的是这个属性吧—Map file extensions to media types for content negotiation. For instance, yml to text/yaml.回复投诉
  • 05、Web开发 - 图39805、Web开发 - 图399💦 💦 💦05-20 19:40回复 @小仓鼠回到原评论不用@RequestParam指定的话,默认是用参数名去匹配表单中的name值,来绑定的回复投诉
  • 05、Web开发 - 图40005、Web开发 - 图401F. Finlay Xio05-21 10:05x-guigu回到原文划线处spring:mvc:contentnegotiation:media-types:gg: application/x-guigufavor-parameter: true回复投诉
  • 05、Web开发 - 图40205、Web开发 - 图403月生洋。05-21 15:05自定义 HandlerMapping回到原文划线处有的时候比如说同一组api有不同的版本,比如v1,v2我们可以在controller中写两组mapping(比如v1/user,v2/user),但同时我们也可以放在两个包下,都是/user,这个时候我们就可以自定义handlermapping,把v1/user映射到一个包下的/user,把v2/user映射到另外一个包下的/user回复投诉
  • 05、Web开发 - 图40405、Web开发 - 图405月生洋。05-21 19:25返回值处理器回到原文划线处mapping方法对应的返回值可以有什么回复投诉
  • 05、Web开发 - 图40605、Web开发 - 图407月生洋。05-22 13:23是否为简单类型回到原文划线处不是简单类型才会调用上面说的这个参数处理器。下面这个代码就是判断是否为简单类型的回复投诉
  • 05、Web开发 - 图40805、Web开发 - 图409月生洋。05-22 13:27WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name);回到原文划线处这些就是上面代码的主要工作流程
    回复投诉
  • 05、Web开发 - 图41005、Web开发 - 图411坤坤05-23 15:29回复 @同情你狼回到原评论我们只要一访问此网站,浏览器就会默认发送请求/favicon.icv,如果我们添加了静态资源访问前缀,浏览器就会无法访问到此资源,但是加个controller应该可以解决回复投诉
  • 05、Web开发 - 图41205、Web开发 - 图413坤坤05-24 10:57回复 @墨明棋妙啊回到原评论分号前为路径,分号后为请求参数回复投诉
  • 05、Web开发 - 图41405、Web开发 - 图415wuhl05-24 17:43PathVariable回到原文划线处@PathVariable Map pv, 用来存放所有的键值对回复投诉
  • 05、Web开发 - 图41605、Web开发 - 图417缪可05-28 14:33回复 @灰孩子的天空回到原评论CTRL+H 打开关系树 (找不到直接回的地方 不好意思打扰啦回复投诉
  • 05、Web开发 - 图41805、Web开发 - 图419哈哈05-28 15:50开启回到原文划线处mvc:hiddenmethod:filter:enabled: true回复投诉
  • 05、Web开发 - 图42005、Web开发 - 图421woo05-29 15:17包装模式回到原文划线处適配器模式
    回复投诉
  • 05、Web开发 - 图42205、Web开发 - 图423handsome coffee05-30 19:15SpringMVC自动配置概览回到原文划线处官方文档要多看[狗头]回复投诉
  • 05、Web开发 - 图42405、Web开发 - 图425handsome coffee05-31 16:46回复 @不器回到原评论你说他是bug它也能说是官方设计的一个bug回复投诉
  • 05、Web开发 - 图42605、Web开发 - 图427handsome coffee05-31 16:57WebMvcProperties==spring.mvc、ResourceProperties==spring.resources回到原文划线处此处应有标注回复投诉
  • 05、Web开发 - 图42805、Web开发 - 图429handsome coffee05-31 17:03欢迎页的处理规则回到原文划线处&&”/**”.equals(staticPathPattern)回复投诉
  • 05、Web开发 - 图43005、Web开发 - 图431handsome coffee05-31 17:36@xxxMapping;回到原文划线处新注解@GetMapping();@PostMapping();@PutMapping();@DeleteMapping();回复投诉
  • 05、Web开发 - 图43205、Web开发 - 图433handsome coffee05-31 22:39HiddenHttpMethodFilter拦截回到原文划线处拦截回复投诉
  • 05、Web开发 - 图43405、Web开发 - 图435handsome coffee05-31 23:01请求信息回到原文划线处同样的请求信息只能有一个回复投诉
  • 05、Web开发 - 图43605、Web开发 - 图437缪可06-01 11:18HandlerInterceptor 接口回到原文划线处preHandle:目标处理方法之前。postHandle:目标处理方法后,可能页面还没渲染,这个时候要做的一些增强或减弱处理。afterCompletion:页面真正渲染完后想要做的一些操作。回复投诉
  • 05、Web开发 - 图43805、Web开发 - 图439缪可06-03 11:45导入xxx组件回到原文划线处@Bean导入组件回复投诉
  • 05、Web开发 - 图44005、Web开发 - 图441topper06-04 11:04手动开启回到原文划线处新版本默认开启了回复投诉
  • 05、Web开发 - 图44205、Web开发 - 图443tsui06-06 00:31“123456”.equals(user.getPassword()为什么我浏览器可以获取到密码,但是idea显示密码为null,导致去不到main.html。有人可以告诉我吗回复投诉
  • 05、Web开发 - 图44405、Web开发 - 图445果酱小猫的栀子花06-07 10:553、页面开发回到原文划线处注意先引入名称空间回复投诉
  • 05、Web开发 - 图44605、Web开发 - 图447一定要在这条路走下去06-07 11:01改变默认的静态资源路径回到原文划线处static-locations:自定义配置静态资源所在路径static-path-pattern:自定义配置静态资源访问路径回复投诉
  • 05、Web开发 - 图44805、Web开发 - 图449春暖花开06-08 10:02HandlerExecutionChain回到原文划线处mappedHandler = getHandler(processedRequest);回复投诉
  • 05、Web开发 - 图45005、Web开发 - 图451春暖花开06-08 13:57FileCopyUtils回到原文划线处底层操作文件的工具类回复投诉
  • 05、Web开发 - 图45205、Web开发 - 图453yang_06-08 17:24回复 @topper回到原评论是的
    回复投诉
  • 05、Web开发 - 图45405、Web开发 - 图455Eivor06-09 09:46controller能处理/index回到原文划线处这块是不是没讲?
    回复投诉
  • 05、Web开发 - 图45605、Web开发 - 图457口亨小木06-09 11:20回复 @小仓鼠回到原评论当修改了静态资源的默认路径之后,所有的静态资源(xxx.jpg)需要放到对应修改的文件夹下,访问地址:localhost:8080/res/xxx.jpgres是虚拟的,静态文件夹是默认的,也不需要在访问地址中出现回复投诉
  • 05、Web开发 - 图45805、Web开发 - 图459春暖花开06-09 15:58View回到原文划线处view的类型StaticView。回复投诉
  • 05、Web开发 - 图46005、Web开发 - 图461羊羊06-09 16:01回复 @韩梦枫回到原评论sb回复投诉
  • 05、Web开发 - 图46205、Web开发 - 图463口亨小木06-09 16:44回复 @handsome coffee回到原评论棒!回复投诉
  • 05、Web开发 - 图46405、Web开发 - 图465春暖花开06-10 20:52重新配置回到原文划线处/ 全面接管springmvc时,定义静态资源行为 @param registry*/// @Override// public void addResourceHandlers(ResourceHandlerRegistry registry) {// /// 访问 /aa/** 所有请求都去 classpath:/static/ 下面进行匹配// /// registry.addResourceHandler(“/aa/**”)// .addResourceLocations(“classpath:/static/“);// }回复投诉
  • 05、Web开发 - 图46605、Web开发 - 图467~~~06-13 18:09传入的值回到原文划线处_method的值回复投诉
  • 05、Web开发 - 图46805、Web开发 - 图469NPC06-20 10:43回复 @yami回到原评论兄弟,为啥配置了location: [classpath:/haha/],但是其他的静态资源文件下的图片还能访问?你现在知道了吗?我没弄明白回复投诉
  • 05、Web开发 - 图47005、Web开发 - 图471猫咪老师06-22 22:46mavContainer回到原文划线处保存Model和View的container
    回复投诉
  • 05、Web开发 - 图47205、Web开发 - 图473猫咪老师06-23 14:30render回到原文划线处render:渲染回复投诉
  • 05、Web开发 - 图47405、Web开发 - 图475yms06-23 22:26webjar回到原文划线处引入一个新的依赖后,项目需要重启回复投诉
  • 05、Web开发 - 图47605、Web开发 - 图477yms06-23 22:31欢迎页支持回到原文划线处默认支持静态的和模板的回复投诉
  • 05、Web开发 - 图47805、Web开发 - 图479西红柿炒蛋06-24 15:07回复 @灰孩子的天空回到原评论确实回复投诉
  • 05、Web开发 - 图48005、Web开发 - 图481Laity06-24 16:15回复 @handsome coffee回到原评论拦截请求回复投诉
  • 05、Web开发 - 图48205、Web开发 - 图483Laity06-24 16:28回复 @~~~回到原评论05、Web开发 - 图484回复投诉
  • 05、Web开发 - 图48505、Web开发 - 图486Laity06-24 18:37回复 @handsome coffee回到原评论同样的请求方式,不能有相同的方法处理,简单来说就是方式一样,方法就要唯一回复投诉
  • 05、Web开发 - 图48705、Web开发 - 图488Laity06-24 18:40回复 @月生洋。回到原评论HandlerMapping意思是处理器映射,把一个URL指定到一个Controller上回复投诉
  • 05、Web开发 - 图48905、Web开发 - 图490Phil06-25 00:23请求进来,先去找Controller看能不能处理。不能处理的所有请求又都交给静态资源处理器。回到原文划线处先去找动态资源,找不到后在去找静态资源回复投诉
  • 05、Web开发 - 图49105、Web开发 - 图492刘尧06-25 10:31回复 @NPC回到原评论对呀,我也看到还是能访问到META-INF下的静态资源,搜了很多博客,感觉是META-INF优先级….不知道能不能这么看回复投诉
  • 05、Web开发 - 图49305、Web开发 - 图494刘尧06-25 11:16回复 @handsome coffee回到原评论https://blog.csdn.net/qq_41027559/article/details/114359380关于添加前缀后欢迎页无法访问的问题回复投诉
  • 05、Web开发 - 图49505、Web开发 - 图496Laity06-25 14:31回复 @苏白回到原评论图标回复投诉
  • 05、Web开发 - 图49705、Web开发 - 图498Laity06-25 14:41回复 @wuhl回到原评论05、Web开发 - 图499回复投诉
  • 05、Web开发 - 图50005、Web开发 - 图501西红柿炒蛋06-25 15:09SpringMVC目标方法能写多少种参数类型。取决于参数解析器回到原文划线处参数解析器对入参进行解析,能否解析取决于参数解析器的种类是否支持入参回复投诉
  • 05、Web开发 - 图50205、Web开发 - 图503·06-25 15:21可以搞一个完整的thymeleaf模板后台管理吗
    回复投诉
  • 05、Web开发 - 图50405、Web开发 - 图505春暖花开06-26 08:42静态资源路径回到原文划线处默认的配置:private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{“classpath:/META-INF/resources/“, “classpath:/resources/“, “classpath:/static/“, “classpath:/public/“};回复投诉
  • 05、Web开发 - 图50605、Web开发 - 图507yms06-26 10:51普通参数与基本注解回到原文划线处26个参数解析器,采用循环遍历的方式找对应的参数解析器,(参数解析器完成第一次加载后,会进到缓存中),15个返回值处理器,最常用的返回值类型:ModelAndView, Model, View, ResponseBody回复投诉
  • 05、Web开发 - 图50805、Web开发 - 图509jcroad06-26 11:02当前解析器是否支持解析这种参数回到原文划线处用流水话解释:当前解析器 判断 是否支持解析这种参数如果支持就调用 resolveArgument 解析回复投诉
  • 05、Web开发 - 图51005、Web开发 - 图511jcroad06-26 11:25解析这个参数的值回到原文划线处为什么能够支持那么多参数类型,就是对这个接口的实现有很多种,每一种针对不同的参数类型(注解)进行支持、实现,然后解析。HandlerMethodArgumentResolver 接口
    (如果有不对,欢迎评论,谢谢!)回复投诉
  • 05、Web开发 - 图51205、Web开发 - 图513yms06-26 12:39true回到原文划线处无论什么类都返回true,换句话说,就是可以将任何类型的对象转换为浏览器所想要的数据类型;回复投诉
  • 05、Web开发 - 图51405、Web开发 - 图515长颈鹿🦒06-28 01:35回复 @农回到原评论不推荐使用了回复投诉
  • 05、Web开发 - 图51605、Web开发 - 图517jwm06-28 15:12回复 @苏白回到原评论厉害
    回复投诉
  • 05、Web开发 - 图51805、Web开发 - 图519Phil06-29 14:27org.springframework.web.servlet.DispatcherServlet-》doDispatch()回到原文划线处都会从此处开始处理回复投诉
  • 05、Web开发 - 图52005、Web开发 - 图521Riptide06-30 09:37开启浏览器参数方式内容协商功能回到原文划线处目的是方便浏览器通过修改参数的方式完成内容协商。前文已经介绍,若不开启参数方式吗,则浏览器根据请求头中Accept方式接受,无法灵活(如postman)的改变接受类型
    若需要响应其余(自定义)的消息类型,则添加自定义messageConverter中添加到IOC中即通过WebMvcConfigure.回复投诉
  • 05、Web开发 - 图52205、Web开发 - 图523Riptide06-30 09:53自定义 MessageConverter回到原文划线处如何以参数的形式进行内容协商?回复投诉
  • 05、Web开发 - 图52405、Web开发 - 图525Riptide06-30 10:08回复 @孙朗 LangSun回到原评论是的,直接配置就好。视频里老师也没错只是覆盖了回复投诉
  • 05、Web开发 - 图52605、Web开发 - 图527莎野卜辉07-01 09:42MultiValueMap回到原文划线处最终以键值对的方式进行取值,key为@RequestPart中的参数名
    回复投诉
  • 05、Web开发 - 图52805、Web开发 - 图529wqjsmile07-01 14:45静态资源访问前缀回到原文划线处为了让拦截时能区分出静态资源和动态资源,所以规定静态资源前面加个前缀,拦截器在看到指定前缀时就放行,从而达到动态静态分开的目的。回复投诉
  • 05、Web开发 - 图53005、Web开发 - 图531Arima、、07-04 16:24回复 @小仓鼠回到原评论/**表示拦截所有请求回复投诉
  • 05、Web开发 - 图53205、Web开发 - 图533Arima、、07-04 16:43回复 @wqjsmile回到原评论为了让拦截时能区分出静态资源和动态资源,所以一般在静态资源前面加个前缀,拦截器在看到指定前缀时就放行,从而达到动态静态分开的目的。回复投诉
  • 05、Web开发 - 图53405、Web开发 - 图535Arima、、07-04 16:53回复 @Arima、、回到原评论实际文件的位置不需要修改,只是访问的地址变了回复投诉
  • 05、Web开发 - 图53605、Web开发 - 图537Arima、、07-04 18:16回复 @yami回到原评论注意,新包(haha)里面不能和旧包(static)里面有重名文件回复投诉
  • 05、Web开发 - 图53805、Web开发 - 图539语雀用户-KQRP8l07-05 22:24配置类只有一个有参构造器回到原文划线处配置类的有参构造器的方法参数,默认从容器中寻找组件来注入回复投诉
  • 05、Web开发 - 图54005、Web开发 - 图541Sleepyhead07-06 17:49获取到_method的值。回到原文划线处无论value是大写还是小写,底层都会统一转换为大写回复投诉
  • 05、Web开发 - 图54205、Web开发 - 图543Sleepyhead07-06 20:00SpringBoot自动配置欢迎页的 WelcomePageHandlerMapping 。访问 /能访问到index.html;回到原文划线处配置在org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java这个类中回复投诉
  • 05、Web开发 - 图54405、Web开发 - 图545刘弼NewB07-06 21:31回复 @灰孩子的天空回到原评论如果不是本机访问,localhost这个地址也能生效吗?回复投诉
  • 05、Web开发 - 图54605、Web开发 - 图547NMT07-07 12:56/回到原文划线处/是说拦截所有请求回复投诉
  • 05、Web开发 - 图54805、Web开发 - 图549NMT07-07 13:03static-path-pattern回到原文划线处static-path-pattern配置的是资源访问路径的前缀,这个例子的话就是说访问静态资源的时候,uri是,前面的项目的跟uri,然后加上配置的前缀,然后才是静态资源名称回复投诉
  • 05、Web开发 - 图55005、Web开发 - 图551Sleepyhead07-07 16:10回复 @Riptide回到原评论使用举例:spring.mvc.contentnegotiation.media-types: {gg: application/x-guigu}回复投诉
  • 05、Web开发 - 图55205、Web开发 - 图553Sleepyhead07-07 23:02自动配置好了 StandardServletMultipartResolver 【文件上传解析器】回到原文划线处自动配置了名为multipartResolver的文件解析器回复投诉
  • 05、Web开发 - 图55405、Web开发 - 图555NMT07-08 10:54PUT回到原文划线处这里应该是_method=希望使用的提交方法回复投诉
  • 05、Web开发 - 图55605、Web开发 - 图557Sleepyhead07-08 12:27模板引擎最终响应这个页面 error/500.htm回到原文划线处查找顺序:’/templates/error/500.‘’/static/error/500.html’’/templates/error/5xx.‘’/static/error/5xx.html’回复投诉
  • 05、Web开发 - 图55805、Web开发 - 图559NMT07-10 09:10n数据回到原文划线处上面的截图是SpringBoot的Web启动器里面有的回复投诉
  • 05、Web开发 - 图56005、Web开发 - 图561Will07-11 10:35回复 @刘弼NewB回到原评论当然不能,如果部署到服务器的话就是服务器的ip:端口号/
    回复投诉
  • 05、Web开发 - 图56205、Web开发 - 图563ageovb07-11 11:11favicon回到原文划线处重新构建(rebuild)下项目,就可以进入欢迎页的 if 了。回复投诉
  • 05、Web开发 - 图56405、Web开发 - 图565摸鱼工程师07-12 20:46WebMvcConfigurer回到原文划线处WebMvcConfigurer是一个接口。里面的方法都是default的方法,可以有选择的实现。方法的返回值都是webmvc需要配置的Bean。所以可以实现这个接口,配合@Configuration注解自定义mvc组件。回复投诉
  • 05、Web开发 - 图56605、Web开发 - 图567NMT07-12 22:10文件上传代码回到原文划线处还有一件事:修改配置文件,对于上传文件大小的限制spring: servlet: multipart: max-file-size: 10MB # 单个上传文件大小上线 max-request-size: 100MB # 一次请求上传所有文件大小上线回复投诉
  • 05、Web开发 - 图56805、Web开发 - 图569zzyu07-13 10:43回复 @Eivor回到原评论我感觉也没讲回复投诉
  • 05、Web开发 - 图57005、Web开发 - 图571NMT07-13 21:58感觉不点赞都不行哪05、Web开发 - 图572回复投诉
  • 05、Web开发 - 图57305、Web开发 - 图574ageovb07-14 21:26客户端工具回到原文划线处也可以使用IDEA中端点工具的HTTP客户端窗口来发送请求。回复投诉
  • 05、Web开发 - 图57505、Web开发 - 图576ageovb07-14 22:03HandlerMapping回到原文划线处05、Web开发 - 图577回复投诉
  • 05、Web开发 - 图57805、Web开发 - 图579ageovb07-14 23:08ServletRequestMethodArgumentResolver回到原文划线处05、Web开发 - 图58005、Web开发 - 图581回复投诉
  • 05、Web开发 - 图58205、Web开发 - 图583stonels007-15 10:57favicon回到原文划线处浏览器会发送 /favicon 请求获取到图标,整个session期间不再获取
    回复投诉
  • 05、Web开发 - 图58405、Web开发 - 图585ageovb07-15 23:13ModelAndViewContainer回到原文划线处05、Web开发 - 图586回复投诉
  • 05、Web开发 - 图58705、Web开发 - 图588ageovb07-15 23:29处理派发结果回到原文划线处05、Web开发 - 图589回复投诉
  • 05、Web开发 - 图59005、Web开发 - 图591ageovb07-16 22:00ServletModelAttributeMethodProcessor回到原文划线处添加条件断点,不必一次次放行:05、Web开发 - 图592回复投诉
  • 05、Web开发 - 图59305、Web开发 - 图594ageovb07-16 22:22是否为简单类型回到原文划线处05、Web开发 - 图595回复投诉
  • 05、Web开发 - 图59605、Web开发 - 图597ageovb07-16 22:33数据绑定器回到原文划线处不用重新Debug,丢帧即可:05、Web开发 - 图598回复投诉
  • 05、Web开发 - 图59905、Web开发 - 图600ageovb07-16 23:13GenericConversionService回到原文划线处05、Web开发 - 图601回复投诉
  • 05、Web开发 - 图60205、Web开发 - 图603ageovb07-16 23:21Converter回到原文划线处05、Web开发 - 图604回复投诉
  • 05、Web开发 - 图60505、Web开发 - 图606ageovb07-17 16:37Converter回到原文划线处binder.conversionService.converters.converters.keySet().stream().collect(Collectors.toList()).get(91)05、Web开发 - 图607回复投诉
  • 05、Web开发 - 图60805、Web开发 - 图609ageovb07-17 16:40Converter回到原文划线处05、Web开发 - 图610回复投诉
  • 05、Web开发 - 图61105、Web开发 - 图612ageovb07-17 17:02返回值处理器回到原文划线处05、Web开发 - 图613回复投诉
  • 05、Web开发 - 图61405、Web开发 - 图615ageovb07-17 17:28supportsReturnType回到原文划线处05、Web开发 - 图616回复投诉
  • 05、Web开发 - 图61705、Web开发 - 图618ageovb07-17 17:30handleReturnValue回到原文划线处05、Web开发 - 图619回复投诉
  • 05、Web开发 - 图62005、Web开发 - 图621ageovb07-17 17:47内容类型回到原文划线处05、Web开发 - 图622回复投诉
  • 05、Web开发 - 图62305、Web开发 - 图624ageovb07-17 17:51默认的MessageConverter回到原文划线处05、Web开发 - 图625回复投诉
  • 05、Web开发 - 图62605、Web开发 - 图627ageovb07-17 18:032 - String回到原文划线处并不是重复了,里面字符集不一样:05、Web开发 - 图628回复投诉
  • 05、Web开发 - 图62905、Web开发 - 图630ageovb07-17 18:13HttpMessageConverter回到原文划线处05、Web开发 - 图631回复投诉
  • 05、Web开发 - 图63205、Web开发 - 图633ageovb07-17 18:18将对象转为json回到原文划线处05、Web开发 - 图634回复投诉
  • 05、Web开发 - 图63505、Web开发 - 图636ageovb07-17 18:44获取客户端Accept请求头字段回到原文划线处05、Web开发 - 图637回复投诉
  • 05、Web开发 - 图63805、Web开发 - 图639ageovb07-17 18:56MessageConverter回到原文划线处7和8以及9和10并不完全一样:05、Web开发 - 图640回复投诉
  • 05、Web开发 - 图64105、Web开发 - 图642ageovb07-17 18:59媒体类型回到原文划线处05、Web开发 - 图643回复投诉
  • 05、Web开发 - 图64405、Web开发 - 图645ageovb07-17 21:18contentNegotiationManager回到原文划线处05、Web开发 - 图646回复投诉
  • 05、Web开发 - 图64705、Web开发 - 图648ageovb07-17 21:27开启回到原文划线处老师粘贴的少了mvcspring:mvc:** contentnegotiation:# 开启请求参数内容协商模式
    favor-parameter: true回复投诉
  • 05、Web开发 - 图64905、Web开发 - 图650ageovb07-17 21:31发请求回到原文划线处05、Web开发 - 图651回复投诉
  • 05、Web开发 - 图65205、Web开发 - 图653ageovb07-17 21:34请求头回到原文划线处不是请求头,而是请求参数中format的值回复投诉
  • 05、Web开发 - 图65405、Web开发 - 图655ageovb07-17 22:05xml的converter回到原文划线处05、Web开发 - 图656回复投诉
  • 05、Web开发 - 图65705、Web开发 - 图658ageovb07-18 08:55返回给客户端json回到原文划线处在响应头的Content-Type字段里指明内容类型。回复投诉
  • 05、Web开发 - 图65905、Web开发 - 图660ageovb07-18 08:59返回不同媒体类型回到原文划线处若客户端无法解析服务端返回的内容,即媒体类型未匹配,那么响应406回复投诉
  • 05、Web开发 - 图66105、Web开发 - 图662ageovb07-18 09:15内容协商回到原文划线处https://www.cnblogs.com/yourbatman/p/11420796.html优先级为:后缀 > 请求参数 > HTTP首部Accept05、Web开发 - 图663回复投诉
  • 05、Web开发 - 图66405、Web开发 - 图665ageovb07-18 09:16开启浏览器参数方式内容协商功能回到原文划线处优缺点:回复投诉
    • 优点:不受浏览器约束
    • 缺点:需要额外的传递format参数,URL变得冗余繁琐,缺少了REST的简洁风范。还有个缺点便是:还需手动显示开启。
  • 05、Web开发 - 图66605、Web开发 - 图667ageovb07-18 09:22内容协商回到原文划线处05、Web开发 - 图668回复投诉
  • 05、Web开发 - 图66905、Web开发 - 图670ageovb07-18 18:06目标方法处理的过程中,所有数据都会被放在 ModelAndViewContainer 里面回到原文划线处05、Web开发 - 图671回复投诉
  • 05、Web开发 - 图67205、Web开发 - 图673ageovb07-18 18:17View对象回到原文划线处05、Web开发 - 图674回复投诉
  • 05、Web开发 - 图67505、Web开发 - 图676ageovb07-18 18:25new RedirectView()回到原文划线处05、Web开发 - 图677回复投诉
  • 05、Web开发 - 图67805、Web开发 - 图679ageovb07-18 18:32render回到原文划线处05、Web开发 - 图680回复投诉
  • 05、Web开发 - 图68105、Web开发 - 图682ageovb07-18 18:33response.sendRedirect(encodedURL);回到原文划线处05、Web开发 - 图683回复投诉
  • 05、Web开发 - 图68405、Web开发 - 图685ageovb07-18 18:39视图解析回到原文划线处05、Web开发 - 图686回复投诉
  • 05、Web开发 - 图68705、Web开发 - 图688ageovb07-18 22:18preHandle回到原文划线处责任链模式05、Web开发 - 图689回复投诉
  • 05、Web开发 - 图69005、Web开发 - 图691沉默的大多数07-19 17:37原理: 静态映射/**。回到原文划线处实际上就是用/后面匹配到的字符串去上面几个文件中寻找指定文件比如如果文件放在static/picture/pig.png下,则访问路径应该为项目路径+picture/pig.png回复投诉
  • 05、Web开发 - 图69205、Web开发 - 图693划过忧伤07-20 16:22@ServletComponentScan(basePackages = “com.atguigu.admin”)回到原文划线处放在主函数的上面回复投诉
  • 05、Web开发 - 图69405、Web开发 - 图695lhy07-20 18:55spring boot 真的像雷神说的那样,封装的很深..spring的脚手架名不虚传…回复投诉
  • 05、Web开发 - 图69605、Web开发 - 图697格子格子07-21 18:15静态资源目录回到原文划线处默认情况下,Spring Boot 从类路径中的/static (或/public 或/resources 或/META-INF/resources)目录或 ServletContext 的根目录提供静态内容。它使用 Spring MVC 中的 ResourceHttpRequestHandler,因此您可以通过添加自己的 webmvcconfigureer 和重写resourcehandlers方法来修改该行为。回复投诉
  • 05、Web开发 - 图69805、Web开发 - 图699格子格子07-21 18:23改变默认的静态资源路径回到原文划线处spring.web.xml. resources.static-locations 属性(用目录位置列表替换默认值)自定义静态资源位置。回复投诉
  • 05、Web开发 - 图70005、Web开发 - 图701ageovb07-21 21:18DefaultErrorAttributes回到原文划线处1、自定义错误页面属性回复投诉
  • 05、Web开发 - 图70205、Web开发 - 图703ageovb07-21 21:18BasicErrorController回到原文划线处2、自定义页面跳转逻辑回复投诉
  • 05、Web开发 - 图70405、Web开发 - 图705ageovb07-21 21:19DefaultErrorViewResolver回到原文划线处3、自定义错误页面html路径回复投诉
  • 05、Web开发 - 图70605、Web开发 - 图707胜天半子07-23 09:50回复 @Arima、、回到原评论我没重名文件,但是不能访问新包,可以访问旧包回复投诉
  • 05、Web开发 - 图70805、Web开发 - 图709ageovb07-24 10:33/回到原文划线处/Ant风格的路径配置,两个星号代表匹配任意层级的路径。
    回复投诉
  • 05、Web开发 - 图71005、Web开发 - 图711ageovb07-24 10:45资源处理的默认规则回到原文划线处会把/webjars/以及我们自定义spring.mvc.static-path-pattern**的路径都添加到资源处理器中。回复投诉
  • 05、Web开发 - 图71205、Web开发 - 图713ageovb07-24 10:50回复 @handsome coffee回到原评论还有@PatchMapping,它是对Put的补充,区别是Patch是部分更新,Put是全部更新,这些注解都是Spring4.3引入的。回复投诉
  • 05、Web开发 - 图71405、Web开发 - 图715ageovb07-24 11:22MappingJackson2HttpMessageConverter回到原文划线处相应的,MappingJackson2XmlHttpMessageConverter将对象写为xml格式。回复投诉
  • 05、Web开发 - 图71605、Web开发 - 图717ageovb07-24 18:02ServletWebServerFactory回到原文划线处05、Web开发 - 图718回复投诉
  • 05、Web开发 - 图71905、Web开发 - 图720ageovb07-24 18:05手动把启动服务器的代码调用回到原文划线处05、Web开发 - 图721回复投诉
  • 05、Web开发 - 图72205、Web开发 - 图723ageovb07-24 18:11initialize回到原文划线处05、Web开发 - 图724回复投诉
  • 05、Web开发 - 图72505、Web开发 - 图726H9pert08-02 16:24tes先来处理异常。把异常信息回到原文划线处之所以这样设计,是因为每个错误都要进行第一个默认解析器的处理?而且这样也方便,如果希望移除某一个解析器,也可以用相同的逻辑进行选择回复投诉
  • 05、Web开发 - 图72705、Web开发 - 图728沉梦昂志08-02 21:16回复 @ageovb回到原评论几年前的博客就别拿出来说了,自Spring 5.2.4以后,不推荐使用通过后缀的方式来获取MediaType,内容协商策略默认也只开启HeaderContentNegotiationStrategy回复投诉
  • 05、Web开发 - 图72905、Web开发 - 图730七十一08-04 13:02按照 doDispatch 函数一步一步的源码解析,整理了老师讲课的知识顺序:https://www.cnblogs.com/seazean/p/15095819.html。
    全套知识笔记欢迎关注个人 Github 仓库:https://github.com/Seazean/JavaNotes回复投诉
  • 05、Web开发 - 图73105、Web开发 - 图732X6RUzWK08-13 13:13回复 @Sleepyhead回到原评论测试了一下,正确写法是spring.mvc.contentnegotiation.media-types.gg=application/x-guigu
    回复投诉
  • 05、Web开发 - 图73305、Web开发 - 图734Aúpa🦊08-13 20:12HandlerMapping回到原文划线处2.5.3 是 pathLookup回复投诉
  • 05、Web开发 - 图73505、Web开发 - 图736ageovb08-14 09:19ServletModelAttributeMethodProcessor回到原文划线处05、Web开发 - 图737回复投诉
  • 05、Web开发 - 图73805、Web开发 - 图739ageovb08-14 09:35执行目标方法回到原文划线处05、Web开发 - 图740回复投诉
  • 05、Web开发 - 图74105、Web开发 - 图742ageovb08-14 13:12返回值回到原文划线处05、Web开发 - 图743回复投诉
  • 05、Web开发 - 图74405、Web开发 - 图745ageovb08-14 13:39返回值回到原文划线处05、Web开发 - 图746回复投诉
  • 05、Web开发 - 图74705、Web开发 - 图748F. Finlay Xio08-17 10:56@RequestParam回到原文划线处05、Web开发 - 图749回复投诉
  • 05、Web开发 - 图75005、Web开发 - 图751王昊08-17 16:01改变默认的静态资源路径回到原文划线处其他位置的静态资源会失效回复投诉
  • 05、Web开发 - 图75205、Web开发 - 图753王昊08-17 16:34资源处理的默认规则回到原文划线处!this.resourceProperties.isAddMappings()控制静态资源的访问是否生效回复投诉
  • 05、Web开发 - 图75405、Web开发 - 图755王昊08-17 16:36回复 @王昊回到原评论DurationcachePeriod=this.resourceProperties.getCache().getPeriod();静态资源存放的时间回复投诉
  • 05、Web开发 - 图75605、Web开发 - 图757王昊08-17 17:38如PostMan直接发送Put、delete等方式请求,无需Filter回到原文划线处当表单发送的时候需要filter,因为只有get和post回复投诉
  • 05、Web开发 - 图75805、Web开发 - 图759A KAY08-18 00:04回复 @墨明棋妙啊回到原评论05、Web开发 - 图760回复投诉
  • 05、Web开发 - 图76105、Web开发 - 图762王昊08-18 10:11WebMvcConfigurer回到原文划线处向容器中添加该类型的组件或者配置类实现该接口都可以达到定制Mvc的目的回复投诉
  • 05、Web开发 - 图76305、Web开发 - 图764张二橼08-18 10:33页面开发回到原文划线处xmlns:th=”http://www.thymeleaf.org"这声明thymeleaf的方式回复投诉
  • 05、Web开发 - 图76505、Web开发 - 图766nowhere08-18 15:28回复 @X6RUzWK回到原评论这样直接配置可以修改默认的匹配协议吗??回复投诉
  • 05、Web开发 - 图76705、Web开发 - 图768皮卡丘 停电08-18 17:21回复 @摸鱼工程师回到原评论你说的是不是有点瑕疵呀,WebMvnConfiguer里面的发方法的返回值都是void,并不是bean!,我们是通过重写里面的方法来修改mvc的配置的。回复投诉
  • 05、Web开发 - 图76905、Web开发 - 图770MrLinxi08-18 19:34回复 @topper回到原评论SpringBoot 2.5.3不是默认开启05、Web开发 - 图771回复投诉
  • 05、Web开发 - 图77205、Web开发 - 图773摸鱼工程师08-19 10:59回复 @皮卡丘 停电回到原评论奥,wc,我理解错了(好尴尬),不是通过注册bean的方式。有的入参是注册器,可以通过注册器注册相关的mvc组件,有的入参是list可以直接往list里面添加组件。应该是这样的。。回复投诉
  • 05、Web开发 - 图77405、Web开发 - 图775Value[]08-19 16:10现在: /user GET-获取用户 DELETE-删除用户 PUT-修改用户 POST-保存用户回到原文划线处Rest风格则使用http请求方式的动词来表示对资源的操作回复投诉
  • 05、Web开发 - 图77605、Web开发 - 图777wallflower08-25 16:08回复 @zzyu回到原评论有一种方法:把映射路径设为@RequestMapping(“/“),后面return要访问的欢迎页回复投诉
  • 05、Web开发 - 图77805、Web开发 - 图779wallflower08-25 20:11controller能处理/index回到原文划线处} else if (this.welcomeTemplateExists(templateAvailabilityProviders, applicationContext)) {
    logger.info(“Adding welcome page template: index”);
    this.setRootViewName(“index”);
    }源码在这里但是看不懂,有谁懂的吗回复投诉
  • 05、Web开发 - 图78005、Web开发 - 图781今天与明天08-26 11:11回复 @语雀用户-KQRP8l回到原评论看了下我们项目用的还是1.5.7的版本,好多都不一样,天啊回复投诉
  • 05、Web开发 - 图78205、Web开发 - 图783付龙州08-28 23:02回复 @Eivor回到原评论controller中配置@RequestMapping(“/“) return 返回的页面为欢迎页回复投诉
  • 05、Web开发 - 图78405、Web开发 - 图785小爽09-02 11:26SpringMVC功能的自动配置类 WebMvcAutoConfiguration,生效回到原文划线处创建xxxConfig类并实现WebMvcConfiger,就会使WebMvcAutoConfiguration配置类失效,因为在该类中有@ConditionalOnMissingBean(WebMvcConfigurationSupport.class),这个注解会触发 ,这是因为我们在自定义的xxxConfig类中实现了WebMvcConfiger,点进这个接口就可以知道它继承了WebMvcConfigurationSupport,所以springboot自动帮我们配置好的webMvcAutoConfiguration就会失效,注意只是我们在xxxConfig类中重写的default失效回复投诉
  • 05、Web开发 - 图78605、Web开发 - 图787F. Finlay Xio09-07 11:45为了方便内容协商,开启基于请求参数的内容协商功能回到原文划线处05、Web开发 - 图788回复投诉
  • 05、Web开发 - 图78905、Web开发 - 图790今天与明天09-08 11:14回复 @樊广辉回到原评论为什么我项目中全局搜不到ServletWebServerApplicationContext,是因为我版本太低吗回复投诉
  • 05、Web开发 - 图79105、Web开发 - 图792F. Finlay Xio09-08 13:04添加一个 WebMvcConfigurer回到原文划线处05、Web开发 - 图793回复投诉
  • 05、Web开发 - 图79405、Web开发 - 图795F. Finlay Xio09-08 13:04怎么配置呢?回到原文划线处05、Web开发 - 图796回复投诉
  • 05、Web开发 - 图79705、Web开发 - 图798F. Finlay Xio09-08 20:22基本语法回到原文划线处05、Web开发 - 图799回复投诉
  • 05、Web开发 - 图80005、Web开发 - 图801F. Finlay Xio09-09 16:11自动配置好了thymeleaf回到原文划线处05、Web开发 - 图802
    回复投诉

05、Web开发 - 图803
返回文档
正文
⌘ + B粗体

回复
05、Web开发 - 图804
关于语雀使用帮助数据安全服务协议English