SpringMVC(2)
0.总体结构
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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>gy.com</groupId>
<artifactId>springmvc</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>6</source>
<target>6</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>3.0-alpha-1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.3</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.18</version>
</dependency>
</dependencies>
</project>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<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:application.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<!--除了web资源根路径下的jsp文件,其余所有都经过dispatcherServlet-->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
application.xml
把自定义的转换器组件String2DateConverter(id=conversionService2)放入到converters
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.parameter"/>
<mvc:annotation-driven conversion-service="conversionService2"/>
<bean id="conversionService2" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set>
<ref bean="string2DateConverter"/>
<!--<bean class="com.cskaoyan.converter.String2DateConverter"/>-->
</set>
</property>
</bean>
<!--组件id为固定值,不可以修改为其他值-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="500000"/>
</bean>
</beans>
1.SpringMVC案例一
1.1 Handler方法的形参
主要讲请求参数的封装
springMvc提供的转换器让我们能够直接以需要的类型来接收请求参数
1.1.1 直接封装(请求参数名和handler方法的形参名一致)
1.1.1. 主要是基本类型和对应的包装类
localhost:8080/register?username=xxxx&password=zzzzz&age=36
1.1.2 Date
(1)使用springmvc提供的日期转换器@DateTimeFormat(pattern)
(2)自定义转换器String2DateConverter(String 👉 Date)
implements Converter<S,T>
BaseRespVo
@Data
public class BaseRespVo<T> {
T data;
String message;
long errno;
public static BaseRespVo ok(){
BaseRespVo baseRespVo = new BaseRespVo();
baseRespVo.setMessage("成功");
baseRespVo.setErrno(0);
return baseRespVo;
}
public static BaseRespVo ok(Object data){
BaseRespVo ok = BaseRespVo.ok();
ok.setData(data);
return ok;
}
}
String2DateConverter(转换器)
@Component
public class String2DateConverter implements Converter<String, Date> {
//请求参数名和handler方法的形参名一致,类型又匹配为Converter接口这里的类型
@Override
@SneakyThrows
public Date convert(String s) {
Date date=null;
String pattern1 = "yyyy-MM-dd";
String pattern2 = "yyyy-MM-dd HH:mm:ss";
String pattern3 = "yyyy-MM-dd HH:mm";
if (s.length() == pattern1.length()){
try {
date = new SimpleDateFormat(pattern1).parse(s);
} catch (ParseException e) {
e.printStackTrace();
}
}else if (s.length() == pattern2.length()){
try {
date = new SimpleDateFormat(pattern2).parse(s);
} catch (ParseException e) {
e.printStackTrace();
}
} else if (s.length() == pattern3.length()) {
try {
date = new SimpleDateFormat(pattern3).parse(s);
} catch (ParseException e) {
e.printStackTrace();
}
}
return date;
}
}
ParameterController
//请求参数的封装
@RestController
public class ParameterController {
//localhost:8080/register?username=ffffff&password=uuuu&age=36
//👉 建议:若想接收基本类型,不建议直接写基本类型,
// 建议以基本类型所对应的包装类来接收
@RequestMapping("register")
public BaseRespVo register(String username, String password, Integer age, Boolean married) {
return BaseRespVo.ok(username + ":" + password + ":" + age);
}
//localhost:8080/register2?username=jingtian&password=niupi&age=36&birthday=2000-05-15
//如果想要接收Date需要指定日期的格式
@RequestMapping("register2")
public BaseRespVo register2(String username, String password, Integer age, @DateTimeFormat(pattern = "yyyy-MM-dd") Date birthday) {
System.out.println(birthday);
return BaseRespVo.ok();
}
@Autowired
ConfigurableConversionService conversionService;
//localhost:8080/register3?username=jingtian&password=niupi&age=36&birthday=2000-05-15
//localhost:8080/register3?username=jingtian&password=niupi&age=36&birthday=2000-05-15 15:24
//localhost:8080/register3?username=jingtian&password=niupi&age=36&birthday=2000-05-15 15:24:28
@RequestMapping("register3")
public BaseRespVo register3(String username, String password, Integer age,Date birthday) {
System.out.println(birthday);
return BaseRespVo.ok();
}
}
结果:
1.2 文件类型(文件的接收、上传)
1.2.1 依赖
commons-io/commons-fileupload
1.2.2 组件注册
multipartResolver
1.2.3 构造form表单
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>文件上传</h1>
<form action="/file/upload" enctype="multipart/form-data" method="post">
<%--name属性会体现为请求参数名--%>
<input type="file" name="myfile">
<input type="submit">
</form>
<hr>
<h1>多个文件上传</h1>
<form action="/files/upload" enctype="multipart/form-data" method="post">
<%--name属性会体现为请求参数名--%>
<input type="file" multiple name="myfiles">
<input type="submit">
</form>
</body>
</html>
1.2.4 handler方法接收文件
-
String[] hobbys
localhost/register4?hobyys=sing&hobbys=dance&hobbys=basketball
多个请求参数名相同,就意味着可以使用数组来接收 -
文件也可以以数组的形式来接收
-
多文件上传页面属性
-
@RestController
public class ParameterController {
//请求参数名和handler方法的形参名(MultiparFile)一致
@RequestMapping("file/upload")
public BaseRespVo fileUpload(MultipartFile myfile){
String name = myfile.getName();//请求参数名 👉 myfile
String originalFilename = myfile.getOriginalFilename(); //上传时选择的文件名
String contentType = myfile.getContentType(); //文件类型
long size = myfile.getSize();
//save
File path = new File("D:\\gy\\spring");
//构造一个file来接收multipartFile
File file = new File(path, originalFilename);//想要以什么文件名保存,第二个参数就写什么
try {
//将multipartFile转换为file
myfile.transferTo(file);
} catch (IOException e) {
e.printStackTrace();
}
return BaseRespVo.ok();
}
//localhost:8080/register4?hobyys=sing&hobbys=dance&hobbys=basketball&username=jingtian&age=25
//数组数据
@RequestMapping("register4")
public BaseRespVo register4(String username,Integer age,String[] hobbys){
return BaseRespVo.ok(hobbys);
}
//请求参数名和handler方法的形参名(MultipartFile)一致
@RequestMapping("files/upload")
public BaseRespVo filesUpload(MultipartFile[] myfiles) {
for (MultipartFile myfile : myfiles) {
String name = myfile.getName();//请求参数名 👉 myfile
String originalFilename = myfile.getOriginalFilename();//上传时选择的文件名
String contentType = myfile.getContentType();//文件类型
long size = myfile.getSize();
//save
File path = new File("D:\\gy\\spring");
//构造一个file来接收multipartFile
File file = new File(path, originalFilename);//你想要以什么文件名保存,第二个参数就写什么
try {
myfile.transferTo(file);
} catch (IOException e) {
e.printStackTrace();
}
}
return BaseRespVo.ok();
}
}
结果:
1.3使用pojo封装
handler形参变更为pojo类中的成员变量 👉 请求参数名和javabean的成员变量名(set)一致
Order
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class Order {
String name;
Double price;
}
UserDetail
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class UserDetail {
String mobile;
String email;
}
User
@Data
@AllArgsConstructor//有参构造
@NoArgsConstructor//无参构造
@Accessors(chain = true)//可以连续调用
public class User {
String username;
String password;
Integer age;
//@DateTimeFormat //请求参数封装过程中的转换
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")//响应结果json格式的限定
Date birthday;
//localhost:8080/javabean/register?username=jingtian&userDetail.mobile=100&userDetail.email=cskaoyan@qq.com
UserDetail userDetail;
//localhost:8080/javabean/register?username=jingtian&
// orders[0].name=lanqiu&orders[0].price=50&
// orders[1].name=tiaowuji&orders[1].price=5000
//[]需要使用到uri编码
// [ 👉 %5B
// ] 👉 %5D
//http://localhost:8080/javabean/register?username=jingtian&orders%5B0%5D.name=lanqiu&orders%5B0%5D.price=50&orders%5B1%5D.name=tiaowuji&orders%5B1%5D.price=5000&birthday=2021-04-02
List<Order> orders;
}
//localhost:8080/javabean/register?username=jingtian&orders[0].name=lanqiu&orders[0].price=50&
// orders[1].name=tiaowuji&orders[1].price=5000不能访问
[]需要使用到uri编码
[ 👉 %5B
] 👉 %5D
以下为转换网站:
http://tool.chinaz.com/tools/urlencode.aspx
手动转换后:
http://localhost:8080/javabean/register?username=jingtian&orders%5B0%5D.name=lanqiu&orders%5B0%5D.price=50&orders%5B1%5D.name=tiaowuji&orders%5B1%5D.price=5000&birthday=2021-04-02
访问成功:
1.4 json请求参数
请求方法:post
Content-Type:application/json
data: json字符串
JsonController
@RestController
public class JsonController {
@RequestMapping("json/login")
public BaseRespVo login(@RequestBody User user){
return BaseRespVo.ok(user);
}
}
{“username”:“jingtian”,“password”:35777,“age”:66,“birthday”:“2021-04-02 00:00:00”,“userDetail”:{“mobile”:“4444”,“email”:“67657”},“orders”:[{“name”:“lanqiu”,“price”:50.0},{“name”:“tiaowuji”,“price”:5000.0}]}
json格式化校验:
https://www.bejson.com/json/format/
或者下载插件:GsonFormat
快捷键:Alt+s
JsonBean
public class JsonBean {
/**
* username : jingtian
* password : 35777
* age : 66
* birthday : 2021-04-02 00:00:00
* userDetail : {"mobile":"4444","email":"67657"}
* orders : [{"name":"lanqiu","price":50},{"name":"tiaowuji","price":5000}]
*/
private String username;
private int password;
private int age;
private String birthday;
private UserDetailBean userDetail;
private List<OrdersBean> orders;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getPassword() {
return password;
}
public void setPassword(int password) {
this.password = password;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
public UserDetailBean getUserDetail() {
return userDetail;
}
public void setUserDetail(UserDetailBean userDetail) {
this.userDetail = userDetail;
}
public List<OrdersBean> getOrders() {
return orders;
}
public void setOrders(List<OrdersBean> orders) {
this.orders = orders;
}
public static class UserDetailBean {
/**
* mobile : 4444
* email : 67657
*/
private String mobile;
private String email;
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
public static class OrdersBean {
/**
* name : lanqiu
* price : 50
*/
private String name;
private int price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
}
1.5 Model
1.5.1
- 返回值为String作为viewname时,使用Model作为形参
- 由于cookie不能直接写在形参中,要通过request来获得
CookieSessionController
@RestController
public class CookieSessionController {
@RequestMapping("fetch/cookie")
public BaseRespVo fetchCookie(HttpServletRequest request){
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
System.out.println(cookie.getName() + " = " + cookie.getValue());
}
return BaseRespVo.ok();
}
@RequestMapping("put/session")
public BaseRespVo putSession(String username, HttpSession session){
session.setAttribute("username",username);
return BaseRespVo.ok();
}
@RequestMapping("fetch/session")
public BaseRespVo fetchSession(HttpSession session) {
Object username = session.getAttribute("username");
return BaseRespVo.ok(username);
}
@RequestMapping("fetch/session2")
public BaseRespVo fetchSession2(HttpServletRequest request) {
HttpSession session = request.getSession();
return BaseRespVo.ok();
}
}
再次发送后
或者使用postman
1.5.2 Session
可以直接在形参中获得