Spring MVC 复习
概念
三层架构 将整个业务应用划分为三层
 表现层:用来和客户端进行数据交互,一般采用MVC设计模式
 业务层:处理公司具体业务逻辑
 持久层:用来操作数据库
MVC模型 Model View Controller模型视图控制器
 Model:数据模型,JavaBean的类,用来封装数据
 View:通过jsp, html等展示数据
 Controller:接收用户请求,整个流程的控制器
Spring MVC spring提供的mvc框架
 与struts2的区别:前者入口为servlet,后者用filter接收请求;前者基于方法,后者基于类(每次执行都会新建一个对象,效率低);前者使用更方便;前者使用JSTL表达式执行效率高,后者使用OGNL表达式开发效率高
		

应用
环境搭建
- 新建maven项目(不使用骨架) 
- 完善目录结构 - 在main目录下新建webapp/WEB-INF/web.xml文件并导入约束和新建jsp.index文件 - <!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >
 <web-app>
 <display-name>Web Application</display-name>
 </web-app>
 - main
 / | \
 java resources webapp
 / \
 WEB-INF index.jsp
 |
 web.xml
 
- 添加web moudules - 打开project structure的Modules添加Web 
- 设置Deployment Descriptors的Path为web.xml文件的路径 
- 设置Web Resource Directories的为webapp目录的路径 
 
- 配置pom.xml - <properties>
 <!-- 版本锁定 -->
 <spring.version>5.0.2.RELEASE</spring.version>
 </properties> <dependencies>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-context</artifactId>
 <version>${spring.version}</version>
 </dependency> <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-web</artifactId>
 <version>${spring.version}</version>
 </dependency> <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-webmvc</artifactId>
 <version>${spring.version}</version>
 </dependency> <dependency>
 <groupId>javax.servlet</groupId>
 <artifactId>servlet-api</artifactId>
 <version>2.5</version>
 <scope>provided</scope>
 </dependency> <dependency>
 <groupId>javax.servlet.jsp</groupId>
 <artifactId>jsp-api</artifactId>
 <version>2.0</version>
 <scope>provided</scope>
 </dependency>
 </dependencies>
 
- 配置Tomcat - 打开Add Configuration添加Tomcat local
- 随意取Name,在Deployment中添加当前Artifact并设置访问路径
- 在Server的On'update'action中可以选择Redeploy
 
