乐趣区

关于spring-mvc:SpringBoot强化篇四Spring-MVC框架的整合及原理分析

Spring MVC 简介

在大型软件系统设计时,业务个别会绝对简单,如果所有业务实现的代码都纠缠在一起,会呈现逻辑不清晰、可读性差,保护艰难,改变一处就牵一发而动全身等问题。为了更好解决这个问题就有了咱们当初常说的分层架构设计。

MVC 是什么

MVC 是一种软件架构设计思维, 基于 MVC 架构将咱们的应用软件进行分层设计和实现, 例如能够分为视图层(View), 管制层(Controller), 模型层(Model), 通过这样的分层设计让咱们程序具备更好的灵活性和可可扩展性. 因为这样能够将一个简单应用程序进行简化, 实现各司其职, 各尽所能. 比拟适宜一个大型利用的开发.
▪ 视图(View)– UI 设计人员进行图形界面设计,负责实现与用户交互。
▪ 控制器(Controller)- 负责获取申请,解决申请,响应后果。
▪ 模型(Model)– 实现业务逻辑,数据逻辑实现。

Spring MVC 概述

Spring MVC 是 MVC 设计思维在 Spring 框架中的一种实现,基于这样的思维 spring 框架设计了一些相干对象,用于更好的基于 MVC 架构解决申请和响应,其繁难架构如图所示:

1. 前端控制器 DispatcherServlet 是客户端所有申请解决的入口, 负责申请转发。
2. 处理器映射器 RequestMapping 负责存储申请 url 到后端 handler 对象之间的映射。
3. 处理器适配器 Handler 用于解决 DispatcherServlet 对象转发过去的申请数据。
4. 视图解析器 ViewResolver 负责解决所有 Handler 对象响应后果中的 view。

Spring MVC 疾速入门

筹备工作

第一步:创立我的项目 module,根本信息如图所示:

第二步:增加我的项目依赖(能够在 module 创立时,也能够创立后),代码如下:

Spring Web 依赖(提供了 spring mvc 反对并且会嵌入一个 tomcat)

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Thymeleaf 依赖(提供了以 html 作为页面模板进行解析和操作的相干对象)

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

static 目录剖析及利用

static 目录为 springboot 工程创立时增加了 web 依赖当前主动创立的目录,此目录中能够存储 html、css、js、image,这些资源能够在启动服务器当前,间接在浏览器进行拜访。

templates 目录剖析及利用

templates 目录为 springboot 工程创立时增加了 thymeleaf 依赖当前主动创立的目录,此目录中要存储一些 html 模板,这个模板页面不能间接通过浏览器 url 进行拜访,须要基于后端控制器,在办法中定义页面响应

其中, 如果 default.html 要在放在 templates 子目录中, 则还须要在配置文件中配置 thymeleaf 的前缀

#server port
server.port=80
#spring web
spring.thymeleaf.prefix=classpath:/templates/health/
spring.thymeleaf.suffix=.html
#spring thymeleaf
spring.thymeleaf.cache=false

定义 HealthController 类来测试

package com.cy.pj.health.controller;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
@Controller
public class HealthController {//Handler 对象 来解决 DispatcherServlet 散发过去的申请
    // 三种状况
    //1. 只返回页面
    //2. 返回 json 字符串
    //3. 返回页面加参数
     @RequestMapping("/doPrint")
     @ResponseBody
     public void doPrint(HttpServletResponse response) throws Exception{Map<String,Object> map =new HashMap<>();
         map.put("username", "tony");
         map.put("state", true);
         //return map ;
         // 将 map 中的数据转换成 json 格局的字符串,底层实现如下
         ObjectMapper om=new ObjectMapper();
         String jsonStr=om.writeValueAsString(map);//jackson 中转换 json 字符串的办法
         System.out.println("jsonStr="+jsonStr);
         // 将字符串响应到客户端
         response.setCharacterEncoding("utf-8");// 批改编码方式
         response.setContentType("text/html;charset=utf-8");// 通知客户端咱们的编码格局让其以这种形式解析数据
         PrintWriter pw = response.getWriter();// 写入响应流中
         pw.println(jsonStr);
     }
     @RequestMapping("/doHealth")
     public String doHealth(Model model) {model.addAttribute("username","张三");
        model.addAttribute("state","亚健康");
        return "default"; // 返回的字符串交给 ViewResolver 视图解析器,会主动剖析,传参且出现页面
     }
     @RequestMapping("/health.html")
     @ResponseBody
     // 应用此注解形容管制办法时,用于通知 spring 框架,这个办法返回值能够依照特定格局(例 json 字符串)进行转换,来响应客户端
     // 将转换当前的后果写到 response 对象的响应体中
     // f 昂发的返回值不再封装为 ModelAndView 对象,不会再交给视图解析器进行解析,而是间接基于 response 对象响应到客户端
     public Map<String, Object> doHealth(){Map<String,Object> map =new HashMap<>();
         map.put("username", "tony");
         map.put("state", true);
         return map ;
     }
    //public ModelAndView doHealth(){// 此办法由 DispatcherServlet 对象通过反射调用
        //ModelAndView mv =new ModelAndView();
        //mv.setViewName("default");//viewname
        //mv.addObject("username","李四");
        //mv.addObject("state","亚健康");// 传的是个对象,所以能够传的不止字符串
        //return mv;
     //1. 返回值会交给 DispatcherServlet 对象进行解决
     //2.DispatcherServlet 对象会调用 viewresolver 对后果进行解析
     //2.1 基于 viewname 找对应的 view 页面(prefix+viewname+suffix)//2.2 将 model 中的数据填充到 view 页面上
     //2.3 返回一个带有 module 数据的页面给 DispatcherServlet
     //3.DispatcherServlet 将带有 model 数据的页面返回给客户端
    
