Эта статья представляет собой краткий обзор привязки данных в SpringMVC.
1. Разница между SpringMVC и Struts2
И Struts2, и SpringMVC являются платформами уровня представления в веб-разработке. Обе они реализуют автоматическую привязку данных, не требуя от нас ручного получения параметров, а затем связывания их с соответствующими свойствами. Давайте поговорим о разнице между ними.
- Spring MVC основан на методах и получает параметры через формальные параметры; Struts2 основан на классах и получает параметры через инкапсуляцию на основе модели.
- SpringMVC сопоставляет URL-адрес и метод в классе контроллера для создания объекта Handler для выполнения метода метода; Struts2 сопоставляет URL-адрес с методом в классе действия в соответствии с файлом конфигурации и создает объект действия для выполнения метода метода.
- Формальные параметры SpringMVC получают параметры, метод имеет эксклюзивные данные ответа на запрос и разрабатывается с использованием одного экземпляра; переменные-члены Struts2 получают параметры, а несколько методов совместно используют переменные-члены, которые должны разрабатываться с использованием нескольких экземпляров.
- Запись SpringMVC — это Servlet, метод для контекста запроса, который вводит данные запроса в параметры метода через аннотации; а запись Struts2 — это фильтр, перехватывающий каждый запрос, создающий действие и вызывающий методы получения и установки переменных-членов для данные запроса.Внедрение переменных-членов, два механизма реализации различны.
- SpringMVC более легкий, Struts2 имеет много настроек, а эффективность разработки и производительность SpringMVC выше, чем у Struts2.
- Данные, возвращаемые методом SpringMVC, более гибкие, и для взаимодействия с JSON удобно использовать AJAX, рендеринг данных меток Struts2 медленный, а его производительность не так высока, как у меток JSTL.
Я пользовался обоими этими фреймворками.Это только мое личное мнение.Конфигурация Struts2 действительно сложна в написании.Ограниченность классов делает использование недостаточно гибким, а совмещение с некоторыми front-end фреймворками не очень удобно.Лично я , я отказываюсь от фреймворка Struts2. .
2. Различные типы привязки данных
Данные, которые взаимодействуют с интерфейсом и сервером во время разработки, представляют собой не что иное, как следующее:
- Примитивные типы (int, double, Integer, String и т. д.)
- Тип объекта (класса) (пользовательский класс сущностей)
- Тип даты (java.util.Date)
- Сложные типы (массив объектов, список, набор, карта и т. д.)
- Специальные типы текста (JSON, XML и т. д.)
Ниже показано, как эти данные связаны с параметрами метода в SpringMVC.
Используйте Maven для создания проекта, весь код загружен на GitHub, нуждающиеся друзья могут перейти наскачать, вы также можете пометить этот репозиторий!
После добавления аннотации @ResponseBody в метод обработанные данные выводятся напрямую в поток ответа, и нет попытки разобрать процесс, то есть возвращается тип JSON. SpringMVC использует режим адаптера для обработки преобразования данных.Когда мы используем Jackson в качестве инструмента для разбора JSON, обратите внимание на большую яму здесь.Кодировка по умолчанию в Джексоне — ISO-8859-1 (большая яма), что приведет к вывод китайского.Искаженный код можно посмотреть через консоль браузера.Решения следующие.
1. Добавьте настройки кодирования для каждого метода@RequestMapping(value = "basetype3.do", produces = "application/json; charset=utf-8")
2. Измените кодировку Джексона по умолчанию на UTF-8 в файле конфигурации SpringMVC.Обратите внимание, что она должна быть помещена в<mvc:annotation-driven/>
Спереди внутрь ставить не эффективно.
3. Измените инструмент парсинга JSON.Рекомендуется использовать fastjson Alibaba.Кодировка по умолчанию — UTF-8, а скорость парсинга выше, чем у Jackson.
Подробная конфигурация методов 2 и 3 выглядит следующим образом:
<!--特别注意:必须放在mvc:annotation-driven前面,放在内部是不会生效的-->
<!--json装换器使用 Jackson 默认编码是 ISO-8859-1 需要重新设置编码-->
<!--<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">-->
<!--<property name="messageConverters">-->
<!--<list>-->
<!--<bean class="org.springframework.http.converter.StringHttpMessageConverter">-->
<!--<property name="supportedMediaTypes">-->
<!--<list>-->
<!--<value>text/plain;charset=UTF-8</value>-->
<!--<value>text/html;charset=UTF-8</value>-->
<!--<value>applicaiton/json;charset=UTF-8</value>-->
<!--</list>-->
<!--</property>-->
<!--</bean>-->
<!--</list>-->
<!--</property>-->
<!--</bean>-->
<!-- json装换器使用 fastjson,默认就是 UTF-8 编码,不需要再重新设置编码-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"/>
</list>
</property>
</bean>
<!--配置注解驱动-->
<mvc:annotation-driven/>
Описание: имя проекта — springmvc, а каждый метод — тестовый адрес.
2.1 Основные типы
При передаче параметров формальное имя параметра в методе должно совпадать с именем параметра в URL-адресе по умолчанию. Вы также можете добавить аннотацию @RequestParam к методу, чтобы изменить имя параметра в URL-адресе.
Базовый тип данных (int, double) в базовом типе устанавливается в параметр и не может быть нулевым, иначе будет сообщено об ошибке, а тип упаковки базового типа данных может быть нулевым, то есть значение по умолчанию равно null если не передается, здесь Также обратите внимание на китайские искаженные иероглифы, упомянутые выше.
// http://localhost:8080/springmvc/basetype1.do?id=1
// http://localhost:8080/springmvc/basetype1.do?id= 不带参数报错
@RequestMapping(value = "basetype1.do")
@ResponseBody
public String baseType1(int id) {
return "id=" + id;
}
// http://localhost:8080/springmvc/basetype2.do?id=1
// http://localhost:8080/springmvc/basetype2.do?id= 不带参数不报错,参数默认为null
@RequestMapping(value = "basetype2.do")
@ResponseBody
public String baseType2(Integer id) {
return "id=" + id;
}
// http://localhost:8080/springmvc/basetype3.do?name='汤姆' 注意中文乱码问题
// http://localhost:8080/springmvc/basetype3.do?name='tom'
@RequestMapping(value = "basetype3.do")
@ResponseBody
public String baseType3(String name) {
return "name=" + name;
}
// http://localhost:8080/springmvc/basetype4.do?xid=1
@RequestMapping(value = "basetype4.do")
@ResponseBody
public String baseType4(@RequestParam(value = "xid") Integer id) {
return "id=" + id;
}
2.2 Типы объектов
Описание класса сущности:
- В классе User есть только два свойства: одно — name типа String, а другое — age типа Integer.
- В классе Order есть только два свойства: одно — идентификатор типа String, а другое — user типа User.
- Свойства в классе People точно такие же, как и в классе User.
Методы получения и установки, а также метод toString сгенерированного свойства в классе.
При передаче атрибутов типа объекта имя параметра в URL-адресе является именем атрибута объекта без имени объекта.
Если атрибут в одном классе является другим классом, при передаче параметров имя параметра в URL-адресе представляет собой имя объекта атрибута плюс атрибут, как во втором методе ниже.
Когда параметры типа входящего объекта одинаковы, если не делается различий, всем атрибутам с одинаковым именем будут присвоены значения, как в третьем методе ниже, привязку данных здесь необходимо настроить, @InitBinder("имя объекта" ) установите значение префикса атрибута по умолчанию в пользовательском методе (имя метода произвольное), чтобы можно было различать атрибуты разных объектов.
// http://localhost:8080/springmvc/objecttype1.do?name='tom'&age=1
// http://localhost:8080/springmvc/objecttype1.do?name='tom'&age=
@RequestMapping(value = "objecttype1.do")
@ResponseBody
public String objecttype1(User user) {
return "user=" + user;
}
// http://localhost:8080/springmvc/objecttype2.do?id='123'&user.name='tom'&user.age=1
// http://localhost:8080/springmvc/objecttype2.do?id='123'&user.name='tom'&user.age=
// http://localhost:8080/springmvc/objecttype2.do?id='123'
@RequestMapping(value = "objecttype2.do")
@ResponseBody
public String objecttype2(Order order) {
return "order=" + order;
}
// http://localhost:8080/springmvc/objecttype3.do?people.name=Tom&user.name=Lucy
// http://localhost:8080/springmvc/objecttype3.do?people.name=Tom
// http://localhost:8080/springmvc/objecttype3.do?name=Tom
@RequestMapping(value = "objecttype3.do")
@ResponseBody
public String objecttype3(People people, User user) {
return "people=" + people + ",user=" + user;
}
@InitBinder("people")
public void initPeople(WebDataBinder binder) {
binder.setFieldDefaultPrefix("people.");
}
@InitBinder("user")
public void initUser(WebDataBinder binder) {
binder.setFieldDefaultPrefix("user.");
}
2.3 Тип даты
В большинстве случаев привязка данных SpringMVC подходит для нашего использования, но для некоторых специальных типов данных, таких как тип java.util.Date. Чтобы преобразовать строку в тип Date, нам нужно настроить Converter или Formatter для привязки данных.
Первый метод ниже будет инициализирован в соответствии с форматом, установленным пользователем при использовании связанных данных, но этот метод действителен только для одного метода. Мы можем настроить класс преобразования типа. Класс преобразования должен реализовать Converter или Formatter Конкретный код выглядит следующим образом.
Чтобы реализовать интерфейс Converter, вам нужно указать два универсальных типа интерфейса, первый — это тип, который нужно преобразовать, второй — преобразованный тип, и вам нужно реализовать метод convert() в интерфейсе, параметры в метод — это тип, который нужно преобразовать, и возвращаемое значение для преобразованного типа.
Чтобы реализовать интерфейс Formatter, вам нужно только указать общий тип интерфейса, то есть преобразованный тип, но реализовать в интерфейсе метод parse() и метод print().Первый метод заключается в преобразовании типа для преобразования в тип, который мы указываем, а затем один из способов — указать, как выводить преобразованный тип.
// DateConverter
public class DateConverter implements Converter<String, Date> {
// 定义日期格式
private String dataPattern = "yyyy-MM-dd HH:mm:ss";
@Override
public Date convert(String s) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dataPattern);
try {
return simpleDateFormat.parse(s);
} catch (ParseException e) {
throw new IllegalArgumentException("无效的日期格式,请使用" + dataPattern + "格式的日期");
}
}
}
// DateFormatter 类
public class DateFormatter implements Formatter<Date> {
// 定义日期格式
private String dataPattern = "yyyy-MM-dd HH:mm:ss";
@Override
public Date parse(String s, Locale locale) throws ParseException {
return new SimpleDateFormat(dataPattern).parse(s);
}
@Override
public String print(Date date, Locale locale) {
return new SimpleDateFormat().format(date);
}
}
После написания пользовательского класса преобразования вам также необходимо настроить его в файле конфигурации SprinMVC, чтобы он действовал для всех методов Конкретная конфигурация выглядит следующим образом:
<!--配置自定义的日期类型转换器-->
<mvc:annotation-driven conversion-service="dataConverterService"/>
<!--使用 Convert 接口-->
<bean id="dataConverterService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.wenshixin.convert.DateConverter"/>
</set>
</property>
</bean>
<!--使用 Formatter 接口-->
<!--<bean id="dataConverterService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">-->
<!--<property name="formatters">-->
<!--<set>-->
<!--<bean class="com.wenshixin.convert.DateFormatter"/>-->
<!--</set>-->
<!--</property>-->
<!--</bean>-->
// http://localhost:8080/springmvc/datetype1.do?date=2018-09-19
@RequestMapping(value = "datetype1.do")
@ResponseBody
public String datetype1(Date date1) {
return date1.toString();
}
@InitBinder("date1")
public void initDate(WebDataBinder binder) {
binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
}
// http://localhost:8080/springmvc/datetype2.do?date2=2018-09-10 22:50:10
@RequestMapping(value = "datetype2.do")
@ResponseBody
public String datetype2(Date date2) {
return date2.toString();
}
2.4 Сложные типы
Сложные типы включают типы массивов и коллекций, такие как List, Set, Map.
Тип массива используется для передачи нескольких значений с одним и тем же именем параметра, например, при получении параметра флажка на странице.
Поддержка SpringMVC для сложных типов не очень хороша, потому что для сложных типов мы в основном используем JSON, XML и другие форматы данных для передачи параметров. Для типов List, Set и Map необходимо задать отдельный класс-оболочку, свойству присвоить соответствующий тип коллекции, а параметром метода является тип оболочки, что громоздко. Функция SpringMVC для привязки данных сложных типов в основном безвкусна.
Описание класса:
- UserList — это класс-оболочка коллекции List, соответствующий User, только с одним свойством,
private List<User> users;
. - UserList — это класс-оболочка коллекции Set, соответствующий User, только с одним свойством,
private Set<User> users = new HashSet<>();
, а размер коллекции Set необходимо инициализировать в конструкторе класса.Размер коллекции Set нельзя изменить динамически.При передаче значения количество объектов не может превышать этот размер. - UserList — это класс-оболочка для коллекции Map, соответствующей User, только с одним атрибутом.
private Map<String, User> users;
.
// http://localhost:8080/springmvc/complextype1.do?ids=1&ids=2
@RequestMapping(value = "complextype1.do")
@ResponseBody
public String objecttype1(String[] ids) {
System.out.println(ids.length);
StringBuilder stringBuilder = new StringBuilder();
for(String id : ids) {
stringBuilder.append(id + " ");
}
return stringBuilder.toString();
}
// http://localhost:8080/springmvc/complextype2.do?users%5B0%5D.name=Tom&users%5B1%5D.name=Lucy 注意特殊字符[]的转义,不然会报错
// http://localhost:8080/springmvc/complextype2.do?users%5B0%5D.name=Tom&users%5B1%5D.name=Lucy&users%5B6%5D.name=Mary 注意特殊字符[]的转义,不然会报错
@RequestMapping(value = "complextype2.do")
@ResponseBody
public String objecttype2(UserList userList) {
return userList.toString();
}
// http://localhost:8080/springmvc/complextype2.do?users%5B0%5D.name=Tom&users%5B1%5D.name=Lucy&users%5B2%5D.name=Mary 注意特殊字符[]的转义,不然会报错
@RequestMapping(value = "complextype3.do")
@ResponseBody
public String objecttype3(UserSet userSet) {
System.out.println(userSet.getUsers().size());
return userSet.toString();
}
// http://localhost:8080/springmvc/complextype4.do?users%5B%270%27%5D.name=Tom&users%5B%271%27%5D.name=Lucy&users%5B%272%27%5D.name=Mary
@RequestMapping(value = "complextype4.do")
@ResponseBody
public String objecttype4(UserMap userMap) {
System.out.println(userMap.getUsers().size());
return userMap.toString();
}
2.5 Специальные типы
SpringMVC больше подходит для передачи данных, разделенных фронтендом и бекендом, он поддерживает JSON, популярный форматированный тип данных, ему нужны только две аннотации, @RequestBody (параметр) и @ResponseBody (выход), что очень удобно в использовании.
Для написания API SpringMVC, несомненно, является преимуществом перед Struts2.
// json 格式
/*
{
"name":"Tom",
"age":1
}
*/
@RequestMapping(value = "jsontype.do")
@ResponseBody
public User jsontype(@RequestBody User user) {
System.out.println(user);
return user;
}
// xml 格式
/*
<?xml version="1.0" encoding="UTF-8" ?>
<user>
<name>Jim</name>
<age>16</age>
</user>
*/
@RequestMapping(value = "xmltype.do")
@ResponseBody
public User xmltype(@RequestBody User user) {
System.out.println(user);
return user;
}
2.6 REST-стиль
API в стиле RESTful был признан в отрасли и даже больше подходит для современной распределенной архитектуры. Многие веб-фреймворки также поддерживают написание API в стиле RESTful, включая SpringMVC, конечно.Вот краткое введение в стиль RESTful.
RESTful даResource Representional State TАббревиатура ransfer, RE — это аббревиатура первых двух слов, первое слово часто опускается, и это слово на самом деле является основной идеей RESTful, китайский переводПереход состояния уровня представления ресурсов.
Автор RESTful также является разработчиком протокола HTTP.Он внедрил идею URI в HTTP в программирование API.Каждый ресурс имеет место хранения.Операция (запрос) ресурса - это преобразование ресурса в уровень представления. , такие как распространенные GET, POST и менее часто используемые PUT, DELETE и т. д.
Стиль RESTful имеет более короткий адрес ресурса, который отличается от общего адреса API, который непосредственно работает с ресурсами, такими как добавление и выбор.Основной частью стиля RESTful является ресурс, а работа ресурса отражается в метод запроса, например DELETE. Разные методы запроса соответствуют разным операциям. Так же, как и адрес, если это метод GET, он вернет страницу напрямую. Если это метод POST, он отправит данные на страницу, чтобы было меньше адресов и более безопасный доступ.
В следующем коде показано, как использовать RESTful API. Использовать браузер для тестирования API неудобно. Можно использовать сетевые инструменты, такие как Postman.
@RequestMapping(value = "/user/{name}", method = RequestMethod.GET)
@ResponseBody
public String findUserByGET(@PathVariable("name") String name) {
return "GET name=" + name;
}
@RequestMapping(value = "/user/{name}", method = RequestMethod.POST)
@ResponseBody
public String findUserByPOST(@PathVariable("name") String name) {
return "POST name=" + name;
}
Добро пожаловать в общедоступную учетную запись WeChat ниже, там есть различные учебные материалы, которыми можно поделиться бесплатно!