美文网首页
基于spring boot的后端如何实现 SPA(single

基于spring boot的后端如何实现 SPA(single

作者: 天地一蜉蝣_6e86 | 来源:发表于2019-06-21 16:16 被阅读0次

        随着UI 技术的发展,react 等技术的流行,越来越多的SPA(single page application),也就是单页面应用。js 的变化引起html dom 的变化,从而展现出各种变化,也就是页面的操作只是引起了dom 的变化,从头到尾就只有一个html。但是UI 中有各种 router 对应各种功能或者 “页面”。这就会导致浏览器中URL 会随着操作发生变化,这些URL很有可能后端服务器没有相应的API,如果在浏览器刷新就会出现错误,这是UI 开发就要求如果URL 不存在,就返回index 页面或者固定页面。

spring 版本:spring boot 2

默认处理方式

spring boot 在web 请求发生异常的时候会自动把请求转到 /error,spring boot 内置了一个BasicErrorController 对异常进行统一的处理

BasicErrorController源码

@Controller

@RequestMapping("${server.error.path:${error.path:/error}}")

public class BasicErrorController extends AbstractErrorController {

   private final ErrorProperties errorProperties;

   public BasicErrorController(ErrorAttributes errorAttributes,

         ErrorProperties errorProperties) {

      this(errorAttributes, errorProperties, Collections.emptyList());

   }

   public BasicErrorController(ErrorAttributes errorAttributes,

         ErrorProperties errorProperties, List<ErrorViewResolver> errorViewResolvers) {

      super(errorAttributes, errorViewResolvers);

      Assert.notNull(errorProperties, "ErrorProperties must not be null");

      this.errorProperties = errorProperties;

   }

   @Override

   public String getErrorPath() {

      return this.errorProperties.getPath();

   }

   @RequestMapping(produces = MediaType.TEXT_HTML_VALUE)

   public ModelAndView errorHtml(HttpServletRequest request,

         HttpServletResponse response) {

      HttpStatus status = getStatus(request);

      Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes(

            request, isIncludeStackTrace(request, MediaType.TEXT_HTML)));

      response.setStatus(status.value());

      ModelAndView modelAndView = resolveErrorView(request, response, status, model);

      return (modelAndView != null) ? modelAndView : new ModelAndView("error", model);

   }

   @RequestMapping

   public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {

      Map<String, Object> body = getErrorAttributes(request,

            isIncludeStackTrace(request, MediaType.ALL));

      HttpStatus status = getStatus(request);

      return new ResponseEntity<>(body, status);

   }

   protected boolean isIncludeStackTrace(HttpServletRequest request,

         MediaType produces) {

      IncludeStacktrace include = getErrorProperties().getIncludeStacktrace();

      if (include == IncludeStacktrace.ALWAYS) {

         return true;

      }

      if (include == IncludeStacktrace.ON_TRACE_PARAM) {

         return getTraceParameter(request);

      }

      return false;

   }

   protected ErrorProperties getErrorProperties() {

      return this.errorProperties;

   }

}

从代码可以看出spring boot 对于json 和html 格式的请求做了不同的处理。html 格式的请求可以返回自定义的view,在resolveErrorView中会寻找不同的模板。

DefaultErrorViewResolver 源码

@Override

    public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status,

            Map<String, Object> model) {

        ModelAndView modelAndView = resolve(String.valueOf(status), model);

        if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {

            modelAndView = resolve(SERIES_VIEWS.get(status.series()), model);

        }

        return modelAndView;

    }

    private ModelAndView resolve(String viewName, Map<String, Object> model) {

        //默认SpringBoot可以去找到一个页面?  error/404

        String errorViewName = "error/" + viewName;

        //模板引擎可以解析这个页面地址就用模板引擎解析

        TemplateAvailabilityProvider provider = this.templateAvailabilityProviders

                .getProvider(errorViewName, this.applicationContext);

        if (provider != null) {

            //模板引擎可用的情况下返回到errorViewName指定的视图地址

            return new ModelAndView(errorViewName, model);

        }

        //模板引擎不可用,就在静态资源文件夹下找errorViewName对应的页面   error/404.html

        return resolveResource(errorViewName, model);

    }

会寻找error 目录下的模板,如果不存在显示默认的view。

解决方案

覆盖默认方式,继承BasicErrorController,在errorhtml  中如果是404,就返回到index

not found 源码

/**

 * @description: ㄟ(▔, ▔)ㄏ

 * @author: pangtoutuo

 * @create: 2019-02-26

 **/

@Controller

public class PageNotFoundController extends BasicErrorController {

    @Value("${spring.web.indexview.path}")

    private String indexViewPath;

    @Autowired

    private IndexView indexView;

    public PageNotFoundController

        (ErrorAttributes errorAttributes, ServerProperties serverProperties) {

        super(errorAttributes, serverProperties.getError());

    }

    @Override

    public ModelAndView errorHtml(

        final HttpServletRequest request, final HttpServletResponse response

    ) {

        HttpStatus status = getStatus(request);

        if (HttpStatus.NOT_FOUND.equals(status)) {

            return new ModelAndView(indexViewPath, indexView.getIndexModel());

        }

        return super.errorHtml(request, response);

    }

}

这样一来json 格式错误按照默认方式返回错误。后端服务之间如果404 还是会异常,不影响后端业务。

相关文章

网友评论

      本文标题:基于spring boot的后端如何实现 SPA(single

      本文链接:https://www.haomeiwen.com/subject/uexuqctx.html