Web项目开发过程中一般都是使用MVC(Model-View-Controller)模式,早先的Struts2到Spring MVC,再到现在Spring Boot,都是相似的思

路。Spring Boot用多了就真的不想回到SSM或者SSH框架(虽然公司还在用Spring MVC),写这篇随笔,算是自己对Spring MVC内容的复习吧。

工作流程

DispatchServlet的配置方式

1、web.xml

2、通过将其配置在Servlet容器中(Tomcat7+版本要求)

/**
* AbstractAnnotationConfigDispatcherServletInitializer的拓展类会自动配置DispatchServlet和
* Spring ApplicationContext(应用上下文位于应用程序的Servlet上下文之中)
*/
public class SpittrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { /**
* 返回带有@Configuration注解的类用来定义ContextLoaderListener创建的应用上下文中的bean
* @return
*/
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{RootConfig.class};
} /**
* 返回带有@Configuration注解的类用来定义DispatchServlet创建的应用上下文中的bean
* @return
*/
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
} /**
* 将一个或多个路径映射到DispatchServlet上。"/"表示使用应用默认的Servlet,会理所有请求
* @return
*/
@Override
protected String[] getServletMappings() {
return new String[] {"/"};
}
}

配置DispatchServlet

public class WebConfig  extends WebMvcConfigurerAdapter{
//通常包含视图解析器配置
//静态资源处理
//。。。。。
}

WebConfig

DispatchServlet启动的时候,会创建Spring应用上下文,加载声明的bean,Spring Web应用中,通常还有另一个应用上下文,由

ContextLoaderListener创建

DispatchServlet:加载包含Web组件的bean,如控制器、视图解析器、处理器映射

ContextLoaderListener:加载应用中的其他bean,通常是驱动应用后端的中间层和数据层组件

常用注解

以下URL测试都是使用restlet client,也可以使用postman等工具

1、@EnableWebMvc:在配置类中开启Web MVC的配置支持,如一些ViewResolver或者MessageConverter等,不使用注解,需要重写

WebMvcConfigurerAdapter方法用于对SpringMVC的配置。

2、@RequestParam:

参数:name、value、defaultValue、required

分别代表:参数名、值、默认值(如果没有这个参数,给默认值),参数必须有,否则400错误(如果有defaultValue就不会有问题)

请求URL:http://localhost:8080/test5?id=1001&name&sex1=1

@RequestMapping(value = "/test5", method = RequestMethod.GET)
public String test5(@RequestParam int id, @RequestParam(value = "name", defaultValue = "zhangsan", required = true) String name) {
System.out.println("test2 id: " + id + " name: " + name );
return "index";
}
test2 id: 1001 name: zhangsan

name和value没有区别,value别名是name,name别名是value

public @interface RequestParam {
@AliasFor("name")
String value() default ""; @AliasFor("value")
String name() default ""; boolean required() default true; String defaultValue() default "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";
}

如果参数名一致,可以选择不使用@RequestParam

URL:localhost:8080/test?name=sam

public String test(HttpServletRequest request,  String name, ModelMap modelMap) {
modelMap.put("name", "sam");
log.info("param is {}", name);
return "home";
}

PS:我们使用@RequestParam只是因为能够提供name,required、defaultValue属性,否则可以选择不使用

3、@RequestMapping:

包含参数:value、method、params、headers、consumes、produces

1).直接使用默认:http://host:port/path?id=1001

@RequestMapping("test1")
public String test1(@RequestParam("id") String id) {
System.out.println("test1 id: " + id);
return "index";
}
test1 id: 1001

2).value、method:

value:指定请求的实际地址,或者使用URI Template模式

method:请求的方法类型,支持以下类型,可选择多种

public enum RequestMethod {
GET,
HEAD,
POST,
PUT,
PATCH,
DELETE,
OPTIONS,
TRACE; private RequestMethod() {
}
}
@ResponseBody
@RequestMapping(value = "/test1", method = RequestMethod.GET)
// @RequestMapping(value = "/test1", method = {RequestMethod.GET, RequestMethod.POST})
public String test1(@RequestParam("id") String id) {
System.out.println("test1 id: " + id);
return "index";
}

3).params、headers:

params: 指定request中必须包含某些参数值才能进入方法

headers: 指定request中必须包含某些指定的header值才能进入方法

@ResponseBody
@RequestMapping(value = "/test3", method = RequestMethod.GET, params = {"id=1001", "name", "!sex"}, headers = {"Accept"})
public String test3(@RequestParam int id, @RequestParam("name") String name, @RequestParam("abc") String addr) {
System.out.println("test2 id: " + id + " name: " + name + " addr: " + addr);
return "index";
}

