目录
壹、SpringMVC简介
1、SpringMVC中重要组件
- DispatcherServlet: 前端控制器,接收所有请求(如果配置/不包含 jsp)
- HandlerMapping: 解析请求格式的.判断希望要执行哪个具体的方法
- HandlerAdapter: 负责调用具体的方法
- ViewResovler:视图解析器.解析结果,准备跳转到具体的物理视图
2、关于SpringMVC的运行原理图
3、Spring容器和SpringMVC容器的关系
Spring容器和SpringMVC容器是父子容器
SpringMVC 容器中能够调用 Spring 容器的所有内容
一、SpringMVC环境搭建
- 导入jar包
- 在 web.xml 中配置前端控制器 DispatcherServlet
- 如 果 不 配 置 <init-param> 会 在/WEB-INF/<servlet-name>-servlet.xml
-
<!-- 配置前端的控制器 --> <servlet> <servlet-name>tk</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>tk</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
- 在src下新建springmvc.xml文件
- 导入xmlns:mvc 命名
-
<?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: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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!-- 扫描注解 --> <context:component-scan base-package="com.tk.controller"></context:component-scan> <!-- 注解驱动 --> <!--org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandler Mapping --> <!--org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerA dapter --> <mvc:annotation-driven></mvc:annotation-driven> <!-- 静态资源 --> <!-- 一个*表示当前文件这一层的文件,而俩个星是当前目录下的所有文件 --> <mvc:resources location="/js/" mapping="/js/**"></mvc:resources> <mvc:resources location="/css/" mapping="/css/**"></mvc:resources> <mvc:resources location="/image/" mapping="/image/**"></mvc:resources> </beans>
二、字符编码过滤器
在web.xml里面配置Filter
<!-- 配置字符编码过滤器 -->
<filter>
<filter-name>encoding</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>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
三、传参
- 把内容写到方法(HandlerMethod)参数中,SpringMVC 只要有这个内容,注入内容
- 基本数据类型参数
- 默认保证参数名称和请求中传递的参数名相同
-
@RequestMapping("demo1") public String demo1(String name,String password,HttpServletRequest req){ System.out.println(name+"---------"+password); System.out.println("执行demo1"); if(name.equals("张三")&&password.equals("123456")) return "mian.jsp"; else{ req.setAttribute("error", "账号密码错误"); return "index.jsp"; } }
-
如果请求参数名和方法参数名不对应使用@RequestParam()赋值
-
@RequestMapping("demo3") public String demo1(@RequestParam("name1")String name,@RequestParam("password1")String password,HttpServletRequest req){ System.out.println(name+"---------"+password); System.out.println("执行demo1"); if(name.equals("张三")&&password.equals("123456")) return "mian.jsp"; else{ req.setAttribute("error", "账号密码错误"); return "index.jsp"; } }
-
-
如果方法参数是基本数据类型(不是封装类)可以通过@RequestParam 设置默认值.
-
防止没有参数时 500
-
@RequestMapping("demo2") public String demo2(@RequestParam(defaultValue="11")String name){ System.out.println("执行demo2"+ name); return "index.jsp"; }
-
-
如果强制要求必须有某个参数
-
@RequestMapping("demo2") public String demo2(@RequestParam(required=true)String name){ System.out.println("执行demo2"+ name); return "index.jsp"; }
-
-
HandlerMethod 中参数是对象类型
-
请求参数名和对象中属性名对应(get/set 方法)
-
@RequestMapping("demo1") public String demo1(User u,HttpServletRequest req){ System.out.println(u.getName()+"---------"+u.getPassword()); System.out.println("执行demo1"); if(u.getName().equals("张三")&&u.getPassword().equals("123456")) return "mian.jsp"; else{ req.setAttribute("error", "账号密码错误"); return "index.jsp"; } }
-
- 请求参数中包含多个同名参数的获取方式
- 复选框传递的参数就是多个同名参数
-
@RequestMapping("demo4") public String demo4(String name,String password,@RequestParam("hobby")List<String> hobby){ System.out.println("执行demo2"+ name +" "+password+" "+hobby); return "index.jsp"; }
-
请求参数中对象.属性格式
-
jsp 中代码
-
<input type="text" name="peo.name"/> <input type="text" name="peo.age"/>
-
-
新建一个类
-
对象名和参数中点前面名称对应
-
public class Demo { private People peo;
-
-
-
控制器
-
@RequestMapping("demo6") public String demo6(Demo demo){ System.out.println(demo); return "main.jsp"; }
-
-
-
在请求参数中传递集合对象类型参数
- JSP中的代码
-
<input type="text" name="peo[0].name"/> <input type="text" name="peo[0].age"/> <input type="text" name="peo[1].name"/> <input type="text" name="peo[1].age"/>
-
- 新建类
-
public class Demo { private List<People> peo;
-
- 控制器
-
@RequestMapping("demo6") public String demo6(Demo demo){ System.out.println(demo); return "main.jsp"; }
-
- JSP中的代码
-
restful传值方式
-
简化 jsp 中参数编写格式
-
在 jsp 中设定特定的格式
-
<a href="demo5/田坤/123456">跳转</a>
-
-
在控制器中
-
在@RequestMapping 中一定要和请求格式对应
- {名称} 中名称自定义名称
-
@PathVariable 获取@RequestMapping 中内容,默认按照方法参数名称去寻找.
-
@RequestMapping("demo5/{name}/{pwd}") public String demo5(@PathVariable String name,@PathVariable("pwd")String password){ System.out.println("执行demo2"+ name +" "+password); return "/index.jsp"; }
-
-
四、跳转方式
- 默认跳转方式请求转发
- 设置返回值字符串内容
- 添加 redirect:资源路径 重定向
- 添加 forward:资源路径 或省略 forward: 转发
五、视图解析器
- SpringMVC 会提供默认视图解析器.
- 程序员自定义视图解析器(springmvc.xml)
-
<!-- 视图解析器 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 给前面加东西 --> <property name="prefix" value="/"></property> <!-- 给后面加东西 --> <property name="suffix" value=".jsp"></property> </bean>
-
-
如果希望不执行自定义视图解析器,在方法返回值前面添加forward:或 redirect
六、ResponseBody
需要导入jackson所需要的包
- 在方法上只有@RequestMapping 时,无论方法返回值是什么认为需要跳转
- 在方法上添加@ResponseBody(恒不跳转)
- 如果返回值满足 key-value 形式(对象或 map)
- 把响应头设置为 application/json;charset=utf-8
- 把转换后的内容输出流的形式响应给客户端
- 如果返回值不满足 key-value,例如返回值为 String
- 把相应头设置为 text/html
- 把方法返回值以流的形式直接输出.
- 如果返回值包含中文,出现中文乱码
- produces 表示响应头中 Content-Type 取值
-
@RequestMapping(value="demo12",produces="text/html; charset=utf-8") @ResponseBody public String demo12(){ return "中文"; }
-
@RequestMapping("demo6") @ResponseBody public User demo6(){ User u = new User(); u.setName("宋旭东"); u.setPassword("123456"); return u; }
- 如果返回值满足 key-value 形式(对象或 map)
- 底层使用Jackson进行json转换,在项目中一定要导入jackson的jar
- spring4.1.6 对 jackson 不支持较高版本,jackson2.7 无效.
七、九大内置对象和四大作用域
1、九大内置对象
名称 | 类型 | 含义 | 获取方式 |
---|---|---|---|
request | HttpSerletRequest | 封装所有请求信息 | 方法参数 |
response | HttpServletResponse | 封装所有响应信息 | 方法参数 |
session | HttpSession | 封装所有会话信息 | request.getSession |
application | ServletContext | 所有信息 | getServletContext() request.getServletContext() |
out | PrintWriter | 输出对象 | response.getWriter() |
exception | Exception | 异常对象 | |
page | Object | 当前页面对象 | |
pageContext | pageContext | 获取其他对象 | |
config | ServletConfig | 配置信息 |
2、四大作用域
- page
- 在当前页面不会重新实例化.
- request
- 在一次请求中同一个对象,下次请求重新实例化一个
- session
- 一次会话
- 只要客户端Cookie中传递的Jsessionid不变,Session不会重新实力会(不超过默认时间.)
- 实际有效时间
-
浏览器关闭.Cookie 失效
-
默认时间.在时间范围内无任何交互.在 tomcat 的web.xml 中配置
-
<session-config> <session-timeout>30</session-timeout> </session-config>
-
-
-
application
-
只有在 tomcat 启动项目时菜实例化.关闭 tomcat 时销毁application
-
3、SpringMVC作用域传值的几种方式
- 使用原生 Servlet
- 在 HanlderMethod 参数中添加作用域对象
-
@RequestMapping("demo1") public String demo1(HttpServletRequest abc,HttpSession sessionParam){ //request 作用域 abc.setAttribute("req", "req 的值"); //session 作用域 HttpSession session = abc.getSession(); session.setAttribute("session", "session 的值"); sessionParam.setAttribute("sessionParam","sessionParam 的值"); //appliaction 作用域 ServletContext application = abc.getServletContext(); application.setAttribute("application","application 的值"); return "/index.jsp"; }
- 使用 Map 集合
- 把 map 中内容放在 request 作用域中
- spring 会对 map 集合通过 BindingAwareModelMap 进行实例化
-
@RequestMapping("demo2") public String demo2(Map<String,Object> map){ System.out.println(map.getClass()); map.put("map","map 的值"); return "/index.jsp"; }
- 使用 SpringMVC 中 Model 接口
- 把内容最终放入到 request 作用域中
-
@RequestMapping("demo3") public String demo3(Model model){ model.addAttribute("model", "model 的值"); return "/index.jsp"; }
- 使用 SpringMVC 中 ModelAndView 类
-
@RequestMapping("demo4") public ModelAndView demo4(){ //参数,跳转视图 ModelAndView mav = new ModelAndView("/index.jsp"); mav.addObject("mav", "mav 的值"); return mav; }
-
八、文件的上传和下载
①文件的下载
- 访问资源时相应头如果没有设置 Content-Disposition,浏览器默认按照 inline 值进行处理
- inline 能显示就显示,不能显示就下载.
- 只需要修改相应头中 Context-Disposition=”attachment;filename=文件名”
- attachment 下载,以附件形式下载
- filename=值就是下载时显示的下载文件名
- 实现步骤
- 导入 apatch 的两个 jar
- 在 jsp 中添加超链接,设置要下载文件
- 在 springmvc 中放行静态资源 files 文件夹
-
<a href="download?fileName=jquery.chm">下载</a>
-
-
编写控制器方法
-
@RequestMapping("demo") private void download(String fileName,HttpServletRequest req,HttpServletResponse resp) throws IOException { //设置响应流中文件进行下载 resp.setHeader("Content-Disposition", "attachment;filename="+fileName); // resp.getWriter().wait(); 文本流 //把二进制流放入到响应中 ServletOutputStream os = resp.getOutputStream(); FILE_PATH = req.getServletContext().getRealPath("files"); System.out.println(FILE_PATH); File file = new File(FILE_PATH, fileName); byte[] bytes = FileUtils.readFileToByteArray(file); os.write(bytes); os.flush(); os.close(); }
-
- 在 springmvc 中放行静态资源 files 文件夹
- 导入 apatch 的两个 jar
②文件上传
- 基于 apache 的 commons-fileupload.jar 完成文件上传
- MultipartResovler 作用
- 把客户端上传的文件流转换成 MutipartFile 封装类
- 通过 MutipartFile 封装类获取到文件流
- 表单数据类型分类
- 在<form>的 enctype 属性控制表单类型
- 默认值 application/x-www-form-urlencoded,普通表单数据.(少量文字信息)
- text/plain 大文字量时使用的类型.邮件,论文
- multipart/form-data 表单中包含二进制文件内容
- 实现步骤:
- 导入 springmvc 包和 apache 文件上传 commons-fileupload 和commons-io 两个 jar
- 编写 JSP 页面
-
<form action="upload" method="post" enctype="multipart/form-data"> <input type="file" name="file"><br> <input type="submit" value="提交"> </form>
-
-
配置springmvc.xml
-
<!-- MutipartResovler的解析器 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 上传文件的最大 单位字节 --> <property name="maxUploadSize" value="500"></property> </bean> <!-- 异常解析类 --> <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <!-- 文件如果超过指定大小报异常, 让其跳转到error.jsp页面里 --> <prop key="org.springframework.web.multipart.MaxUploadSizeExceededException">/error.jsp</prop> </props> </property> </bean>
-
-
编写控制器类
-
MultipartFile 对象名必须和<inputtype=”file”/>的 name 属性值相同
-
@RequestMapping("upload") public String upload(MultipartFile file,String name) throws IOException{ String filename = file.getOriginalFilename(); //获取后缀名 String suffix = filename.substring(filename.lastIndexOf(".")); //随机产生一个字符串 String uuid = UUID.randomUUID().toString(); FileUtils.copyInputStreamToFile(file.getInputStream(), new File("C:/aaa/other/"+uuid+suffix)); return "/mian.jsp"; }
-
九、自定义拦截器
- 跟过滤器比较像的技术
- 发送请求时被拦截器拦截,在控制器的前后添加额外功能
- 拦截器,请求的拦截.针对点是控制器方法.(对 Controller)
- AOP 区分开.AOP 在特定方法前后扩充(对 ServiceImpl)
- SpringMVC 拦截器和 Filter 的区别
- 拦截器只能拦截器 Controller
- Filter 可以拦截任何请求.
- 实现自定义拦截器的步骤
- 新建类实现 HandlerInterceptor
-
package com.tk.intercerpter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; /** * 自定义拦截器 * @data :2019-4-17上午9:43:07 * @author :田坤 */ public class MyIntercerpter implements HandlerInterceptor{ //jsp 执行完成后执行 //记录执行过程中出现的异常. //可以把异常记录到日志中 @Override public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception { // TODO Auto-generated method stub } //控制器执行完成,进入到 jsp 之前执行. //日志记录. //敏感词语过滤 @Override public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception { System.out.println("往"+arg3.getViewName()+"跳转"); System.out.println("model 的值 "+arg3.getModel().get("model")); //敏感词过滤 String word = arg3.getModel().get("model").toString(); String newWord = word.replaceAll("祖国", "**"); arg3.getModel().put("model", newWord); } //在进入控制器之前执行 //如果返回值为 false,阻止进入控制器 //控制代码 public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception { return true; } }
-
-
在 springmvc.xml 配置拦截器需要拦截哪些控制器
-
<!-- 配置拦截器 --> <mvc:interceptors> <!-- 拦截全部的控制器 --> <bean class="com.tk.intercerpter.MyIntercerpter"></bean> <!-- 拦截特定地址的控制器 --> <mvc:interceptor> <mvc:mapping path="/demo"/> <bean class="com.tk.intercerpter.MyIntercerpter"></bean> </mvc:interceptor> </mvc:interceptors>
-
- 新建类实现 HandlerInterceptor
①拦截器栈
- 多个拦截器同时生效时,组成了拦截器栈
- 顺序:先进后出
- 执行顺序和在 springmvc.xml 中配置顺序有关
- 设置先配置拦截器 A 在配置拦截器 B 执行顺序为
preHandle(A)--> preHandle(B)--> 控制器方法 -->postHandle(B)
-->postHanle(A)-->JSP-->afterCompletion(B)-->afterCompletion(A)
十、SpringMVC的运行原理(文字解释)
如果在 web.xml 中设置 DispatcherServlet 的<url-pattern>为 / 时,当用户发 起 请 求 , 请 求 一 个 控 制 器 , 首 先 会 执 行DispatcherServlet. 由DispatcherServlet 调 用 HandlerMapping 的DefaultAnnotationHandlerMapping 解 析 URL, 解 析 后 调 用HandlerAdatper 组 件 的 AnnotationMethodHandlerAdapter 调 用Controller 中的 HandlerMethod.当 HandlerMethod 执行完成后会返回View,会被 ViewResovler 进行视图解析,解析后调用 jsp 对应的.class 文件并运行,最终把运行.class 文件的结果响应给客户端.
以上就是 springmvc 运行原理(给面试官说的)