在大型软件系统设计时,业务通常会相对复杂,假如全部业务实现的代码都纠缠在一块儿,会出现逻辑不清晰、可读性差,维护困难,改动一处就牵一发而动全身等问题。为了更好解决这个问题就有了咱们如今常说的分层架构设计。css
MVC是一种软件架构设计思想,基于MVC架构将咱们的应用软件进行分层设计和实现,例如能够分为视图层(View),控制层(Controller),模型层(Model),经过这样的分层设计让咱们程序具有更好的灵活性和可可扩展性.由于这样能够将一个复杂应用程序进行简化,实现各司其职,各尽所能.比较适合一个大型应用的开发.
▪ 视图(View) - UI设计人员进行图形界面设计,负责实现与用户交互。
▪ 控制器(Controller)- 负责获取请求,处理请求,响应结果。
▪ 模型(Model) - 实现业务逻辑,数据逻辑实现。html
Spring MVC是MVC设计思想在Spring框架中的一种实现,基于这样的思想spring框架设计了一些相关对象,用于更好的基于MVC架构处理请求和响应,其简易架构如图所示:
1.前端控制器 DispatcherServlet是客户端全部请求处理的入口,负责请求转发。
2.处理器映射器 RequestMapping负责存储请求url到后端handler对象之间的映射。
3.处理器适配器 Handler 用于处理DispatcherServlet对象转发过来的请求数据。
4.视图解析器 ViewResolver负责处理全部Handler对象响应结果中的view。前端
第一步:建立项目module,基本信息如图所示:java
第二步:添加项目依赖(能够在module建立时,也能够建立后),代码以下:web
Spring Web 依赖(提供了spring mvc支持而且会嵌入一个tomcat)spring
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
Thymeleaf 依赖(提供了以html做为页面模板进行解析和操做的相关对象)json
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
static 目录为springboot工程建立时添加了web依赖之后自动建立的目录,此目录中能够存储html、css、js、image,这些资源能够在启动服务器之后,直接在浏览器进行访问。segmentfault
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,而后响应到客户端,如何实现呢?
第一步:定义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); } }
咱们在执行业务的过程当中一般会将一些请求参数传递到服务端,服务端如何获取参数并注入给咱们的方法参数的呢?
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对象,用于接受客户端请求参数,例如:
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 + ''' + '}'; } }