springmvc controller

    科技2022-07-13  118

    资料参考:https://mp.weixin.qq.com/s?__biz=Mzg2NTAzMTExNg==&mid=2247483993&idx=1&sn=abdd687e0f360107be0208946a7afc1d&scene=19#wechat_redirect


    控制器Controller

    控制器复杂提供访问应用程序的行为,通常通过接口定义或注解定义两种方法实现。控制器负责解析用户的请求并将其转换为一个模型。在Spring MVC中一个控制器类可以包含多个方法在Spring MVC中,对于Controller的配置方式有很多种

    在开发中我们一般使用注解方式进行开发

    Controller接口

    @FunctionalInterface public interface Controller { /** * Process the request and return a ModelAndView object which the DispatcherServlet * will render. A {@code null} return value is not an error: it indicates that * this object completed request processing itself and that there is therefore no * ModelAndView to render. * @param request current HTTP request * @param response current HTTP response * @return a ModelAndView to render, or {@code null} if handled directly * @throws Exception in case of errors */ @Nullable ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception; }

    主要是看一下这里的注释,是处理请求并返回一个ModelAndView对象,DispatcherServlet将渲染该对象。 一个null的返回值并不是一个错误:它表示这个对象自己完成了请求处理,没有ModelAndView可以渲染。

    在AbstractController类中实现了Controller类,handleRequest实现如下

    @Override @Nullable public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { if (HttpMethod.OPTIONS.matches(request.getMethod())) { response.setHeader("Allow", getAllowHeader()); return null; } // Delegate to WebContentGenerator for checking and preparing. checkRequest(request); prepareResponse(response); // Execute handleRequestInternal in synchronized block if required. if (this.synchronizeOnSession) { HttpSession session = request.getSession(false); if (session != null) { Object mutex = WebUtils.getSessionMutex(session); synchronized (mutex) { return handleRequestInternal(request, response); } } } return handleRequestInternal(request, response); }

    过程可以大致看一下,首先是设置header的allow,允许资源可以用哪些HTTP方法进行请求,比如Allow: GET, HEAD,Allow:*,接着委托给WebContentGenerator进行检查和准备,然后如果需要,在同步块中执行handleRequestInternal,否则直接执行handleRequestInternal方法。

    handleRequestInternal方法的实现

    /** * Retrieves the URL path to use for lookup and delegates to * {@link #getViewNameForRequest}. Also adds the content of * {@link RequestContextUtils#getInputFlashMap} to the model. */ @Override protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) { String viewName = getViewNameForRequest(request); if (logger.isTraceEnabled()) { logger.trace("Returning view name '" + viewName + "'"); } return new ModelAndView(viewName, RequestContextUtils.getInputFlashMap(request)); }

    getViewNameForRequest获取视图的名字,再进行logger.trace,最后创建ModelAndView对象返回。

    但是在真正用的时候我们是只重写handleRequest,封装Model,返回ModelAndView就行了。

    public class HelloController implements Controller { public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { //ModelAndView 模型和视图 ModelAndView mv = new ModelAndView(); //封装对象,放在ModelAndView中。Model mv.addObject("msg","HelloSpringMVC!"); //封装要跳转的视图,放在ModelAndView中 mv.setViewName("hello"); //: /WEB-INF/jsp/hello.jsp return mv; } }

    说明:

    实现接口Controller定义控制器是较老的办法缺点:一个控制器中只有一个方法,如果要多个方法则需要定义多个Controller;定义的方式比较麻烦;(网站开发随便就是几十个接口,创建几十个类是不能接受的)

    Controller注解

    @Controller注解类型用于声明Spring类的实例是一个控制器(被spring接管,注解@Contronller的类下面的所有的String方法,返回值都会被视图解析器解析,如果可以跳转就跳转),Spring可以使用扫描机制来找到应用程序中所有基于注解的控制器类,为了保证Spring能找到你的控制器,需要在配置文件中声明组件扫描。<context:component-scan base-package="com.kuang.controller"/>

    Controller注解的定义,很简单里面用的就就一个value

    @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Controller { @AliasFor( annotation = Component.class ) String value() default ""; }

    注解本质就只是一个接口,程序处理的难点是在反射,而框架把这些处理内容隐藏起来了,除非阅读源码很难接触到。

    Processed: 0.011, SQL: 8