Spring-MVC是Spring提供的用于简化web开发的框架

一 、三层架构及MVC设计模式

三层架构 

我们开发架构通常为两种,及C/S(客户端/服务器)和B/S(浏览器服务器),JAVAEE开发中,主要采用B/S架构,在B/S架构中,系统的标准三层架构为 表现层,业务层,持久层,每一层各司其职

 

                                                               

java spring三层_MVC

表现层:我们常说的web层,负责接收客户端请求,向客户端响应结果。表现层包括展示层(负责结果展示)和控制层(负责接收请求)。表现层依赖业务层,接受到的客户端请求一般需要调用业务层进行处理,并将处理结果响应给客户端。表现层的设计一般使用MVC模型(MVC是表现层设计模型,和其它层不相关)

业务层:我们常说的service层,负责业务逻辑的处理,web层依赖业务层,业务层不依赖web层。业务层的业务处理可能会依赖持久层,对数据持久化需要保证事务的一致性(事务控制应该放在业务层)

持久层:我们常说的dao层,负责数据持久化,包括数据层及数据库(对数据进行持久化的载体)和数据访问层(业务层和持久层交互的载体),业务层通过数据访问层持久化数据到数据库。持久层用于数据库交互,进行增删改查操作

MVC设计模式

MVC全名Module View Controller ,及模型(Module)—— 视图(View)—— 控制器(Controller)模式,一种用于设计创建Web应用程序表现层的模式。

MVC提倡每一层只编写自己相关的代码,不负责任何其它代码,分层能便于解耦,利于后期代码维护及分工

M:Module 包含业务模型和数据模型,业务模型用于处理业务,数据模型用于封装数据

V:View 通常指的是jsp或html,用来展示数据,通常依据模型数据创建

C:Controller 是应用程序与用户交互的部分,一般就是处理程序逻辑的

二、Spring MVC

Spring MVC 的全称 Spring Web MVC ,是SpringFrameWork 的后续产品,本质是对servlet的封装,简化了servlet的开发。通过一套注解,让一个简单的java类成为处理请求的控制器,不需要实现接口,同时支持RESTful风格的请求。是为了解决表现层问题的web框架,基于MVC设计模式,主要功能是处理前端HTTP请求。

作用:1.接收请求  2.返回响应,跳转页面

Spring MVC 工作流程

java spring三层_表现层_02


第⼀步:⽤户发送请求⾄前端控制器 DispatcherServlet


第⼆步: DispatcherServlet 收到请求调⽤ HandlerMapping 处理器映射器


第三步:处理器映射器根据请求 Url 找到具体的 Handler (后端控制器),⽣成处理器对象及处理器拦截器( 如果有则⽣成 ) ⼀并返回 DispatcherServlet


第四步: DispatcherServlet 调⽤ HandlerAdapter 处理器适配器去调⽤ Handler


第五步:处理器适配器执⾏ Handler


第六步: Handler 执⾏完成给处理器适配器返回 ModelAndView


第七步:处理器适配器向前端控制器返回 ModelAndView , ModelAndView 是 SpringMVC 框架的⼀个底层对象,包括 Model 和 View


第⼋步:前端控制器请求视图解析器去进⾏视图解析,根据逻辑视图名来解析真正的视图。


第九步:视图解析器向前端控制器返回 View


第⼗步:前端控制器进⾏视图渲染,就是将模型数据(在 ModelAndView 对象中)填充到 request 域


第⼗⼀步:前端控制器向⽤户响应结果


Spring MVC九大组件

1.HandlerMapping  处理器映射器(核心组件之一)

用于查找Handler处理器,处理器可以是方法(常用),也可以是类(实现Controller接口),标注@RequestMapping的方法都可以视为Handler。Handler负责处理具体请求,请求到达后,HandlerMapping就找到请求相应的Handler和Interceptor拦截器。

2.HandlerAdapter  处理器适配器 (核心组件之一)

Spring MVC的Handler可以是任意形式的(可以是方法,类,接收参数也是多变的),

但当请求交给Servlet时,因为Servlet的方法结构都是doService(HttpServletRequest req,HttpServletResponse resp)形式的,需要HandlerAdapter来让固定的Servlet处理方法调用Handler来进行处理

3.HandlerExceptionResolver

HandlerExceptionResolver用于处理Handler产生的异常情况,根据异常设置ModuleAndView,然后交给渲染方法进行渲染

4.ViewResolver  视图解析器(核心组件之一)

