SpringMVC学习笔记-狂神说

Gitee仓库:狂神-SpringMVC: 学习狂神的课程,练习项目 - Gitee.com

一、MVC框架的历史

1、什么是MVC

SpringMVC学习笔记-狂神说_第1张图片

  • MVC是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范。
  • 是将业务逻辑,数据、显示分离的方法来组织代码。
  • MVC主要作用是降低了视图与业务逻辑间的双向耦合
  • MVC不是一种设计模式,MVC是一种架构模式。当然不同的MVC存在差异。

最经典的MVC就是JSP + Servlet + javabean的模式。

SpringMVC学习笔记-狂神说_第2张图片

  • Model(模型):数据模型,提供要展示的数据,因此包含数据和行为,可以认为是领域模型或JavaBean组件(包含数据和行为),不过现在一般都分离开来:Value Object(数据Dao) 和服务层(行为Service)。也就是模型提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。
  • View(视图):负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西。
  • Controller(控制器):接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责表示。也就是说控制器做了调度员的工作。

2、model时代

Model1时代

  • 在web早期的开发中,通常采用的都是Model1.
  • Model1中,主要分为两层,视图层和模型层。

SpringMVC学习笔记-狂神说_第3张图片

  • Model1 优点:架构简单,比较适合小型项目开发;
  • Model1 缺点:JSP职责不单一,职责过重,不便于维护;

Model2时代

Model2把一个项目分成三部分,包括 视图、控制、模型

SpringMVC学习笔记-狂神说_第4张图片

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

Model2这样不仅提高的代码的复用率与项目的扩展性,且大大降低了项目的维护成本。

Model1模式的实现比较简单,适用于快速开发小规模项目,Model中JSP页面身兼View和Controller两种角色,将控制逻辑和表现逻辑混杂在一起,从而导致代码的重用性非常低,增加了应用的扩展性和维护的难度,Model2消除了Model1的缺点。

MVC框架要做哪些事情?

  1. 将url映射到java类或java类的方法
  2. 封装用户提交的数据
  3. 处理请求-- 调用相关的业务处理–封装响应数据
  4. 将响应的数据进行渲染,jsp/html等表示层数据

常见的服务器端MVC框架有

Struts、Spring MVC、 ASP.NET MVC、 Zend Framework、JSF;常见前端MVC框架:vue、angularjs、react、backbone;由MVC演化出了另外一些模式,如:MVP、MVVM等等……

面试:你的项目架构,是设计好的,还是演进的

  • alibaba    ->    PHP
  • 随着用户变多    ->    java
  • 王坚     ->   去IOE    ->    MYSQL
  • MYSQL    ->    AliSQL    ->    AliRedis
  • All in one    ->    微服务

二、SpringMVC

官方网址

1 、什么是 Spring MVC?

SpringMVC学习笔记-狂神说_第5张图片

 Spring MVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架。

分析源码,看到DispatcherServlet继承了HttpServlet。

SpringMVC学习笔记-狂神说_第6张图片

内部有对request、response的前置处理,后置处理。

SpringMVC学习笔记-狂神说_第7张图片

2、为什么要学习Spring MVC?

Spring MVC的特点:

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

最重要一点还是用的人多,使用得公司多,接触得项目基本都用到了。

Spring的web框架围绕DispatcherServlet[调度Servlet]设计。
DispatcherServlet的作用是将请求分发到不同的处理器。从Spring 2.5开始,使用Java 5或者以上版本的用户可以采用基于注解形式进行开发,十分简洁;

3、DispatcherServlet

Spring MVC框架像许多其它MVC框架一样,以请求为驱动,围绕一个中心Servlet分派请求及提供其它功能,DispatcherServlet是一个实际的Servlet(它继承自HttpServlet基类)。

SpringMVC学习笔记-狂神说_第8张图片

 SpringMVC的原理如下图所示:

SpringMVC学习笔记-狂神说_第9张图片

4、SpringMVC执行原理

