【Java框架】SpringMVC(一)——基本的环境搭建及基本结构体系

发布于:2024-04-23 ⋅ 阅读:(20) ⋅ 点赞:(0)

MVC模式

  • MVC模式是指Model-View-Controller(模型-视图-控制器)模式,是开发Web应用程序时常用的一种代码分层模式。
  • MVC模式是软件工程中的一种架构模式,会强制性地把系统的输入、处理和输出分开,使系统从功能上形成Model-View-Controller三个基本部分。

视图(View)

对应组件:JSP或者HTML文件:负责格式化数据并把它们呈现给用户,包括数据展示、数据验证、界面设计等。

控制器(Controller)

对应组件:Servlet:负责接收并转发请求,对请求进行处理后指派视图并将响应结果发送给客户端。

模型(Model)

对应组件:JavaBean:模型对象拥有最多的处理任务,是应用程序的主体部分,它负责业务逻辑的处理和实现对数据的操作。

在这里插入图片描述

JSP Model1

在这里插入图片描述

JSP Model2

  • Servlet:接受前端请求并调用JavaBean
  • JavaBean:处理业务并操作数据库
  • JSP:将处理结果响应到浏览器呈现给用户
    在这里插入图片描述

MVC的优点

  1. MVC三个模块相互独立,松耦合架构
  2. 多视图共享一个模型,大大提高代码的可重用性
  3. 控制器提高了应用程序的灵活性和可配置性
  4. 有利于软件工程化管理

MVC的缺点

  1. 增加了系统结构和实现的复杂性,不适合小型规模的项目
  2. 视图层与模型之间需要控制器做中间的连接控制,所以效率较低

Spring MVC架构

介绍

  • Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。
  • Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。使用 Spring 可插入的 MVC 架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的Spring MVC框架或集成其他MVC开发框架,如Struts1(现在一般不用),Struts 2(一般老项目使用)等等。

特点

  • 用Controller替换JSP Model2模型中的Servlet
  • Controller收到请求后,完成业务处理并用Model模型对象存储处理结果
  • Controller调用相应的视图解析器View对处理结果进行视图渲染,最终客户端得到响应信息

SpringMVC环境搭建(在前面Spring整合Mybatis的基础上)

1.创建控制器Controller

public class HelloController extends AbstractController {
    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        System.out.println("HelloSpringMVC...");
        ModelAndView m = new ModelAndView("index.jsp");
        return m;
    }
}

2.创建springmvc配置文件,并添加Controller的Bean

springmvc-servlet.xml

<?xml version="1.0" encoding="UTF8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">
        
	<bean name="/hello" class="cn.smbms.controller.HelloController"/>
</beans>

3.web.xml中配置springmvc.xml的加载(配置前端控制器)

  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc-servlet.xml</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

4.webapp下创建index.jsp

因为HelloController中的ModelAndView中返回的视图是index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>首页</title>
</head>
<body>
    <h1>HelloSpringMVC!!!</h1>
    <h1>你好,SpringMVC</h1>
</body>
</html>

5.配置Tomcat并启动,然后访问接口

localhost:8080/smbms/hello
在这里插入图片描述
在这里插入图片描述

6.配置视图解析器

通常情况下,jsp会放在/WEB-INF/下,因此可以配置一个固定的前缀和后缀,这样Controller返回页面时,只需要return逻辑视图名即可
在这里插入图片描述

    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        System.out.println("HelloSpringMVC...");
        //ModelAndView m = new ModelAndView("index.jsp");
        ModelAndView m = new ModelAndView("index");
        return m;
    }
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

在这里插入图片描述

7.优化Controller:注解驱动控制器

使用继承AbstractController 时,一个类只能表示一个接口,不便于开发,使用注解驱动控制器,可以对每个方法设置接口,提高开发效率,节省编码

<context:component-scan />

  • @Controller:标注一个普通的JavaBean成为可以处理请求的控制器
  • @RequestMapping:通过请求URL进行映射

<mvc:annotation-driven />