params={"id=1001", "name", "!sex"}表示参数中,id必须为1001,必须包含name,不能包含sex,否则返回400 Bad Request状态码

headers = {"Accept"}表示请求头包含accept信息

4).consumes、produces

@RequestMapping(value = "/test1", method = RequestMethod.GET, params = {"!id", "name", "!sex"}
, headers = {"Accept"}, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public String test1(HttpServletRequest request, @RequestParam(value = "name", required = false) String name, ModelMap modelMap) {
modelMap.put("name", "sam");
log.info("param is {}", name);
return name;
}

consumes = MediaType.APPLICATION_JSON_VALUE表示request的content-type必须为application/json

produces = MediaType.APPLICATION_JSON_UTF8_VALUE表示response的content-type为application/json,编码为utf-8

4、@PathVariable:

参数:name、value、required,没有了defaultValue

请求URL:http://localhost:8080/test2/id/1001/name/sam

@ResponseBody
@RequestMapping(value = "/test2/id/{id}/name/{name}", method = RequestMethod.GET)
public String test4(@PathVariable("id") int id, @PathVariable("name") String name) {
System.out.println("test2 id: " + id + " name: " + name);
return "index";
}
test2 id: 1001 name: sam

到此时:我们可以看到@PathVariable和@RequestParam的区别

@PathVariable会把URL template变量映射到参数中,而@RequestParam中相当于request.getParameter("name"),去获取请求中的参数

5、表单验证@Valid:都在javax.validation.constraints包里面

public class Login {
@NotNull
@IsMobile
private String mobile; @NotNull
@Length(min=32)
private String password;
}
public Result<String> doLogin(HttpServletResponse response, @Valid LoginVo loginVo) {
log.info(loginVo.toString());
//登录
String token = userService.login(response, loginVo);
return Result.success(token);
}

6、@ResponseBody:支持将返回值放在response内,而不是一个页面,通常用户返回json/xml数据

@ResponseBody
public String test3() {
return "id";//这时候返回到页面的是String,而不是解析到id.html等类似的页面
}

6、@RequestBody:允许request的参数在request体中,而不是在直接连接在地址后面。例如通过ajax传递的json参数

@RequestMapping(value = "/test1", method = RequestMethod.GET, params = {"!id", "name", "!sex"}
, headers = {"Accept"}, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public String test1(HttpServletRequest request, @RequestBody String addr, @RequestParam(value = "name", required = false) String name, ModelMap modelMap) {
modelMap.put("name", "sam");
log.info("param is {} and {}", name, addr);
return name;
}

通过@RequestBody才能在get请求中得到Body中的参数,因为get请求默认只能读取URL中的参数

7、@RestController:相当于@Controller和@ResponseBody的组合,注解在类上,该Controller的所有方法都默认加上了@ResponseBody。

@Controller
@ResponseBody
public @interface RestController {
String value() default "";
}

9、@RequestHeader:把Request请求header部分的值绑定到方法的参数上

请求URL:http://localhost:8080/test6

@ResponseBody
@RequestMapping(value = "/test6", method = RequestMethod.GET)
public String test6(@RequestHeader("Accept-Encoding") String encoding) {
System.out.println("test2 contentType: " + encoding + " date: " );
return "index";
}
test2 contentType: gzip, deflate, br date: 

10、@CookieValue

@ResponseBody
@RequestMapping(value = "/test7", method = RequestMethod.GET)
public String test7(@CookieValue("JSESSIONID") String cookie) {
System.out.println("test2 cookie: " + cookie + " date: " );
return "index";
}
test2 cookie: 3E3E78E5E977EDBAEA388D8829BA2764

视图解析器

Spring自带13个视图解析器,常用的有:

InternalResourceViewResolver:一般用于JSP,在视图名称上面添加前缀和后缀,进而确定页面的物理地址,Prefix和suffix

FreeMarkerViewResolver和VelocityViewResolver分别对应FreeMaker和Velocity模板视图

注解部分参考:https://www.cnblogs.com/leskang/p/5445698.html

Spring框架系列(一)--Spring MVC基础知识的更多相关文章

  1. Spring框架系列(2) - Spring简单例子引入Spring要点

    上文中我们简单介绍了Spring和Spring Framework的组件,那么这些Spring Framework组件是如何配合工作的呢?本文主要承接上文,向你展示Spring Framework组件 ...

  2. Spring框架系列(6) - Spring IOC实现原理详解之IOC体系结构设计

    在对IoC有了初步的认知后,我们开始对IOC的实现原理进行深入理解.本文将帮助你站在设计者的角度去看IOC最顶层的结构设计.@pdai Spring框架系列(6) - Spring IOC实现原理详解 ...

  3. Spring框架系列(11) - Spring AOP实现原理详解之Cglib代理实现

    我们在前文中已经介绍了SpringAOP的切面实现和创建动态代理的过程,那么动态代理是如何工作的呢?本文主要介绍Cglib动态代理的案例和SpringAOP实现的原理.@pdai Spring框架系列 ...

  4. Spring框架系列(7) - Spring IOC实现原理详解之IOC初始化流程

    上文,我们看了IOC设计要点和设计结构:紧接着这篇,我们可以看下源码的实现了:Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的. ...

  5. Spring框架系列(8) - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等)

    上文,我们看了IOC设计要点和设计结构:以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的:容器中存放的是Bean的定义即Be ...

  6. Spring框架系列(9) - Spring AOP实现原理详解之AOP切面的实现

    前文,我们分析了Spring IOC的初始化过程和Bean的生命周期等,而Spring AOP也是基于IOC的Bean加载来实现的.本文主要介绍Spring AOP原理解析的切面实现过程(将切面类的所 ...

  7. Spring框架系列(10) - Spring AOP实现原理详解之AOP代理的创建

    上文我们介绍了Spring AOP原理解析的切面实现过程(将切面类的所有切面方法根据使用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor).本文在此基 ...

  8. Spring框架系列(12) - Spring AOP实现原理详解之JDK代理实现

    上文我们学习了SpringAOP Cglib动态代理的实现,本文主要是SpringAOP JDK动态代理的案例和实现部分.@pdai Spring框架系列(12) - Spring AOP实现原理详解 ...

  9. Spring框架系列(七)--Spring常用注解

    Spring部分: 1.声明bean的注解: @Component:组件,没有明确的角色 @Service:在业务逻辑层使用(service层) @Repository:在数据访问层使用(dao层) ...

随机推荐

  1. FineUI之使用SQL脚本从数据库表中生成对应的输入控件

    在WEB开发时.常常须要根据数据库表中的字段建立对应的输入控件,来获取输入的数据.每次都须要按字段来敲,显然太低效.并且easy出错.这里提供一个SQL脚本生成对应输入控件的方法. USE DBDem ...

  2. hdu 1711 KMP算法模板题

    题意:给你两个串,问你第二个串是从第一个串的什么位置開始全然匹配的? kmp裸题,复杂度O(n+m). 当一个字符串以0为起始下标时.next[i]能够描写叙述为"不为自身的最大首尾反复子串 ...

  3. C# 实现WEBSOCKET聊天应用示例

    C# 实现WEBSOCKET聊天应用示例 http://blog.163.com/da7_1@126/blog/static/10407267820121016103055506/ 2012-11-1 ...

  4. javascript遍历数组的两种方法

    var array=new Array(); array [0]="北京"; array [1]="天津"; ...//solution 1 for(var i ...

  5. 2015/12/29 Java语言概述 操作中注意事项

    java语言概述 ①版本分类:JavaSE 标准版 桌面开发                 JavaEE 企业版 网络开发                 JavaME 移动版 嵌入式开发(塞班系统 ...

  6. 容器LinkedList原理(学习)

    一.概述 数据结构和ArrayList有本质不同,LinkedList 是基于链表实现,它的插入和删除操作比 ArrayList 更加高效,基于链表的,所以随机访问的效率要比 ArrayList 差. ...

  7. JLabel作为展现元素时需要注意的事项

    如果没有内容,JLabel默认透明就无法作为点击区域了,所以为了让其可以响应鼠标事件需要设置 setOpaque(true) 这样就可以响应鼠标事件了 (吐槽一下,多年以前在大学做个web地图导航的网 ...

  8. flash、flex builder、flash builder、 air的关系

    flash VS flex builder flash被adobe收购的时候是flash8,已经可以AS2面向对象了. 而被adobe收购后,adobe准备把flash打造成一个开发工具.就比如JBU ...

  9. 蓝书2.3 Trie字典树

    T1 IMMEDIATE DECODABILITY poj 1056 题目大意: 一些数字串 求是否存在一个串是另一个串的前缀 思路: 对于所有串经过的点权+1 如果一个点的end被访问过或经过一个被 ...

  10. IJ:Eclipse快捷键大全

    ylbtech-IJ:Eclipse快捷键大全 1.返回顶部 1. Ctrl+1 快速修复(最经典的快捷键,就不用多说了)Ctrl+D: 删除当前行 Ctrl+Alt+↓ 复制当前行到下一行(复制增加 ...