SpringMVC学习笔记-狂神说_第10张图片

 注: 图为SpringMVC的一个较完整的流程图,实线表示SpringMVC框架提供的技术,不需要开发者实现,虚线表示需要开发者实现。

简要分析执行流程

  1. DispatcherServlet表示前置器是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求。                                                                                
    – 我们假设请求的url为:http://localhost:8080/SpringMVC/hello
    – 如上url拆分成三部分:
    – http://localhost:8080服务器域名
    – SpringMVC部署在服务器上的web站点
    – hello表示控制器
    – 通过分析,如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器。
  2. HandleMapping为处理器映射。DispatcherServlet调用HandlerMapping,HandlerMapping根据请求url查找Handler.
  3. HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器,如上url被查找控制器为:hello.
  4. HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。
  5. HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler。
  6. Handler让具体的Controller执行。
  7. Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。
  8. HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。
  9. DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名。
  10. 视图解析器将解析的逻辑视图名传给DispatcherServlet。
  11. DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。
  12. 最终视图呈现给用户。

三、编写SpringMVC的项目

首先在父项目导入依赖


    
        
        
            org.springframework
            spring-webmvc
            5.3.10
        
        
        
            javax.servlet
            javax.servlet-api
            3.1.0
        
        
        
            javax.servlet.jsp
            javax.servlet.jsp-api
            2.3.3
        
        
        
            javax.servlet.jsp.jstl
            jstl-api
            1.2
        
        
        
            org.projectlombok
            lombok
            1.18.20
        
        
        
            junit
            junit
            4.13
        

    


    
        
            
                src/main/java
                
                    **/*.properties
                    **/*.xml
                
                false
            
            
                src/main/resources
                
                    **/*.properties
                    **/*.xml
                
                false
            
        
    

1、配置版

首先创建maven项目,然后添加项目支持

SpringMVC学习笔记-狂神说_第11张图片

选择WebApp的4.0版本

 SpringMVC学习笔记-狂神说_第12张图片

项目结构

SpringMVC学习笔记-狂神说_第13张图片

配置Project Structure,否则会识别不出web项目结构,报500can not find springmvc-servlet.xml

SpringMVC学习笔记-狂神说_第14张图片

报错页面

SpringMVC学习笔记-狂神说_第15张图片

web.xml




    
    
    
        springmvc1
        org.springframework.web.servlet.DispatcherServlet
        
        
            contextConfigLocation
            classpath:springmvc1-servlet.xml
        
        
        1
    

    
    
    
    
        springmvc1
        /
    

springMVC1-servlet.xml




    
    

    
    

    
    
        
        
        
        
    

    


HelloController.java

public class HelloController implements Controller {

    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 创建返回对象
        ModelAndView modelAndView = new ModelAndView();
        // 放入参数
        modelAndView.addObject("msg", "hello Controller");
        // 设置跳转的页面  /WEB-INF/jsp/hello.jsp
        modelAndView.setViewName("hello");
        return modelAndView;
    }
}

 防止启动项目报错404,导入jar包到项目内SpringMVC学习笔记-狂神说_第16张图片

 启动项目测试

SpringMVC学习笔记-狂神说_第17张图片

2、注解版

只有列出来的2个文件和配置版有不同。

项目结构

SpringMVC学习笔记-狂神说_第18张图片

springmvc2-servlet.xml




    
    
    
    
    
    

    
    
        
        
        
        
    


HelloController.java

@Controller
public class HelloController {

    @RequestMapping("/hello")
    public String hello(Model model) {
        model.addAttribute("msg", "hello Controller");
        return "hello";
    }

启动项目测试

SpringMVC学习笔记-狂神说_第19张图片

小结
实现步骤其实非常的简单:

  1. 新建一个web项目
  2. 导入相关jar包
  3. 编写web.xml , 注册DispatcherServlet
  4. 编写springmvc配置文件
  5. 接下来就是去创建对应的控制类 , controller
  6. 最后完善前端视图和controller之间的对应
  7. 测试运行调试.

四、Restful风格

1、什么是Restful

SpringMVC学习笔记-狂神说_第20张图片Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

2、RestFul的功能

