Struts2.3.24 + Spring4.1.6 + Hibernate4.3.11 + MySQL5.5.25 Среда.
1. Цель
1. Создайте традиционную среду разработки SSH и успешно запустите ее (вставьте, запрос)
2. Понять конфигурацию пула соединений C3P0
3. Понять вторичный кэш спящего и проверить
4. Понять конфигурацию весенних вещей и проверить
5. Понять IOC Spring (инъекция зависимости), передайте объект действия (бобы) Struts2 управлению пружиной, пользовательские бобы и т. Д., И проверить
6. Понять Spring AOP (программирование, ориентированное на раздел), и напишите пользовательские функции раздела, чтобы проверить результаты
2. Подготовка
Среда развития: затмение для Java EE; mysql5.5.25; JDK1.7.0_79; Navicat10.1.7 (необязательно);
Создайте демонстрацию базы данных:
/*Navicat MySQL DataFersource Server: LocalHOST_3306SOURCE Сервер Версия: 50519SOURCE HOST: LOCALHOST: 3306SOURCE База данных: Демотаржевый Сервер Тип: Mysqltarget Server Версия: 50519file Encoding: 65001date: 2016-01-09 23: 36: 02*/worty_keeceming = worrine_kecks_keecks. ------------------------------- Структура таблицы для `user`-- -------------------------------- Таблица сброса, если существует` user`; создать таблицу `user` (` id 'bigint (20) не null auto_increment, `chounct' varchar (200) не null,` name` varhar (200) не null, ‘Адрес 'varchar (1000) не null, name' varchar (200) не null,‘ Адрес 'varchar (1000) не null, name' varhch (200) не null. По умолчанию charset = utf8;
Создайте новый веб -проект, структура каталогов заключается в следующем:
Приготовьте пакет JAR и поместите его в каталог Web-Inf LIB (если вам интересно, вы можете использовать Maven для управления процессом, но иногда очень медленно загружать пакет JAR ...)
Связанные пакеты JAR можно найти в загруженных стойках, Spring и Hibernate. Вот ссылка. Некоторые из них могут быть удалены, например, пакеты банок в пружинной части MVC:
3. Настройка web.xml
Настройте фильтр struts2, чтобы отобразить все запросы *.
Настройте параметр контекста-параметра и укажите путь файла конфигурации пружины. Параметры в <context-param> можно получить с помощью ServletContext.getInitParameter ("param-name");
Настройка прослушивателя в основном для чтения информации о файле конфигурации ApplicationContext.xml, создания бобов и других работ по инициализации;
<? xml version = "1.0" Encoding = "utf-8"?> <web-app xmlns: xsi = "http://www.w3.org/2001/xmlschema-instance" xmlns = "http://java.sun.com/xml/ns/javaee" xsi: schemalocation = "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" = "webapp" = "webapp" = "webapp_dapp_3_0.0. <SIVEL-name> ssh </display-name> <filter> <filter-name> struts2 </filter-name> <filter-class> org.apache.struts2.dispatcher.ng.filter.strutsprepareandexecutefilter </filter-class> </filter> <filter-mapping> <filter-name> strut-name </filter> </filter> <filter> <filter-name> strut-name> </filter-class> </filter> <filter> <filter-name> </filter> </filter> <filter> <filter-name> </filter-class> </filter> <Filter> <Url-pattern>*. action </url-pattern> </filter-mapping> <stext-param> <param-name> contextconfiglocation </param-name> <param-value> classpath: ApplicationContext.xml </param-value> </context-param> <dellasser> <lisserer-class> org.spramework. </stirlicer> <selcopply-file-list> <selclow-file> index.jsp </wervedied-file> </werving-file-list> </web-app>
4. Настройка ApplicationContext.xml
Настройка автоматического сканирования @Repostory, @Service и других аннотаций в пакете SSH и генерировать соответствующие бобы;
Настройте источник данных (Pool Connection Pool JDBC - это C3P0, вы можете обратиться к подробной конфигурации C3P0). Основная функция пула соединений состоит в том, чтобы быстро обеспечить соединение и повторно использовать его. Это не требует каждого разрушения и творения. Это требует конфигурации имени пользователя, пароля, максимального количества соединений, минимального количества соединений, начального количества соединений и других связанных параметров;
Configure SessionFactory (вы можете ссылаться на подробную конфигурацию Hibernate, где вы настраиваете кеш -кэш уровня 2), основная функция состоит в том, чтобы предоставить сеанс и выполнить операторы SQL; Здесь мы будем использовать HibernateTemplate для управления базой данных для облегчения физического контроля пружины; PS, отображение между классами и таблицами базы данных также должно быть настроено в конфигурации Hibernate;
Настройте боб управления транзакциями как hibernateTransactionManager и инициализируйте атрибут члена SessionFactory для сеансафакторного бона, настроенного ранее;
Настройте характеристики распространения транзакции и настройте раздел для обозначения ее, и проведите управление транзакцией всех методов добавления, удаления, обновления и сохранения во всех пакетах и подпакетах SSH.Service. Вы также можете настроить поведение распространения транзакций и другие параметры;
Наконец, существует пользовательская конфигурация AOP, которая применяет пользовательский раздел «MyAOP» для управления всеми методами, начиная с тестов в рамках ssh.aop.aoptest, и результаты будут проверены позже;
<? xml version = "1.0" Encoding = "UTF-8"?> <Beans xmlns = "http://www.springframework.org/schema/beans" xmlns: p = "http://www.springframework.org/schema/p" xmlns: context = "http://www.springframework.org/schema/context" xmlns: tx = "http://www.springframework.org/schema/tx" xmlns: xsi = "http://www.w3. xmlns: aop = "http://www.springframework.org/schema/aop" xmlns: jdbc = "http://www.springframework.org/schema/jdbc" xsi: schemalocation = "http:/www.spramema.spramemema.spramemema. http://www.springframework.org/schema/beans http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop http://www.springframework.org/schema/aopmpma/Sshema/aopm.-aopmema.-aopmema-aopmema/sschema/aopm.-aopmasmasm.-aopmema htt http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd http://www.spramework.org/schema/context-4.4. <!-Сканирует обход класса для аннотированных компонентов (включая @Repostory и @Service, которые будут автоматически зарегистрированы как пружинные бобы-> <Контекст: компонент-сканирование Base-package = "ssh" /> <!-Источник поддержки данных-> <bean name = "dessource Method =" close "> <properation name =" value "value =" com.methd. name = "jdbcurl" value = "jdbc: mysql: // localhost: 3306/demo"/> <name = "user" value = "root"/> <name = "password" value = "root"/> <property name = "ucipeIncrement" value = "1"> </propetion> <properation name = "valueSize" value = "/"/"Propetory> <proportical =" valueSize ". name = "maxidletime" value = "60"> </property> <свойство name = "maxpoolsize" value = "80"> </property> <property name = "minpoolsize" value = "30"> </property> <name = "acciereretrydelay" value = "1000"> </property> <property = "Property". name = "breakafteracquirefailure" value = "false"> </property> <!-Если появится слишком много соединений, обратите внимание, что если вы измените файл конфигурации my.ini mysql для увеличения максимального количества соединений (см. Текущее соединение команды: Show Processlist)-> </bean> <bean id = "SessionFactory"> <properation nelection = "DataSource" DataSource "ref =" reft "/" dataSource "/" dataSource "/" dataSource "/" reft "/" reft "/" reft "/" reft-"<foperce"/"/" Properate ". name = "hibernateproperties"> <prop key = "hibernate.dialect"> org.hibernate.dialect.mysqlidialect </prop> <prop key = "hibernate.show_sql"> true </prop> <prop key = "hibernate.hbm2ddl.auto"> update </prop> <prop = "hibernate.hbm2ddl.auto"> key = "current_session_context_class"> Thread </prop> <prop key = "hibernate.cache.use_second_level_cache"> true </prop> <prop key = "hibernate.cache.use_second_level_cache"> true </prop> <prop> key = "hibernate.cache.region.factory> key = "hibernate.cache.provider_configuration_file_resource_path"> ehcache.xml </prop> </prop> </props> </property> <name = "mappingLocations"> <silect> <cviod> classpath: ssh/model/user.hbm.xml </value> </list> </list> </! name = "AnnotatedClasses"> <sist> <dall> ssh.model.user </value> </list> </property>-> </bean> <!-Конфигурирование менеджера транзакций-> <Bean Id = "TransactionManager"> <Свойство = "SessionFactory" Ref = "SessionFactory"/> </bean> <! <tx: атрибуты> <tx: method name = "add*" opragation = "required" read-only = "false" hollback-for = "java.lang.exception"/> <tx: method name = "delete*" Propagation = "требуется" readmonaly = "false" rowback-for = "java.lang.except read-only = "false" hollback-for = "java.lang.exception"/> <tx: method name = "save*" propagation = "required" read-only = "false" hollback-for = "java.lang.exception"/> </tx: атрибуты> </tx: Совет> <aop: config> <aop: pactcut id id = ". ssh.service ..*.*(..)) "/> <aop: Advisor pointcut-ref =" pcmethod "ref-ref =" txadvice "/> </aop: config> <!-Custom AOP-обработка Proxy-target-class = "true"> <aop: aspision ref = "myaop"> <aop: pointcut id = "pcmethodtest" Expression = "execution (* ssh.aop.aoptest.test* (..))"/> <aop: перед pointcut-ref = "pcmethdetest" method = "/> <aop: athercut-ref =" pcmethdetest ". method = "после"/> </aop: аспект> </aop: config> </beans>
5. Настройка struts.xml
Настройте структуры. Объектфакторная постоянная к пружине, указывая на то, что действие получается бобов до пружины;
Настройте тип результата на «JSON», и вы также можете настроить другие вещи. Здесь, для удобства взаимодействия переднего и внутреннего взаимодействия данных, оно настроено в формате JSON;
Настройте два действия, Adduser и QueryAlluser;
<? xml version = "1.0" Encoding = "UTF-8"?> <! Doctype Struts Public "-// Apache Software Foundation // Configuration struts 2.3 // en" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <stustant name = "string.obctecor name = "struts.enable.dynamicmethodinvocation" value = "false" /> <constant name = "struts.devmode" value = "false" /> <name = "default" extends = "struts-default, json-default"> < /global-results> <result type = "json"> <param = root "> json < /param> < /param> < /param> < /param> < /param> < /param> < /param> < /param> < /param> < /param> < /param> < /param> < /param> < /param> < /param> < /param> name = "contentType"> text/html </param> </result> </global-results> <name = "adduser" method = "adduser"> <sesult>. </result> </action> <name = "QueryAlluser" method = "QueryAlluser"> <Slues>. </result> </action> </package> <!
6. Напишите соответствующий код
Примечания:
Дао наследует класс hibernatedaosupport, и все операции, связанные с базой данных, эксплуатируются HibernateTemplate;
Добавьте соответствующие аннотации в слой DAO, уровень обслуживания и действие, и зарегистрируйтесь в виде пружинных бобов;
Прилагаемый код выглядит следующим образом:
UserAction.java
Пакет SSH.Action; импорт java.io.printwriter; import java.util.list; import javax.annotation.resource; импорт javax.servlet.http.httpservletrequest; import javax.servlet.http.httpsersersponse; import org.apache.log4j.lgger; org.apache.struts2.servletactionContext; import org.springframework.stepolype.controller; import ssh.aop.aoptest; import ssh.model.user; import ssh.service.userservice; import com.gogle.gson.gson; @controllerpublic class userauct Logger.getLogger (userAction.class); @Resource private userservice userservice; @Resource private aoptest aoptest; public void Adduser () {printWriter Out = null; try {httpservletRequest request = servletactionContext.getRequest (); Httpservletresponse response = servletactionContext.getResponse (); response.setContentType ("text/html; charset = utf-8"); String account = request.getParameter ("Account"); String name = request.getParameter ("name"); String address = request.getParameter ("Адрес"); Пользователь пользователь = новый пользователь (); user.setAccount (учетная запись); user.setAddress (адрес); user.setname (имя); userservice.add (пользователь); out = response.getWriter (); out.write (new gson (). Tojson ("успех")); } catch (Exception e) {e.printstackTrace (); logger.error (e.getMessage ()); if (out! = null) out.write (new gson (). tojson ("Fail")); } наконец {out.flush (); out.close (); }} public void QueryAlluser () {printWriter Out = null; aoptest.test1 (); aoptest.test2 (); //logger.error("i "); try {httpservletresponse response = servletactionContext.getResponse (); response.setContentType ("text/html; charset = utf-8"); Gson Gson = new Gson (); Список <user> userlist = userservice.queryalluser (); String gsonstr = gson.tojson (userlist); out = response.getWriter (); out.write (gsonstr); } catch (Exception e) {e.printstackTrace (); logger.error (e.getMessage ()); if (out! = null) out.write (new gson (). tojson ("Fail")); } наконец {out.flush (); out.close (); }}}Aoptest.java
пакет ssh.aop; public class aoptest {public void test1 () {System.out.println ("Aoptest Test1 метод запускается ~"); } public void test2 () {System.out.println ("Aoptest Test2 работает ~"); }}Myaop.java
пакет ssh.aop; public class myaop {public void до () {System.out.println ("befor ~"); } public void After () {System.out.println ("After ~"); }}Baserao.java
package ssh.dao.base;import javax.annotation.Resource;import org.hibernate.SessionFactory;import org.springframework.orm.hibernate4.support.HibernateDaoSupport;public class BaseDao extends HibernateDaoSupport{ @Resource public void setMySessionFactory(SessionFactory sessionFactory){ this.setsessionFactory (SessionFactory); }}Userdao.java
Пакет ssh.dao; import java.util.arraylist; import java.util.list; import org.springframework.orm.hibernate4.hibernateTemplate; импорт org.springframework.stereotype.Repository; импорт ssh.dao.base.basedao; FASTAO {public void add (пользователь пользователя) {this.gethibernateTemplate (). Save (user); } @Suppresswarnings ("unchecked") public list <user> Queryalluser () {list <user> users = new ArrayList <user> (); HibernateTemplate hibernateTemplate = this.gethibernateTemplate (); hibernateTemplate.setCacheequeries (true); users = (list <user>) hibernateTemplate.find ("от пользователя"); hibernateTemplate.setCacheequeries (false); вернуть пользователей; }}User.java
пакет ssh.model; import java.io.serializable; Пользователь открытого класса реализует serializable { / ** * * / private static final long serialversionuid = -6190571611246371934L; частный длинный идентификатор; частная строковая учетная запись; Приватное название строки; частный строковый адрес; public String getAccount () {return account; } public String getName () {return name; } public String getAddress () {return Adder; } public void setAccount (string account) {this.account = account; } public void setName (string name) {this.name = name; } public void setAddress (строковый адрес) {this.address = address; } / ** * @return the id * / public long getId () {return id; } / ** * @param id Идентификатор для установки * / public void setid (long id) {this.id = id; }}User.hbm.xml
<? xml version = "1.0"?> <!-~ Hibernate, реляционная стойкость для идиоматической Java ~ ~ Copyright (C) 2010, Red Hat Inc. или сторонние участники, как указано @author Tags или Appry Copyright Attribute ~ Заявления, применяемые авторами. Все сторонние взносы распространяются по лицензии Red Hat Inc. ~ ~ Этот материал, защищенный авторским правом, предоставляется всем, кто хочет использовать, модифицировать, копировать или перераспределить его в соответствии с условиями и условиями Меньше всего общей публичной лицензии, опубликованной Фондом бесплатного программного обеспечения. ~ ~ Эта программа распространяется в надежде, что она будет полезна, но без каких -либо гарантий; даже без подразумеваемой гарантии товарной способности ~ или пригодности для определенной цели. Смотрите GNU меньшую общую публичную лицензию ~ для получения более подробной информации. ~ ~ Вы должны были получить копию GNU меньшей общей публичной лицензии ~ вместе с этим распределением; Если нет, напишите: ~ Free Software Foundation, Inc. ~ 51 Franklin Street, Пятый этаж ~ Бостон, MA 02110-1301 USA-> <! Doctype Hibernate Mapping Public "-// Hibernate/Hibernate Mapping DTD 3.0 // en" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> функции пакета MAPPAPION =" SSH.Model "> <class name =" table = "user"> <cache usage = "readwrite"/> <id name = "id" column "> <generator/> </id name =" jost> </id name = "jeckspoce> </id </id> </id </id> </id </id </id =" = "=" ID? type = "java.lang.string" colun = "account"/> <name = "name" type = "java.lang.string" column = "name"/> <name = "address" type = "java.lang.string" column = "Адрес"/> </class> </hibernate-картирование>
Userservice.java
пакет ssh.service; import java.util.list; import javax.annotation.resource; import org.springframework.stereoty.service; import ssh.dao.userdao; import ssh.model.user; @servicepublic class userservice {@resour private aserda aserda userda userda use userda use userda use userda use userda use userda use userda use userda (@servicepublic classerervice. public List <user> QueryAlluser () {return userDao.QueryAlluser (); } public void add (пользователь пользователя) {userDao.add (user); }}index.jsp (не забудьте добавить библиотеку jQuery)
<%@ page language = "java" contentType = "text/html; charset = utf-8" pageencoding = "utf-8"%> <! doctype html public "-// w3c // dtd html 4.01 transitional // en"-// w3c // dtd html 4.01 // en "http://www.w3.org/tr/html4/loose.dtd"><html><head><meta http-equiv =" content-type "content =" text/html; charset = utf-8 "> <teply-type здесь </title> <style> .mt20 {margin-top: margin-top: 20px;} </style> </head> <body> <div style = "text-align: center;"> <div> <babel> учетная запись: </label> <input id = "account" type = "text"/> </div> <div> <babel> name: </label> <input use = name "type ="/> </div> <div> <div> <dip> type = "text"/> </div> <div> <button id = "Adduser"> добавить </button> </div> <h3> Список пользователей: </h3> <ul id = "userlist"> </ul> <script type = "text/javascript" src = "js/jquery-1.11.1.min.js"> </script> (script> <script> () () () () <) <) <). $ .ajax ({url: 'Queryalluser.action', type: 'post', datatype: 'json', success: function (data) {try {for (var i = 0; i <data.length; i ++) {$ ("#user list"). style = 'color: red'> id = "+data [i] .id+" </span>, account = "+data [i] .account+", name = "+data [i] .name+", address = "+data [i] .address+" </li> "); }} catch (e) {}; }, ошибка: function (e) {alert ("sys error"); }}); $("#addUser").on("click", function() { var account = $("#account").val(); var name = $("#name").val(); var address = $("#address").val(); $.ajax({ url : 'addUser.action', type : 'post', dataType : 'json', data : { account : account, name : name, address : address } успех: функция (data) {try {$ ("#userlist"). }); }); </script> </body> </html>7. Результаты проверки
Вернитесь к началу, начните ознакомиться с соответствующими технологиями и проверить результаты
1. Создайте традиционную среду разработки SSH и успешно запустите ее (вставьте, запрос)
Следующий рисунок: Запрос и успешно добавить пользователей;
2. Понять конфигурацию пула соединений C3P0
Соединения базы данных - это дорогие ресурсы, а открытие и закрытие потребляет производительность. Следовательно, их можно управлять пулом соединений, инициализацию нескольких соединений и повторно их использование, а не неоднократно создавать закрытие, что немного похоже на пул потоков;
Конфигурация заключается в следующем. Чтобы разумно настроить минимальное и максимальное количество соединений в соответствии с фактической ситуацией проекта, пожалуйста, обратитесь к ссылке для подробного значения каждого параметра.
Кроме того, очень просто проверить конфигурацию номера подключения. Вы можете написать программу, чтобы проверить ее самостоятельно. Например, когда максимальное количество соединений составляет 10, вы можете написать программу для ее проверки. После открытия 10 соединений 11 -е соединение будет находиться в состоянии ожидания и не может быть получено. Следовательно, вы должны настроить количество соединений разумно в соответствии с ситуацией, в противном случае это может повлиять на производительность приложения;
<!--Support data source--> <bean name="dataSource" destroy-method="close"> <property name="driverClass" value="com.mysql.jdbc.Driver" /> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/demo" /> <property name="user" value="root" /> <property name="password" value="root" /> <property name="acquireIncrement" value="1"></property> <property name="initialPoolSize" value="80"></property> <property name="maxIdleTime" value="60"></property> <property name="maxPoolSize" value="80"></property> <property name="minPoolSize" value="30"></property> <property name = "acpireretryDelay" value = "1000"> </property> <name = "acfireretryattempts" value = "60"> </property> <Property name = "breakafteracquirefailure" value = "false"> </property> <! Процесс) -> </bean>
3. Понять вторичный кэш спящего и проверить
Кэш первого уровня Hibernate относится к кэшу во всем сеансе, который включен по умолчанию. Кэш второго уровня-это кэш диапазона SessionFactory. При настройке SessionFactory мы настроили кэш второго уровня как ehcache. Затем мы проверяем эффект и запросим работу пользователя. Мы обнаружили, что первый запрос будет управлять базой данных, распечатать оператор SQL, и после обновления страницы мы обнаружили, что запрос был успешным, и не было напечатано заявление SQL. Как показано на рисунке ниже, мы видим, что вторичная работа кэша в порядке;
4. Понять конфигурацию весенних вещей и проверить
Так называемый принцип управления транзакциями тот же, который должен обеспечить атомичность, последовательность, изоляцию и стойкость. При программировании JDBC он контролируется само по себе. Установите AutoCommit = false, чтобы не автоматически отправлять, а затем начните записывать конкретные операции базы данных. Когда происходит исключение, отказ, иначе совершайте; Фактически, принцип управления пружиной на вещах похож, и он добавляется с некоторой упаковкой, конфигурацией и т. Д., Который более удобен, например, контроль различных методов на уровне обслуживания;
Проверка очень проста. Напишите две операции вставки в методе на уровне службы (обратите внимание, что имя метода должно соответствовать правилам, настроенным в файле конфигурации пружины), добавьте исключение в середину, а затем выполнить его. Если вы обнаружите, что первый пользователь успешно вставлен, это означает, что управление транзакцией недействителен, в противном случае все в порядке;
5. Понять IOC Spring (инъекция зависимости), передайте объект действия (бобы) Struts2 управлению пружиной, пользовательские бобы и т. Д., И проверить
Если вы внимательно соблюдаете процесс настройки файла ApplicationContext.xml, основной работой является настройка информации, связанной с бобами. Эти бобы создаются заранее, но на самом деле так называемые бобы являются объектами;
Цель передачи создания объектов в пружинный контейнер состоит в том, чтобы отделить;
Кроме того, при использовании стойки Spring регистрируют действие как Bean, который по умолчанию является одиноким. Не каждый раз, когда новое действие выпускается во время доступа, при одновременном доступе будут риски;
Тем не менее, вы можете настроить действие в несколько случаев через Scope = "Прототип"; PS: Действие в Struts2 является многоказовым по умолчанию;
ПРИМЕЧАНИЕ. Бобы, настроенные в ApplicationContext.xml и бобы, настроенные в пользовательских аннотациях, могут быть получены непосредственно во время работы программы. Это легко проверить, просто напишите небольшую программу;
6. Понять Spring AOP (программирование, ориентированное на раздел), и напишите пользовательские функции раздела, чтобы проверить результаты
Эта идея используется во многих местах в этой форме программирования секционного раздела, таких как фильтры, перехватчики, управление транзакциями и т. Д.
Принцип - Java Reflection и Dynamic Proxy, который управляет методом до и после выполнения, и добавляет код, который вы хотите выполнить;
В небольшом примере добавляется раздел, а до и после и после напечатаны строки до и после выполнения метода. Как показано на рисунке ниже, он работает нормально. Пожалуйста, обратитесь к предыдущей части кода:
<!-Пользовательский тест обработки AOP-> <bean id = "aoptest"> </bean> <bean id = "myaop"> </bean> <aop: config proxy-class = "true"> <aop: аспект ref = "myaop" ssh.aop.aoptest.test*(..)) "/> <aop: перед pointcut-ref =" pcmethodtest "method =" до "/> <aop: после pointcut-ref =" pcmethodtest "method =" после "/> </aop: аспект> </aop: config>
@author, похожий на ветру, кодировщик
Выше всего содержание этой статьи. Я надеюсь, что это будет полезно для каждого обучения, и я надеюсь, что все будут поддерживать Wulin.com больше.