Spring MVC

1. 简介

  • M(Model)V(View)C(Controller),是一种软件设计规范
  • 将业务逻辑、数据、显示分离的方式来组织代码。
  • 降低视图业务逻辑间的双向耦合
  • SpringMVC是Spring Framework的一部分,基于Java实现MVC的轻量级Web框架
  • MVC不是一种设计模式,而是一种架构模式,当然不同的MVC存在差异
    注:
  1. 设计模式对在某种环境中反复出现的问题以及解决该问题的方案的描述,它比架构更抽象。
  2. 架构模式只是针对某一领域的具体实现,一个软件可能包含多种设计模式;而设计模式是一种思想,可适用于各种应用。
  3. 简单来说,框架是软件,而设计模式是软件的知识。

Model (模型)

数据模型,提供要展示的数据,因此包含数据和行为。
可以认为是领域模型或JavaBean组件(包含数据和行为) 。
不过现在一般都分离开来:Value Object (数据Dao)和服务层(行为Service) 。
也就是模型提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。

View (视图):

负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西。

Controller (控制器) :

接收用户请求,委托给模型进行处理(状态改变) ,处理完毕后把返回的模型数据返回给视图,由视图负责展示。也就是说控制器做了个调度员的工作。最典型的MVC就是JSP + servlet + javabean的模式。

  1. 用户发送请求。
  2. Servlet接收请求数据并调用对应的业务逻辑方法。
  3. 业务处理完毕返回更新的数据给Servlet。
  4. Servlet发送到JSP来渲染页面。
  5. 响应给前端更新后的页面。

特点

  1. 轻量级,简单易学
  2. 高效,基于请求响应的MVC框架
  3. 与Spring兼容性好,无缝结合
  4. 约定由于配置
  5. 功能强大:RESTful、数据验证、格式化、本地化、主题等
  6. 简洁灵活

2、MVC的演变历史

2.1、Model1

Spring MVC_第1张图片
优点:架构简单,比较适合小型项目开发

缺点:JSP职责不单一,职责过重,不便于维护

2.2、Model2

Model1虽已在一定程度上解耦,但JSP即要负责页面控制,又要负责逻辑处理,职责不单一。于是Model2应运而生,使得各个部分各司其职。 Model2基于MVC模式:

Controller:控制器

  1. 取得表单数据
  2. 调用业务逻辑
  3. 转向指定的页面

Model:模型

  1. 业务逻辑
  2. 保存数据状态

View:视图

  1. 显示页面

Spring MVC_第2张图片
优点:职责清晰,较适合于大型项目架构

缺点:分层较多,不适合小型项目开发

区别

	Model2 在 Model1 的基础上分离了控制,将JSP中的逻辑操作部分分离出来,这样做不仅减轻了JSP的职责,而且更有利于分工开发,耦合性降低。

2.3、三层

	Model2巧妙的将JSP中的业务逻辑部分分给了Servlet,使得页面控制与逻辑处理彻底分离,达到了部分解耦的目的。但我们现实项目开发中,
	往往在Model2的基础上又进行了分层。将业务逻辑细分为业务逻辑和持久化逻辑两层。
	
	往往使用一个Dao接口隐藏持久化操作的细节,业务对象不需要了解底层的数据库持久化知识。使得业务逻辑与持久化逻辑分离,
	业务逻辑通常关系的是应用程序的核心流程和业务规则,持久化逻辑关注的是如何访问和操作持久化数据。

Spring MVC_第3张图片

3、SpringMVC工作原理

  1. 用户发送请求至前端控制器DispatcherServlet
  2. DispatcherServlet收到请求调用HandlerMapping处理器映射器。
  3. 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet
  4. DispatcherServlet调用HandlerAdapter处理器适配器。
  5. HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
  6. Controller执行完成返回ModelAndView
  7. HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet
  8. DispatcherServletModelAndView传给ViewReslover视图解析器。
  9. ViewReslover解析后返回具体View.
  10. DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
  11. DispatcherServlet响应用户
    Spring MVC_第4张图片

4、Hello,SpringMVC(xml版)

4.1. 创建Maven工程,添加Web框架

Spring MVC_第5张图片
Spring MVC_第6张图片

4.2. 导入Maven依赖

<dependency>
   <groupId>org.springframeworkgroupId>
   <artifactId>spring-webmvcartifactId>
   <version>5.2.0.RELEASEversion>
dependency>
<dependency>
   <groupId>javax.servletgroupId>
   <artifactId>servlet-apiartifactId>
   <version>2.5version>
dependency>
<dependency>
   <groupId>javax.servlet.jspgroupId>
   <artifactId>jsp-apiartifactId>
   <version>2.2version>
dependency>
<dependency>
   <groupId>javax.servletgroupId>
   <artifactId>jstlartifactId>
   <version>1.2version>
dependency>

