Spring学习 基础(三)MVC

5、Spring MVC

传统Web模式:

  1. Model:系统涉及的数据,也就是 dao 和 bean。
  2. View:展示模型中的数据,只是用来展示。
  3. Controller:处理用户请求都发送给 ,返回数据给 JSP 并展示给用户。

随着 Spring 轻量级开发框架的流行,Spring 生态圈出现了 Spring MVC 框架, Spring MVC 是当前最优秀的 MVC 框架。相比于 Struts2 , Spring MVC 使用更加简单和方便,开发效率更高,并且 Spring MVC 运行速度更快。

Spring MVC 下我们一般把后端项目分为 Service 层(处理业务)、Dao 层(数据库操作)、Entity 层(实体类)、Controller 层(控制层,返回数据给前台页面)。

组件:
  • DispatcherServlet核心的中央处理器,负责接收请求、分发,并给予客户端响应。
  • HandlerMapping处理器映射器,根据 uri 去匹配查找能处理的 Handler ,并会将请求涉及到的拦截器和 Handler 一起封装。
  • HandlerAdapter处理器适配器,根据 HandlerMapping 找到的 Handler ,适配执行对应的 Handler;
  • Handler请求处理器,处理实际请求的处理器。
  • ViewResolver视图解析器,根据 Handler 返回的逻辑视图 / 视图,解析并渲染真正的视图,并传递给 DispatcherServlet 响应客户端
流程:
  1. 客户端(浏览器)发送请求, DispatcherServlet拦截请求。
  2. DispatcherServlet 根据请求信息调用 HandlerMapping 。HandlerMapping 根据 uri 去匹配查找能处理的 Handler(也就是我们平常说的 Controller 控制器) ,并会将请求涉及到的拦截器和 Handler 一起封装。
  3. DispatcherServlet 调用 HandlerAdapter适配执行 Handler 。
  4. Handler 完成对用户请求的处理后,会返回一个 ModelAndView 对象给DispatcherServlet,ModelAndView 顾名思义,包含了数据模型以及相应的视图的信息。Model 是返回的数据对象,View 是个逻辑上的 View。
  5. ViewResolver 会根据逻辑 View 查找实际的 View。
  6. DispaterServlet 把返回的 Model 传给 View(视图渲染)。
  7. 把 View 返回给请求者(浏览器)
层次结构
  1. Model 层(Model)
  • 数据访问对象(Data Access Object, DAO):与数据库的交互,负责提供数据操作的方法。
  • 服务层(Service Layer):封装业务逻辑,进行事务管理。
  • 数据传输对象(Data Transfer Object, DTO):在各层之间传输数据。
  1. 视图层(View)
  • 视图技术:如 JSP、FreeMarker、Thymeleaf 等,用来渲染界面。
  • 静态资源:如 HTML、CSS、JavaScript 文件。
  1. 控制层(Controller)
  • DispatcherServlet: 作为前端控制器,所有的请求都会先经过它。它负责将请求路由到相应的处理器,并处理其他如多视图解析、国际化、主题解析等。
  • 控制器(Controllers):处理用户请求,将请求映射到对应的处理逻辑,并返回响应或视图名给前端。
  • 表单对象(Form Object)/命令对象(Command Object):封装客户端提交数据。

除了这三个主要层次外,在实际的Spring MVC应用中,还可能有以下组件或层次:

  1. Web 层
  • 过滤器(Filters):进行请求的预处理和响应的后处理。
  • 拦截器(Interceptors):在控制器执行前后或视图渲染前执行特定逻辑。
  1. 配置层
  • 配置类或XML文件:定义 Spring Bean、数据源、事务管理器等配置信息。
  1. 安全层
  • Spring Security:提供认证和授权的机制来保护应用程序。

DTO和DAO?

  • DTO 主要用于传输跨层或跨系统边界的数据。

  • DAO 专注于提供数据访问技术的抽象,例如数据库操作。

    目的:DTO 主要用于封装从一个系统到另一个系统的数据传输,是一种简单的Java对象,它用于聚合多个数据项以便于传输。
    作用范围:DTO 通常用于服务层与控制层之间或者不同应用程序/服务之间的数据传递。DTO 的目的是减少数据交换时的网络开销,并且可以定制所需展现给客户端的数据结构。
    内容:DTO 不包含任何业务逻辑,仅包含数据字段及其getter和setter方法。有时候,DTO 也可能包含一些简单的转换逻辑或校验逻辑。
    示例:如果需要展示用户信息和他们的订单数量,可以创建一个 UserOrdersDTO 类来封装这两类信息,即使用户信息和订单数量来自不同的源头。
    
    目的:DAO 是指访问数据源的对象,它封装了对数据源CRUD(创建、检索、更新、删除)操作的实现。
    作用范围:DAO 直接与数据存储(如数据库)打交道。它抽象和封装了所有与数据持久化相关的操作,使上层业务逻辑不直接依赖于底层的数据持久化细节。
    内容:DAO 通常会提供各种方法来访问数据源,如 findById, findAll, save, update, 和 delete 等。
    示例:有一个 UserDAO 类,提供了获取用户信息、保存新用户等与用户表直接关联的数据库操作方法。
    

DispatcherServlet?

  • 请求路由DispatcherServlet 根据请求的URL来确定选择哪个控制器(Controller)进行处理,并且将请求转发给相对应的控制器。
  • 控制器选择:通过使用处理器映射(Handler Mapping)来识别URL请求所对应的控制器。
  • 调用适配器:使用处理器适配器(Handler Adapter)来执行控制器中相应的方法。
  • 模型和视图解析 :控制器处理完请求后,返回一个模型和视图(ModelAndView)对象,DispatcherServlet 会根据这个对象来选择相应的视图技术进行渲染。