- 创建springmvc.xml(resources目录下,ioc下的bean.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: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">
 </beans>
 
- 配置web.xml - <web-app>
 <!-- 配置前端控制器 -->
 <servlet>
 <servlet-name>dispatcherServlet</servlet-name>
 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
 <!-- 指定springmvc配置文件路径 -->
 <init-param>
 <param-name>contextConfigLocation</param-name>
 <param-value>classpath:springmvc.xml</param-value>
 </init-param>
 <!-- 启动服务器就加载此servlet,默认发请求时才创建 -->
 <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
 <servlet-name>dispatcherServlet</servlet-name>
 <url-pattern>/</url-pattern>
 </servlet-mapping>
 </web-app>
 
入门程序
- 编写View - 在WEB-INF下编写index.jsp(用a或form发送请求)和返回页面pages/success.jsp - <%@ page contentType="text/html;charset=UTF-8" language="java" %>
 <html>
 <head>
 <title>Start Program</title>
 </head>
 <body>
 <a href="hello">Start Program</a>
 </body>
 </html>
 
- 配置springmvc.xml - <bean ...>
 <!-- 开启扫描注解 -->
 <context:component-scan base-package="com.whteway"/> <!-- 视图解析器 -->
 <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
 <!-- 文件所在路径 -->
 <property name="prefix" value="/pages/"/>
 <!-- 文件后缀名 -->
 <property name="suffix" value=".jsp"/>
 </bean> <!-- 开启SpringMVC框架注解支持,自动加载处理映射器、处理适配器和注解处理器 -->
 <mvc:annotation-driven/>
 </bean>
 
- 编写控制器类 - @Controller //放入IOC容器
 public class HelloController{
 @RequestMapping("/hello") //处理路径为hello的请求
 public String sayHello(){
 //TODO
 return "success"; //根据视图解析器找到对应success的页面并返回
 }
 }
 
- @RequestMapping - 可以放在类或方法上,放在类上时可以定义路径公共前缀(分模块) - 属性path:用于指定请求的URL - 属性value(常用):与path一致,单用value的时候可以省略掉value= - 属性method(常用):定义能接收的请求方法,method={RequestMethod.POST} - 属性params:用于指定限制请求参数的条件 -  如@RequestMapping(value="/hello", params={"username"})则请求的参数必须有username -  如params={"username=abc"}则传过来的username必须为abc,还可以用!表示不等于 - 属性headers:用于指定限制请求消息头的条件 -  如headers={"Accept"}则请求中必须包含有Accept请求头 - 多个属性同时出现,关系为与 
请求参数绑定
- 绑定机制(名字相同,自动注入) - 表单提交的数据都是键值对形式的k=v
- SpringMVC把表单提交的参数作为控制器中方法的参数
- 要求表单参数的name和方法参数的的名称相同
 
- 支持的数据类型 - 基本数据类型和String:区分大小写 
- 实体类型(JavaBean) - 表单数据的name要与JavaBean的属性名相同,方法参数中加一个JavaBean类型的参数,自动封装名称随意 
- 若JavaBean类中包含其他的引用类型,则表单name为对象.属性,如address.name 
 
- 集合数据类型 - 设JavaBean中存在myList或myMap,则表彰数据的name=myList[0],myMap['one']
 
 
- 解决中文乱码(web.xml中配置) - <!-- 配置解决中文乱码的过滤器 -->
 <filter>
 <filter-name>characterEncodingFilter</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>characterEncodingFilter</filter-name>
 <url-pattern>/*</url-pattern>
 </filter-mapping>
 
- 自定义类型转换器 - 页面提交的参数都是字符串形式
- 正常情况下框架自动把传过来的字符串参数转换为对应类型,但有时可能会异常,如不同格式的日期
 - 编写转换类实现Converter接口 - import org.springframework.core.convert.converter.Converter;
 public class StringToDateConvert implements Converter<String,Date>{
 @Override
 public Date convert(String source){
 if(source == null){
 throw new RuntimeException("请传入数据");
 }
 DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
 try{
 return df.parse(source);
 } catch(Exception e){
 throw new RuntimeException("数据类型转换出现错误");
 }
 }
 }
 
- 配置自定义类型转换器(springmvc.xml中) - <!-- 配置自定义类型转换器 -->
 <bean id="conversionServiceFactoryBean" class="org.springframework.context.support.ConversionServiceFactoryBean">
 <property name="converters">
 <set>
 <bean class="包路径.StringToDateConverter"/>
 </set>
 </property>
 </bean>
 <!--修改注解支持使转换器生效-->
 <mvc:annotation-driven conversion-service="conversionServiceFactoryBean"/>
 
 
- 获取servlet原生API - 在方法参数中加对应类型的参数,如HttpServletRequest request, HttpServletResponse response - request.getSession()可以拿到HttpSession 
- Model(最常用) - 方法参数接收一个Model model(map结构),向model中存值,值会自动存入request域中,可以代替获取原生request方式,存用set(),取用get(),取值时可以用实现类ModelMap 
常用注解
- @RequestParam - 用在方法的参数前,把请求中指定名称的参数给控制器中的形参赋值,当页面参数与方法参数名不一致时可以用 
- 属性value:请求参数中的名称 - 属性required:是否必须提供此参数,默认true 
 
- @RequestBody - 用在方法的参数前,用于获取请求体的内容,直接使用得到的是k=v&k=v...结构的数据,get方式不适用
- 属性required:默认true,为true时用get方式会报错,false时get方式得到null
 
- @PathVariable - restful编程风格,简单来说就是通过不同请求方式访问同一请求路径的不同方法(用@RequestMapping的method属性指定),或路径上加参数来区分方法如 @RequestMapping(path="/user/{id}")
- 用于取请求路径上的参数 如 public String test(@PathVariable(name="id") String id){}
- 请求路径写 user/10
 
- @RequestHeader(不常用) - 用在方法的参数前,用于取请求头
 
- @CookieValue(不常用) - 用在方法的参数前,用于取指定名称Cookie的值,属性value
 
- @ModelAttribute - 在控制器方法执行前对参数进行预处理 
- 用在方法上,使该方法会在别的控制器的方法执行之前执行,方法的返回值会作为之后实际控制器方法上的参数 
- 用在参数上,获取指定的数据给参数赋值,当表单提交的数据不是完整的实体类数据时,保证没有提交数据的字段使用数据库对象原来的数据 
 - @RequestMapping("/user") //此方法的参数user是findUser方法的返回值
 public String test(User user){} @ModelAttribute
 public User findUser(String name){
 //数据库中根据传入参数name查找user
 return user;
 } @ModelAttribute //无返回值写法,取参时参数上要用@ModelAttribute("u")
 public void findUser(String name, Map<String, User> map){
 //数据库中根据传入参数name查找user
 map.put("u", user);
 }
 
- @SessionAttribute - 用于多次制造控制器方法(多次请求)间的参数共享,代替request.getSession()...方式
- 用在类上,@SessionAttributes(value={"key"}) 用于将model中的键值对存入session域中
- 清空session用SessionStatus(参数接收)中setComplete()方法
 
响应方式
- 页面跳转及存值 - 字符串:根据前端控制器配置好的前缀和后缀找到要跳转的页面,存值用model,底层用ModelAndView实现 
- void - 默认跳转以路径名为名的jsp文件 
- 使用request.getRequestDispatcher("/WEB-INF开始路径全名").forward(request,response); return;进行请求转发 
- 使用response.sendRedirect(request.getContextPath+"/index.jsp");进行重定向 
- 直接进行响应 - response.setCharacterEncoding("UTF-8");
 response.setContentType("text/html;charset=UTF-8");
 response.getWriter().print("hello");
 
 
- ModelAndView - 方法内用new创建,最后返回
- ModelAndView可以当作Model存数据
- 使用setViewName("success")指定跳转页面,使用视图解析器
 
- 使用关键字进行转发和重定向(不能使用视图解析器) - return "forward:/WEB-INF/pages/success.jsp";
- return "redirect:/index.jsp"; 框架自动添加项目名
 
 
- 响应json数据 - springmvc.xml中配置前端控制器不拦截的静态资源 - <mvc:resources mapping="/js/**" location="/js/**" />
 
- 添加坐标,导入jackson包 - <dependency>
 <groupId>com.fasterxml.jackson.core</groupId>
 <artifactId>jackson-databind</artifactId>
 <version>2.9.0</version>
 </dependency>
 <dependency>
 <groupId>com.fasterxml.jackson.core</groupId>
 <artifactId>jackson-core</artifactId>
 <version>2.9.0</version>
 </dependency>
 <dependency>
 <groupId>com.fasterxml.jackson.core</groupId>
 <artifactId>jackson-annotations</artifactId>
 <version>2.9.0</version>
 </dependency>
 
- 接收json数据,用JavaBean作为参数接收,参数上用@RequestBody,后台自动将json按照名称封装进JavaBean 
- 响应json数据,在返回值类型前加@ResponseBody,后台自动将JavaBean转换为json - @RequestMapping("/test")
 public @ResponseBody User test(@RequestBody User user){
 //TODO
 return user;
 }
 
 
- 文件上传 - 导入坐标 - <dependency>
 <groupId>commons-fileupload</groupId>
 <artifactId>commons-fileupload</artifactId>
 <version>1.3.1</version>
 </dependency>
 <dependency>
 <groupId>commons-io</groupId>
 <artifactId>commons-io</artifactId>
 <version>1.3.1</version>
 </dependency>
 
- 编写前端代码 - form表单的enctype取值必须是multipart/form-data
- method必须是Post
- 需要提供一个文件选择域《input type="file"/》
 
- 配置文件解析器(beanId为固定写法,springmvc.xml) - <bean id="multipartResolver" class="org.springframework.multipart.commons.CommonsMultipartResolver">
 <property name="maxUploadSize" value="10485760"/>
 </bean>
 
- 编写控制器方法(参数中的upload必须对应表单中文件的name) - @RequestMapping("/upload")
 public String fileupload(HttpServletRequest request, MultipartFile upload) throws Exception{
 //上传位置
 String path = request.getSession().getServletContext().getRealPath("/uploads");
 File file = new File(path);
 if(!file.exists()){file.mkdirs();}
 //说明上传文件项
 //获取文件名称
 String filename = upload.getOriginalFilename();
 //把文件的名称设置唯一值
 String uuid = UUID.randomUUID().toString().replace("-", "");
 filename = uuid + "_" + filename;
 //完成文件上传
 upload.transferTo(new File(path, filename));
 return "success";
 }
 
 - 传统文件上传的控制器方法的写法 - @RequestMapping("/traUpload")
 public String traFileupload(HttpServletRequest request) throws Exception{
 //使用fileupload组件完成文件上传
 //上传位置
 String path = request.getSession().getServletContext().getRealPath("/uploads/");
 File file = new File(path);
 if(!file.exists()){file.mkdirs();}
 //解析request对象,获取上传文件项
 DiskFileItemFactory factory = new DiskFileItemFactory();
 ServletFileUpload upload = new ServletFileUpload(factory);
 //解析request
 List<FileItem> items = upload.parseRequest(request);
 for (FileItem item : items) {
 //判断对象是否是上传文件项
 if(item.isFormField()){
 //为普通表单项
 }else{
 //为上传文件项
 //获取文件名称
 String filename = item.getName();
 //完成文件上传
 item.write(new File(path, filename));
 //删除临时文件
 item.delete();
 }
 }
 
- 跨服务器上传文件 - 准备另一个文件上传专用项目,按照路径写好文件上传的控制器方法 - @RequestMapping("/upload")
 public String fileupload(HttpServletRequest request, MultipartFile upload) throws Exception{
 //定义上传文件服务器路径
 String path = "http://localhost:9090/uploads/";
 //说明上传文件项
 //获取文件名称
 String filename = upload.getOriginalFilename();
 //把文件的名称设置唯一值
 String uuid = UUID.randomUUID().toString().replace("-", "");
 filename = uuid + "_" + filename;
 //完成文件上传
 //创建客户端的对象
 Client client = Client.create();
 //和图片服务器进行连接
 WebResource webResource = client.resource(path+filename);
 //上传文件
 webResource.put(upload.getBytes());
 return "success";
 }
 
 
- 异常处理 - 出现异常后跳转到自定义的友好页面,默认情况下各层出现异常后都向上一级抛出,最终会到视图层,可以在前端控制器处配置一个异常处理器,在异常处理器中处理异常 - 编写自定义异常类(做提示信息) - public class SysException extends Exception{
 //存储提示信息的
 private String message;
 public String getMessage(){
 return message;
 }
 public String setMessage(String message){
 this.message = message;
 }
 public SysException(String message){
 this.message = message;
 }
 }
 
- 编写异常处理器 - public class SysExceptionResolver implements HandlerExceptionResolver{
 @Override
 public ModelAndView resolveException(...){
 //获取异常对象
 SysException e = null;
 if(e instanceof SysException)
 e = (SysException)e;
 else
 e = new SysException("系统正在维护...");
 //创建ModelAndView对象
 ModelAndView mv = new ModelAndView();
 mv.addObject("errorMsg", e.getMessage());
 mv.setViewName("error"); //提前写好error.jsp页面
 return nmv;
 }
 }
 
- 配置异常处理器(跳转到提示页面,springmvc.xml) - <bean id="sysExceptionResolver" class="异常处理器全限定类名"/>
 
- 在可能出现异常的地方catch到异常后new一个新的自定义异常对象存入提示信息并throw - try{
 int a = 10/0;
 } catch(Exception e){
 e.printStackTrace();
 throw new SysException("赋值失败...");
 }
 
 
- 拦截器 - SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理,也是AOP思想的具体应用 - 拦截器与过滤器的区别 - 过滤器是servlet规范中的一部分,任何java web项目都能用 - 拦截器是SpringMVC自己的,只有使用了SpringMVC框架的工程才能用 
- 过滤器在url-pattern中配置了/*后可以对所有要访问的资源 拦截 - 拦截器只会拦截访问的控制器方法,不能拦截jsp,html,css,image,js等静态资源 
 
 - 创建自定义拦截器类(接口方法有默认实现,可以不重写) - public class MyInterceptor implements HandlerInterceptor{
 @Override
 public boolean preHandle(...){
 //TODO before controller, 返回true表示放行,不放行可以request转发
 return true;
 }
 @Override
 public boolean postHandle(...){
 //TODO after controller
 return true;
 }
 @Override
 public void afterCompletion(...){
 //TODO after showing page
 }
 }
 
- 配置拦截器(springmvc.xml) - <mvc:interceptors>
 <mvc:interceptor>
 <!-- 要拦截的方法(二选一) -->
 <mvc:mapping path="/user/*"/>
 <!-- 不拦截的方法(二选一) -->
 <mvc:exclude-mapping path=""/>
 <!-- 配置拦截器对象 -->
 <bean class="拦截器全限定类名"/>
 </mvc:interceptor>
 </mvc:interceptors>
 
 
原理
- Tomcat 启动,对 DispatcherServlet 进行实例化,然后调用它的 init() 方法进行初始化,在这个初始化过程中完成了:
- 对 web.xml 中初始化参数的加载;建立 WebApplicationContext (SpringMVC的IOC容器);进行组件的初始化;
- 客户端发出请求,由 Tomcat 接收到这个请求,如果匹配 DispatcherServlet 在 web.xml 中配置的映射路径,Tomcat 就将请求转交给 DispatcherServlet 处理;
- DispatcherServlet 从容器中取出所有 HandlerMapping 实例(每个实例对应一个 HandlerMapping 接口的实现类)并遍历,每个 HandlerMapping 会根据请求信息,通过自己实现类中的方式去找到处理该请求的 Handler (执行程序,如Controller中的方法),并且将这个 Handler 与一堆 HandlerInterceptor (拦截器) 封装成一个 HandlerExecutionChain 对象,一旦有一个 HandlerMapping 可以找到 Handler 则退出循环;
- DispatcherServlet 取出 HandlerAdapter 组件,根据已经找到的 Handler,再从所有 HandlerAdapter 中找到可以处理该 Handler 的 HandlerAdapter 对象;
- 执行 HandlerExecutionChain 中所有拦截器的 preHandler() 方法,然后再利用 HandlerAdapter 执行 Handler ,执行完成得到 ModelAndView,再依次调用拦截器的 postHandler() 方法;
- 利用 ViewResolver 将 ModelAndView 或是 Exception(可解析成 ModelAndView)解析成 View,然后 View 会调用 render() 方法再根据 ModelAndView 中的数据渲染出页面;
- 最后再依次调用拦截器的 afterCompletion() 方法,一次请求就结束了。
Spring MVC 复习的更多相关文章
- Spring MVC 复习笔记01
		1. springmvc框架 1.1 什么是springmvc spring mvc是spring框架的一个模块,springmvc和spring无需通过中间整合层进行整合.spring mvc是一个 ... 
- Spring MVC 复习笔记04
		复习 springmvc框架: DispatcherServlet前端控制器:接收request,进行response HandlerMapping处理器映射器:根据url查找Handler.(可以通 ... 
- Spring MVC 复习笔记02
		1. 非注解的处理器映射器和适配器 1.1 非注解的处理器映射器 处理器映射器:org.springframework.web.servlet.handler.BeanNameUrlHandlerMa ... 
- Spring MVC 复习笔记05
		1. 上传图片 1.1 springmvc中对多部件类型解析 在 页面form中提交enctype="multipart/form-data"的数据时,需要springmvc对mu ... 
- Spring MVC 复习笔记03
		1. @RequestMapping 1). url映射 定义controller方法对应的url,进行处理器映射使用. 2). 窄化请求映射 3). 限制http请求方法 出于安全性考虑,对htt ... 
- Spring MVC面试复习整理
		Spring MVC Spring MVC 是Spring Framework 提供的 web 组件 它的实现基于 MVC 的设计模式:Model(模型层).View(视图层).Controller( ... 
- Spring MVC入门实战(一)
		本文主要把一个菜鸟从“只是听说过Spring MVC”到“可以手动创建并运行一个Spring MVC工程”的过程记录下来,供以后复习. 0. 开发环境准备 计算机平台:Windows 7 X64. 需 ... 
- Spring MVC无法获取ajax POST的参数和值
		一.怎么会这个样子 很简单的一个想法,ajax以POST的方式提交一个表单,Spring MVC解析.然而一次次的打印null折磨了我整整一天…… 最后的解决现在看来是很明显的问题,“只是当时已惘然” ... 
- spring mvc中的@PathVariable(转)
		鸣谢:http://jackyrong.iteye.com/blog/2059307 ------------------------------------------------ spring m ... 
随机推荐
- dapi 基于Django的轻量级测试平台二 前端页面
			QQ群: GitHub:https://github.com/yjlch1016/dapi 一.登录页login.html: 二.首页home.html: 三.产品线列表页product.html: ... 
- JavaWeb中的监听器
			JavaWeb中的监听器 l 事件源:三大域! ServletContext ¨ 生命周期监听:ServletContextListener,它有两个方法,一个在出生时调用,一个在死亡时 ... 
- Struts CRUD
			Struts CRUD 利用struts完成增删改查 思路: 1.导入相关的pom依赖(struts.自定义标签库的依赖) 2.分页的tag类导入.z.tld.完成web.xml的配置 3.dao层去 ... 
- md5-js加密
			JS-MD5加密/html页面使用 大家都知道,传输明文信息很不安全,尤其像密码.卡号等这些敏感私密的信息,更不能暴露出去.在这里给大家介绍一种在前端JS中的MD5加密算法(因为要匹配的后台数据是MD ... 
- hdu 6620 Just an Old Puzzle(N数码问题)
			http://acm.hdu.edu.cn/showproblem.php?pid=6620 N数码问题: n*n矩阵,里面填着1—n*n-1,还有1个空格, 通过上下左右移动空格的位置, 使矩阵里的 ... 
- day 19
			If you think you can, you can. And if you think you can't, you're right. 
- PATB1024科学计数法
			代码是部分正确,只得了13分还有两个测试点没有通过,不知道原因是啥,先不深究了,赶进度. 参考代码: #include<cstdio> #include<cstring> #i ... 
- 深度学习之TCN网络
			论文链接:https://arxiv.org/pdf/1803.01271.pdf TCN(Temporal Convolutional Networks) TCN特点: 可实现接收任意长度的输入序列 ... 
- E-value    identity    bitscore
			E-value: The E-value provides information about the likelihood that a given sequence match is purely ... 
- Python网络爬虫神器PyQuery的使用方法
			#!/usr/bin/env python # -*- coding: utf-8 -*- import requests from pyquery import PyQuery as pq url ... 
