Spring MVC简介

Spring MVC 简介

传统的 MVC 架构 web 开发
  • Model1

    • 早期的 Java Web开发,统一把显示层、控制层、数据层的操作全部交给 JSP 或者 JavaBean 来操作,称之为 Model1
      image-20211126222027240
    • 弊端:
      • JSP 和 JavaBean 的耦合太高 大量的Java 代码和 HTML 耦合在一起
      • 开发者的前后端水平都要高 前后端高度依赖
      • 代码不好复用等
  • Model2

    • model1 很快就被 servlet + JSP + JavaBean 替代 早期的 model2

    • MVC三层架构很明显了

  • Spring MVC

    • 为了解决持久层的一直没有解决好的数据库事务编程的问题 迎合 NoSql 的崛起,Spring MVC给出了一种解决

    -

    • NoSQL,指的是非关系型的数据库,用于超大规模的存储

    • 传统的模型层被拆分为了业务层(Service)和数据访问层(DAO,Data Access Object)。 在 Service 下可以通过 Spring 的声明式事务操作数据访问层,而在业务层上还允许我们访问 NoSQL,这样就能够满足异军突起的 NoSQL 的使用了,它可以大大提高互联网系统的性能。

概述

Spring MVC 是一种基于 MVC 设计模式的, 请求驱动类型的 轻量级 Web 框架。是Spring 框架的一个模块。