软件架构

在软件架构中,持久层(Persistence Layer)、业务层(Business Layer)和表示层/视图层(Presentation Layer)是三个主要的层次结构,它们各自负责不同的功能区域,并且通常相互分离,以实现关注点分离(Separation of Concerns)。以下是每一层的简单介绍:

持久层(Persistence Layer)

持久层,也称为数据访问层(Data Access Layer),负责与数据库进行交互,执行CRUD操作(创建、读取、更新、删除)。它提供了一个抽象层使得业务逻辑可以访问数据库操作所需的数据。在Java应用中,这一层可以通过使用ORM框架如Hibernate,或者使用数据访问技术如JDBC、JPA、MyBatis来实现。

业务层(Business Layer)

业务层包含应用程序的业务逻辑,其核心功能是实现应用程序的业务规则。业务层协调应用程序的工作流程,处理用户请求,并对持久层发送的数据执行业务决策。在复杂应用中,业务层可能还会处理事务、授权和其他核心功能。常见的Spring注解@Service就是用来标记业务层的组件。

表示层/视图层(Presentation Layer)

表示层是用户看到并与之交互的界面,它负责数据的展示和用户输入的处理。在Web应用中,表示层可以由HTML、CSS和JavaScript组成,而在服务器端,Spring MVC框架中的@Controller注解被用来处理HTTP请求,并返回对应的视图名称或响应体。表示层通常从业务层获取数据,并将用户输入传送到业务层进行处理。

每层都专注于其职责范围内的特定任务,从而实现了代码的模块化和清晰的架构设计。通过这种分层,开发人员能够独立地开发和测试每个层次,提高了应用程序的维护性和可扩展性。在Spring框架中,这些层通常由不同的Spring组件来实现,比如使用@Repository注解的类实现持久层,@Service注解的类实现业务层,@Controller或@RestController注解的类实现表示层。

常用Bean
java 复制代码
<!-- 对模型视图名称的解析,即在模型视图名称添加前后缀 --> ResourceViewResolver
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/" />
    <property name="suffix" value=".jsp" />
</bean>
java 复制代码
<!-- 上传限制 --> MultipartResolver
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
     <!-- 上传文件大小限制为31M,31*1024*1024 -->
     <property name="maxUploadSize" value="32505856"/>
</bean>
  
  //当解析器MultipartResolver完成处理时,请求便会像其他请求一样被正常流程处理。
  @RequestMapping(path = "/form", method = RequestMethod.POST)
 public String handleFormUpload(@RequestParam("name") String name, 
            @RequestParam("file") MultipartFile file) {

   if (!file.isEmpty()) {
          byte[] bytes = file.getBytes();
          // store the bytes somewhere
          return "redirect:uploadSuccess";
    }
    return "redirect:uploadFailure";
}
统一异常处理怎么做?

使用注解的方式统一异常处理,具体会使用到 @ControllerAdvice + @ExceptionHandler 这两个注解 。这种异常处理方式下,会给所有或者指定的 Controller 织入异常处理的逻辑(AOP),当 Controller 中的方法抛出异常的时候,由被@ExceptionHandler 注解修饰的方法进行处理。

java 复制代码
@ExceptionHandler(Exception.class)
public Object exceptionHandler(Exception ex, HttpServletResponse response, 
          HttpServletRequest request) throws IOException {
    String url = "";
    String msg = ex.getMessage();
    Object resultModel = null;
    try {
        if (ex.getClass() == HttpRequestMethodNotSupportedException.class) {
            url = "admin/common/500";
            System.out.println("--------毛有找到对应方法---------");
        } else if (ex.getClass() == ParameterException.class) {//自定义的异常

        } else if (ex.getClass() == UnauthorizedException.class) {
            url = "admin/common/unauth";
            System.out.println("--------毛有权限---------");
        }

        String header = req.getHeader("X-Requested-With");
        boolean isAjax = "XMLHttpRequest".equalsIgnoreCase(header);
        String method = req.getMethod();
        boolean isPost = "POST".equalsIgnoreCase(method);

        if (isAjax || isPost) {
            return Message.error(msg);
        } else {
            ModelAndView view = new ModelAndView(url);
            view.addObject("error", msg);
            view.addObject("class", ex.getClass());
            view.addObject("method", request.getRequestURI());
            return view;
        }
    } catch (Exception exception) {
        logger.error(exception.getMessage(), exception);
        return resultModel;
    } finally {
        logger.error(msg, ex);
        ex.printStackTrace();
    }
}
相关推荐
P.H. Infinity12 分钟前
【RabbitMQ】04-发送者可靠性
java·rabbitmq·java-rabbitmq
生命几十年3万天16 分钟前
java的threadlocal为何内存泄漏
java
caridle27 分钟前
教程:使用 InterBase Express 访问数据库(五):TIBTransaction
java·数据库·express
^velpro^32 分钟前
数据库连接池的创建
java·开发语言·数据库
苹果醋336 分钟前
Java8->Java19的初步探索
java·运维·spring boot·mysql·nginx
秋の花40 分钟前
【JAVA基础】Java集合基础
java·开发语言·windows
小松学前端43 分钟前
第六章 7.0 LinkList
java·开发语言·网络
Wx-bishekaifayuan1 小时前
django电商易购系统-计算机设计毕业源码61059
java·spring boot·spring·spring cloud·django·sqlite·guava
customer081 小时前
【开源免费】基于SpringBoot+Vue.JS周边产品销售网站(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·java-ee·开源
全栈开发圈1 小时前
新书速览|Java网络爬虫精解与实践
java·开发语言·爬虫