SpringMVC的解析与理解

SpringMVC的解析与理解

九月 19, 2022

SpringMVC的解析 和 部分运用

1、简单总结一下MVC

  • 一种基于Java实现的轻量级Web框架,spring框架的一个模块
  • 通过一套注解,让Java类成为处理请求的控制器,无需实现任何接口

是一种软件设计典范(设计的真的很不错),它是用一种 数据-界面显示-业务逻辑 分离的方法来组织代码(将众多的业务逻辑聚集到一个部件里面)

2、执行流程

先看图,我建议是结合代码看,便于理解

20200314193953559.png

  1. 用户点击某个请求路径,发起一个request请求,此请求会被前端控制器处理。
  2. 前端控制器请求处理器映射器去查找Handler。可以依据注解或者XML配置去查找。
  3. 处理器映射器根据配置找到相应的Handler(可能包含若干个Interceptor拦截器),返回给前端控制器。
  4. 前端控制器请求处理器适配器去执行相应的Handler处理器(常称为Controller)。
  5. 处理器适配器执行Handler处理器。
  6. Handler处理器执行完毕之后会返回给处理器适配器一个ModelAndView对象(SpringMVC底层对象,包括Model数据模型和View视图信息)。
  7. 处理器适配器接收到Handler处理器返回的ModelAndView后,将其返回给前端控制器。
  8. 前端控制器接收到ModelAndView后,会请求视图解析器(ViewResolver)对视图进行解析。
  9. 视图解析器根据View信息匹配到相应的视图结果,反馈给前端控制器。
  10. 前端控制器收到View具体视图后,进行视图渲染,将Model中的模型数据填充到View视图中的request域,生成最终的视图(View)。
  11. 前端控制器向用户返回请求结果。

以上是比较正式、且全面的说法,以下是我总结的关键部分

1.用户从客户端发起request请求,dispatchController(前端控制器)接收

2.dispatchController跑去找HandlerMapping帮忙,HandleMapping根据内容、注解或者配置去找到对应可以干活的Handler,返回这个Handler的信息给dispatchController

3.dispatchController再叫HandlerAdapter 让 Handler处理器 去执行这个操作

4.Handler处理器返回一个ModelAndView模型回去,先给中间商HandlerApater,再传给dispatchController

4.dispatchController接受到模型后,请求视图解析器(ViewResolver)解析一下

5.解析好了之后又还给dispatchController

6.dispatchController收到解析后的试图,将Model中的数据填充到View中的request域,生成最终的View

7.dispatchController向用户的客户端返回请求结果

3.SpringMVC的主要组件

看完上面,理解完了之后就会发现,组件其实就那几个

  1. 前端控制器(DispatchController):其作用是接收用户请求,然后给用户反馈结果。它的作用相当于一个转发器或中央处理器,控制整个流程的执行,对各个组件进行统一调度,以降低组件之间的耦合性,有利于组件之间的拓展。
  2. 处理器映射器(HandlerMapping):其作用是根据请求的URL路径,通过注解或者XML配置,寻找匹配的处理器信息。
  3. 处理器适配器(HandlerAdapter):其作用是根据映射器处理器找到的处理器信息,按照特定规则执行相关的处理器(Handler)。
  4. 处理器(Handler):其作用是执行相关的请求处理逻辑,并返回相应的数据和视图信息,将其封装至ModelAndView对象中。
  5. 视图解析器(ViewResolver):其作用是进行解析操作,通过ModelAndView对象中的View信息将逻辑视图名解析成真正的视图View(如通过一个JSP路径返回一个真正的JSP页面)。
  6. 视图(View):View是一个接口,实现类支持不同的View类型(JSP、FreeMarker、Excel等)

4、简单代码理解

①前端页面,提交一个表单

1
2
3
4
5
6
7
<form action="login.do" method="post">
名字<input type="text" name="name">
<br/>
密码<input type="text" name="password">
<br/>
<input type="submit" value="登录">
</form>

②后端页面

