SpringMVC的概念:
springMVC是spring框架采用MVC思想实现的一套web层框架。
M:model模型,数据模型,业务模型
V:view视图
C:controller控制器【在springMVC中也叫处理器】
所谓mvc思想即:请求视图【view】发送请求到处理器【controller】,由处理器去调用service和dao封装模型【model】,然后由处理器【controller】再返回到结果视图【view】。
这些功能其实我们之前原生的servlet的api都可以实现,springMVC只是对原生servlet的api进行了封装。
环境搭建:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<!-- 如果是tomcat7以后的版本,jsp和servlet的jar包不加scope作用域也可以
因为tomcat7之后加入了自动的容错机制,不加不也不会报错.但是7之前的版本必须加上
scope作用域,否则运行的时候会发生jar包的依赖冲突
-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
</dependencies>
<!-- web.xml配置 -->
<!-- 前端控制器
servlet拦截控制的四种机制:
一: 精确匹配 /xxx/xxx/xx.jsp
二: 路径匹配 /xxxx/*
三: 后缀名匹配 *.xxxx
四: 缺省 /
如果匹配规则相同的两个servlet,自己写的servlet优先级高于tomcat的
-->
<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:spring-mvc.xml</param-value>
</init-param>
<!-- 立即加载: 容器已启动,servlet自动加载 数字越小,优先级越高 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- spring-mvc配置 -->
<!-- 组件扫描 -->
<context:component-scan base-package="com.itheima"/>
<!-- 开启MVC注解支持 对三大组件中的处理映射器和处理适配器进行加强 -->
<mvc:annotation-driven/>
<!-- 网络视图解析器 -->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>
处理器
注意:springMVC的处理器是Controller对象中的方法。
处理器是方法级的,一个方法是一个处理器。这时,所有方法之间是没有关联的。也就是说Controller对象中是不能有公用的私有成员属性的。除了service。
由此,springMVC的处理器所在对象Day01Controller就可以设计成单例的。
而struts2的控制器是一个类,里面所有方法可以公用任何私有属性,必须设计成多例,strut2的效率不如springmvc。
@Controller
@RequestMapping("/day57")
public class MyController {
@RequestMapping("/rm")
public String rm() {
return "success";
}
}
SpringMVC流程图说明
springMVC中组件说明
springmvc有三大组件:
处理器映射器:找处理器的RequestMappingHandlerMapping
处理器适配器:处理处理器RequestMappingHandlerAdapter
视图解析器:拼装视图路径InternalResourceViewResolver
其实默认前端控制器什么都不配置,也有三大组件在工作。而我们在springMVC配置文件中配置开启mvc注解支持和视图解析器只是对功能进行了增强。
@RequestMapping注解的说明
接收各种类型的参数
1.接收简单类型的参数
<a href="${pageContext.request.contextPath}/day57/simpleParams?id=1&name=小明">入门案例get请求</a>
@RequestMapping("/simpleParams")
public String simpleParams(Integer id,String name) {
System.out.println(id);
System.out.println(name);
return "success";
}
注意:
如果是get请求,直接使用处理器参数介绍请求参数,中文是可以正常接收的。
2.接收复杂对象类型参数
<form action="${pageContext.request.contextPath}/day57/dtoParams" method="post">
id:<input type="text"><br>
name:<input type="text"><br>
User对象中的id:<input type="text" name="id"><br>
User对象中的name:<input type="text" name="name"><br>
List集合中第一个User的id:<input type="text" name="users[0].id"><br>
List集合中第一个User的name:<input type="text" name="users[0].name"><br>
List集合中第二个User的id:<input type="text" name="users[1].id"><br>
List集合中第二个User的name:<input type="text" name="users[1].name"><br>
Map集合中第一个User的id:<input type="text" name="userMap['one'].id"><br>
Map集合中第一个User的name:<input type="text" name="userMap['one'].name"><br>
Map集合中第二个User的id:<input type="text" name="userMap['two'].id"><br>
Map集合中第二个User的name:<input type="text" name="userMap['two'].name"><br>
<input type="submit" value="发送复杂类型的参数">
</form>
@RequestMapping("/dtoParams")
public String dtoParams(UserDTO userDTO){
System.out.println(userDTO);
return "success";
}
注意:
如果是直接使用处理器参数来接收请求参数,post请求中文是乱码
解决post请求中文乱码问题
<!-- 配置过滤器解决传递参数中文乱码的问题 -->
<filter>
<filter-name>encodingFilter</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>
<!-- 设置强制转换 -->
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
接收数组类型参数
<form action="${pageContext.request.contextPath}/day57/arrayParams" method="post">
<input type="checkbox" name="ids" value="1"><br>
<input type="checkbox" name="ids" value="2"><br>
<input type="checkbox" name="ids" value="3"><br>
<input type="checkbox" name="ids" value="4"><br>
<input type="checkbox" name="ids" value="5"><br>
<input type="checkbox" name="ids" value="6"><br>
<input type="submit" value="提交数组类型的参数">
</form>
@RequestMapping("arrayParams")
public String arrayParams(Integer[] ids){
System.out.println(Arrays.toString(ids));
return "success";
}
日期类型的参数
注意:
springMVC默认只能介绍2019/10/10个数的日期,其余格式的日期都必须自定义日期转换器.
form action="${pageContext.request.contextPath}/day57/dateParams">
<input type="text" name="date">
<input type="submit" value="提交日期类型的参数">
</form>
@RequestMapping("dateParams")
public String dateParams(Date date){
System.out.println(date);
return "success";
}
public class DateConverter implements Converter<String, Date> {
public Date convert(String s) {
try {
Date date = null;
if (s.indexOf("-")>0){
date = new SimpleDateFormat("yyyy-MM-dd").parse(s);
}
if (s.indexOf("/")>0){
date = new SimpleDateFormat("yyyy/MM/dd").parse(s);
}
return date;
} catch (Exception e) {
throw new RuntimeException("日期转换异常!");
}
}
}
<!-- 加载注解 -->
<mvc:annotation-driven conversion-service="conversionService"/>
<!-- 配置日期转换器 -->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.itheima.converter.DateConverter"/>
</set>
</property>
</bean>
</beans>
接收请求头@RequestHeader
<a href="${pageContext.request.contextPath}/day57/requestHeader">获取指定请求头的信息</a>
@RequestMapping("requestHeader")
public String requestHeader(@RequestHeader("Cookie") String header) {
System.out.println(header);
return "success";
}
获取Cookie中的信息@CookieValue
<a href="${pageContext.request.contextPath}/day57/cookieValue">获取Cookie头指定名称的信息</a>
@RequestMapping("cookieValue")
public String cookieValue(@CookieValue("JSESSIONID") String value){
System.out.println(value);
return "success";
}
使用SpringMVC进行文件上传
<!-- 文件解析器 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="5242880"/>
</bean>
<%--
文件上传的三要素:
1.必须是form表单中的post请求方式
2.必须是enctype="multipart/form-data类型
3.input 的type必须为file
--%>
<form action="${pageContext.request.contextPath}/day58/shangchuan" method="post" enctype="multipart/form-data">
请选择想要上传的文件:<input type="file" name="fileParams"/><br>
请选择想要上传的文件:<input type="file" name="fileParams"/><br>
<input type="submit" value="点击上传">
</form>
@RequestMapping("/shangchuan")
public String shangchuan(MultipartFile[] fileParams) throws IOException {
//创建并绑定一个文件夹对象
File file = new File("E:\\照片");
for (MultipartFile fileParam : fileParams) {
//设置文件在文件夹中的名称
String fileName = UUID.randomUUID() + fileParam.getOriginalFilename();
//上传文件
fileParam.transferTo(new File(file,fileName));
}
return "success";
}
@responseBody的使用说明[重点]
说明
此注解可以放在处理器方法或者类上。表示当前处理器是一个异步返回数据的处理器。
如果返回的数据是一个javaBean对象,而且项目中有jackson的jar包,那么可以直接被转成json返回给页面。
<button id="btnId">提交json格式的数据到服务器</button>
<script type="text/javascript">
$(function () {
$("#btnId").click(function () {
$.ajax({
type:"POST",
url:"${pageContext.request.contextPath}/day58/jsonAndBean",
contentType:"application/json;charset=UTF-8",
data:'{"id":"1","name":"小明"}',
success:function (date) {
}
})
});
})
</script>
@RequestMapping("jsonAndBean")
public String jsonAndBean(@RequestBody User user) {
System.out.println(user);
return "success";
}
@responseBody的使用说明[重点]
说明
此注解可以放在处理器方法或者类上。表示当前处理器是一个异步返回数据的处理器。
如果返回的数据是一个javaBean对象,而且项目中有jackson的jar包,那么可以直接被转成json返回给页面。