编程知识 cdmana.com

SpringBoot强化篇(四)--Spring MVC框架的整合及原理分析

Spring MVC 简介

在大型软件系统设计时,业务一般会相对复杂,假如所有业务实现的代码都纠缠在一起,会出现逻辑不清晰、可读性差,维护困难,改动一处就牵一发而动全身等问题。为了更好解决这个问题就有了我们现在常说的分层架构设计。

MVC 是什么

MVC是一种软件架构设计思想,基于MVC架构将我们的应用软件进行分层设计和实现,例如可以分为视图层(View),控制层(Controller),模型层(Model),通过这样的分层设计让我们程序具备更好的灵活性和可可扩展性.因为这样可以将一个复杂应用程序进行简化,实现各司其职,各尽所能.比较适合一个大型应用的开发.
视图(View) - UI设计人员进行图形界面设计,负责实现与用户交互。
控制器(Controller)- 负责获取请求,处理请求,响应结果。
模型(Model) - 实现业务逻辑,数据逻辑实现。
image.png

Spring MVC 概述

Spring MVC是MVC设计思想在Spring框架中的一种实现,基于这样的思想spring框架设计了一些相关对象,用于更好的基于MVC架构处理请求和响应,其简易架构如图所示:
image.png
1.前端控制器 DispatcherServlet是客户端所有请求处理的入口,负责请求转发。
2.处理器映射器 RequestMapping负责存储请求url到后端handler对象之间的映射。
3.处理器适配器 Handler 用于处理DispatcherServlet对象转发过来的请求数据。
4.视图解析器 ViewResolver负责处理所有Handler对象响应结果中的view。

Spring MVC 快速入门

准备工作

第一步:创建项目module,基本信息如图所示:

image.png

第二步:添加项目依赖(可以在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,这些资源可以在启动服务器以后,直接在浏览器进行访问。
image

templates 目录分析及应用

templates 目录为springboot工程创建时添加了thymeleaf依赖以后自动创建的目录,此目录中要存储一些html模板,这个模板页面不能直接通过浏览器url进行访问,需要基于后端控制器,在方法中定义页面响应
image
其中,假如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 + ''' +
                '}';
    }
}

版权声明
本文为[禾白少二]所创,转载请带上原文链接,感谢
https://segmentfault.com/a/1190000037792495

Scroll to Top