用于将Controller层返回的String类型视图名解析成View视图,View是用来渲染页面的,也就是说,它会将程序返回的参数和数据填入模板中,生成html文件。

ViewResolver主要完成两件事:找到渲染用的模板(第一件事)和所用的技术(第二件事,也就是找到视图的类型,如JSP)并填入参数

SpringMVC会默认配置一个InternalResourceViewResolver,是针对JSP的

5.RequestToViewNameTranslator

用于从请求中获取ViewName,当Handler没有处理完成后,没有设置View,也没有设置ViewName的时候,通过RequestToViewNameTranslator组件从请求中获取ViewName

6.LocaleResolver

用于从请求中解析出Locale,用来表示一个区域,这个组件也是 i18n (国际化,指让产品(出版物,软件,硬件等)无需做大的改变就能够适应不同的语言和地区的需要)的基础

7.ThemeResolver

用于解析主题,SpringMVC中,每一套主题对应一个properties文件,创建主题只需要将对应资源设置进去,放在classpath下,之后就可以直接在页面中使用

SpringMVC中与主题相关的类有 ThemeResolver、ThemeSource和Theme。

ThemeResolver负责从请求中解析出主题名, ThemeSource根据主题名找到具体的主题,其抽象也就是Theme,可以通过Theme来获取主题和 具体的资源。

8.MultipartResolver

用于文件上传请求,将请求包装成 MultipartHttpServletRequest 来实现,

MultipartResolver 的作⽤就是封装普通的请求,使其拥有⽂件上传的功能。

9.FlashMapManager

用于重定向时的参数传递,如处理订单时,为了避免重复提交,可以将处理结束的post请求之后重定向到get请求,获取处理后订单信息,此时需要重新传递参数信息,如果不使用拼接URL的方式(不推荐使用,拼接参数安全性,参数长度cun'zai'xian'z),可以使用flashMap进行传递,

只需要在重定向之前将要传递的数据写⼊请求(可以通过ServletRequestAttributes.getRequest()⽅法获得)的属性OUTPUT_FLASH_MAP_ATTRIBUTE 中,这样在重定向之后的Handler中Spring就会自动将其设置到Model中,在显示订单信息的页面上就可以直接从Model中获取数据。FlashMapManager 就是用来管理 FalshMap 的。

/**
     * SpringMVC 重定向时参数传递的问题
     * 转发:A 找 B 借钱400,B没有钱但是悄悄的找到C借了400块钱给A
     *      url不会变,参数也不会丢失,一个请求
     * 重定向:A 找 B 借钱400,B 说我没有钱,你找别人借去,那么A 又带着400块的借钱需求找到C
     *      url会变,参数会丢失需要重新携带参数,两个请求
     */

    @RequestMapping("/handleRedirect")
    public String handleRedirect(String name,RedirectAttributes redirectAttributes) {

        //return "redirect:handle01?name=" + name;  // 拼接参数安全性、参数长度都有局限
        // addFlashAttribute方法设置了一个flash类型属性,该属性会被暂存到session中,在跳转到页面之后该属性销毁
        redirectAttributes.addFlashAttribute("name",name);
        return "redirect:handle01";

    }

请求参数绑定

SpringMVC是对servlet的封装,接收参数时,既可以像servler一样使用原生对象,如 HttpServletRequest、HttpServletResponse、HttpSession,直接声明使用即可。

绑定简单参数时,同样直接声明使用(形参的参数名要和传递的参数名保持一致,建议使用包装类型,当形参参数名和传递的不一致时,使用@RequestParam注解进行手动映射)

绑定pojo类型参数时,直接形参声明,类型就是pojo的类型,此时形参名无要求,但要求传递的参数名必须和pojo的属性名保持一致

绑定pojo包装对象参数,直接声明pojo,需要注意,当不能够定位数据项,使用属性名+ "." 的方法进一步锁定,如/demo/handle05?user.id=1&user.username=zhangsan

绑定日期类型参数,因为传递是String,日期格式存在多种,无法直接转换,

需要自定义类型转换器(通过创建类实现Converter<String, Date>接口,并在springmvc的xml中注册)

类型转换器注册:

<!--
        自动注册最合适的处理器映射器,处理器适配器(调用handler方法)
    -->
    <mvc:annotation-driven conversion-service="conversionServiceBean"/>


    <!--注册自定义类型转换器-->
    <bean id="conversionServiceBean" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="com.lagou.edu.converter.DateConverter"></bean>
            </set>
        </property>
    </bean>