一、概念
什么是MVC?
MVC是一种设计模式(不属于Java的23钟设计模式),最开始应用域桌面端,后来广泛应用域web领域,
主要用于业务逻辑,数据,界面的分离。
MODEL:代表我们的JavaBean(数据库模型,service实现类等)。
VIEW:代表我们的页面(HTMl,JSP等)
CONTROLLER:代表用于控制页面跳转,参数接收的层(Servlet,controller等)
什么是SpringMVC:
SpringMVC是一个基于MVC的框架,他能解决web开发中很多常见的问题。
例如: 1、界面跳转(视图返回)
2、参数接收
3、文件上传
4、国际化、表单校验等......
SpringMVC中的主要组件:
1、DispatcherServlet:前端控制器,就是一个Servlet,我们主要通过配置它,然后才完成所有的请求拦截。
它里面有以下角色(属性):
2、handler: (处理器)后端控制器,由于handler牵扯到后台业务请求,所以所有的handler都是由程序员自身编写
(controller中的所有的方法都会被springMVC编译成一个handler)
3、HandlerMapping:(处理器映射)根据url找到对应的handler处理器,可以使用requestMapping注解实现一个handlerMapping
4、HandlerAdapter:(处理器适配器)通过HandlerAdapter来执行我们的handler,也就是说我们写在controller中的方法
都由springmvc通过适配器模式来执行。
5、HandlerExceptionResolver:异常处理器。
6、ViewResolvers:视图解析器,通过我们返回的逻辑视图名,来解析成具体的视图名称,然后创建视图对象。
7、multipartResolver:文件上传组件,用于配置文件上传的各种信息。
SpringMVC的请求流程:
1、用户发送请求到tomcat
2、tomcat查看请求的url是否符合DispatcherServlet的拦截规则,如果符合的话则将请求交由DispatcherServlet
处理,如果不符合则直接404。
3、DispatcherServlet接收到请求后,去查看HandlerMapping中是否有对应的映射,如果没有就直接404(在控制台报一个没有对应的处理器)
4、如果找到了对应了HandlerMapping,那么HandlerMapping会将请求映射为HandlerExecutionChain对象(里面封装
了handler与多个拦截器对象),然后将其返回给DispatcherServlet。
5、DispatcherServlet通过HandlerAdapter来执行handler。
6、handler执行完成之后会返回给HandlerAdapter一个ModelAndView对象。
7、HandlerAdapter将ModelAndView返回给DispatcherServlet。
8、DispatcherServlet去请求ViewResolvers,进行视图的解析(根据逻辑视图找到真实视图,比如根据show,加上前后缀变成真实视图)
10、ViewResolver(视图解析器)将视图返回给DispatcherServlet
9、DispatcherServlet对视图进行渲染(将数据写入带页面中)
11、DispatcherServlet将视图响应给用户
具体使用
注解使用跳转controller
可以在方法中加上一个注解
@RequestMapping(“hello”)
里面填写我们的请求路径,如果修饰在方法上,就代表对应的这个方法来处理我们的请求
@RequestMapping(name=“hello2”,method=RequestMethod.POST)
修饰在方法上,代表这个方法用来处理请求路径是hello2并且请求是post类型的。如果没有指定method的话,
默认是get与post都能处理。
@PostMapping(“hello2”)
代表只处理hello2的post请求
@GetMapping(“hello2”)
代表只处理hello2的get请求
SpringMVC接收参数的四种方式:
1、使用Servlet原生API
2、使用形参列表接收 可以自动进行类型转换,但是要求前台页面中name值与形参变量名称一致
3、使用模型接收,需要model类中属性名与页面中的name一致(实际上是set注入,与set方法中名字一致就行)
4、使用url接收。 在路径后面使用{id}写一个占位符,在形参中使用@PathVariable("id") 注解接收参数
SpringMVC传值给页面的5钟方式:
1:servlet原生API
2:使用modelANDVIEW,传递参数以及回显页面
3、直接返回对象(不使用)
4、使用原生API配合视图解析器(常用)
如果我们的方法直接放回字符串的haul,那么默认返回的字符串就是页面的名称,并且会自动加上视图解析器的
前后缀,然后使用请求转发的方法跳转到这个页面
5、使用@ResponseBody 直接返回数据到当前页面,不进行页面的跳转,不走视图解析器。(常用,配合ajax使用)
SpringMVC跳转页面四种的方式
1、使用原生API(不用了)
2、使用ModelndView
3、直接返回字符串,让其去找视图解析器,跳转对应页面
4、5钟,直接返回String,然后通过redirect:指定到某一个位置(可以是其他的@RequestMapping的路径)
也可以是页面,如果是页面的 话需要手动加上前后缀
拦截器与过滤器的区别:
1、过滤器会拦截所有请求(html,jsp,css,js,img 等),而拦截器不拦截jsp。
2、过滤器只有在servlet执行之前拦截,但是拦截器可以再之前或之后拦截(深入方法前后拦截)。
3、过滤去是基于函数回调实现,而拦截器基于反射实现。
4、过滤器会发访问servlet中的值,拦截器可以访问controller中的值。
5、过滤器在一次请求中只执行一次,拦截器执行多次。
6、过滤器依赖于servlet容器,拦截器不依赖servlet容器。
spring配置文件的代码
application_jdbc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:util="http://www.springframework.org/schema/util"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 告诉Spring容器扫描那些包,以及包下的类 -->
<context:component-scan base-package="com.zhiyou"></context:component-scan>
<!-- 1、加载属性文件到这里面 -->
<util:properties id="db" location="classpath:db.properties" />
<!-- 2、配置数据库连接池 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<!-- 3、通过set注入将数据库连接信息注入类的实例对象中 -->
<property name="driverClassName" value="#{db.driver}" />
<property name="url" value="#{db.url}" />
<property name="username" value="#{db.username}" />
<property name="password" value="#{db.password}" />
</bean>
<!-- 4、配置springjdbc模板,并注入dataSource -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 声明事务管理器 -->
<bean id="txManage"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 开启注解事务驱动 -->
<tx:annotation-driven transaction-manager="txManage"/>
<!-- 通知:在什么时候做什么 -->
<!-- <tx:advice id="txAdvice" transaction-manager="txManage">
<tx:attributes> -->
<!-- 在这里写都有哪些方法需要使用事务 -->
<!-- <tx:method name="del*" />
</tx:attributes>
</tx:advice> -->
<!-- 配置AOP切入点 -->
<!-- <aop:config>
<aop:pointcut expression="execution(* com.zhiyou.service..*(..))"
id="op" /> -->
<!-- 使用上面的通知,以及我们配置的切入点 -->
<!-- <aop:advisor advice-ref="txAdvice" pointcut-ref="op" />
</aop:config> -->
</beans>
application_mvc.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<!-- 开启SpringMVC的注解驱动 -->
<mvc:annotation-driven/>
<!-- SpringMVC扫描注解的路径 -->
<context:component-scan base-package="com.zhiyou.controller"/>
<!-- 开启静态资源的支持 -->
<mvc:default-servlet-handler/>
<!-- 视图解析器: 可以给我们返回的视图自动添加前缀,后缀-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 给视图添加一个后缀 -->
<property name="suffix" value=".jsp"/>
</bean>
<!-- 配置文件上传 id要求固定-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--文件上传大小 -->
<property name="maxUploadSize" value="#{1024*1024*100}"/>
<!-- 读取文件的速度 -->
<property name="maxInMemorySize" value="4096"/>
<!-- 指定编码格式 -->
<property name="defaultEncoding" value="utf-8"></property>
</bean>
<!-- 文件上传拦截器配置 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/upload"/>
<mvc:mapping path="/upload2"/>
<bean class="com.zhiyou.interceptor.UploadInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
</beans>
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>SpringMVC</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<!-- 加载Spring配置文件 -->
<!-- 配置一个全局参数,加载Spring配置文件,并通过全局参数配置,将配置文件的位置告诉监听器 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application_jdbc.xml</param-value>
</context-param>
<listener>
<!-- 这个监听器,可以读取SPring配置文件,然后帮助我们初始化spring容器 -->
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 配置SPringMVC的前端控制器 DispatcherServlet-->
<servlet>
<servlet-name>spring-mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application_mvc.xml</param-value>
</init-param>
</servlet>
<!-- 配置前端控制器的拦截路径 -->
<servlet-mapping>
<servlet-name>spring-mvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
pom.xml需要下载的jar包:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zhiyou</groupId>
<artifactId>SpringMVC</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.3.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.3.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.3.RELEASE</version>
</dependency>
<!-- mysql驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils -->
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<!-- 文件上传 -->
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
</dependencies>
</project>
SpringMVC上传文件
普通上传文件需要注意的点:
1、文件大小
2、上传速度
3、编码格式
SPringMVC上传文件的步骤:
1、修改form表单提交方式
2、指定编码 数据格式为文件上传
3、在配置文件中配置文件上传解析器CommonsMultipartResolver,上传文件的大小,每次缓存文件的大小,默认编码等。
4、写个文件上传拦截器,用于拦截不符合要求的文件。
5、编写controller核心代码,调用service将文件传到服务器。
SpringMVC文件上传注意点:
1、form表单请求必须是post,且 enctype="multipart/form-data" -->
2、文件上传解析器的ID要求是multipartResolver
3、controller中接收的类型必须是MultipartFile
文件上传的代码
前台页面upload.jsp:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<!-- 上传文件提交方式一定要是post,并且指定编码方式为文件上传: enctype="multipart/form-data" -->
<form action="upload" method="post" enctype="multipart/form-data">
上传头像:<input type="file" name="file">
<input type="submit" value="提交">
</form>
<hr>
<!-- 上传文件提交方式一定要是post,并且指定编码方式为文件上传: enctype="multipart/form-data" -->
<form action="upload2" method="post" enctype="multipart/form-data">
上传头像:<input type="file" name="file">
<input type="submit" value="提交">
</form>
</body>
</html>
文件上传的控制器uploadController:
/**
* 1、文件大小
* 2、文件格式
* 3、文件名
* @param file
* @param request
* @param response
* @return
* @throws IOException
*/
@RequestMapping("upload")
public ModelAndView upload(MultipartFile file,HttpServletRequest request,HttpServletResponse response) throws IOException{
//文件的类型
System.out.println(file.getContentType());
//文件的大小
System.out.println(file.getSize());
//文件的名称
System.out.println(file.getOriginalFilename());
//准备输入流
InputStream in = file.getInputStream();
//准备输出流,并传入输出地址
FileOutputStream oStream = new FileOutputStream("E:/upload/"+file.getOriginalFilename());
//实现流的拷贝
IOUtils.copy(in, oStream);
//关闭流
in.close();
oStream.close();
return null;
}
/**
* 使用spring自带的文件上传
*/
@RequestMapping("upload2")
public ModelAndView upload2(MultipartFile file,HttpServletRequest request,HttpServletResponse response) throws IOException{
file.transferTo(new File("E:/upload/"+file.getOriginalFilename()));
return null;
}
/**
* 文件下载
*/
@RequestMapping("download")
public ModelAndView download(HttpServletRequest request,HttpServletResponse response) throws IOException{
//需要准备一个被用户下载的文件
File file = new File("E:/upload/1.png");
//设置响应的类型为图片下载
response.setHeader("content-disposition", "attachment;filename=mao.png");
//准备一个输入流
FileInputStream inputStream = new FileInputStream(file);
//获得相应输出流
ServletOutputStream outputStream = response.getOutputStream();
//将文件输出到客户端
IOUtils.copy(inputStream, outputStream);
//关闭流
inputStream.close();
outputStream.close();
return null;
}
拦截器UploadInterceptor中的preHandle方法代码:
//把请求强转为文件类型的请求
MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) request;
//获取请求中的所有文件
Map<String, MultipartFile> fileMap = multipartHttpServletRequest.getFileMap();
//遍历所有文件集合
Collection<MultipartFile> values = fileMap.values();
for (MultipartFile multipartFile : values) {
//看文件是否符合格式
System.out.println(multipartFile.getContentType()+":"+multipartFile.getSize());
if(multipartFile.getContentType().contains("image/")){//判断是否是图片
if(multipartFile.getSize()<(1024*1024*10)){//判断图片大小,不能超过是10M
return true;
}
}
}
response.sendRedirect("upload.jsp");
return false;