springMVC
springMVC的快速入门
-
导入依赖
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.2.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.5.RELEASE</version> </dependency>
-
在web.xml中配置前端控制器
<!--配置前端控制器--> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--加载spring-mvc文件--> <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> <url-pattern>/</url-pattern> </servlet-mapping>
-
开启springMVC的注解扫描
<context:component-scan base-package="com.boke.controller"></context:component-scan>
-
编写视图
编写一个前端页面
-
开启映射
@Controller public class UserController { //注解配置映射 @RequestMapping(path = "/save") public String save(){ System.out.println("save"); return "/success.jsp"; }
springMVC的执行流程
- 客户端发送请求到DispatcherServlet(前端控制器)
- DispatcherServlet发送请求调用HandlerMapping处理器映射器
- 处理器映射器根据路径匹配到需要执行的方法,但它不执行方法
- HandlerMapping返回处理器执行链给DispatcherServlet
- DispatcherServlet调用处理器适配器
- 处理器适配器经过具体的适配调用处理器(controller,也叫后端控制器)
- 处理器适配器返回ModelAndView给前端控制器
- 前端控制器调用视图解析器
- 视图解析器进行渲染后返回前端控制器
- 前端控制器响应客户端请求
释放静态资源
<mvc:resource mapping="/img/**" location="/img/"/>
<!-- 释放全部静态资源-->
<mvc:default-servlet-handler/>
解决中文乱码
<!--解决中文乱码-->
<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>
请求
普通类型参数
//访问url:http://localhpst/boke?neme = zhangsan
@RequestMapping("/boge")
public void show(string name){
}
//多个参数访问
//url:http://localhpst/boke?neme=zhangsan&age=12
@RequestMapping("/boge")
public void show(string name,int age){
}
//参数名和形参名不一致
//访问url:http://localhpst/boke?neme = zhangsan
@RequestMapping("/boge")
public void show(@RequestParam(value="name",requird=ture)(string username)){
}
@RequestParam
作用: 把请求中指定名称的参数给控制器中的形参赋值。
属性:
value:请求参数中的名称。
required:请求参数中是否必须提供此参数。默认值:true。表示必须提供,如果不提供将报错。
POJO类型参数传参
访问URL: http://localhost/requestParam3?name=itheima&age=14
Controller
@RequestMapping("/requestParam3")
public String requestParam3(User user){
System.out.println("name="+user.getName());
return "page.jsp";
}
POJO类
public class User {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
复杂POJO类型参数
当POJO中出现对象属性时,参数名称与对象层次结构名称保持一致
访问URL: http://localhost/requestParam5?address.province=beijing
public class User {
private String name;
private Integer age;
private Address address;
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
@RequestMapping("/requestParam5")
public String requestParam5(User user){
System.out.println("user.address="+user.getAddress().getProvince());
return "page.jsp";
}
当POJO中出现List,保存对象数据,参数名称与对象层次结构名称保持一致,使用数组格式描述集合中对象的位置
访问URL: http://localhost/requestParam7?addresses[0].province=bj&addresses[1].province=tj
public class User {
private String name;
private Integer age;
private List<Address> addresses;
}
public class Address {
private String province;
private String city;
private String address;
}
@RequestMapping("/requestParam7")
public String requestParam7(User user){
System.out.println("user.addresses="+user.getAddress());
return "page.jsp";
}
数组与集合类型参数传参
数组类型参数
请求参数名与处理器方法形参名保持一致,且请求参数数量> 1个
访问URL: http://localhost/requestParam9?nick=Jockme&nick=zahc
@RequestMapping("/requestParam9")
public String requestParam9(String[] nick){
System.out.println(nick[0]+","+nick[1]);
return "page.jsp";
}
集合类型参数
保存简单类型数据,请求参数名与处理器方法形参名保持一致,且请求参数数量> 1个
访问URL: http://localhost/requestParam10?nick=Jockme&nick=zahc
@RequestMapping("/requestParam10")
public String requestParam10(@RequestParam("nick") List<String> nick){
System.out.println(nick);
return "page.jsp";
}
注意: SpringMVC默认将List作为对象处理,赋值前先创建对象,然后将nick作为对象的属性进行处理。由于
List是接口,无法创建对象,报无法找到构造方法异常;修复类型为可创建对象的ArrayList类型后,对象可
以创建,但没有nick属性,因此数据为空。此时需要告知SpringMVC的处理器nick是一组数据,而不是一个单
一数据。通过@RequestParam注解,将数量大于1个names参数打包成参数数组后, SpringMVC才能识别该数
据格式,并判定形参类型是否为数组或集合,并按数组或集合对象的形式操作数据。
类型转换
标量转换器
StringToBooleanConverter String→Boolean
ObjectToStringConverter Object→String
StringToNumberConverterFactory String→Number( Integer、 Long等)
NumberToNumberConverterFactory Number子类型之间(Integer、 Long、 Double等)
StringToCharacterConverter String→java.lang.Character
NumberToCharacterConverter Number子类型(Integer、 Long、 Double等)→java.lang.Character
CharacterToNumberFactory java.lang.Character→Number子类型(Integer、 Long、 Double等)
StringToEnumConverterFactory String→enum类型
EnumToStringConverter enum类型→String
StringToLocaleConverter String→java.util.Local
PropertiesToStringConverter java.util.Properties→String
StringToPropertiesConverter String→java.util.Properties
集合、数组相关转换器
ArrayToCollectionConverter 数组→集合( List、 Set)
CollectionToArrayConverter 集合( List、 Set) →数组
ArrayToArrayConverter 数组间
CollectionToCollectionConverter 集合间( List、 Set)
MapToMapConverter Map间
ArrayToStringConverter 数组→String类型
StringToArrayConverter String→数组, trim后使用“,”split
ArrayToObjectConverter 数组→Object
ObjectToArrayConverter Object→单元素数组
CollectionToStringConverter 集合( List、 Set) →String
StringToCollectionConverter String→集合( List、 Set), trim后使用“,”split
CollectionToObjectConverter 集合→Object
ObjectToCollectionConverter Object→单元素集合
默认转换器
ObjectToObjectConverter Object间
IdToEntityConverter Id→Entity
FallbackObjectToStringConverter Object→String
日期类型格式转换
-
声明自定义的转换格式并覆盖系统转换格式
<!--5.启用自定义Converter--> <mvc:annotation-driven conversion-service="conversionService"/> <!--1.设定格式类型Converter,注册为Bean,受SpringMVC管理--> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <!--2.自定义Converter格式类型设定,该设定使用的是同类型覆盖的思想--> <property name="formatters"> <!--3.使用set保障相同类型的转换器仅保留一个,避免冲突--> <set> <!--4.设置具体的格式类型--> <bean class="org.springframework.format.datetime.DateFormatter"> <!--5.类型规则--> <property name="pattern" value="yyyy-MM-dd"/> </bean> </set> </property> </bean>
-
日期类型格式转换(简化版)
名称: @DateTimeFormat
类型: 形参注解、成员变量注解
位置:形参前面 或 成员变量上方
作用:为当前参数或变量指定类型转换规则
范例:public String requestParam12(@DateTimeFormat(pattern = "yyyy-MM-dd") Date date){ System.out.println("date="+date); return "page.jsp"; }
@DateTimeFormat(pattern = "yyyy-MM-dd") private Date birthday;
-
注意:依赖注解驱动支持
<mvc:annotation-driven />
自定义类型转换器
-
自定义类型转换器,实现Converter接口,并制定转换前与转换后的类型
<!--1.将自定义Converter注册为Bean,受SpringMVC管理--> <bean id="myDateConverter" class="com.itheima.converter.MyDateConverter"/> <!--2.设定自定义Converter服务bean--> <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> <!--3.注入所有的自定义Converter,该设定使用的是同类型覆盖的思想--> <property name="converters"> <!--4.set保障同类型转换器仅保留一个,去重规则以Converter<S,T>的泛型为准--> <set> <!--5.具体的类型转换器--> <ref bean="myDateConverter"/> </set> </property> </bean>
//自定义类型转换器,实现Converter接口,接口中指定的泛型即为最终作用的条件 //本例中的泛型填写的是String,Date,最终出现字符串转日期时,该类型转换器生效 public class MyDateConverter implements Converter<String, Date> { //重写接口的抽象方法,参数由泛型决定 public Date convert(String source) { DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); Date date = null; //类型转换器无法预计使用过程中出现的异常,因此必须在类型转换器内部捕获,不允许抛出,框架无法预计此类异常如何处理 try { date = df.parse(source); } catch (ParseException e) { e.printStackTrace(); } return date; } }
-
通过注册自定义转换器,将该功能加入到SpringMVC的转换服务ConverterService中
<!--开启注解驱动,加载自定义格式化转换器对应的类型转换服务--> <mvc:annotation-driven conversion-service="conversionService"/>
请求映射注解 @RequestMapping
响应
页面跳转
- 转发(默认)
@RequestMapping("/showPage1")
public String showPage1() {
System.out.println("user mvc controller is running ...");
return "forward:page.jsp";
}
- 重定向
@RequestMapping("/showPage2")
public String showPage2() {
System.out.println("user mvc controller is running ...");
return "redirect:page.jsp";
}
注意:页面访问地址中所携带的 /
页面访问快捷设定 (InternalResourceViewResolver)
展示页面的保存位置通常固定,且结构相似,可以设定通用的访问路径,简化页面配置格式
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
/bean>
public String showPage3() {
return "page";
}
如果未设定了返回值,使用void类型,则默认使用访问路径作页面地址的前缀后缀
//最简页面配置方式,使用访问路径作为页面名称,省略返回值
@RequestMapping("/showPage5")
public void showPage5() {
System.out.println("user mvc controller is running ...");
}
带数据页面跳转
-
方式一:使用HttpServletRequest类型形参进行数据传递
@RequestMapping("/showPageAndData1") public String showPageAndData1(HttpServletRequest request) { request.setAttribute("name","itheima"); return "page"; }
-
方式二:使用Model类型形参进行数据传递
@RequestMapping("/showPageAndData2") public String showPageAndData2(Model model) { model.addAttribute("name","itheima"); Book book = new Book(); book.setName("SpringMVC入门实战"); book.setPrice(66.6d); model.addAttribute("book",book); return "page"; }
-
方式三:使用ModelAndView类型形参进行数据传递,将该对象作为返回值传递给调用者
//使用ModelAndView形参传递参数,该对象还封装了页面信息 @RequestMapping("/showPageAndData3") public ModelAndView showPageAndData3(ModelAndView modelAndView) { //ModelAndView mav = new ModelAndView(); 替换形参中的参数 Book book = new Book(); book.setName("SpringMVC入门案例"); book.setPrice(66.66d); //添加数据的方式,key对value modelAndView.addObject("book",book); //添加数据的方式,key对value modelAndView.addObject("name","Jockme"); //设置页面的方式,该方法最后一次执行的结果生效 modelAndView.setViewName("page"); //返回值设定成ModelAndView对象 return modelAndView; }
返回json数据
方式一:基于response返回数据的简化格式,返回JSON数据
//使用jackson进行json数据格式转化
@RequestMapping("/showData3")
@ResponseBody
public String showData3() throws JsonProcessingException {
Book book = new Book();
book.setName("SpringMVC入门案例");
book.setPrice(66.66d);
ObjectMapper om = new ObjectMapper();
return om.writeValueAsString(book);
}
使用SpringMVC提供的消息类型转换器将对象与集合数据自动转换为JSON数据
//使用SpringMVC注解驱动,对标注@ResponseBody注解的控制器方法进行结果转换,由于返回值为引用类型,自动调用jackson提供的类型转换器进行格式转换
@RequestMapping("/showData4")
@ResponseBody
public Book showData4() {
Book book = new Book();
book.setName("SpringMVC入门案例");
book.setPrice(66.66d);
return book;
}
需要手工添加信息类型转换器
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
</list>
</property>
</bean
方式三:使用SpringMVC注解驱动简化配置
<!--开启springmvc注解驱动,对@ResponseBody的注解进行格式增强,追加其类型转换的功能,具体实现由MappingJackson2HttpMessageConverter进行-->
<mvc:annotation-driven/>
Servlet相关接口-Servlet相关接口替换方案
HttpServletRequest / HttpServletResponse / HttpSession
-
SpringMVC提供访问原始Servlet接口API的功能,通过形参声明即可
@RequestMapping("/servletApi") public String servletApi(HttpServletRequest request, HttpServletResponse response, HttpSession session){ System.out.println(request); System.out.println(response); System.out.println(session); request.setAttribute("name","itheima"); System.out.println(request.getAttribute("name")); return "page.jsp"; }
-
Head数据获取
名称: @RequestHeader
类型: 形参注解
位置:处理器类中的方法形参前方
作用:绑定请求头数据与对应处理方法形参间的关系
范例:@RequestMapping("/headApi") public String headApi(@RequestHeader("Accept-Language") String head){ System.out.println(head); return "page.jsp"; }
-
Cookie数据获取
名称: @CookieValue
类型: 形参注解
位置:处理器类中的方法形参前方
作用:绑定请求Cookie数据与对应处理方法形参间的关系
范例:@RequestMapping("/cookieApi") public String cookieApi(@CookieValue("JSESSIONID") String jsessionid){ System.out.println(jsessionid); return "page.jsp"; }
-
Session数据获取
名称: @SessionAttribute
类型: 形参注解
位置:处理器类中的方法形参前方
作用:绑定请求Session数据与对应处理方法形参间的关系
范例:@RequestMapping("/sessionApi") public String sessionApi(@SessionAttribute("name") String name){ System.out.println(name); return "page.jsp"; }
-
Session数据设置(了解)
名称: @SessionAttributes
类型: 类注解
位置:处理器类上方
作用:声明放入session范围的变量名称,适用于Model类型数据传参
范例:@Controller @SessionAttributes(names={"name"}) public class ServletController { @RequestMapping("/setSessionData2") public String setSessionDate2(Model model) { model.addAttribute("name", "Jock2"); return "page.jsp"; } }
-
注解式参数数据封装底层原理
数据的来源不同,对应的处理策略要进行区分
Head
Cookie
Session
SpringMVC使用策略模式进行处理分发
顶层接口: HandlerMethodArgumentResolver
实现类: …异步提交
@RequestBody
@RequestBody
作用: 用于获取请求体内容。直接使用得到是key=value&key=value...结构的数据。 get请求方式不适用。将异步提交数据组织成标准请求参数格式 属性: required:是否必须有请求体。默认值是:true。当取值为true时,get请求方式会报错。如果取值为false,get请求得到是null。
文件上传插件
1.必要前提
1.form表单的enctype取值必须是:multipart/form-data (默认值是:application/x-www-form-urlencoded
) enctype:是表单请求正文的类型
2.method属性取值必须是Post
3.提供一个文件选择域<input type="file" />
2.导入相关依赖
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
3.配置文件解析器
<!--
配置文件上传解析器
id的值是固定的
class的值也是固定的
-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置上传文件的最大尺寸为5MB -->
<property name="maxUploadSize">
<value>5242880</value>
</property>
</bean>
false,get请求得到是null。
## 拦截器
## 文件上传插件
1.必要前提
1.form表单的enctype取值必须是:multipart/form-data (默认值是:`application/x-www-form-urlencoded`) enctype:是表单请求正文的类型
2.method属性取值必须是Post
3.提供一个文件选择域`<input type="file" />`
2.导入相关依赖
```xml
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
3.配置文件解析器
<!--
配置文件上传解析器
id的值是固定的
class的值也是固定的
-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置上传文件的最大尺寸为5MB -->
<property name="maxUploadSize">
<value>5242880</value>
</property>
</bean>