上一期我们写到原生版本的SpringMVC的执行流程
配置web.xml的DispatcherSrevlet和Spring容器Spring容器的配置文件使用bean注册处理器映射器,处理器适配器,和视图解析器写一个类实现Controller表示这个就是Controller,并返回ModelAndView给视图解析器显而易见这样我们能清晰的分析出SpringMVC的执行流程
用户的请求交给服务器,服务器会在启动的时候加载web.xml文件注册了DispathcerServlet并指出Sping容器的加载文件,这时前端处理器会根据请求进行映射,处理器映射的这个类在Spring容器中已经注册过了,映射器(HandlerMapping)会把请求映射为HandlerExecutionChain类型的handler对象交给这个中央控制器;然后中央处理器将handler对象作为参数传递给适配器(HandlerAdapter)的实例化对象,适配器对其进行处理,还会调用其他模型层最后返回ModelAndView给前端处理器。前端处理器调用视图解析器对视图名进行前缀和后缀拼接,并且前端处理器进行视图渲染(将模型装入view中)。
具体的流程我们是清楚了,但是实际开发我们不会采取这样的方法,太过于复杂,下面来介绍介绍注解开发
使用这个注解直接表示这个类是Controller,不需要再实现controller接口并重写方法。 为了保证Spring能找到控制器类,还需要在Sping容器配置文件中添加扫描配置信息。如下:
(1)配置文件中引入约束spring-context (2)使用<context:component-scan base-package="com.sang.controller"/>这里的base-package表示的是包名,需要扫描的包名。
这里<context:component-scan base-package="com.sang.controller"/>指定了com.sang.controller这个包,在运行的时候,该包以及包下所有标注了注解的类都会被Spring所识别并处理。
控制器负责解析用户的请求并且将其转化为一个模型其中规定了各样的复杂的访问应用程序的方式对比: 使用注解的方式比原生的方法更加简单,同时,原生实现的实现类只能处理一个单一的请求动作,而基于注解的方式可以同时处理多个请求动作,更加灵活,节省开发者的效率
Spring容器通过@Controller注解找到相应的 控制器类后,还需要知道控制器内部是对每个请求是如何处理的,这就需要使用RequestMqpping注解类型。RequestMapping注解类型用于映射一个请求或者一个方法。
当标注在方法上时 表示该请求会直接映射成指定的value值,例如: @RequestMapping(value= "/admin") public String fun1(Model model){ model.addAttribute("msg","hello!"); return "hello"; }当用户发送请求http://localhost:8080/springmvc-05/adminDispatcherServlet会直接找项目下/admin对应的方法,这个方法中,传递了参数Model类型的数据,加入了一个字符串属性的值,方法最后返回一个字符串,而字符串返回到视图解析器中,视图解析器会根据规定的前缀和后缀来拼接字符串就像/WEB-INF/jsp/hello.jsp,然后给前端控制器,随后前端控制将模型渲染在jsp或者其他的前端模板页面里,返回给用户。
当标注在类上时 @Controller @RequestMapping(value= "/user") public class MyCotroller{ @RequestMapping("/admin") public String fun1(Model model){ model.addAttribute("msg","hello!"); return "hello"; } }当用户在地址栏上访问localhost:8080/springmvc-05/user/admin同上原理一致,但是访问的请求在层级目录上分的很明确,用户在/user下访问/admin请求,中央处理器就会处理指定的“层级目录”下的请求方法,然后返回给视图解析器一个视图名称,最后解析为“WEB-INF/jsp/xxx.jsp"让中央处理器去返回给用户。
啥也不写,默认的属性是value
目的:简化HTTP方法的映射
GetMapping:匹配Get方式的请求PostMapping:匹配Post方式的请求PutMapping:匹配Put方式的请求DeleteMapping:匹配Delete方式的请求PatchMapping:匹配Patch方式的请求 标注了@GetMapping的方法的请求如下 @GetMapping(value= "/admin") public String fun1(Model model){ model.addAttribute("msg","hello!"); return "hello"; }与@RequestMapping注解方法(如下)一致
@RequestMapping(value= "/admin",method=RequestMethod) public String fun1(Model model){ model.addAttribute("msg","hello!"); return "hello"; }在我们常见的SpringMVC的使用中,我们见过最多的是return一个字符串 如下:
@GetMapping(value= "/admin") public String fun1(Model model){ model.addAttribute("msg","hello!"); return "hello"; }这里String类型的返回值会被"Servlet"传递到视图解析器中,视图解析器得到字符串会拼接前缀和后缀,成为“/WEB-INF/jsp/hello.jsp”,然后ViewResolver就会把该逻辑视图路径解析为真正的View视图对象,然后通过View的渲染,将最终结果返回给中央处理器,然后呈现给用户
但是还有另外的使用方法: ServletAPI
通过设置ServletAPI , 不需要视图解析器 .
1、通过HttpServletResponse进行输出
2、通过HttpServletResponse实现重定向
3、通过HttpServletResponse实现转发
@Controller public class ResultGo { @RequestMapping("/result/t1") public void test1(HttpServletRequest req, HttpServletResponse rsp) throws IOException { rsp.getWriter().println("Hello,Spring BY servlet API"); } @RequestMapping("/result/t2") public void test2(HttpServletRequest req, HttpServletResponse rsp) throws IOException { rsp.sendRedirect("/index.jsp"); } @RequestMapping("/result/t3") public void test3(HttpServletRequest req, HttpServletResponse rsp) throws Exception { //转发 req.setAttribute("msg","/result/t3"); req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req,rsp); } }我们的Controller里的标注了注解的方法其实也就相当于一个个的Servlet,直接通过Servlet的API进行视图转发,这时不需要制图解析器,不信可以注释掉MVC配置文件中的视图解析器。
测试前,需要将视图解析器注释掉
@Controller public class ResultSpringMVC { @RequestMapping("/rsm/t1") public String test1(){ //转发 return "/index.jsp"; } @RequestMapping("/rsm/t2") public String test2(){ //转发二 return "forward:/index.jsp"; } @RequestMapping("/rsm/t3") public String test3(){ //重定向 return "redirect:/index.jsp"; } }重定向 , 不需要视图解析器 , 本质就是重新请求一个新地方嘛 , 所以注意路径问题.可以重定向到另外一个请求实现 .
@Controller public class ResultSpringMVC2 { @RequestMapping("/rsm2/t1") public String test1(){ //转发 return "test"; } @RequestMapping("/rsm2/t2") public String test2(){ //重定向 return "redirect:/index.jsp"; //return "redirect:hello.do"; //hello.do为另一个请求/ } }传统方式操作资源 :通过不同的参数来实现不同的效果!方法单一,post 和 get
http://localhost/item/queryItem.action?id=1 查询,GET
http://localhost/item/saveItem.action 新增,POST
http://localhost/item/updateItem.action 更新,PUT
http://localhost/item/deleteItem.action?id=1 删除,GET或POST
RestFul风格 使用RESTful操作资源 :可以通过不同的请求方式来实现不同的效果!如下:请求地址一样,但是功能可以不同!
http://127.0.0.1/item/1 查询,GET
http://127.0.0.1/item 新增,POST
http://127.0.0.1/item 更新,PUT
http://127.0.0.1/item/1 删除,DELETE
Controller层
@GetMapping(value="/admin/{a}/{b}") public String test(@PathVariable int a,@PathVariable int b, Model model){ model.addAttribute("msg",a+b); return "hello"; }访问http://localhost:8080/springmvc-05/admin/1/5结果如下: 这里@PathVariable int a,@PathVariable int b会将URL里的参数赋值,最后在model中加入参数msg的值是a+b,呈现给用户。
RestFul风格的好处:URL更加简洁,获取参数更加方便,框架会自动进行类型转换。通过路径变量的类型可以约束访问参数,如果类型不一样,则访问不到对应的请求方法,如这里访问是的路径是/commit/1/a,则路径与方法不匹配,而不会是参数转换失败。所有的地址栏请求默认都会是 HTTP GET 类型的。