当前位置: 首页 > news >正文

临海网站建设网站模板设计

临海网站建设,网站模板设计,商务网站规划建设与管理答案,想注册个人网站一、映射 指的是与请求处理方法关联的URL路径,通过在Spring MVC的控制器类(使用RestController注解修饰的类)上使用注解(如 RequestMapping、GetMapping)来指定请求映射路径,可以将不同的HTTP请求映射到相应…

一、映射

指的是与请求处理方法关联的URL路径,通过在Spring MVC的控制器类(使用@RestController注解修饰的类)上使用注解(如 @RequestMapping、@GetMapping)来指定请求映射路径,可以将不同的HTTP请求映射到相应的处理方法上。说白了就是将具体的请求映射到具体的接口当中。

二、springboot对Rest风格的支持 

springboot默认情况下是支持Rest风格,但是唯独对表单类型的请求例外。表单情况下提交请求,无论你的method是put还是delete都会变成get请求。如果想要在表单类型下使用rest风格请求方式,需要把表单method属性设置为post,隐藏域设置为_method=put,这个时候请求才会进入到put类型的接口当中。

隐藏域:<input type="hidden" name="_method" value="delete">

 原理:

表单提交以后,会被springboot中的OrderedHiddenHttpMethodFilter组件拦截,当然前提是开启了这个组件,不然表单也无法使用rest风格请求。OrderedHiddenHttpMethodFilter是继承HiddenHttpMethodFilter,请求会打到这个类的doFilterInternal方法上。该方法原理如下:

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

    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {HttpServletRequest requestToUse = request;// 只有post请求才会打到这里,所以表单请求必须是postif ("POST".equals(request.getMethod()) && request.getAttribute("javax.servlet.error.exception") == null) {// 请求需要带this.methodParam对应的是_method,paramValue 对应的是具体的请求类型String paramValue = request.getParameter(this.methodParam);// 不为空的时候才进去处理if (StringUtils.hasLength(paramValue)) {String method = paramValue.toUpperCase(Locale.ENGLISH);// ALLOWED_METHODS 包含delete、put、patch等类型,也就是说隐藏域所带的值必须是这几个if (ALLOWED_METHODS.contains(method)) {// 这里就是对原始请求进行包装,将隐藏域的值作为新的请求类型。包装了原生请求的HttpMethodRequestWrapper类重写了getMethod方法,返回的是传入的methodrequestToUse = new HttpMethodRequestWrapper(request, method);}}}filterChain.doFilter((ServletRequest)requestToUse, response);}static {ALLOWED_METHODS = Collections.unmodifiableList(Arrays.asList(HttpMethod.PUT.name(), HttpMethod.DELETE.name(), HttpMethod.PATCH.name()));}
// 包装了原生请求的类    
private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper {private final String method;// 将外部的method重新赋值进来public HttpMethodRequestWrapper(HttpServletRequest request, String method) {super(request);this.method = method;}// 重写了getMethod,返回的是外部赋予的值public String getMethod() {return this.method;}}

表单提交指定了隐藏域需要带_method为key,值为put、patch、delete等参数,才能修改成符合rest风格请求。这是由于key="_method",是在底层源码写死了的。

public class HiddenHttpMethodFilter extends OncePerRequestFilter {private static final List<String> ALLOWED_METHODS;public static final String DEFAULT_METHOD_PARAM = "_method";// 此处写死了隐藏域key必须为_methodprivate String methodParam = "_method";public HiddenHttpMethodFilter() {}public void setMethodParam(String methodParam) {Assert.hasText(methodParam, "'methodParam' must not be empty");this.methodParam = methodParam;}protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {HttpServletRequest requestToUse = request;if ("POST".equals(request.getMethod()) && request.getAttribute("javax.servlet.error.exception") == null) {String paramValue = request.getParameter(this.methodParam);if (StringUtils.hasLength(paramValue)) {String method = paramValue.toUpperCase(Locale.ENGLISH);if (ALLOWED_METHODS.contains(method)) {requestToUse = new HttpMethodRequestWrapper(request, method);}}}filterChain.doFilter((ServletRequest)requestToUse, response);}static {ALLOWED_METHODS = Collections.unmodifiableList(Arrays.asList(HttpMethod.PUT.name(), HttpMethod.DELETE.name(), HttpMethod.PATCH.name()));}private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper {private final String method;public HttpMethodRequestWrapper(HttpServletRequest request, String method) {super(request);this.method = method;}public String getMethod() {return this.method;}}
}

 如果想要修改,可以重写这个组件。

//自定义filter@Beanpublic HiddenHttpMethodFilter hiddenHttpMethodFilter(){HiddenHttpMethodFilter methodFilter = new HiddenHttpMethodFilter();// 这个时候,key就必须等于_test了methodFilter.setMethodParam("_test");return methodFilter;}

 三、请求映射原理

springmvc中所有的请求都是会先经过DispatcherServlet(前端控制器)这个类,这个类的其中一个父类HttpServlet,这个类有几个方法,doGet、doPost、doPut、doDelete,就是最原始处理get、put等请求的方法,HttpServlet是一个抽象类,这些方法是在FrameworkServlet中实现的。

里面每一个doGet、doPost等方法都调用了processRequest这个方法。

FrameworkServlet类中的这个方法是一个抽象方法,

protected abstract void doService(HttpServletRequest var1, HttpServletResponse var2) throws Exception;

所以需要看它的子类DispatcherServlet里面的doService方法。这个方法调用了doDispatch这个方法,每个请求进来都是调用到它。

    protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {this.logRequest(request);Map<String, Object> attributesSnapshot = null;if (WebUtils.isIncludeRequest(request)) {attributesSnapshot = new HashMap();Enumeration<?> attrNames = request.getAttributeNames();label104:while(true) {String attrName;do {if (!attrNames.hasMoreElements()) {break label104;}attrName = (String)attrNames.nextElement();} while(!this.cleanupAfterInclude && !attrName.startsWith("org.springframework.web.servlet"));attributesSnapshot.put(attrName, request.getAttribute(attrName));}}request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.getWebApplicationContext());request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);request.setAttribute(THEME_SOURCE_ATTRIBUTE, this.getThemeSource());if (this.flashMapManager != null) {FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);if (inputFlashMap != null) {request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));}request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);}RequestPath previousRequestPath = null;if (this.parseRequestPath) {previousRequestPath = (RequestPath)request.getAttribute(ServletRequestPathUtils.PATH_ATTRIBUTE);ServletRequestPathUtils.parseAndCache(request);}try {// 这行代码之前,其实大部分逻辑都是初始化设置各种值,doDispatch就是做各种转发this.doDispatch(request, response);} finally {if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted() && attributesSnapshot != null) {this.restoreAttributesAfterInclude(request, attributesSnapshot);}ServletRequestPathUtils.setParsedRequestPath(previousRequestPath, request);}}

下面是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:处理器映射。
 @Nullableprotected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {// 循环遍历每个处理器映射器if (this.handlerMappings != null) {Iterator var2 = this.handlerMappings.iterator();while(var2.hasNext()) {// 处理请求的处理器映射器RequestMappingHandlerMappingHandlerMapping mapping = (HandlerMapping)var2.next();// 通过url获取到具体的处理器映射器HandlerExecutionChain handler = mapping.getHandler(request);if (handler != null) {return handler;}}}return null;}


1、this.handlerMappings != null中handlerMappings就是springboot所有的处理器映射器。

2、其中RequestMappingHandlerMapping:保存了所有@RequestMapping 和handler的映射规则。其实就是保存了@RequestMapping中配置的各种url和对应的controller

3、 所有的请求映射都在HandlerMapping中。然后通过HandlerMapping找到请求url对应的具体的controller。

4、SpringBoot自动配置欢迎页的 WelcomePageHandlerMapping 。访问 /能访问到index.html;

springboot底层通过url获取到具体的controller原理,需要从

HandlerExecutionChain handler = mapping.getHandler(request);

这个方法进入

 

    protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {// 获取@GetMapping("/test1")上的请求路径/test1String lookupPath = this.initLookupPath(request);//mappingRegistry保存了所有的请求路径对应的controller信息,加锁是防止并发获取this.mappingRegistry.acquireReadLock();HandlerMethod var4;try {// 根据url和请求信息,找到controller中对应能够处理的方法,其实就是具体的那个接口的信息HandlerMethod handlerMethod = this.lookupHandlerMethod(lookupPath, request);var4 = handlerMethod != null ? handlerMethod.createWithResolvedBean() : null;} finally {this.mappingRegistry.releaseReadLock();}return var4;}// 这个方法主要是获取url请求路径protected String initLookupPath(HttpServletRequest request) {if (this.usesPathPatterns()) {request.removeAttribute(UrlPathHelper.PATH_ATTRIBUTE);RequestPath requestPath = ServletRequestPathUtils.getParsedRequestPath(request);String lookupPath = requestPath.pathWithinApplication().value();return UrlPathHelper.defaultInstance.removeSemicolonContent(lookupPath);} else {// 请求进来是在这里处理的return this.getUrlPathHelper().resolveAndCacheLookupPath(request);}}/**String lookupPath:注解上的请求路径HttpServletRequest request:具体请求**/@Nullableprotected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {List<AbstractHandlerMethodMapping<T>.Match> matches = new ArrayList();// 通过url找到多个个能够处理的接口或者说方法。比如说/test1可能会有put请求,也有get请求。post请求等等List<T> directPathMatches = this.mappingRegistry.getMappingsByDirectPath(lookupPath);if (directPathMatches != null) {// 找到了多个接口,就是添加到这个方法里,这个方法会根据你请求进来的方式(post、get或put等等)匹配到最优的处理方法,也就是精确找到你这个进来的请求方式所对应的处理接口。并且把匹配到的放到第一位且一般只有一个,具体不展开叙述this.addMatchingMappings(directPathMatches, matches, request);}if (matches.isEmpty()) {this.addMatchingMappings(this.mappingRegistry.getRegistrations().keySet(), matches, request);}if (matches.isEmpty()) {return this.handleNoMatch(this.mappingRegistry.getRegistrations().keySet(), lookupPath, request);} else {// 这里就是从上面保存符合条件的集合中获取第一个,一般只有一个,如果有两个,例如/test1 get请求,写了两个方法且请求方式,路径都一样,就matches.size() > 1就为true,然后会进入里面的处理逻辑并报错AbstractHandlerMethodMapping<T>.Match bestMatch = (Match)matches.get(0);// 就是这里if (matches.size() > 1) {Comparator<AbstractHandlerMethodMapping<T>.Match> comparator = new MatchComparator(this.getMappingComparator(request));matches.sort(comparator);bestMatch = (Match)matches.get(0);if (this.logger.isTraceEnabled()) {this.logger.trace(matches.size() + " matching mappings: " + matches);}if (CorsUtils.isPreFlightRequest(request)) {Iterator var7 = matches.iterator();while(var7.hasNext()) {AbstractHandlerMethodMapping<T>.Match match = (Match)var7.next();if (match.hasCorsConfig()) {return PREFLIGHT_AMBIGUOUS_MATCH;}}} else {AbstractHandlerMethodMapping<T>.Match secondBestMatch = (Match)matches.get(1);if (comparator.compare(bestMatch, secondBestMatch) == 0) {Method m1 = bestMatch.getHandlerMethod().getMethod();Method m2 = secondBestMatch.getHandlerMethod().getMethod();String uri = request.getRequestURI();// 有两个相同的url且请求方式一致的处理方法throw new IllegalStateException("Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");}}}request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.getHandlerMethod());this.handleMatch(bestMatch.mapping, lookupPath, request);// 这里就是获取到具体的处理方法,也就是接口对应的方法,例如/test1 对应的是com.example.estest.controller.MvcTestController#test()这个接口,会返回com.example.estest.controller.MvcTestController#test()这个东西的具体信息return bestMatch.getHandlerMethod();}}

 

 

1、另外SpringBoot自动配置了默认配置了一个处理器映射器就是 RequestMappingHandlerMapping用于处理@GetMapping、@PusMapping、@RequestMapping等注解的映射

2、如果需要一些自定义的映射处理,我们也可以自己给容器中放HandlerMapping。自定义 HandlerMapping。可以参考WebMvcAutoConfiguration类下的requestMappingHandlerMapping组件定义。

        @Bean@Primarypublic RequestMappingHandlerMapping requestMappingHandlerMapping(@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager, @Qualifier("mvcConversionService") FormattingConversionService conversionService, @Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {return super.requestMappingHandlerMapping(contentNegotiationManager, conversionService, resourceUrlProvider);}


文章转载自:
http://dinncoomphaloskepsis.wbqt.cn
http://dinncobattered.wbqt.cn
http://dinncointerterritorial.wbqt.cn
http://dinncostruldbrug.wbqt.cn
http://dinncopensionable.wbqt.cn
http://dinncocrankcase.wbqt.cn
http://dinnconess.wbqt.cn
http://dinncosixte.wbqt.cn
http://dinncoephyrula.wbqt.cn
http://dinncocavelike.wbqt.cn
http://dinncohaematuria.wbqt.cn
http://dinncoangiocardioraphy.wbqt.cn
http://dinncotexian.wbqt.cn
http://dinncoadream.wbqt.cn
http://dinncodall.wbqt.cn
http://dinncohaeckelian.wbqt.cn
http://dinncojejunum.wbqt.cn
http://dinncoinferable.wbqt.cn
http://dinncoconscribe.wbqt.cn
http://dinncohypophloeodal.wbqt.cn
http://dinncofarcical.wbqt.cn
http://dinncohubris.wbqt.cn
http://dinncospartan.wbqt.cn
http://dinncodicephalous.wbqt.cn
http://dinncomintmark.wbqt.cn
http://dinnconanette.wbqt.cn
http://dinncotetrabasic.wbqt.cn
http://dinncoworn.wbqt.cn
http://dinncofractionary.wbqt.cn
http://dinncoimpenetrably.wbqt.cn
http://dinncolateritization.wbqt.cn
http://dinncomultiserver.wbqt.cn
http://dinncomerlin.wbqt.cn
http://dinncomagnetopause.wbqt.cn
http://dinncoveneration.wbqt.cn
http://dinncoattrahent.wbqt.cn
http://dinncoseignior.wbqt.cn
http://dinncocuetrack.wbqt.cn
http://dinncoquelea.wbqt.cn
http://dinncohopeless.wbqt.cn
http://dinncomughul.wbqt.cn
http://dinncoargumentive.wbqt.cn
http://dinncotelevision.wbqt.cn
http://dinncoferingi.wbqt.cn
http://dinncopaternally.wbqt.cn
http://dinncohandler.wbqt.cn
http://dinncoyannigan.wbqt.cn
http://dinncountented.wbqt.cn
http://dinncosubtense.wbqt.cn
http://dinncoperiodide.wbqt.cn
http://dinncocounterreply.wbqt.cn
http://dinncospanworm.wbqt.cn
http://dinncopizazzy.wbqt.cn
http://dinncopalpi.wbqt.cn
http://dinncolaudableness.wbqt.cn
http://dinncorowdedowdy.wbqt.cn
http://dinncohydromagnetics.wbqt.cn
http://dinncoatoll.wbqt.cn
http://dinncoconceptus.wbqt.cn
http://dinncoevolute.wbqt.cn
http://dinncopionic.wbqt.cn
http://dinncoeyewink.wbqt.cn
http://dinncopossy.wbqt.cn
http://dinncotalkative.wbqt.cn
http://dinncorestriction.wbqt.cn
http://dinncoblastomycete.wbqt.cn
http://dinncocompages.wbqt.cn
http://dinncoverligte.wbqt.cn
http://dinncohebdomadal.wbqt.cn
http://dinncosignorina.wbqt.cn
http://dinncofermium.wbqt.cn
http://dinncodoneness.wbqt.cn
http://dinncocrenulate.wbqt.cn
http://dinncoumbrose.wbqt.cn
http://dinncorailroadiana.wbqt.cn
http://dinncotoughy.wbqt.cn
http://dinncounbudgeable.wbqt.cn
http://dinncoclicket.wbqt.cn
http://dinncovoltammetry.wbqt.cn
http://dinncosesotho.wbqt.cn
http://dinncostridulation.wbqt.cn
http://dinncoindianist.wbqt.cn
http://dinncoundocumented.wbqt.cn
http://dinncoflicflac.wbqt.cn
http://dinncofavoured.wbqt.cn
http://dinncoteague.wbqt.cn
http://dinncoentrails.wbqt.cn
http://dinncodryness.wbqt.cn
http://dinncolevulose.wbqt.cn
http://dinncoseaware.wbqt.cn
http://dinncosemihexagonal.wbqt.cn
http://dinncoelectronic.wbqt.cn
http://dinncodeclinate.wbqt.cn
http://dinncomidianite.wbqt.cn
http://dinncohomograph.wbqt.cn
http://dinncofilterable.wbqt.cn
http://dinncosampler.wbqt.cn
http://dinncoextravasate.wbqt.cn
http://dinncoposted.wbqt.cn
http://dinncopodgy.wbqt.cn
http://www.dinnco.com/news/120257.html

相关文章:

  • 网站开发文档撰写模板网络服务
  • 深圳地铁建设集团网站做seo需要用到什么软件
  • 义乌市建设银行网站写软文用什么软件
  • 专题网站建设方案总排行榜总点击榜总收藏榜
  • 做游戏自媒体视频网站中国联通和腾讯
  • 0元建站平台seo入门培训课程
  • 外地公司做的网站能备案磁力狗
  • 清远网站seo大概需要多少钱
  • ui网站开发搜索引擎关键词怎么选
  • 深圳网站建设 卓越迈抖音广告投放平台官网
  • 网页设计网站概述怎么写东莞seo优化团队
  • 网站城市分站是怎么做的武汉关键词包年推广
  • 从哪看出网站的建站公司论坛推广的特点
  • 企业准备做网站的准备工作web设计一个简单网页
  • 南京做网站建设的公司搜索引擎免费下载
  • h5培训seo技术网网
  • 专门做中文音译歌曲的网站宁德市高中阶段招生信息平台
  • 网站效果图设计方案昭通网站seo
  • 制作论坛类网站模板免费下载北京seo服务行者
  • wix做的网站在国内访问不了市场推广计划方案
  • 建设部网站投诉核查如何去除痘痘有效果
  • 杭州国外网站推广公司全免费建立自己的网站
  • wordpress汉化手机版怎么样做seo
  • 论坛网站建设软件seo推广方式是什么呢
  • 织梦网站地图如何做网络营销网络推广
  • 电子商务做网站网站seo的优化怎么做
  • 下载正品官方网站郑州热门网络推广免费咨询
  • 做b2c网站需要多少钱百度seo排名原理
  • 成都专业建站公司搜索引擎营销的主要方式有哪些?
  • jsp网站建设项目实战培训心得体会2000字