Spring MVC
spring mvc:是spring框架的一个模块,spring mvc和spring之间无需通过中间层进行整合。spring mvc是一个基于mvc的web框架
mvc:是一个设计模式,
B/S中(Browser/Server,浏览器/服务器模式)
mvc中的c:是用户通过发送request请求给服务器的控制器,也就是controller层,控制器请求模型进行处理,过然后控制器将模型数据填充到request中发送给view进行渲染,发送给viewer进行渲染,然后进行响应给用户(B/S视图下无法将数直接填充到视图)
mvc中的m:是model,包括pojo,action,service,dao,负责将处理结果返回给controller层
mvc中的v:是view,也就是渲染层。
Spring MVC框架运行流程和内部构造:
第一步:发起请求到前端控制器(DispatcherServlet)
第二步:前端控制器请求HandlerMapping 查找Handler,可以根据xml和注解来进行查找
HandlerMapping:Handler相当于一个指针,可在不同界面之间传递数据 (https://blog.csdn.net/nmwwbreed/article/details/79485773),
而HandlerMapping 是处理器映射器,由 DispatcherServlet 调用,DispatcherServlet 会从容器中取 出所有 HandlerMapping 实例并遍历,让 HandlerMapping 实例根据自己实现类的方式去尝试查找 Handler
第三步:处理器映射器HandlerMapping向前端控制器返回Handler
第四步:前端控制器调用处理适配器去执行Handler
第五步:处理适配器HHandlerAdapter去执行Handler
第六步:Handler执行完成给适配器返回ModelAndView
第七步:处理器适配器向前端控制器返回ModelAndView
第八步:前端控制器视图解析器Viewresolver去进行视图解析(根据视图解析名解析成真正的视图(jsp))
第九步:视图解析器向前端控制器返回View
第十步:前端控制器进行视图渲染
视图渲染将模型数据(在ModelAndView对象中)填充到request域
第十一步:前端控制器向用户响应结果
1、前端控制器 DispatcherServlet:作用是结收请求,响应结果,相当于转发器
2、处理器映射器 HandlerMapping:作用是根据请求的URL查找Handler
3、处理器适配器 HandlerAdapter:作用按照特定规则(HandlerAdapter要求的规则)去执行Handler
注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler
4、视图解析器 Viewresolver
作用是进行视图解析,=根据逻辑视图名解析成真正的视图(View)
5、视图 View
View是一个接口,实现类姐支持不同的View类型(jsp,freemaker,pdf…)
Spring MVC 中,处理器映射器,处理器配置器,视图解析器称为Spring MVC的三大组件,在配置文件中使用mvc:annotation-driven可替代这三个组件的注解配置
RequestMapping注解
RequestMapping:用于建立请求URL和处理请求方法之间的对应关系
用户端发的请求必须要和对应方法建立关联关系,也就是映射,可以放在方法上也可以放在类上,放在类上请求的时候需要写二级目录,用来表示某一个模块
属性:
value和path属性可以互换,也就是说
@RequestMapping(path="/testRequestMapping")
@RequestMapping(value="/testRequestMapping")
只有洗个属性时value可以省略不写,也就是可以为:@RequestMapping("/testRequestMapping")
但是如果有多个属性时,value和path不能省略不写
method属性其中的类RequestMethod是一个枚举类,method的值是用于限制请求类型,如:method={RequestMethod.POST}被使用时,本方法只能接受Post请求,若是其他请求则会报405
是get类型的请求
params属性用于吸顶限制请求参数的条件,支持简单的表达式,要求请求参数的key和value必须和配置的一模一样。是一个字符串数组类型,其中的字符表示请求此方法的时候要传过来一个属性,如果不传,则会报BadRequest错误,使用方法如图:
1、若请求时不加属性
1、若请求时加属性
运行成功,如果这样配置的话和传什么值无关。但是如果params中规定了以什么名称传的话,就必须匹配,如下面栗子:
请求参数绑定
请求时加属性,传到后台,后台就会将其视为键值对,如username=“hahaha”中的username会自动匹配testparams方法中的参数名,并将其值传入方法中的形参中
请求参数绑定实体类型
例1、
表单中的action是将表单提交到params/testAccount路径下的类中
要求输入框的名称必须和被封装的类的变量名相同,否则无法匹配
例2、
在Account类中引入一个User类,将输入信息封装到Account类对象中
封装user对象时,必须要指定对象名和变量名
RequestParam注解
作用:
把请求中指定名称的参数给控制器中的形参赋值
属性:
value/name:请求参数中的名称
required:请求参数中是否必须提供此参数,默认值:true。表示必须提供,如果不提供将报错
栗子:
错误:
对传入数据的名称有要求,必须和@requestParam中定义的属性相同
正确:
RequestBody注解
作用:
用于获取请求体内容,直接使用得到的是key=value&key=value…结构的数据。 get请求方式不适用
属性:
required:是否必须有请求体。默认值是true。当请求方式为true时,get请求方式会报错。如果取值为false,get请求得到的数据将是null
栗子:
<form action="/params/testRequestbody" method="post">
用户姓名:<input type="text" name="uname"><br/>
用户年龄:<input type="text" name="age"><br/>
<input type="submit" value="submit"/>
</form>
@RequestMapping("/testRequestbody")
public String testRequestbody(@RequestBody String body){
System.out.println("已运行~");
System.out.println(body);
return "success";
}
PathVariable注解
作用:
用于绑定URL中的占位符。例如:请求URL中/delete/{id},这个{id}就是URL占位符
属性:
value:用于指定URL中占位符的名称
required:是否必须提供占位符
<a href="params/testPathVariable/10">测试程序</a> //注意格式,10不需要用{ }括起来
@RequestMapping("/testPathVariable/{id}")
public String testPathVariable(@PathVariable(name = "id") String id){
System.out.println("已运行~");
System.out.println(id);
return "success";
}
CookieValue注解
作用:
用于把指定cookie的值传入控制器的方法参数
属性:
value:指定cookie的名称
required:是否必须有此cookie
<a href="params/testCookieValue">测试程序</a>
@RequestMapping("/testCookieValue")
public String testCookieValue(@CookieValue(value = "JSESSIONID") String CookieValue){
System.out.println("已运行~");
System.out.println(CookieValue);
return "success";
}
ModelAttribute注解
作用:
出现在方法上,表示当前方法会在控制器的方法之前执行,先执行,可以修饰没有返回值的方法,也可以修饰有返回值的方法,出现在参数上,获取指定数据给参数赋值
属性:
value:用于获取数据的key,key可以是POJO 的属性,也可以是map结构的key
应用场景:
档表单提交数据不是额安正的实体类数据时,保证没有提交数据的字段使用数据库对象原来的数据
当前方法会在控制器的方法之前执行
@RequestMapping("/testModelAttribute")
public String testModelAttribute(){
System.out.println("ModelAttribute已运行~");
return "success";
}
@ModelAttribute
public void showUser(){
System.out.println("User已运行~");
}
<form action="/params/testModelAttribute" method="post">
用户姓名:<input type="text" name="uname"><br/>
用户年龄:<input type="text" name="age"><br/>
用户生日:<input type="text" name="date"><br/>
<input type="submit" value="submit"/>
</form>
有返回值
<form action="/params/testModelAttribute" method="post">
用户姓名:<input type="text" name="uname"><br/>
用户年龄:<input type="text" name="age"><br/>
<!--user对象少获取到一个date值,可以通过利用后台uname从ModelAttribute从持久层获取到-->
<input type="submit" value="submit"/>
</form>
@RequestMapping("/testModelAttribute")
public String testModelAttribute(User user){//由于是showUser方法先执行,所以testModelAttribute可以获取到showUser方法返回的uesr
System.out.println("ModelAttribute已运行~");
System.out.println(user);
return "success";
}
//相当于是加了一层缓冲,来处理数据
@ModelAttribute
public User showUser(String uname,Integer age){
System.out.println("User已运行~");
//通过用户名查询数据库(模拟持久化)
User user = new User();
user.setUname(uname);
user.setAge(age);
user.setDate(new Date());
return user;//返回给testModelAttribute()方法
}
无返回值
<form action="/params/testModelAttribute" method="post">
用户姓名:<input type="text" name="uname"><br/>
用户年龄:<input type="text" name="age"><br/>
<!--user对象少获取到一个date值,可以通过利用后台uname从ModelAttribute从持久层获取到-->
<input type="submit" value="submit"/>
</form>
@RequestMapping("/testModelAttribute")
public String testModelAttribute(@ModelAttribute("abc") User user){//用@ModelAttribute注解修饰user对象,也就是将abc对应的value赋值给user
System.out.println("ModelAttribute已运行~");
System.out.println(user);
return "success";
}
@ModelAttribute
public void showUser(String uname, Integer age, Map<String,User> map){
System.out.println("User已运行~");
//通过用户名查询数据库(模拟)
User user = new User();
user.setUname(uname);
user.setAge(age);
user.setDate(new Date());
map.put("abc",user);
}
SessionAttribute注解
作用
用于实现各个控制器之间的参数共享(对session的操作),jsp页面需要用到EL表达式
属性
value/names:用于指定存入的属性名称
name:用于指定存入的数据类型
<a href="params/testsessionAttributes">testsessionAttributes</a>
<br/>
<a href="params/getsessionAttributes">getsessionAttributes</a>
@SessionAttributes(names = "wcc")//把wcc=wang存入到session对象域中,只能作用于类上,不能作用于方法上。
@RequestMapping("/testsessionAttributes")
public String testsessionAttributes(Model model){
System.out.println("testsessionAttributes~");
model.addAttribute("wcc","wang");//以map形式存储
return "success";
}
@RequestMapping("/getsessionAttributes")
public String getsessionAttributes(ModelMap modelMap){//以map形式读取
System.out.println("getsessionAttributes~");
String name = (String)modelMap.get("wcc");
System.out.println(name);
return "success";
}