一键式配置,通过注解的方式进行Spring MVC开发

  • RequestMappingHandlerMapping
  • RequestMappingHandlerAdapter

代码示例

    <context:component-scan base-package="cn.smbms.controller"/>
    <mvc:annotation-driven/>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
@Controller
public class HelloController {
    @RequestMapping("/hello")
    public String hello(){
        return "index";
    }
    @RequestMapping("/welcome")
    public String welcome(){
        return "welcome";
    }
    ...
}

思考:如果另外一个IndexController中也有一个hello接口,会怎样

@Controller
public class IndexController {
    @RequestMapping("/hello")
    public String hello(){
        return "hello";
    }
}
  • 会报错,因此在一个系统中,不能有两个完全重名的接口

    [ERROR] 2024-04-19 11:04:31,774 org.springframework.web.servlet.DispatcherServlet - Context initialization failed
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping': Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'indexController' method 
    public java.lang.String cn.smbms.controller.IndexController.hello()
    to { /hello}: There is already 'helloController' bean method
    
  • 开发过程中,不能避免的一个Controller中的接口名与其他各个Controller中的接口名重复

  • 因此可以在各自的Controller的类名上加上一个各自的统一前缀

  • 如下示例,此时访问IndexController中的hello接口时,访问路径就应该是/index/hello

@Controller
@RequestMapping("/index")
public class IndexController {
    @RequestMapping("/hello")
    public String hello(){
        return "hello";
    }
}

总结:SpringMVC的工作流程

在这里插入图片描述

Spring MVC体系结构

DispatcherServlet(前端控制器)

  • Spring MVC最核心的类
  • web.xml中配置

Handler(处理器):对应MVC中C(Controller层)

  • 类型:Object
  • 作用:实际处理请求
  • 标注了@RequestMapping的所有方法都可以看作是一个Handler

ModelAndView

  • 逻辑视图名
  • 模型对象
    核心组件

核心组件

HandlerMapping(处理器映射)
  • BeanNameUrlHandlerMapping(默认)
    • 将请求URL映射到同名的控制器Bean上
  • DefaultAnnotationHandlerMapping
    • 将请求映射到标注@RequestMapping注解的控制器和处理方法上
  • RequestMappingHandlerMapping
HandlerAdapter(适配器)
  • AnnotationMethodHandlerAdapter
  • RequestMappingHandlerAdapter
ViewResolver(视图解析器)
  • InternalResourceView

面试题:简述SpringMVC工作流程?

在这里插入图片描述

  1. 浏览器发送请求送至前端控制器DispatcherServlet。
  2. DispatcherServlet收到请求后调用HandlerMapping处理器映射器。
  3. 处理器映射器找到具体的Handler处理器返回给DispatcherServlet。
  4. DispatcherServlet调用HandlerAdaptor处理器适配器。
  5. HandlerAdaptor去调用具体的处理器(Controller)。
  6. Controller返回一个ModelAndView对象给HandlerAdaptor。
  7. HandlerAdaptor将接收到的ModelAndView对象返回给DispatcherServlet。
  8. DispatcherServlet将ModelAndView对象传给ViewResolver视图解析器进行解析。
  9. ViewResolver视图解析器将解析的结果View返回给DispatcherServlet。
  10. DispatcherServlet根据View进行渲染视图。
  11. DispatcherServlet响应浏览器的请求。

组件说明

  1. DispatcherServlet:前端控制器(由框架提供),作为流程控制的中心,控制其他组件执行,统一调度,能够接受请求、响应结果。
  2. HandlerMapping:处理器映射器(由框架提供),根据用户请求的url路径找到负责处理的Handler处理器。
  3. HandlerAdaptor:处理器适配器(由框架提供),根据特定规则去执行Handler。
  4. Handler:处理器(需要自己开发),作为后端控制器,对具体用户的业务请求进行请求,并将处理的结果封装在ModelAndView对象中,并返回给调用者。
  5. ViewResolver:视图解析器(由框架提供),主要进行视图解析,根据逻辑视图名解析出真正的视图。