4.3. 在resource目录下创建springmvc.xml配置文件


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

    
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

    
    <bean id="/myController" class="com.qhit.controller.MyController"/>

    
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        
        <property name="prefix"  value="/WEB-INF/jsp/"/>
        
        <property name="suffix" value=".jsp"/>
    bean>
beans>

4.4. 在web.xml中配置DispatcherServlet


<servlet>
   <servlet-name>dispatcherServletservlet-name>
   <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>

   <init-param>
       <param-name>contextConfigLocationparam-name>
       <param-value>classpath:springmvc-servlet.xmlparam-value>
   init-param>
   
   <load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
   <servlet-name>dispatcherServletservlet-name>
   
   
   <url-pattern>/url-pattern>
servlet-mapping>

4.5、编写处理器,配置映射

package com.qhit.controller;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
         // 返回一个ModelAndView对象给HandlerAdapter
        ModelAndView mv = new ModelAndView();
        // 调用service层
        String result = "result";
        // 封装执行结果
        mv.addObject("result", result);
        // 封装跳转地址
        mv.setViewName("index");
        return mv;
    }
}

<bean id="myController" class="com.qhit.controller.MyController" />

4.6、配置Tomcat

在这里插入图片描述
Spring MVC_第7张图片
Spring MVC_第8张图片
Spring MVC_第9张图片
Spring MVC_第10张图片
在这里插入图片描述

4.7、可能遇到的问题

4.7.1、404

Spring MVC_第11张图片

Spring MVC_第12张图片
原因是jar包添加失败
接下来我们手动添加jar

  1. Shift+Control+Alt+S快捷键打开Project Structure
  2. 找到Artifacts,选中报错的项目,检查项目名,在WEB-INF下创建lib
    Spring MVC_第13张图片

Spring MVC_第14张图片
3. 选中lib,点击+号,选择Library Files库文件,选中要添加的jar,确认

Spring MVC_第15张图片
Spring MVC_第16张图片

4.7.2、库源与类DispatcherServlet的字节码不符

检查maven依赖

4.7.3、1099 is already in use

方案一:按快捷键 Ctrl+Shift+Esc 打开任务管理器,找到java.exe,然后点击“结束任务”即可!
Spring MVC_第17张图片
方式二:这种方式适用于所有端口被占用的情况

  1. 通过端口找到PID
    打开dos命令行,输入netstat -ano | find “1099”,得到下列内容,看到最后一列是9280,就是PID:
    Spring MVC_第18张图片
  2. 通过PID找到进程
    输入:tasklist | find “9280”(双引号里面的是PID)
    Spring MVC_第19张图片
  3. 关闭进程
    输入命令关闭进程:taskkill /f /t /im java.exe
    Spring MVC_第20张图片

5、Hello,SpringMVC(注解)

5.1、 新建项目,导入依赖

Spring MVC_第21张图片

<dependency>
  <groupId>org.springframeworkgroupId>
  <artifactId>spring-webmvcartifactId>
  <version>5.2.0.RELEASEversion>
dependency>
<dependency>
  <groupId>javax.servletgroupId>
  <artifactId>jstlartifactId>
  <version>1.2version>
dependency>
<dependency>
  <groupId>javax.servlet.jspgroupId>
  <artifactId>jsp-apiartifactId>
  <version>2.2version>
dependency>
<dependency>
  <groupId>javax.servletgroupId>
  <artifactId>servlet-apiartifactId>
  <version>2.5version>
dependency>

5.2、配置DispatcherServlet


<servlet>
    <servlet-name>dispatcherServletservlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
    
    <init-param>
        <param-name>contextConfigLocationparam-name>
        <param-value>classpath:springmvc.xmlparam-value>
    init-param>
    
    <load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
    <servlet-name>dispatcherServletservlet-name>
    
    
    <url-pattern>/url-pattern>
servlet-mapping>

5.3、配置springmvc.xml


<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/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/context 
       http://www.springframework.org/schema/context/spring-context.xsd">
    
    <context:component-scan base-package="com.qhit.controller"/>
    
    <mvc:default-servlet-handler/>
    

    
    <mvc:annotation-driven/>

    
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        
        <property name="prefix"  value="/WEB-INF/jsp/"/>
        
        <property name="suffix" value=".jsp"/>
    bean>
beans>

5.4、HelloController

package com.qhit.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/hello")  //访问地址:/项目名/hello
public class HelloController{

    //访问地址:/项目名/hello/h1
    @RequestMapping("/h1")
    public String hello(Model model){/* model:向前端传递数据 */
        model.addAttribute("msg", "hello, springmvc!");
		return "hello"; //view名称,会被视图解析器解析
    }
}

5.5、配置Tomcat,运行。如上

Spring MVC_第22张图片

5.6、注解