  • 资源:互联网所有的事物都可以被抽象为资源
  • 资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作。
    分别对应 添加、 删除、修改、查询。

传统方式操作资源 :

通过不同的参数来实现不同的效果!方法单一,post 和 get

http://127.0.0.1/item/queryItem.action?id=1 查询,GET

http://127.0.0.1/item/saveItem.action 新增,POST

http://127.0.0.1/item/updateItem.action 更新,POST

http://127.0.0.1/item/deleteItem.action?id=1 删除,GET或POST

使用RESTful操作资源 :

可以通过不同的请求方式来实现不同的效果!如下:请求地址一样,但是功能可以不同!

http://127.0.0.1/item/1 查询,GET

http://127.0.0.1/item 新增,POST

http://127.0.0.1/item 更新,PUT

http://127.0.0.1/item/1 删除,DELETE

编写项目测试

SpringMVC学习笔记-狂神说_第21张图片

RestfulController.java

    // @PathVariable 注解,让方法参数的值对应绑定到一个URI模板变量上。PathVariable:路径变量
    @RequestMapping(value = "/restful1/{a}/{b}")
    public String restful1(@PathVariable int a, @PathVariable int b, Model model) {

        int result = a + b;
        //Spring MVC会自动实例化一个Model对象用于向视图中传值
        model.addAttribute("msg", "result = " + result);
        //返回视图位置
        return "hello";
    }

    // 使用method属性指定请求类型
    @RequestMapping(value = "/restful2/{a}/{b}", method = RequestMethod.POST)
    public String restful2(@PathVariable int a, @PathVariable int b, Model model) {

        int result = a + b;
        //Spring MVC会自动实例化一个Model对象用于向视图中传值
        model.addAttribute("msg", "result = " + result);
        //返回视图位置
        return "hello";
    }

思考:使用路径变量的好处?

  1. 使路径变得更加简洁;
  2. 获得参数更加方便,框架会自动进行类型转换。
  3. 通过路径变量的类型可以约束访问参数,如果类型不一样,则访问不到对应的请求方法,如这里访问是的路径是/hello/1/a,则路径与方法不匹配,而不会是参数转换失败。

SpringMVC学习笔记-狂神说_第22张图片

方法级别的注解变体有如下几个:组合注解

@GetMapping        =        @RequestMapping(method =RequestMethod.GET)
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping

五、重定向和转发

 servlet本身具有转发和重定向,springMVC对他做了封装

1、通过SpringMVC来实现转发和重定向 - 无需视图解析器

SpringMVC学习笔记-狂神说_第23张图片

 视图解析器,默认就是转发,所以要把他注释掉

    @RequestMapping("/redirect1")
    public String redirect1(HttpServletRequest request, HttpServletResponse response) {
        HttpSession session = request.getSession();
        System.out.println(session.getId());

//        return "hello";

        // 转发方式一
//        return "/WEB-INF/jsp/hello.jsp";
//         转发方式二
        return "forward:/WEB-INF/jsp/hello.jsp";
        // 重定向
//        return "redirect:/index.jsp";
    }

2、通过SpringMVC来实现转发和重定向 - 有视图解析器