Spring MVC 也是服务到工作模式的实现,可进行优化。前端控制器是 DispatcherServlet、应用控制器被拆分为 处理器映射器 Handler Mapping 和 视图解析器 ViewResolver、处理器为 Controller 接口(仅包含 ModelAndView handleRequest(request, response)方法的实现)(也可以是任何 POJO类)、支持本地化Locale` 解析、主题解析和文件上传等;提供了非常灵活的数据验证、格式化和数据绑定机制;提供了强大的约定大于配置(惯例优先原则)的契约式编程支持。

优点
  • 容易设计清爽干净的web层。
  • 与Spring框架集成(IOC容器、AOP等)。
  • 提供约定优于配置的契约式编程支持。
  • 更加快捷、简单的单元测试。
  • 灵活的URL到控制器的映射。
  • 支持Rest风格。
体系结构

Spring MVC的整体处理流程如下:

image-20211126235405374
  • 前端控制器:DispatcherServlet【分发servlet】
  • 应用控制器:拆分为 处理器映射器【HandlerMapping】 和 视图解析器 【ViewResolver
  • 处理适配器:HandlerAdapter

​ 需要我们开发的组件:Handler View

构建第一个Spring MVC架构项目

  • 创建 maven 项目

  • 选择 war 包

  • 加入 spring mvc、jstl、servlet、jsp 等依赖

    <project xmlns="http://maven.apache.org/POM/4.0.0"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    	<groupId>com.gpb</groupId>
    	<artifactId>springmvc1</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<packaging>war</packaging>
    
    	<properties>
    		<!-- **********************编译器配置**************************** -->
    		<maven.compiler.source>11</maven.compiler.source>
    		<maven.compiler.target>11</maven.compiler.target>
    		<maven.compiler.compilerVersion>11</maven.compiler.compilerVersion>
    		<!-- 自定义属性 -->
    		<spring.version>5.2.0.RELEASE</spring.version>
    	</properties>
    
    	<dependencies>
    		<!-- spring mvc -->
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-webmvc</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    		<!-- jstl -->
    		<dependency>
    			<groupId>javax.servlet</groupId>
    			<artifactId>jstl</artifactId>
    			<version>1.2</version>
    		</dependency>
    		<!-- servlet -->
    		<dependency>
    			<groupId>javax.servlet</groupId>
    			<artifactId>javax.servlet-api</artifactId>
    			<version>3.1.0</version>
    			<scope>provided</scope>
    		</dependency>
    		<!-- jsp -->
    		<dependency>
    			<groupId>javax.servlet.jsp</groupId>
    			<artifactId>jsp-api</artifactId>
    			<version>2.2</version>
    			<scope>provided</scope>
    		</dependency>
    	</dependencies>
    	<!-- tomcat7 插件 -->
    	<build>
    	<finalName></finalName>
    	<plugins>
    		<plugin>
    			<groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                   <configuration>
                      <path>/springmvc</path>
                      <port>8082</port>
                      <server>tomcat7</server>
                   </configuration>
                    <executions>
                        <execution>
                            <phase>package</phase>
                            <goals>
                                <goal>run</goal>
                            </goals>
                        </execution>
                    </executions>
    		</plugin>
    	</plugins>
    	</build>
    </project>
    
  • src/main/webapp 下面加入 WEB-INF 主要是下面的 web.xml【没加这个之前会报错的 pom war 的那行】

  • 配置文件:springmvc.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xmlns:mvc="http://www.springframework.org/schema/mvc"
    	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
    		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-4.3.xsd">
    		
    	<!-- 启动组件扫描 -->
    	<context:component-scan base-package="com.gpb"/>
    	
    	<!-- 启动mvc注解 -->
    	<mvc:annotation-driven/>
    	
    	<!-- 启动视图解析 -->
    	<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    		<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    		<property name="prefix" value="/WEB-INF/views/"/>
    		<property name="suffix" value=".jsp"/>
    	</bean>
    </beans>
    
    • 启动组件扫描

    • 启动 mvc 的注解

    • 启动视图解析

      • Bean的位置:org.springframework.web.servlet.view.InternalResourceViewResolver

      • 属性:

        • 配置viewClass这个属性是JstlView类:org.springframework.web.servlet.view.JstlView
        • prefix:配置的controller转发页面的前缀
        • suffix:配置的controller转发页面的后缀

        记得配置的路径要在项目里面存在并且在 controller 层返回的时候加上这个前后缀路径是存在的

  • web.xml 配置分发控制器去拦截请求

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://JAVA.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
      <display-name>test</display-name>
      <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
      </welcome-file-list>
      <!-- 配置 DisPatchServlet 分发控制器 拦截请求到这个servlet 里面去做分发 -->
      <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.xml</param-value>
      	</init-param>
      </servlet>
      <servlet-mapping>
      	<servlet-name>springMvc</servlet-name>
      	<url-pattern>/</url-pattern>
      </servlet-mapping>
    </web-app>
    
    • 可能你的 servlet标签 会报红 把上面的 xmlns="http://JAVA.sun.com/xml/ns/javaee" 里面的第一个 java 全大写 【这里已经大写了】
  • controller

    package com.gpb.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    public class UserInfoController {
    	
    	@RequestMapping("/index")
    	public String name(Model model) {
    		model.addAttribute("welcome", "欢迎来到SpringMVC框架");
    		return "index";
    	}
    }
    
    • 创建一个 UserInfoController

    • 这个方法在返回 index 后 在后面拼接好 位置 采取转发的【定义的视图解析器的前后缀】 /WEB-INF/views/index.jsp

      注意:这里的类是普通类 不用专门去建立servlet 而且这里可以写很多控制器方法 以前的 servlet 但是一般都是一张表一个类的

开发 Handler 【我们常说的MVC里面的Controller】

URL映射到Controller的方法
@RequestMapping
  • 设置映射路径

    • @RequestMapping("/index"):一个参数

    • @RequestMapping( value = "/index"):一个参数

    • @RequestMapping({"/index","/index.do"}):多个 value 值是数组

  • 设置请求方式

    • @RequestMapping(value= "/index", method=RequestMethod.GET):设置请求方式只能是GET

    • @RequestMapping(value= "/index", method=RequestMethod.POST):设置请求方式只能是POST

    • @RequestMapping(value="/editGoods",method={RequestMethod.GET,RequestMethod.POST}):GET和POST都可以

@GetMapping
  • @GetMapping(value = "/home") 仅限与 GET 方式请求映射
@PostMapping
  • @PostMapping(value = "/home") 仅限与 POST 方式请求映射
Controller 方法的返回值

在MVC架构中,controller返回值需要包含视图的URL和视图中显示的数据。视图的URL可以是JSP文件,显示的数据通常来自于数据库。

ModelAndView
public ModelAndView(String viewName, Map<String, ?> model) {  
        this.view = viewName;  
        if (model != null) {  
            getModelMap().addAllAttributes(model);  
        }  
}
  • ModelAndView: springmvc 底层封装的 包含视图名称或视图对象以及一些模型属性
  • setViewName(String viewName):跳转到指定页面
  • addObject(String attributeName, Object attributeValue):设置要返回的值,键值对的方式设置,页面中利用${keyName} 取值【使用 jstl 表达式, 它返回到页面的 request 域中】
  • 通过构造将 跳转的页面 和 键值对绑定的数据 放进去 然后返回这个对象就好了 DispatchServlet 前端控制器会调用 ViewResolver 页面解析器 解析 并返回 View 然后渲染 View 最后响应请求
void

老式 Servlet 控制器里面的写法,用请求转发或者地址重定向, 但是方法里面要把常用的几个对象传进去,框架会自动注入的

@Controller
@RequestMapping("/goods")
public class HomeController {
	@RequestMapping("/list")
	public void home(HttpServletRequest request,HttpServletResponse response, HttpSession session) {
		try {
			request.getRequestDispatcher("/index.jsp").forward(request, response);
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}
}
  • 请求转发:request.getRequestDispatcher("/index.jsp").forward(request, response);
    • 服务器端跳转,访问不需要加项目名
    • 地址栏不发生变化
    • 返回数据:resquest.setAttribute(键值对);
  • 响应:response.sendRedirect(request.getContextPath()+"/index.jsp");
    • 客户端跳转, 需要加上项目名【根就变到端口号去了】
    • 地址栏发生变化
    • 指定响应数据:response.getWrite().write("json串");
String
  • controller 方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址 return home;

    • 视图解析器为

      <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      		<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
      		<property name="prefix" value="/WEB-INF/views/"/>
      		<property name="suffix" value=".jsp"/>
      </bean>
      
    • 视图解析器解析后的地址:WEB-INF/views/home.jsp

  • Redirect 重定向:return "redirect:/index.jsp";

    • 相当于 response.sendRedirect(...);
    • 由于重定向后请求和响应都失效了,所以参数传递可以使用 :/index.jsp?id=1&…..
    • 浏览器地址变化
    • 注意:这里面的地址是写全的
  • forward 转发:"forward:/goods/update.action";

    • 相当于请求转发
    • 请求和响应没有失效,正常使用
    • 浏览器地址不变
    • 地址写全
Controller的参数绑定

处理器适配器【HandlerAdapter】在执行 controller 之前需要把 http 请求的 key/value 数据绑定到 controller 方法形参上,相当于request.getParameter(“key”)。默认支持的参数类型如下,处理器适配器会自动识别并注入进去。

  • 什么是参数绑定:就是将URL中的的请求参数,进行类型转换(String或其他类型),将转换后的值在赋值给Controller方法形参中,然后Controller就可以直接使用该形参。
默认参数类型
  • HttpSession、HttpServletResponse、 HttpServletRequest:获取请求信息、处理响应信息、获取session信息

  • ModelModelMap:通过 它们 向页面传输数据
    • ModelMapModel 接口的一个实现类,作用是将 Model 数据填充到 request 域,即使使用 Model, 其内部绑定还是 ModelMap【父类LinkedHashMap—> 继承自HashMap —> 实现Map接口】
      • 整个链条上都可以, 不过后面他们没有 addAttribute 这样的方法, 只能使用原生的自己的方法
    • model.addAttribute("goods", goods);:页面通过 ${goods.属性}取得 goods 属性值

    • 使用ModelModelMap的效果一样,如果直接使用Modelspringmvc会实例化ModelMap。保存到ModelModelMap中的数据会被springmvc保存到request作用域中,因此界面可以通过${}获取。

基本数据类型的绑定

基本数据类型(byte short int long char boolean float double),自动获得,不给默认初始值

包装数据类型的绑定

包装类 (Byte Short Integer Long Character Float Double),自动获得,不给报异常

String 类型

正常使用,类似 get 地址栏传参,不给报异常

POJO实体类的绑定

自动获得,和以前使用一样, form 表单的属性 name 要与 实体的属性相同

VO类型的绑定

和以前使用一样,但是注意在页面取值时,用 对象.属性 去取值,name 也要注意

数组集合类型的绑定
  • 数组:Controller方法中可以用String[]接收,多选框的名字得一致,通过这个名字去注入取值
  • List:List 中存放对象,并将定义的 List 放在包装类中,controller 使用包装对象接收。
  • Map:
注意
  • 传递的参数名称不同:@RequestParam(value="paramName") String str 给这个参数给个别的名字

  • 不穿参数异常的解决办法:@RequestParam(value="isResult",required = true,defaultValue = "8") 加入默认值以及是否必须

  • 表单不要写该属性:disabled=``"disabled" 不会提交,可以改用:readonly="readonly"

  • Date 日期 单独在实体类中使用注解处理一下:@DateFormat("yyyy-MM-dd")

  • tomcatWEB-INF目录是受保护的目录,该目录中的所有文件都不允许通过浏览器地址栏直接访问,只能通过后台程序通过请求转发访问,所以访问的话需要专门写个 Controller 去访问。

  • 中文乱码问题

    • POST 提交数据:在 web.xml 中配置 springmvc 提供的过滤器

      <!-- post乱码 -->
      <filter>
      	<filter-name>CharacterEncodingFilter</filter-name>
      	<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
      	<init-param>
      	<param-name>encoding</param-name>
      	<param-value>utf-8</param-value>
      	</init-param>
      </filter>
      <filter-mapping>
      	<filter-name>CharacterEncodingFilter</filter-name>
      	<url-pattern>/*</url-pattern>
      </filter-mapping>
      
    • GET 提交数据:

      • 修改 tomcatserver.xml 配置文件

        <Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
        
      • ISO8859-1tomcat默认编码,需要将tomcat编码后的内容转换为utf-8编码

        String userName = new String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8");
        
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值