springMVC
回顾MVC
MVC是模型(Model) 、视图(View) 、控制器(Controller) 的缩写,是一种软件设计规范。
Model : javaBean (1.处理业务逻辑,2. 封装数据) View: 视图 jsp/html(展示数据) controller:控制器 (1.接收请求,2.调用模型,3.转发视图)
是将业务逻辑、数据、显示进行分离的方式来组织代码。
MVC主要作用是降低了视图与业务逻辑间的耦合度。
MVC不是一种设计模式,MVC是一种架构模式。当然不同的MVC存在一些差异!
SpringMVC概述
Spring MVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架。它可以通过一套注解,让一个简单的Java类成为控制器,而无须实现任何接口。
简单一句话:SpringMVC简化Servlet的开发!!
总结:
SpringMVC主要解决web层的代码,本质是Servlet
Spring MVC的特点
1. 轻量级,简单易学 2. 高效 , 基于请求响应的MVC框架 3. 与Spring兼容性好,无缝结合 4. 约定优于配置(SpringBoot) 5. 功能强大:RESTful、数据验证、格式化、本地化、主题等 6. 简洁灵活
springmvc 整体架构
原理-流程-springmvc面试必问
1、用户发起请求到控制器 DispatcherServlet(前端控制器) 2、前端控制器去handlerMapper查找Handler对象 3、HandlerMapper返回HandlerExecutorChain 执行链(包含两部分内容:Handler ,拦截器集合) 4、前端控制器,通过HandlerAdapter 适配器执行 Handler对象 5、Handler处理具体的业务逻辑 6、Handler处理完业务逻辑之后,返回ModelAndView 其中的View是视图名称 7、将ModelAndView返回前端控制器 8、前端控制器,通过ModelAndView 中的视图名称。在视图解析器中查找视图 9、返回真正的View 视图对象 10、渲染视图 11、返回用户响应
springmvc入门
创建一个工程
创建的maven web工程
导入依赖
<!--springmvc依赖包,springmvc 只有这一个包--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.9.RELEASE</version> </dependency> <!--serlvet--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <!--jsp--> <dependency> <groupId>javax.servlet</groupId> <artifactId>jsp-api</artifactId> <version>2.0</version> <scope>provided</scope> </dependency> <!--日志--> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.6.4</version> </dependency> <!--测试--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency>
tomcat插件
<build> <plugins> <!--添加tomcat插件--> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <port>8080</port> <path>/</path> </configuration> </plugin> </plugins> </build>
dispatcherServlet控制器
配置web.xml中的添加dispatcherServlet
<!--前端控制器--> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--加载指定配置文件--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-servlet.xml</param-value> </init-param> <!--指定servlet在tomcat启动时创建--> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <!-- springmvc基于拦截器实现; 拦截所有的controller请求,都会进入controller类中 / 拦截所有controller请求, 包括 webapp下的静态资源如:html,js,css,img (不包括jsp) /* 拦截所有controller请求,包括 webapp下的静态资源如: jsp(包括jsp) html,js,css,img .. *.xx *.do 匹配后缀 --> <url-pattern>*.do</url-pattern> </servlet-mapping>
springmvc核心配置文件
- springmvc-servlet.xml中的约束
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> </beans>
自定义Handler(Controller)
public class Hello implements Controller { public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView mv = new ModelAndView(); mv.addObject("msg","这是第一个springmvc程序!!"); //设置视图名 hello仅仅是视图的名字 mv.setViewName("hello"); return mv; } }
配置HandlerMapping&HandlerAdapter -了解
<!--HandlerMapping springmvc会自己配置无需配置 --> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/> <!--HandlerAdapter springmvc会自己配置无需配置--> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
配置handler
<!--配置自定义的Handler,controller--> <bean name="/hello.do" class="cn.yanqi.controller.Hello"/>
配置视图解析器
通过源码分析,可以看是放在WEB-INF下
<!--配置视图解析器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean>
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> ${msg} </body> </html>
测试
请求过程分析
注解开发
入门案例中的思考: 1、每个类需实现Controller,麻烦 2、每个类只能处理一个业务逻辑,不能是controller处理多个业务逻辑。 3、每一个Controller都需要进行配置 使用注解:解决上述问题
创建controller类
package cn.yanqi.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; /** * @Auther: yanqi */ @Controller //表示当前是一个controller类 @RequestMapping("hello2") public class Hello2 { // @RequestMapping(value="/show1.do") // @RequestMapping("show1.do") // @RequestMapping("/show1") @RequestMapping("show1") public ModelAndView test1(){ ModelAndView mv = new ModelAndView(); mv.addObject("msg","这是第一个springmvc注解!!"); //设置视图名 hello仅仅是视图的名字 mv.setViewName("hello"); return mv; } @RequestMapping("show2") public ModelAndView test2(){ ModelAndView mv = new ModelAndView(); mv.addObject("msg","这是第一个springmvc注解!!"); //设置视图名 hello仅仅是视图的名字 mv.setViewName("hello"); return mv; } }
配置注解扫描器
<!--配置注解扫描包 扫描含有@Controller的类 --> <context:component-scan base-package="cn.yanqi"/> <!--开启注解驱动--> <mvc:annotation-driven/>
测试
五种映射
1、标准URL映射 2、Ant风格的URL映射* ** 3、占位符映射 @requestMapping (show/{userid}/{name} ) 方法中(@pathVariable(“ userid”) String id) http://localhost/hello2/833/yanqi.do 4、限制请求方式映射 @requestMapping ( value=“ show2” , method=requestMehtod.POST) 错误405 @GetMapping @PostMapping 5、限制请求参数映射 @requestMapping( value=”show3” , params=”abc”) 方法中(@requestParam(“abc”) String abc)
标准映射
/** * 标准映射 * @return */ @RequestMapping(value = "/show1.do") public ModelAndView test1(){ ModelAndView mv = new ModelAndView(); mv.addObject("msg","这是第一个springmvc注解!!"); //设置视图名 hello仅仅是视图的名字 mv.setViewName("hello"); return mv; }
Ant风格的URL映射
单级目录匹配 @RequestMapping("test/*/show") 访问: /test/a/show.do 访问: /test/abc/show.do 单级目录匹配: @RequestMapping("test/**/show") 访问: hello/test/a/b/c/show.do
//http://localhost:8080/hello2/test/a/b/c/show4.do //http://localhost:8080/hello2/test/a/show4.do 多级目录可以写单级目录 @RequestMapping("/test/**/show4") public ModelAndView test4(){ ModelAndView mv = new ModelAndView(); mv.addObject("msg","我是多级目录"); mv.setViewName("hello"); return mv; } //http://localhost:8080/hello2/test/a/show4.do @RequestMapping("/test/*/show5") public ModelAndView test5(){ ModelAndView mv = new ModelAndView(); mv.addObject("msg","我是单级目录"); mv.setViewName("hello"); return mv; }
占位符映射
@RequestMapping(“/user/{userId}/query")
通过*@PathVariable(“xxx”)* 获取请求路径中参数值
/** * 占位符 * @param itemId * @param name * @return */ @RequestMapping("/show6/{itemId}/{name}") public ModelAndView test6(@PathVariable("itemId") String itemId ,@PathVariable("name") String name){ ModelAndView mv = new ModelAndView(); mv.addObject("msg","占位符:"+itemId +" : "+name); mv.setViewName("hello"); return mv; }
限制请求方式映射
RequestMethod.POST @PostMapping(“xx”)
RequestMethod.GET @GetMapping(“xx”)
405 请求方式不合法
//get post 两种请求方式 @RequestMapping(value = "/show9",method = {RequestMethod.POST,RequestMethod.GET}) public ModelAndView test9(){ ModelAndView mv = new ModelAndView(); mv.addObject("msg","限定请求方式为 GET , POST"); mv.setViewName("hello"); return mv; } //post 请求方式 @RequestMapping(value = "/show8",method = RequestMethod.POST) public ModelAndView test8(){ ModelAndView mv = new ModelAndView(); mv.addObject("msg","限定请求方式为 POST "); mv.setViewName("hello"); return mv; } //get 请求方式 @RequestMapping(value = "/show7",method = RequestMethod.GET) public ModelAndView test7(){ ModelAndView mv = new ModelAndView(); mv.addObject("msg","限定请求方式为 GET "); mv.setViewName("hello"); return mv; }
//post 请求方式 @PostMapping("show11") public ModelAndView test11(){ ModelAndView mv = new ModelAndView(); mv.addObject("msg","限定请求方式为 POST"); mv.setViewName("hello"); return mv; } //get 请求方式 @GetMapping("show10") public ModelAndView test10(){ ModelAndView mv = new ModelAndView(); mv.addObject("msg","限定请求方式为 GET"); mv.setViewName("hello"); return mv; }
<html> <head> <title>Title</title> </head> <body> <form action="/hello2/show11.do" method="post"> <input type="submit"> </form> </body> </html>
接口测试工具 : postmain
限定请求参数
可以防止用户把不必要的信息注入进来
400 请求参数不合法
@GetMapping(value = "show15",params = "id") 必须包含id @GetMapping(value = "show15",params = "!id") 不能包含id @GetMapping(value = "show15",params = "id!=1007") 包含id其值不为1007
- 代码演示
//请求参数必须包含id 方式一 @GetMapping(value = "show15",params = "id") public ModelAndView test15(@RequestParam("id") int id){ ModelAndView mv = new ModelAndView(); mv.addObject("msg","限定请求参数:"+id); mv.setViewName("hello"); return mv; } //请求参数必须包含id 方式二 @GetMapping("show12") public ModelAndView test12(@RequestParam("id") int id){ ModelAndView mv = new ModelAndView(); mv.addObject("msg","限定请求参数:"+id); mv.setViewName("hello"); return mv; } //请求参数不参包含id @GetMapping(value ="show14",params = "!id") public ModelAndView test14(@RequestParam("name") String name){ ModelAndView mv = new ModelAndView(); mv.addObject("msg","限定请求参数:"+name); mv.setViewName("hello"); return mv; } //请求参数包含id其值不能为1007 @GetMapping(value ="show13",params = "id!=1007") public ModelAndView test13(@RequestParam("id") int id){ ModelAndView mv = new ModelAndView(); mv.addObject("msg","限定请求参数:"+id); mv.setViewName("hello"); return mv; }
SpringMVC页面跳转
转发
返回字符串
@Controller @RequestMapping("test") public class TestController { //第一种 ModelAndView 转发到视图解析器 @RequestMapping("show") public ModelAndView show(){ return new ModelAndView("hello"); } //第二种 String 转发到视图解析器 @RequestMapping("show2") public String show2(){ return "hello"; } //第三种 void 没有返回的视图 @RequestMapping("show3") @ResponseStatus(HttpStatus.OK) public void show3(){ System.out.println("我没有要返回的结果。。。"); } //第四种 转发--通过servlet内置对象 @RequestMapping("show4") @ResponseStatus(HttpStatus.OK) public void show5(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //转发 -- 视图解析器 request.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(request,response); } }
forward关键字
以上我们用string类型,只能转发到视图解析器下, webapp下就无法转发,forward就可以解决
//第一种 转发--webapp 页面 @RequestMapping("show3") public String show3(){ return "forward:/user.html"; //转发到webapp下的user.html } //第二种 转发--webapp controller类 @RequestMapping("show4") public String show4(){ return "forward:/userController/getUser.do";//转发到controller中 } //第三种 转发--ModelAndView @RequestMapping("show5") public ModelAndView show5(ModelAndView mv) { mv.setViewName("forward:/user.html");//webapp下 return mv; } //第四种 转发--通过servlet内置对象 @RequestMapping("show6") @ResponseStatus(HttpStatus.OK) public void show5(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //转发 -- webapp下 request.getRequestDispatcher("/user.html").forward(request,response); }
重定向
redirect关键字
此关键字的底层:response.sendRedirect(“web项目地址+重定向地址”);
@Controller @RequestMapping("test") public class TestController { //第一种 重定向 ModelAndView @RequestMapping("show5") public ModelAndView show5(){ ModelAndView mv = new ModelAndView(); mv.setViewName("redirect:/user.html");//重定向webapp下的具体页面 // mv.setViewName("redirect:/UserController/show1.do");//重定向具体的controller return mv; } //第二种 重定向 redirect关键字 @RequestMapping("show6") public String show6(){ return "redirect:/user.html"; // return "redirect:/UserController/show1.do"; } //第三种 重定向 绑定servlet内置对象 @RequestMapping("show7") public void show7(HttpServletRequest request ,HttpServletResponse response) throws IOException { response.sendRedirect(request.getContextPath()+"/user.html"); // response.sendRedirect(request.getContextPath()+"/UserController/show1.do"); } }
SpringMVC存储数据
servlet存数据
@RequestMapping("/requestAPI") public void requestAPI(HttpServletRequest request, HttpServletResponse response) throws Exception { request.setAttribute("name", "江一燕"); request.getRequestDispatcher("/list.jsp").forward(request, response); }
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> list页面 ${name} </body> </html>
Model存数据
ModelAndView 存数据
Model 存数据
ModelMap 存数据
Map 存数据
以上都存在放request域中
//方式一 ModelAndView存数据 @RequestMapping("TestModelAndView") public ModelAndView modelAndView(ModelAndView mv) { mv.addObject("name", "小面包"); // 设置数据 mv.setViewName("list");// 设置视图 return mv; } //方式二 Model @RequestMapping("TestModel") public String modelAndView(Model model) { model.addAttribute("email","yanqi@126.com"); return "forward:/list.jsp"; } //方式三 ModelMap @RequestMapping("TestModelMap") public String modelAndView(ModelMap modelMap) { modelMap.addAttribute("city","beijing"); return "forward:/list.jsp"; } //方式四 Map @RequestMapping("TestMap") public String modelAndView(Map<Object,Object> map) { map.put("age",28); return "forward:/list.jsp"; }
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h3>我是list页面</h3> ${requestScope.name} ${requestScope.email} ${requestScope.city} ${requestScope.age} </body> </html>
url-pattern
关于SpringMVC的\解读
一、\的作用
二、\配置详解
(1) .do
(2) /
(3) /
三、静态资源访问
方法一:使用
方法二:使用
目录显示问题无法处理
关于SpringMVC的解读
一、的作用
首先我们要知道配置的作用:将请求当作一个controller处理,然后dispatcherServlet(中央调度器)去调用HandleMapping(处理器映射器)查找到相应的处理器。
简单的来说就是匹配到的请求会去寻找controller
二、配置详解
(1) *.do
*.do会匹配这种格式的请求(请求地址),然后去查看controller中是否有这样的的controller。
(2) /
匹配根目录下的所有请求,包括静态资源的获取请求,例如:.css,.js,.html等静态资源,但是不会匹配到.jsp这样的后缀的url。
也就是说这些.html的请求都会被当作一个controller去请求,这样肯定是访问不到的,会报错404。
但是不会匹配到.jsp这样的后缀的url,也就是说.jsp就不会被经过dispatcherServelt,可以直接被访问,因此我们配置为\的时候就会访问.jsp是不会报错的,能被访问到。
(3) /*
匹配根目录下的所有请求,包括静态资源的获取请求,例如:.css,.js,.html等静态资源,包括.jsp这样的后缀的url。
也就是说这些,无论什么请求都会被当作一个controller来处理,所以我们在访问这些静态资源的时候都会报404错误。
三、静态资源访问
我们写成上面的/或者/*,就不能访问静态资源了,但是这样是不行的。所以我们再经过一些配置就可以访问静态资源了。
方法一:使用mvc:default-servlet-handler/
声明了后 springmvc 框 架 会 在 容 器 中 创 建DefaultServletHttpRequestHandler 处理器对象。它会像一个检查员,对进入 DispatcherServlet 的 URL 进行筛查,如果发现是静态资源的请求,就将该请求转由 Web 应用服务器默认的 Servlet 处理。一般的服务器都有默认的 Servlet。
在 Tomcat 中,有一个专门用于处理静态资源访问的 Servlet 名叫 DefaultServlet。其为 default。可以处理各种静态资源访问请求。该 Servlet 注册在 Tomcat 服务 器的 web.xml 中。在 Tomcat 安装目录/conf/web.xml。
记得
声明注解驱动:mvc:annotation-driven />
方法二:使用mvc:resources/
声明格式:
location:标识静态资源所在目录。目录不要使用/WEB-INF/及其子目录。
mapping:标识对该资源的请求,全部资源注意是两个*号。
例:
记得
声明注解驱动:mvc:annotation-driven />
当作一个controller来处理,所以我们在访问这些静态资源的时候都会报404错误。
三、静态资源访问
我们写成上面的/或者/*,就不能访问静态资源了,但是这样是不行的。所以我们再经过一些配置就可以访问静态资源了。
方法一:使用mvc:default-servlet-handler/
声明了后 springmvc 框 架 会 在 容 器 中 创 建DefaultServletHttpRequestHandler 处理器对象。它会像一个检查员,对进入 DispatcherServlet 的 URL 进行筛查,如果发现是静态资源的请求,就将该请求转由 Web 应用服务器默认的 Servlet 处理。一般的服务器都有默认的 Servlet。
在 Tomcat 中,有一个专门用于处理静态资源访问的 Servlet 名叫 DefaultServlet。其为 default。可以处理各种静态资源访问请求。该 Servlet 注册在 Tomcat 服务 器的 web.xml 中。在 Tomcat 安装目录/conf/web.xml。
记得
声明注解驱动:mvc:annotation-driven />
方法二:使用mvc:resources/
声明格式:
location:标识静态资源所在目录。目录不要使用/WEB-INF/及其子目录。
mapping:标识对该资源的请求,全部资源注意是两个*号。
例:
记得
声明注解驱动:mvc:annotation-driven />