SpringMVC:
SpringMVC概念
SpringMVC是方法级别的拦截, SpringMVC的方法之间基本上独立的,独享request response数据.
它还可以和很多框架进行无缝集成,开发效率和性能高.
Spring Web MVC
Spring框架中提供的一个实现了MVC架构的功能模块,主要作用便于快速开发一个MVC架构的web应用程序.
SpringMVC模块中提供了很多web开发需要的工具API,用于简化开发过程.
SpringMVC框架的优点
1.基于Servlet的一个请求驱动,使用驱动响应模式开发
2.使用前端控制器模式来进行请求分发,将不同的请求分发给相应的控制器来进行处理.
3.可以使用基于方法级别的请求处理
4.支持Restful开发风格
SpringMVC的运行流程:
1. jsp页面
2. 匹配web.xml
(1) 防止POST请求中文乱码配置
(2)请求方式转换的过滤器
(3) SpringMVC主要是通过DispatcherServlet实现了Servlet这个接口,
又叫前端控制器,来自前端的请求会先到这里,它负责到后台取匹配合适的handler.
DispatcherServlet的主要工作流程:
1) 前端请求到达 DispatcherServlet
2)前端控制器请求HandlerMappering 查找 Handler
3)如果查找到存在的处理器,进一步去调用service和dao层
4) 返回结果再到controller层,渲染具体的视图,返回结果给页面
3.加载SpringMVC_beans.xml配置文件
4.开始扫描controller这个类,通过注解来找到自己需要的方法
5.通过SpringMVC_beans.xml里面的界面解析器配置 根据逻辑视图名称匹配到物理视图.
web.xml配置
<!--(1)防止POST请求中文乱码配置-->
<filter> <!--注意这里是filter,不要配置成servlet -->
<filter-name>CharactorFilter</filter-name> <!--过滤器名称 -->
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <!--过滤器的完整类名 -->
<init-param> <!--初始化参数 -->
<param-name>encoding</param-name> <!--参数名称 -->
<param-value>utf-8</param-value> <!--参数值 -->
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping> <!--过滤器映射 -->
<filter-name>CharactorFilter</filter-name><!--过滤器名称 -->
<url-pattern>/*</url-pattern><!--URL映射,给所有页面处理乱码 -->
</filter-mapping>
<!--(2)请求方式转换的过滤器 -->
<filter>
<filter-name>HiddenHTTPMethodFilter</filter-name>
<filter-class> org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHTTPMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--(3)struts2是通过过滤器对请求进行处理
springMVC主要是通过DispatcherServlet实现了Servlet这个接口,又叫前端控制器,来自前端的请求会先到达这里,它负责到后台去匹配合适的handler.
1.servlet比过滤器效率高 2.好管理-->
<servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<!-- 配置spring的bean配置文件 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springMVC_beans.xml</param-value>
</init-param>
<!-- 加载顺序,元素标记容器是否在启动的时候就加载这个servlet
(实例化并调用其init()方法).这是servlet不用初始化,而是交给容器可取处理 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!--前端控制器的映射路径配置,由于前端控制器是处理所有请求的,所以此处路径配置为根目录-->
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
springMVC_beans.xml配置
<!-- 扫描已经在spring配置文件中注册过的bean中的注解 -->
<context:annotation-config></context:annotation-config>
<!--扫描包底下的spring的注解,包含了<context:annotation-config>中的所有功能,而且还能扫描包中的spring注解 -->
<context:component-scan base-package="com.xalo.controller"></context:component-scan>
<!-- 自带了默认的handleMapping.Adapter,支持json,XML数据 -->
<mvc:annotation-driven></mvc:annotation-driven>
<!--静态资源请求不用前端控制器处理 -->
<mvc:resources location="/js/" mapping="/js/**"></mvc:resources>
<!-- 界面解析器配置 根据逻辑视图名称匹配到物理视图.
例如:逻辑视图名称为 hello 逻辑视图拼接上前缀后缀 /hello.jsp -->
<bean id="viewParse" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"></property> <!-- 前缀 -->
<property name="suffix" value=".jsp"></property> <!-- 后缀 -->
</bean>
springMVC错误信息
1. 405: 请求路径有误
2. 404: 请求参数有误
3. 400: 请求参数
springMVC塔建流程
1.导入相关jar包
2. 在web.xml中配置前端控制器(DispatcherServlet), 路径为 /
3. 在 springMVC bean的配置文件,扫描包注解,视图解析器
4. 在需要springMVC管理的实体中加上相应的注解
springMVC常用注解
@Controller
<!--@Controller:
将当前实体交给spring进行管理,等同于在IOC容器中配置了
<bean id="FirstController" class="包名.类名">
value:指定bean的id名称,如果不指定默认为类名-->
<!--@Controller:在spring IOC容器中注册该实体,并且表明该实体是后端控制器(Action)
1. Servlet 单例模式 与前端产生交流是通过doGet和doPost方法
2. struts2 Action 多例模式 通过成员变量
3. springMVC Controller 单例 多例等都可以-->
URL的形式
1.占位符形式: /aa/{name}
name就是占位符,前端可以为name赋值
2.Ant风格的URL:
? : 任意一个字符 例如: /a?b 可以是/acb /abb等
* : 任意0个或者多个字符,单独作为路径时不能省略
例如: /*/a 可以是 /aa/a /sss/a等
<!--如果*是作为目录存在,必须存在
如果*是作为目录名称的一部分存在,代表0个或者多个字符-->
<!--@RequestMapping("/*/tas")-->
@RequestMapping("/*tas")
public String testAntStar(){
System.out.println("url中*号的作用");
return "hello";
}
** : 任意多个路径
@RequestMapping("/**/tads")
public String testAntDoubleStar(){
System.out.println("url中**的作用");
return "hello";
}
@RequestMapping设置请求的映射
1.装饰类:等同于命名空间
要访问该类中的方法,需要拼接该路径,等同于package中的namespace属性
例如:
@Controller
@RequestMapping("/fc")
public class FirstController {
}
<form action="fc/xxxx.action" method="post"></form>
method: 不写默认为get请求
--->
2.修饰方法:
1.配置资源路径 :value = “路径”; 方法的访问路径类似于action的路径
2.设置请求方式: RequestMethod.请求方式 RequestMethod: 枚举
只要不设置默认的请求方式都是GET请求,要设置POST请求,用ajax或者form表单
3.指定前端提交的参数
params = {“参数1”, “参数2”,……}
(1) name: 当前请求时必须带参数名为name的参数
(2) !name: 参数中不能包含name
(3) name=”aa”: 前端提交的name的参数必须是ab
(4) name!= ‘aa’: 前端提交的name的参数不能是aa
@RequestMapping(value="/test", method=RequestMethod.GET, params={"name","age"})
4.headers: 设置请求头信息String[] 类型
TEST风格架构
HTTP的请求动作一般有四种:
a): GET获取资源
b): POST增加资源
c): PUT 修改资源
d): DELETE 删除资源
前端的请求方式只能是get或者post请求,所以我们需要将POST请求转化为PUT或者DELETE请求
通过此过滤器 HiddenHTTPMethodFilter 进行转换
在前端请求发起请求时,添加一个参数 _method 将此参数的值指定为请求类型 PUT或者DELETE
PUT 和 DELETE 不能设置一级路径(@RequestMapping(“/xxxx”),修饰类,直接修饰方法即可)
//(1)SecondController.java
@Controller
public class SecondController {
@RequestMapping(value="/testGET/{name}", method=RequestMethod.GET)
public String testGET(@PathVariable("name") String name){
System.out.println("查询某个学生的信息");
return "hello";
}
@RequestMapping(value="/testPOST",method=RequestMethod.POST)
public String testPOST(){
System.out.println("添加某个学生");
return "hello";
}
@RequestMapping(value="/testPUT",method=RequestMethod.PUT)
public String testPUT(){
System.out.println("修改某个学生的信息");
return "redirect:hello.jsp";
}
@RequestMapping(value="/testDELETE",method=RequestMethod.DELETE)
public String testDELETE(){
System.out.println("删除某个学生的信息");
return "redirect:hello.jsp";
}
}
//(2) hello.jsp
<h1>hello</h1>
//(3)index.jsp
<h1>REST风格架构</h1>
<form action="testGET/李白" method="get">
<input type="submit" value="get">
</form>
<br>
<form action="testPOST" method="post">
<input type="submit" value="post">
</form>
<br>
<form action="testPUT" method="post">
<input type="hidden" name="_method" value="put">
<input type="submit" value="put">
</form>
<br>
<form action="testDELETE" method="post">
<input type="hidden" name="_method" value="delete">
<input type="submit" value="delete">
</form>
@PathVariable:
获取路径中占位符的值
获取路径中占位符的值,value的值必须和占位符的名称一致
//name age 就是占位符,前端可以为name age赋值
@RequestMapping("/test/{age}/{name}")
public String testURL(@PathVariable("age") Integer age,
@PathVariable("name") String name) {
System.out.println(age);
System.out.println(name);
return "hello";
}
@RequestParam:
(1)接收前端传递过来的数据
value: 前端的参数名
required: 该参数前端是否必须提交 required默认是true
defaultValue: 为参数设置默认值,如果前端未提交该参数,defaultValue的值就是该参数的值.
如果前端提交的参数名和方法的参数名一致,可以不写该注解
@RequestMapping("/testParams")
public String getDataFromParams(@RequestParam(value="name",required=false,defaultValue="碧瑶") String name,
@RequestParam("age") Integer age) {
System.out.println(name);
System.out.println(age);
return "hello";
}
//前端提交的参数名和方法的参数名一致,可以不写注解
@RequestMapping("/testParams")
public String getDataFromParams(String name. Integer age){
System.out.println(name);
System.out.println(age);
return "hello";
}
(2)接收前端传递过来的数据
通过java对象来接受参数,将前端提交的参数,存入User对象中
前端的参数名必须和User中的成员变量名保持一致
如果User对象中的成员变量有非基本类型,前端参数名为user对象中的address.变量名
public class User{
private String name;
private Integer age;
private Address address;
//定义无参的构造方法
//定义setter getter方法
//重写toString() 方法
}
public class Address{
private String prov; //省
private String city; //市
private String area; //区
//定义无参的构造方法
//定义setter getter方法
//重写toString() 方法
}
@Controller
@RequestMapping("/fc")
public class FristController{
@RequestMappping("/testPOJO")
public String getDataPOJO(User user){
System.out.println(user);
return "hello";
}
}
<form action="fc/testPOJO" method="POST">
用户名: <input type="text" name="name"><br>
年 龄: <input type="text" name="age"><br>
省: <input type="text" name="address.prov">
<input type="submit">
</form>
@ModelAttribute:
作用: 业务方法执行之前,给参数赋值
1.在我们执行业务方法之前会先执行被此注解修饰的方法
2.如果业务方法的参数为POJO对象,将Model中此对象类名首字母小写的属性值和业务方法的参数绑定
3.前端提交过来的数据,就只更改POJO对应的成员变量
//(1)SecondController.java
@Controller
public class SecondController{
@ModelAttribute
public void queryUser(Model model){
//从数据库中检查出要修改信息的用户
User user = new User();
user.setName("碧瑶");
user.setAge(20);
Address address = new Address();
address.setProv("陕西");
address.setArea("西安");
address.setCity("雁塔");
//键必须要绑定的POJO类型的类名首字母小写
model.addAttribute("aa", user);
}
@RequestMapping("/update")
public String UpdateUserInfo(@ModelAttribute("aa") User user) {
System.out.println(user);
return "hello";
}
}
//(2) index.jsp
<h1>修改用户信息</h1>
<form action="fc/update">
age: <input type="text" name="age"><br>
<input type="submit">
</form>
@RequestMapping("/ant?")
public String testAnt(){
System.out.println("testURL");
return "hello";
}
向前端返回数据: 都是将数据存储在request中
所有的方法都是存放在请求域中,前端获取都是从请求域中获取到所有的数据
<1> ModeAndView: 此对象中封装了要返回的界面和数据
方法返回值类型为ModelAndView,当前方法的返回值就是ModelAndView对象
设置要返回的界面: setView(View); setViewName(“编辑视图逻辑名称”)
设置要返回给前端的数据:该数据存放在request中等同于 request setAttribute();
addObject(String,Object);
addAllObjects(map); 将map中的键值对存放在request中
<!--(1)FirstController.java-->
@Controller <!--将当前实体交给spring进行管理-->
@RequestMapping("/fc") <!--修饰类-->
public class FirstController{
<!--修饰方法-->
@RequestMapping("/tmav")
public ModelAndView testModelAndView(){
ModelAndView mv = new ModelAndView();
mv.setViewName("hello");
mv.addObject("name","道玄真人");
HashMap<String,Object> map = new HashMap<>();
map.put("age", 25);
map.put("height", 175.8);
mv.addAllObjects(map);
return mv;
}
}
<!--(2)hello.jsp-->
<h1>ModelAndView</h1>
<!--El表达式-->
<h1>${requestScope.name}</h1>
<h1>${requestScope.age}</h1>
<h1>${requestScope.height}</h1>
<!--(3)index.jsp-->
<a href = "fc/tmav">ModelAndView测试</a>
<2> map比较常用
方法的参数为Map类型
设置返回给前端的数据:map.put(key,value)将要返回给界面的数据添加到map即可
当前方法的返回值,是逻辑视图名称
<!--(1)FirstController.java-->
@Controller <!--将当前实体交给spring进行管理-->
@RequestMaping("/fc") <!--修饰类-->
public class FirstController {
@RequestMapping("/tm")
public String testMap(Map<String, Object> map) {
map.put("money",1000);
return "hello";
}
}
<!--(2)hello.jsp-->
<h1>Map</h1>
<h1>${requestScope.money}</h1>
<!--(3)index.jsp-->
<a href = "fc/tm">Map测试</a>
<3> Model
和Map一样,只是添加数据model.addAttribute(“属性名”,”属性值”)
<!--(1)FirstController.java-->
@Controller <!--将当前实体交给spring进行管理-->
@RequestMapping("/fc") <!--修饰类-->
public class FirstController {
@RequestMapping("/tmo")
public String testModel(Model model) {
model.addAttribute("aa","我是aa")
return "hello"
}
}
<!--(2)hello.jsp-->
<h1>Model</h1>
<h1>${requestScope.aa}</h1>
<!--(3)index.jsp-->
<a href = "fc/tmo">Map测试</a>
<4> ModelMap
既可以使用map形式添加数据,也可以使用Model形式添加数据
添加数据 mm.addAttribute(“属性名”, “属性值”)
<5> ServletAPI
<!--(1)FirstController.java-->
@Controller <!--将当前实体交给spring进行管理-->
@RequestMapping("/fc") <!--修饰类-->
public class FirstController {
@RequestMapping("/testServlet")
public String testServlet(HttpServletRequest request,HttpServletResponse response){
<!--接收前端传递过来的参数-->
String name = request.getParameter("name");
System.out.println(name);
<!--给前端返回数据-->
request.setAttribute("name", "张小凡");
return "hello";
}
}
<!--(2)hello.jsp-->
<h1>ServletAPI</h1>
<h1>${requestScope.name}</h1>
<!--(3)index.jsp-->
<a href="fc/testServlet?name=周帅">servletAPI测试</a>
<6> 将Model中的数据存储在session中
//(1) FirstController.java
@Controller
@RequestMapping("/fc")
@SessionAttributes(value = {"age","name"})
public class FristController{
@RequestMapping("/tmav")
public ModelAndView testModelAndView(){
ModelAndView mv = new ModelAndView();
mv.setViewName("hello");
mv.addObject("name", "道玄真人");
HashMap<String, Object> map = new HashMap<>();
map.put("age", 23);
map.put("height", 156.3);
mv.addAllObjects(map); //将map的键值对存放在request中
return mv;
}
//从session域中取值
@RequestMapping("/gsd")
public String getSessionData(){
return "hello";
}
}
//(2) hello.jsp
<h1>hello SpringMVC</h1>
<a href="gsd">从session中取值</a>
<h1>session</h1>
<h1>${sessionScope.name}</h1>
<h1>${sessionScope.age}</h1>
//(3) index.jsp
<a href = "fc/tmav">ModelAndView</a>