  • 重定向 , 不需要视图解析器 , 本质就是重新请求一个新地方嘛 , 所以注意路径问题.
  • 可以重定向到另外一个请求实现 .
    @RequestMapping("/redirect2")
    public String redirect2(Model model) {
        model.addAttribute("msg", "hello Controller");
        // return "hello";

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

六、请求和响应的数据处理

1、处理提交数据

提交的域名称和处理方法的参数名一致

    // http://localhost:8080/springmvc3_restful/user/test1?name=Daniel
    @RequestMapping("/test1")
    public String test1(Model model, String name) {
        // 1.接收前端传过来的数据
        System.out.println("前端传过来的数据" + name);
        // 2.将返回的结果传递给前端
        model.addAttribute("msg", name);
        // 3.视图跳转
        return "hello";
    }

提交的域名称和处理方法的参数名不一致

    // http://localhost:8080/springmvc3_restful/user/test2?username=Daniel
    @RequestMapping("/test2")
    public String test2(Model model, @RequestParam("username") String name) {
        // 1.接收前端传过来的数据
        System.out.println("前端传过来的数据" + name);
        // 2.将返回的结果传递给前端
        model.addAttribute("msg", name);
        // 3.视图跳转
        return "hello";
    }

提交的是一个对象

    // http://localhost:8080/springmvc3_restful/user/test3?name=Daniel&age=18
    @RequestMapping("/test3")
    public String test3(Model model, User user) {
        // 1.接收前端传过来的数据
        System.out.println("前端传过来的数据" + user.toString());
        // 2.将返回的结果传递给前端
        model.addAttribute("msg", user.toString());
        // 3.视图跳转
        return "hello";
    }

启动项目运行

SpringMVC学习笔记-狂神说_第24张图片

SpringMVC学习笔记-狂神说_第25张图片

2、数据显示到前端

第一种 : 通过ModelAndView

    @RequestMapping("/t1")
    public ModelAndView test1(ModelAndView model) {
        model.addObject("msg", "Jenny311");
        model.setViewName("hello");
        return model;
    }

第二种 : 通过ModelMap

    @RequestMapping("/t2")
    public String test2(ModelMap model) {
        model.addAttribute("msg", "Jenny311");
        return "hello";
    }

第三种 : 通过Model

    @RequestMapping("/t3")
    public String test3(Model model) {
        model.addAttribute("msg", "Jenny311");
        return "hello";
    }

总结对比:

Model 只有寥寥几个方法只适合用于储存数据,简化了新手对于Model对象的操作和理解;
ModelMap 继承了 LinkedMap ,除了实现了自身的一些方法,同样的继承 LinkedMap 的方法和特性;
ModelAndView 可以在储存数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转。

七、JSON

1、什么是JSON

SpringMVC学习笔记-狂神说_第26张图片

在 JavaScript 语言中,一切都是对象。因此,任何JavaScript 支持的类型都可以通过 JSON 来表示,例如字符串、数字、对象、数组等。看看他的要求和语法格式:

  • 对象表示为键值对,数据由逗号分隔
  • 花括号保存对象
  • 方括号保存数组

jsonTest.html




    
    Title







启动项目

SpringMVC学习笔记-狂神说_第27张图片

2、Jackson

导入依赖



    com.fasterxml.jackson.core
    jackson-databind
    2.13.3

项目结构

SpringMVC学习笔记-狂神说_第28张图片

web.xml




    
        springmvc4
        org.springframework.web.servlet.DispatcherServlet
        
            contextConfigLocation
            classpath:springmvc4-json.xml
        
        1
    

    
        springmvc4
        /
    

    
        encoding
        org.springframework.web.filter.CharacterEncodingFilter
        
            encoding
            utf-8
        
    
    
        encoding
        /
    

JacksonController.java

package com.kuang.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.kuang.pojo.User;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

// 相当于@Controller    +    @ResponseBody
@RestController
public class JacksonController {

    // 不走视图解析器,直接返回(字符串)
    @ResponseBody
    // 防止乱码
    @RequestMapping(value = "/jackson1", produces = "application/json;charset=utf-8")
    public String jackson1() throws JsonProcessingException {

        ObjectMapper objectMapper = new ObjectMapper();
        User user = new User(12, "安卓", "男");

        return objectMapper.writeValueAsString(user);
    }

    @RequestMapping("/jackson2")
    public String jackson2() throws JsonProcessingException {

        ObjectMapper objectMapper = new ObjectMapper();
        // 测试集合的输出
        List userList = new ArrayList<>();
        User user = new User(12, "安卓", "男");
        User user2 = new User(12, "安卓", "男");

        userList.add( user);
        userList.add( user2);
        return objectMapper.writeValueAsString(userList);
    }

    @RequestMapping("/jackson3")
    public String jackson3() throws JsonProcessingException {

        ObjectMapper objectMapper = new ObjectMapper();
        // 测试集合的输出
        Date date = new Date();
        return objectMapper.writeValueAsString(date);
    }
}

启动项目测试

SpringMVC学习笔记-狂神说_第29张图片

输出集合

SpringMVC学习笔记-狂神说_第30张图片

输出日期格式

SpringMVC学习笔记-狂神说_第31张图片

Jackson 默认是会把时间转成timestamps(时间戳)形式

3、Fastjson

fastjson.jar是 阿里 开发的一款专门用于Java开发的包,可以方便的实现json对象与JavaBean对象的转换,实现JavaBean对象与json字符串的转换,实现json对象与json字符串的转换。实现json的转换方法很多,最后的实现结果都是一样的。

导入依赖



    com.alibaba
    fastjson
    2.0.10

fastjson 三个主要的类:

(1) JSONObject 代表 json 对象

  • JSONObject实现了Map接口, 猜想 JSONObject底层操作是由Map实现的。
  • JSONObject对应json对象,通过各种形式的get()方法可以获取json对象中的数据,也可利用诸如size(),isEmpty()等方法获取"键:值"对的个数和判断是否为空。其本质是通过实现Map接口并调用接口中的方法完成的。

(2) JSONArray 代表 json 对象数组

  1. 内部是有List接口中的方法来完成操作的。
  2. JSON代表 JSONObject和JSONArray的转化

(3) JSON类源码分析与使用

仔细观察这些方法,主要是实现json对象,json对象数组,javabean对象,json字符串之间的相互转化。

FastJsonController.java

package com.kuang.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.kuang.pojo.User;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
public class FastjsonController {

    @RequestMapping("/fastJson")
    public String fastJson() {
        //创建对象
        User user1 = new User("安卓1", 12, "男1");
        User user2 = new User("安卓2", 12, "男2");
        User user3 = new User("安卓3", 12, "男3");
        User user4 = new User("安卓4", 12, "男4");
        List list = new ArrayList<>();
        list.add(user1);
        list.add(user2);
        list.add(user3);
        list.add(user4);

        String fast = JSON.toJSONString(list);

        System.out.println("*******Java对象 转 JSON字符串*******");
        String str1 = JSON.toJSONString(list);
        System.out.println("JSON.toJSONString(list)==>" + str1);
        String str2 = JSON.toJSONString(user1);
        System.out.println("JSON.toJSONString(user1)==>" + str2);

        System.out.println("\n****** JSON字符串 转 Java对象*******");
        User jp_user1 = JSON.parseObject(str2, User.class);
        System.out.println("JSON.parseObject(str2,User.class)==>" + jp_user1);

        System.out.println("\n****** Java对象 转 JSON对象 ******");
        JSONObject jsonObject1 = (JSONObject) JSON.toJSON(user2);
        System.out.println("(JSONObject) JSON.toJSON(user2)==>" + jsonObject1.getString("name"));

        System.out.println("\n****** JSON对象 转 Java对象 ******");
        User to_java_user = JSON.toJavaObject(jsonObject1, User.class);
        System.out.println("JSON.toJavaObject(jsonObject1, User.class)==>" + to_java_user);

        return fast;
    }

}

启动项目

SpringMVC学习笔记-狂神说_第32张图片

八、Ajax

1、什么是Ajax

SpringMVC学习笔记-狂神说_第33张图片SpringMVC学习笔记-狂神说_第34张图片

同步与异步区别

SpringMVC学习笔记-狂神说_第35张图片

SpringMVC学习笔记-狂神说_第36张图片

局部更新

资源跳转方式: 请求转发 重定向 (整体更新)

应用场景:

  • 购物时需要对商品的数量和白条进行局部更新
  • 内容自动补全
  • 用户登录失败的提示信息

 JS原生的异步无刷新方法

项目结构

SpringMVC学习笔记-狂神说_第37张图片

normalTest.html




    
    iframe测试体验无数新页面

    





请输入地址: