概念

MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。

  • Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。
    通常模型对象负责在数据库中存取数据。
  • View(视图)是应用程序中处理数据显示的部分。
    通常视图是依据模型数据创建的。
  • Controller(控制器)是应用程序中处理用户交互的部分。
    通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。

MVC的目的是将Model和View的实现代码分离,从而使同一个程序可以使用不同的表现形式。对于同一批数据(Model),可以通过不同的View以不同的形式展示给用户。

配置

Servlet3.0之前

步骤

  1. 添加依赖
  2. 配置spring-config.xml
  3. 配置视图解析器
  4. 配置DispatcherServlet

原理

当Tomcat启动时,就会创建DispatcherServlet的对象,并且,DispatcherServlet会读取所配置的spring-configs.xml文件,以加载Spring环境,后续,DispatcherServlet将接收所有以.do为后缀的请求!

路径映射

  • 一个action配置多个URL映射
    @RequestMapping(value={“/index”, “/hello”}, method = {RequestMethod.GET})
  • URL请求参数映射
    @RequestMapping(value="/detail/{id}", method = {RequestMethod.GET})
    通过@PathVariable(value="id") Integer id接收
  • URL通配符映射“?”表示1个字符,“*”表示匹配多个字符,“**”表示匹配0个或多个路径
    SpringMVC会按照最长匹配优先原则(即映射配置中哪个匹配的最多)来匹配。
  • URL正则表达式映射Spring MVC还支持正则表达式方式的映射配置

参数传递

  • @RequestParam,绑定单个请求数据,可以是URL中的数据,表单提交的数据或上传的文件;可以和@RequestBody同用
  • @PathVariable,绑定URL模板变量值;
  • @CookieValue,绑定Cookie数据;
  • @RequestHeader,绑定请求头数据;
  • @ModelAttribute,绑定数据到Model;
  • @SessionAttributes,绑定数据到Session;
  • @RequestBody,用来处理Content-Type不是application/x-www-form-urlencoded编码的内容,例如application/json, application/xml等;
  • @RequestPart,绑定“multipart/data”数据,并可以根据数据类型进项对象转换;

@RequestBody 和 @RequestParam的区别

@RequestParam

用来处理Content-Type: 为 application/x-www-form-urlencoded编码的内容。(Http协议中,如果不指定Content-Type,则默认传递的参数就是application/x-www-form-urlencoded类型)

RequestParam可以接受简单类型的属性,也可以接受对象类型。
实质是将Request.getParameter() 中的Key-Value参数Map利用Spring的转化机制ConversionService配置,转化成参数接收对象或字段。

@RequestBody

处理HttpEntity传递过来的数据,一般用来处理非Content-Type: application/x-www-form-urlencoded编码格式的数据。

GET请求中,因为没有HttpEntity,所以@RequestBody并不适用。
POST请求中,通过HttpEntity传递的参数,必须要在请求头中声明数据的类型Content-Type,SpringMVC通过使用HandlerAdapter 配置的HttpMessageConverters来解析HttpEntity中的数据,然后绑定到相应的bean上。

总结

在GET请求中,不能使用@RequestBody。
在POST请求,可以使用@RequestBody和@RequestParam,但是如果使用@RequestBody,对于参数转化的配置必须统一。
RequestBody和RequestParam同时使用时,RequestParam等于get传输,加在url上。

SpringMVC运行流程

20200819205025

  1. 用户发送请求至前端控制器DispatcherServlet。
  2. DispatcherServlet收到请求调用HandlerMapping处理器映射器。
  3. 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
  4. DispatcherServlet调用HandlerAdapter处理器适配器。
  5. HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
  6. Controller执行完成返回ModelAndView。
  7. HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
  8. DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
  9. ViewReslover解析后返回具体View。
  10. ispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
  11. DispatcherServlet响应用户。

实现REST

RESTful即Representational State Transfer (资源)“表现层状态转换”。RESTful不是一种标准,而是一种设计风格。
优点: 结构清晰、符合标准、易于理解、扩展方便
RESTful本质上是一种分布式系统的应用层解决方案,它的主要作用是充分并正确利用HTTP协议的特性,规范资源获取的URL路径。
通俗地讲,RESTful风格的设计允许将参数通过URL拼接传到服务端,目的是让URL看起来更简洁实用。并且对于不同操作,要指定不同的HTTP方法(POST/GET/PUT/DETELE)。
可以这么说,只要是具有上述相关约束条件和原则的应用程序或设计就可以被称为RESTful风格的应用。

