SpringMVC概述
SpringMVC是Spring产品对MVC模式的一种具体体现,它可以通过一套注解让一个简单的java类成为控制器,无需实现任何借口。同时它还支持restful风格的请求。
SpringMVC工作流程
- 用户通过浏览器发送请求到DispatcherServlet。
- DispatcherServlet收到请求调用HandlerMapping。
- HandlerMapping找到具体的处理器链返回给DispatcherServlet。
- DispatcherServlet会根据返回的处理器链调用HandlerAdapter。
- HandlerAdapter经过适配调用具体的Handler(Controller)。
- Controller执行完会返回一个执行结果(ModelAndView)。
- HandlerAdapter将Handler的结果返回给DispatcherServlet。
- DispatcherServlet将ModelAndView对象传给ViewResolver。
- ViewResolver解析后得到具体的View,并返回给DispatcherServlet。
- DispatcherServlet根据View进行视图渲染(将模型数据填充到视图中)。
- DispatcherServlet会将渲染后的视图响应到浏览器。
SpringMVC三大组件
处理器映射器:根据URL寻找对应的方法。
处理器适配器:真正的去调用程序员自己写的处理器。
视图解析器:将逻辑视图转换为物理视图。
SpringMVC配置
在springmvc.xml中需添加
<!--包扫描-->
<context:component-scan base-package="com.itheima"/>
<!--注解驱动-->
<mvc:annotation-driven/>
<!--视图解析器-->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--配置前缀后缀,当控制器中返回页面时会进行拼接,
拼接之后才是真正的返回地址-->
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
在web.xml中需添加
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<!--指定配置文件的位置-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<!--/ 代表默认配置 它会拦截除了jsp之外的所有请求-->
<url-pattern>/</url-pattern>
</servlet-mapping>
请求接收之参数限定
我们可以通过@RequestMapping这个注解里的一些属性来对请求参数做出限定。主要了解的有以下几个:
- value:用于限制请求URL。
- method:用于限制请求类型,如果不做限制,任何类型都可以访问。
- params:用于限制前台必传的参数,支持数组,不写代表不限制。
请求接收之参数封装
对于参数的封装,我只做了常用类型的介绍,如数组和集合不常用的类型不做介绍。
简单类型
(基本类型\基本类型的包装类型\字符串),只需要保证前台传递的参数名跟方法的形参名称一致就好。
对象类型
只需要保证前台传递的参数名跟实体类的属性名(set方法)一致就行。
日期类型
对于常见类型,SpringMVC内置了类型转换器,对于格式比较灵活的参数(日期,时间),SpringMVC无法完成类型转换,需要我们自定义类型转换器,并注册到SpringMVC转换服务中。
自定义的日期类型转换器
//自定义的日期类型转化器需要实现一个接口,Converter<源类型,目标类型>
public class DateConverter implements Converter<String, Date> {
//自定义转换方法
public Date convert(String dateStr) {
try {
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date date = dateFormat.parse(dateStr);
return date;
} catch (ParseException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
在springmvc.xml中将自定义的日期类型转换器注册到Spring转换服务中。
<!--注解驱动-->
<mvc:annotation-driven conversion-service="conversionService"/>
<!--将自己开发的转换器注册到Spring的转换服务中-->
<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.itheima.converter.DateConverter"/>
</set>
</property>
</bean>
请求接收之接收消息体
get请求的时候是没有消息体的,所以是针对post请求的。
如果想在后台直接使用实体类来接收消息体时,必须满足一下几个条件:
1.工程中需导入Json转换包,如:jackson;
2.必须存在一个用于接收的实体类;
3.前端传递过来的必须是Json格式的数据。
例如:
@RequestMapping("/demo1")
//@RequestBody会将消息体封装到后面的javaBean中
public String demo(@RequestBody User user){
System.out.println(user);
return "/index.jsp";
}
请求接收之接收文件类型(文件上传)
由于我使用的maven创建的工程,所以首先需要导入文件上传的依赖。
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
接下来就需要配置SpringMVC的文件上传解析器了。
<!--配置文件解析器时,这个id不能随便写,只能是multipartResolver-->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--每次最大的上传大小,单位是B,5M = 5*1024*1024-->
<property name="maxInMemorySize" value="5242880"/>
</bean>
Java后台代码如下:
@RequestMapping("/demo")
/*文件接收的类型必须是MultipartFile,
接收的形参必须和表单中type=file的input域中的name一致*/
public String demo4(MultipartFile uploadFile) throws IOException {
System.out.println(uploadFile);
File file = new File("D:\\upload");
//如果文件后缀名可编辑,就需要在后面拼接文件类型
String newFileName = UUID.randomUUID().toString();
File newFile = new File(file, newFileName);
uploadFile.transferTo(newFile);
return "/index.jsp";
}
文件上传的页面有三要素:
1.form表单的method必须是post;
2.form表单的enctype必须是multipart/form-data;
3.form表单中必须有一个type=file的input域;
SpringMVC文件上传的原理
当DispatcherServlet中有一个属性叫multipartResolver时,它就对应着一个文件解析器。当SpringMVC启动时,它就会在容器中寻找一个id为multipartResolver的bean。如果找到了,那么以后只要是文件上传的工作就都会交给它。当文件上传上来的时候,DispatcherServlet会调用multipartResolver进行文件上传的解析,解析完成后会将结果封装进一个MultipartFile对象中,并返回给DispatcherServlet。再当DispatcherServlet调用到controller方法的时候就可以将MultipartFile作为参数传进去了。
请求接收之参数处理
中文乱码
SpringMVC在使用post提交请求时,对于中文参数是有乱码问题的,针对这种情况它提供了一个中文乱码的过滤器,我们只需要在web.xml中配置一下即可。
<!--中文乱码过滤器-->
<filter>
<filter-name>encodingFilter</filter-name>
<filterclass>
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>encodingFilter</filter-name>
<!--/*代表过滤所有-->
<url-pattern>/*</url-pattern>
</filter-mapping>
默认值设置
@RequestParam标注在参数之前,用于对传入的参数做一些限制,支持三个属性:
value:默认属性,用于指定前端传入的参数名称;
required:用于指定该参数是否必传;
defaultValue:当参数为非必传参数且前端没有传入参数时,指定一个默认值。
请求接收之接收restful风格请求
###### 什么是restful风格
rest是一种软件架构风格,也可称为规范,其强调http应当以资源为中心(建议URL中不要出现动词)。它规范了http请求动作,使用四个词语分别表示对资源的CRUD操作:
GET(获取)、POST(新建)、PUT(更新)、DELETE(删除)
原来 | Restful | |
---|---|---|
保存 | /saveUser | POST /user |
修改 | /updateUser?id=1 | PUT /user/1 |
删除 | /deleteUser?id=1 | DELETE /user/1 |
查询所有 | /findAllUser | GET /user |
查询一个 | /findUserById?id=1 | GET /user/1 |
请求接收之释放静态资源
由于我们在web.xml中配置DispatcherServlet时,servlet的匹配方式使用的是“/”默认,当使用这种匹配方式时,会只有DispatcherServlet和jsp生效,而且jsp的优先级高,也就是访问jsp的请求由jsp的servlet处理,其他请求由DispatcherServlet处理,处理不了的就会报错,例如(jpg,css,js这种静态资源就处理不了)。
所以SpringMVC给出了两种释放静态资源的方式:
- 方式一,在springmvc.xml中添加(推荐):
<!--当配置了这个以后,DispatcherServlet还是根据URL找方法,
找不到的就交给外部默认的servl处理-->
<mvc:default-servlet-handler/>
- 方式二,在springmvc.xml中添加:
<!--mapping用于匹配URL路径
如果匹配成功,就不会再调用HandlerMapping寻找响应的方法了,
而是直接将URL请求定位到location指定的路径寻找静态资源
-->
<mvc:resource mapping="/images/*" location="/images/"/>
当资源过多时,就需要添加多条,所以方式二不推荐。