@RestController
修饰类,方法直接返回JSON数据,跳过视图解析器
@ResponseBody
将java对象转为json格式的数据。
@Controller
控制层类注解,声明一个类是bean,放入IOC容器,相当于@Component
@PathVariable
加在控制器入参上,用于接收Restful风格的参数。

//访问地址:/项目名/hello/h1
    @RequestMapping(path = "/h1/{a}/{b}", method = RequestMethod.DELETE)
    @GetMapping //简化
    public String hello(@PathVariable int a,@PathVariable int b, Model model){/* model:向前端传递数据 */
        model.addAttribute("msg", "hello, springmvc!");
        return "hello"; //view名称,会被视图解析器解析
    }

6、Restful风格

Restful就是一个资源定位及资源操作的风格。
不是标准也不是协议。
基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等。
在这里插入图片描述

Spring MVC_第23张图片
Spring MVC_第24张图片

7、JSON

7.1、简介

  • JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
  • JSON 是轻量级的文本数据交换格式
  • JSON 独立于语言:JSON 使用 Javascript语法来描述数据对象,但是 JSON 仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不同的编程语言。 目前非常多的动态(PHP,JSP,.NET)编程语言都支持JSON。
  • JSON 具有自我描述性,更易理解

7.1.1、与 XML 的异同

    • JSON 是纯文本 JSON 具有"自我描述性"(人类可读)
    • JSON 具有层级结构(值中存在值)
    • JSON 可通过 JavaScript
    • 进行解析 JSON 数据可使用 AJAX 进行传输
    • 没有结束标签
    • 更短
    • 读写的速度更快
    • 能够使用内建的 JavaScript eval() 方法进行解析
    • 使用数组
    • 不使用保留字

7.1.2、为什么使用 JSON?

对于 AJAX 应用程序来说,JSON 比 XML 更快更易使用:
使用 XML

  • 读取 XML 文档
  • 使用 XML DOM 来循环遍历文档
  • 读取值并存储在变量中

使用 JSON

  • 读取 JSON 字符串
  • 用 eval() 处理 JSON 字符串

7.2、语法

  • 数据在名称/值对中
  • 数据由逗号分隔
  • 大括号 {} 保存对象
  • 中括号 [] 保存数组,数组可以包含多个对象,例:
{
    "sites": [
	    { "name":"菜鸟教程" , "url":"www.runoob.com" }, 
	    { "name":"google" , "url":"www.google.com" }, 
	    { "name":"微博" , "url":"www.weibo.com" }
    ]
}

可以像这样访问 JavaScript 对象数组中的第一项(索引从 0 开始):

sites[0].name;

返回的内容是:

runoob

可以像这样修改数据:

sites[0].name="菜鸟教程";

7.3、JSON乱码问题


<mvc:annotation-driven>
   <mvc:message-converters>
       <bean class="org.springframework.http.converter.StringHttpMessageConverter">
           <constructor-arg value="utf-8"/>
       bean>
       <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
           <property name="objectMapper">
               <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
                   <property name="failOnEmptyBeans" value="false"/>
               bean>
           property>
       bean>
   mvc:message-converters>
mvc:annotation-driven>

7.4、Jackson

7.4.1、maven依赖


        <dependency>
            <groupId>com.fasterxml.jackson.coregroupId>
            <artifactId>jackson-coreartifactId>
            <version>2.9.0version>
        dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.coregroupId>
            <artifactId>jackson-databindartifactId>
            <version>2.9.0version>
        dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.coregroupId>
            <artifactId>jackson-annotationsartifactId>
            <version>2.9.0version>
        dependency>

7.4.2、Controller编写

package com.qhit.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.text.SimpleDateFormat;
import java.util.Date;

@RestController//Controller + ResponseBody
public class HelloController {
   
    //访问地址:/项目名/hello/h1
    @GetMapping(path = "/h1")
    //@ResponseBody // 返回值不会经过视图解析器,会直接返回字符串
    public String hello() throws JsonProcessingException {
        return new ObjectMapper().writeValueAsString(new User("1", "Candy"));
    }

    @GetMapping("h2")
    public String jsonDate() throws JsonProcessingException {
        ObjectMapper om = new ObjectMapper();
        //关闭时间戳(时间解析后的默认格式为:时间戳TimeStamp)
        om.configure(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS, false);
        //定义时间格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
        om.setDateFormat(sdf);
        return om.writeValueAsString(new Date());
    }
}

Spring MVC_第25张图片

7.4、FastJSON

7.4.1、依赖

<dependency>
    <groupId>com.alibabagroupId>
    <artifactId>fastjsonartifactId>
    <version>1.2.60version>
dependency>

7.4.2、Controller编写

8、工具

Lombok

参考文献

框架和设计模式的区别 忘崖
浅析Java开发模式—Model1、Model2和三层 想太多先森

你可能感兴趣的:(mvc,spring,restful)