URL

URI: /资源名称/资源标识 HTTP请求方式区分资源CRUD操作

普通CRUD(uri来区分操作) RESTfulCRUD
查询 getEmp emps–GET
添加 addEmp emps–POST
修改 updateEmp?id=xxx emps/{id}–PUT
删除 deleteEmp?id=xxx emps/{id}–DELETE

如上:uri中不应该包含动词,只能有名词,并且名词中也应该使用复数。实现者应使用相应的Http动词GET、POST、PUT、PATCH、DELETE、HEAD来操作这些资源即可

返回数据格式

对于合法的请求应该统一返回数据格式,这里演示的是json

  • code——包含一个整数类型的HTTP响应状态码。
  • status——包含文本:”success”,”fail”或”error”。HTTP状态响应码在500-599之间为”fail”,在400-499之间为”error”,其它均为”success”(例如:响应状态码为1XX、2XX和3XX)。这个根据实际情况其实是可要可不要的。
  • message——当状态值为”fail”和”error”时有效,用于显示错误信息。参照国际化(il8n)标准,它可以包含信息号或者编码,可以只包含其中一个,或者同时包含并用分隔符隔开。
  • data——包含响应的body。当状态值为”fail”或”error”时,data仅包含错误原因或异常名称、或者null也是可以的

成功:

1
2
3
4
5
6
7
8
9
10
{
"status": "successs",
"code": 200,
"message": "success",
"data": {
"userName": "123456",
"age": 16,
"address": "beijing"
}
}

失败:

1
2
3
4
5
6
{
"status": "fail",
"code": 401,
"message": "error message",
"data": null
}

REST配置

修改路径配置,过滤所有请求类型的请求至前端控制器

1
2
3
4
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

静态资源访问

  • 原因:
    由于JavaWeb的保护机制,WEB-INF文件夹下的文件不可以直接访问,但配置拦截后所有静态资源访问都会被拦截;

  • 解决方法:

    • 单个放行:在SpringMVC的核心配置文件中使用mvc:resource标签配置静态资源的解析路径,将需要加载的静态资源的URI路径配置在标签中,然后配置该URI映射的真实资源路径。例:

      1
      2
      3
      4
      <!-- 静态资源的解析,包括:js/css/img... -->
      <mvc:resources location="/js/" mapping="/js/**"/>
      <mvc:resources location="/css/" mapping="/css/**"/>
      <mvc:resources location="/img/" mapping="/img/**"/>

      当在SpringMVC的核心配置文件中配置了静态资源文件的解析路径后,前端控制器就会根据请求URL中的具体子路径来映射出静态资源的真实路径,然后为前端反馈真实的静态资源信息。

    • 全部放行:在SpringMVC的核心配置文件中使用<mvc:default-servlet-handler/>配置默认的Servlet处理器。
      该配置将在SpringMVC上下文中定义一个DefaultServletHttpRequestHandler,它会对进入DispatcherServlet前端控制器的请求进行筛查,如果发现是没有经过映射的请求,就将该请求交由Web应用服务器默认的Servlet处理,如果不是静态资源的请求,才由DispatcherServlet前端控制器继续处理。此时就可以将请求中的静态资源与其他业务请求分开处理,从而正常地返回静态资源信息。
      <mvc:default-servlet-handler/>

权限控制

当系统启动的时候会将所有权限信息加入到Map集合,URL作为key,有此权限访问该URL的角色作为value;然后具体某个用户登录的时候会首先获取其对应的角色,存到session中;当该用户访问某个具体的URL时会进行角色判断其是否由此权限进行访问

步骤

定义拦截器

1
2
3
4
5
6
7
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<mvc:exclude-mapping path="/**/*.js" />
<bean class="com.xqm.filter.LoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>

定义一个类在启动的时候加载所有功能对应的权限

1
2
3
4
5
6
7
8
public class AuthorityCache{
public static Map<String, Object> Authority_MAP = new HashMap<>(16);
static{
// 如1-交易所 2-机构管理员 24-表示仓库机构有权限
//定义访问网页需要的权限
Authority_MAP.put("/warehouse/init", ",1,24,29");
}
}

定义拦截方法继承HandlerInterceptorAdapter并重写其三个方法,在Controller之前执行

参考

面试官:你连RESTful都不知道我怎么敢要你?

SSM搭建