1
2
3
4
5
6
7
8
9
10
11
12
@Controller
public class LoginControl {
@RequestMapping("login")
public String Login(String name,String password){
if(name.equals("三")&&password.equals("123456"))
{
return "welcome"; //跳转到welcome.jsp
}else {
return "no";//跳转到no.jsp
}
}
}

③web.xml配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- 前端控制器  所有请求带.do后缀的都进入该前端控制器中-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>

<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>

简易的分为这三部分,比较好理解

5、重定向与转发

转发(在返回值前加forward:)

1
2
3
4
5
6
7
8
9
10
@RequestParam("/login")
public String redirect(User user){
if{
//登录成功...
}else{
//登录失败,转发到登录页面
return "forward:tologin";
}
}

重定向(在返回值前加redirect:)

1
2
3
4
5
6
7
8
9
10
@RequestParam("/login")
public String redirect(User user){
if{
//登录成功...
}else{
//登录失败,重定向到登录页面
return "redirect:tologin";
}
}

转发与重定向的区别

  • 转发是在服务端完成;重定向是在客户端完成
  • 转发速度块;重定向速度偏慢
  • 转发是一次不同的请求;重定向是俩次不同的请求

6、常用注解(个人觉得比较常用的)

  • @RequastMapping:处理请求url地址映射的注解,不用多说
  • @RequestBody:将前端传来的json数据,转换为java对象,一般写在传入的参数前面
  • @ResponseBody:将后端Controller代码中方法返回的对象转成json对象,响应给前端,一般写在方法的头上
  • @RestController注解相当于@ResponseBody + @Controller

@RequestParam与@PathVariable的区别

都是用在传入参数的前面

@PathVariable

@PathVariable用于接收uri地址传过来的参数,Url中可以通过一个或多个{Xxx}占位符映射,通过@PathVariable可以绑定占位符参数到方法参数中,在RestFul接口风格中经常使用

1
2
3
4
@RequestMapping("/user/{userId}/{userName}/query")
public User query(@PathVariable("userId") Long userId, @PathVariable("userName") String userName){
}

@RequestParam

@RequestParam用于将请求参数映射到控制器方法的形参上,有如下三个属性

  • value:请求中传入参数的名称,如果不设置后台接口的value值,则会默认为该变量名
  • required:该参数是否为必传项。默认是true,表示请求中一定要传入对应的参数,否则会报404错误,如果设置为false时,当请求中没有此参数,将会默认为null,而对于基本数据类型的变量,则必须有值,这时会抛出空指针异常
  • defaultValue:参数的默认值,如果请求中没有同名的参数时,该变量默认为此值
1
2
3
4
@RequestMapping("/list")
public JsonResult<List<User>> listUser(@RequestParam(required=false,defaultValue="0",value="page") int pageNum,@RequestParam(required=false,defaultValue="0",value="page") int pageSize){
return UserService.list();
}

7、SpringMVC用什么对象从后台向前台传递数据

1.使用Map、Model和ModelMap的方式,这种方式存储的数据是在request域中,用map比较好理解

1
2
3
4
5
6
7
8
9
10
11
12
13
@RequestMapping("/getUser")
public String getUser(Map<String,Object> map,Model model,ModelMap modelMap){
//1.放在map里
map.put("name", "xq");
//2.放在model里,一般是使用这个
model.addAttribute("habbit", "Play");
//3.放在modelMap中
modelMap.addAttribute("city", "gd");
modelMap.put("gender", "male");
return "userDetail";
}


2.使用request的方式

1
2
3
4
5
6
7
@RequestMapping("/getUser")
public String getUser(Map<String,Object> map,Model model,ModelMap modelMap,HttpServletRequest request){
//放在request里
request.setAttribute("user", userService.getUser());
return "userDetail";
}

3.使用ModelAndView(作为返回头)

1
2
3
4
5
6
7
@RequestMapping("/getUser")  
public ModelAndView getUser(ModelAndView modelAndView) {
mav.addObject("user", userService.getUser());
mav.setViewName("userDetail");
return modelAndView;
}