    //public String doHealth(){
    //   return "default" ;// 能够间接返回对应名字的页面
    //    }
}

JSON 数据响应

咱们有一业务不须要页面, 只须要将响应数据转换为 json, 而后响应到客户端, 如何实现呢?
第一步: 定义 ResponseResult 对象用于封装响应数据, 例如:

package com.cy.pj.module.pojo;
public class ResponseResult {
    private Integer code;
    private String message;
    public Integer getCode() {return code;}
    public void setCode(Integer code) {this.code = code;}
    public String getMessage() {return message;}
    public void setMessage(String message) {this.message = message;}
}

第二步: 定义 JsonObjectController 以及办法, 代码如下:

package com.cy.pj.health.controller;
import com.cy.pj.health.pojo.ResponseResult;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
@RestController//=@Controller+@ResponseBody
public class JsonObjectController {@RequestMapping("/doConvertResponseToJson")
    public ResponseResult doConvertResponseToJson(){ResponseResult rs=new ResponseResult();
 rs.setCode(200);
 rs.setMessage("OK");
 return rs;
 }
    @RequestMapping("/doConvertMapToJson")
    public Map<String,Object> doConvertMapToJson(){Map<String,Object> map=new HashMap<>();
 map.put("username","刘德华");
 map.put("state",true);
 return map;
 }
    @RequestMapping("/doPrintJSON")
    public void doPrint(HttpServletResponse response)throws Exception{Map<String,Object> map=new HashMap<>();
 map.put("username","刘德华");
 map.put("state",true);
 // 将 map 中的数据转换为 json 格局字符串
 ObjectMapper om=new ObjectMapper();
 String jsonStr=om.writeValueAsString(map);
 System.out.println("jsonStr="+jsonStr);
 // 将字符串响应到客户端
 // 设置响应数据的编码
 response.setCharacterEncoding("utf-8");
 // 通知客户端, 要向它响应的数据类型为 text/html, 编码为 utf-8. 请以这种编码进行数据出现
 response.setContentType("text/html;charset=utf-8");
 PrintWriter pw=response.getWriter();
 pw.println(jsonStr);
 }
}

SpingMVC 申请参数数据处理

咱们在执行业务的过程中通常会将一些申请参数传递到服务端, 服务端如何获取参数并注入给咱们的办法参数的呢?

package com.cy.pj.health.controller;
import com.cy.pj.health.pojo.RequestParameter;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
public class ParamObjectController {
//    @GetMapping
//    @PostMapping
 // 对申请加了限度类型,如果类型不匹配客户端会报 405 谬误(申请类型不匹配)@RequestMapping("/doParam01")
    public String doMethodParam(@RequestParam(required = false) String name){// 间接量接管申请参数,参数名要与申请参数名雷同
 // 加了 @RequestParam(required = false) 示意能够传参能够不传 如果注解不加 required 参数 会报错 400(参数类型数量不匹配)return "request params" +name;
 }
    @RequestMapping("/doParam02")
    public String doMethodParam(RequestParameter param){//pojo 对象接管申请参数,pojo 对象中需提供与参数名相匹配的 set 办法
 return "request params" +param.toString();}
    @RequestMapping("/doParam03")
    public String doMethodParam(@RequestParam Map<String,Object> param){// 应用 map 接管参数时需应用注解 @RequestParam 对参数进行形容
 return "request params" +param.toString();}
}

POJO 对象形式

定义 pojo 对象, 用于承受客户端申请参数, 例如:

package com.cy.pj.module.pojo;
public class RequestParameter {
    private String name;
    //......
 public String getName() {return name;}
    public void setName(String name) {this.name = name;}
    @Override
 public String toString() {
        return "RequestParam{" +
                "name='" + name + '''+'}';
    }
}
退出移动版