В предыдущем разделе «Первая битва за рамки SSH Framework Online Mall Project: интеграция Struts2, Hibernate4.3 и Spring4.2», мы создали среду разработки для Struts2, Hibernate и Spring и успешно интегрировали их вместе. Этот раздел в основном завершает некоторые основные дополнения, удаление, модификацию и поиск, а также извлечение услуг, DAO и действия.
1. Извлечение сервисного слоя
В предыдущем разделе мы просто написали методы сохранения и обновления на уровне обслуживания. Здесь мы начинаем улучшать код в этой части, а затем извлекаем код в сервисном уровне.
1.1 Улучшить уровень категории сервиса
Работа базы данных - это не что иное, как добавление, удаление, изменение и проверку. Во -первых, давайте улучшим интерфейс и реализацию уровня категории -сервиса:
// категория интерфейса интерфейса общего интерфейса CategoryService Extends BaseService <Категория> {Public void Said Save (категория категория); // вставить публичное обновление void (категория категории); // Обновление Public void Delete (INT ID); // Удалить публичную категорию GET (INT ID); // Получить публичный список категории <Категория> Query (); // Получить всю категорию} Конкретная реализация интерфейса категории -сервиса:
Общедоступный класс CategoryServiceImpl Extends BaseServiceImpl <Категория> реализует категорию {private SessionFactory SessionFactory; // Spring будет вводить public void setSessionFactory (sessionFactory SessionFactory) {this.SessionFactory = sessionFactory; } Защищенный сеанс getSession () {// получить сеанс из текущего потока, если нет, создать новый сеанс return sessionFactory.getCurrentSession (); } @Override public void said (категория категория) {getSession (). Save (Category); } @Override public void update (категория категории) {getSession (). Обновление (категория); } @Override public void delete (int id) { /*Первый метод имеет недостаток, то есть вы должны запросить его один раз, прежде чем удалить его. Object obj = getSession (). Get (Category.class, id); if (obj! = null) {getsession (). Delete (obj); }*/ String hql = "Удалить категорию, пока id =: id"; getSession (). CreateQuery (hql) // .setInteger ("id", id) // .executeUpdate (); } @Override public Category get (int id) {return (категория) getSession (). Get (category.class, id); } @Override public list <Категория> Query () {String hql = "из категории"; return getSession (). CreateQuery (hql) .list (); }} 1.2 Реализация извлечения уровня обслуживания
После завершения категории обслуживания мы извлеките основную реализацию уровня обслуживания. Идея заключается в следующем: мы извлекаем базовый интерфейс BaseService и BaseServiceImpl, и при разработке позже, если необходим новый сервис, вам нужно сделать только два шага: сначала определить новый интерфейс XXXService наследует интерфейс BaseService, который может добавить новые абстрактные методы к этому интерфейсу; Затем определите новую реализацию класса XXXServiceImpl, которые наследуют BaseReviceImpl и реализует интерфейс XXXService. Это облегчает поддержание проекта.
Давайте сначала создадим интерфейс BaseService на основе приведенного выше интерфейса категории категории:
// Базовый интерфейс BaseService, используйте общий общедоступный интерфейс BaseService <t> {public void save (t t); Общественное обновление void (t t); public void delete (int id); public t получить (int id); публичный список <T> Query (); } Затем создайте интерфейс BaseService Interface Class BaseServiceImpl в соответствии с классом реализации CategoryServiceImpl:
/ ** * @description todo (извлечение публичных модулей) * @author eson_15 * */ @suppresswarnings ("uncecked") public class baseserviceimpl <t> реализует BaseService <t> {частный класс clazz; // Тип текущей операции хранится в Clazz, то есть Generic T Private SessionFactory SessionFactory; public baseServiceImpl () {// Следующая информация о печати может быть удалена. Вот System.out.println («Это представляет объект, который в настоящее время называет конструктор» + это); System.out.println («Получить информацию о родительском классе текущего этого объекта» + this.getClass (). GetSuperClass ()); System.out.println («Получить информацию о родительском классе текущего этого объекта (включая общую информацию)» + this.getClass (). GetGenericCuperClass ()); // Получить тип параметра общего параметризованного типа = (параметризованный тип) this.getClass (). GetGenericCuperClass (); clazz = (class) type.getactualtypearguments () [0]; } public void setSessionFactory (sessionFactory SessionFactory) {this.SessionFactory = sessionFactory; } Защищенный сеанс getSession () {// получить сеанс из текущего потока, если нет, создать новый сеанс return sessionFactory.getCurrentSession (); } @Override public void said (t t) {getSession (). Save (t); } @Override public void update (t t) {getSession (). Update (t); } @Override public void delete (int id) {System.out.println (clazz.getSimplename ()); String hql = "delete" + clazz.getSimplename () + "как c, где c.id =: id"; getSession (). CreateQuery (hql) // .setInteger ("id", id) // .executeUpdate (); } @Override public t get (int id) {return (t) getSession (). Get (clazz, id); } @Override public list <t> Query () {string hql = "from" + clazz.getSimplename (); return getSession (). CreateQuery (hql) .list (); }} После завершения извлечения мы можем переписать интерфейс категории и класс реализации категории. следующее:
// категория интерфейса интерфейса наследует интерфейс интерфейса BaseService CategoryService Extends BaseService <Категория> { / * * Просто добавьте новый метод, требуемый самим категорией. Общедоступный метод уже находится в BaseService * /} / ** * @description todo (бизнес -логика самого модуля) * @author eson_15 * * / public Class CategoryServiceImpl Extends BaseRviceImpl <Категория> реализует CategoryService { / * * Просто реализует вновь добавленный метод в интерфейсе категории. Общественный метод был реализован в BaseResviceImpl */} Как видно из кода, вновь добавленная служба должна только наследовать интерфейс BaseService, а затем добавить бизнес -логику, требуемую сервисом в интерфейс. Недавно добавленный ServiceImpl должен только наследовать BaseServiceImpl и внедрить недавно добавленную бизнес -логику.
Но не забывайте о важном моменте: он состоит в том , чтобы изменить бобы в File File на конфигурации Spring.xml .
<!-Общие классы не могут быть созданы, поэтому добавьте свойство Lazy-INIT-> <Bean Id = "baseService" lazy-init = "true"> <property name = "sessionFactory" ref = "sessionFactory"/> </bean> <bean id = "CategoryService" parent = "baseService"/>
Убейте собственность в исходной категории, затем добавьте родительское свойство, чтобы указать наследование базового сервиса; Затем настройте основание и настройте SessionFactory на основание. Кроме того, одна вещь, чтобы отметить: установите свойство Lazy-INIT на True, потому что BaseService-это общий класс, а общие классы не могут быть созданы. На данный момент извлечение сервисного уровня выполняется.
2. Добавить учетную запись в сервисный уровень
Уровень обслуживания только что был извлечен, так что теперь очень просто написать службу учетной записи:
Сначала напишите интерфейс Accountservice, чтобы наследовать основание:
Общедоступный интерфейс Accountservice Extends BaseService <cloanc> {// Обратите внимание, что дженерики в BaseService теперь являются учетной записью / * * Просто добавьте новый метод, требуемый самим AccountService, а публичный метод уже находится в BaseService * /} Затем напишите класс реализации AccountServiceImpl, чтобы унаследовать класс реализации BaseServiceImpl и внедрить интерфейс AccountService:
Общедоступный класс AccountServiceImpl Extens BaseServiceImpl <clock> реализует AccountService { / * * Просто реализуйте вновь добавленные методы в интерфейсе AccountService. Общественный метод был реализован в BaseServiceImpl */// Управление функцией входа в систему, и он будет улучшен позже} Наконец, добавьте следующую конфигурацию в файл beans.xml:
<bean id = "accountservice" parent = "baseservice" />
Таким образом, был написан новый сервис. Если вам нужно добавить услугу в будущем, вы будете следовать этому процессу, что очень удобно.
3. Экстракция действия
3.1 Храните данные в действии в домене (запрос, сеанс, приложение и т. Д.)
Мы знаем, что в действии вы можете напрямую получить объект ActionContext через actionContext.getContext (), а затем получить соответствующий объект домена через объект; Вы также можете ввести соответствующий объект домена, реализуя интерфейс XXXAWARE. Давайте сначала посмотрим на эти два метода:
Общедоступный класс CategoryAction расширяет ActionSupport реализует запросы, SessionAware, ApplicationAware {частная категория; частная категория категория категория; public void setCategoryService (CategoryService CategoryService) {this.categoryService = CategoryService; } public String Update () {System.out.println ("---- Update ----"); CategoryService.Update (категория); вернуть "индекс"; } public String save () {System.out.println ("---- Сохранить ----"); вернуть "индекс"; } public String Query () {// Решение 1, используйте соответствующую карту, чтобы заменить исходный встроенный объект, чтобы не было зависимости от JSP, но количество кода относительно большое // actionContext.getContext (). Put ("CategoryList", CategoryService.Query ()); // Поместите его в поле запроса // actionContext.getContext (). GetSession (). Put ("CategoryList", CategoryService.Query ()); // Поместите его в поле сеанса // actionContext.getContext (). GetApplication (). Put ("CategoryList", CategoryService.Query ()); // Поместите его в домен приложения // Solution 2, реализуйте соответствующий интерфейс (requestaware, sessionaware, applicationaware) и позвольте соответствующей карте inject request.put ("CategoryList", CategoryService.Query ()); session.put ("CategoryList", CategoryService.Query ()); Application.put ("CategoryList", CategoryService.Query ()); вернуть "индекс"; } публичная категория getCategory () {return Category; } public void setCategory (категория категория) {this.category = категория; } частная карта <строка, объект> запрос; частная карта <строка, объект> сеанс; частная карта <строка, объект> приложение; @Override public void setApplication (map <string, Object> Application) {this.Application = Application; } @Override public void setSession (map <string, object> session) {this.session = session; } @Override public void setRequest (map <string, объект> запрос) {this.Request = request; }} Это все еще класс категории, который интегрирует три основных структура в предыдущем разделе. Мы добавили метод запроса в этот метод. В этом методе мы храним результаты запроса в домене запроса, домена сеанса и домена приложения. Первым методом является непосредственное использование ActionContext для его реализации. Интерфейс не требуется, но код большой; Второй метод реализует интерфейсы RequestAware, SessionAware и ApplicationAware, а также три абстрактных метода реализации интерфейсного запроса, сеанса и приложения, а затем назначают его соответствующим переменным элемента, чтобы результаты запроса могли храниться в домене в методе запроса. Этот объем кода кажется больше, чем первый метод ... но мы можем извлечь его и сначала прочитать его.
Мы добавляем новое соединение запроса в index.jsp, чтобы проверить, можно ли отображаться результаты запроса:
<%@ page language = "java" import = "java.util.*" pageencoding = "utf-8"%> <%@ taglib uri = "http://java.sun.com/jsp/jstl/core" prefix = "c"%> <! doctpe html public "-//w3c // dtd httm.01.01. <html> <head> <tite> my jsp 'index.jsp' Начальная страница </title> </head> <body> <a href = "$ {pagecontext.request.contextPath} /category_update.action?category.id=2&category.type=gga&category.hot=false"> href = "Category_Save.Action"> Access Save </a> <a href = "category_query.action"> Запрос всех категорий </a> <br/> <c: foreach extaints = "$ {requestScope.categorylist}" var = "Категория"> $ {категория.id} | $ {Category.Type} | $ {Category.hot} <br/> </c: foreach> <c: foreach emes = "$ {sessionscope.categorylist}" var = "Категория"> $ {Category.id} | $ {Category.Type} | $ {Category.hot} <br/> </c: foreach> <c: foreach emits = "$ {applicationscope.categorylist}" var = "Категория"> $ {Category.id} | $ {Category.Type} | $ {Category.hot} <br/> </c: foreach> </body> </html> 3.2 Извлечение базиакции
Как уже уже упоминалось, второй метод имеет больший объем кода, но мы можем извлечь базеатровая, чтобы специфически обрабатывать операции, связанные с этими доменами.
открытый класс BaseAction Extends Actionsupport реализует запрос QuestionAware, SessionAware, ApplicationAware {Protected Map <String, Object> запрос; Защищенная карта <строка, объект> сеанс; Защищенная карта <строка, объект> приложение; @Override public void setApplication (map <string, Object> Application) {this.Application = Application; } @Override public void setSession (map <string, object> session) {this.session = session; } @Override public void setRequest (map <string, объект> запрос) {this.Request = request; }} Затем, если наше собственное действие должно использовать эти объекты домена для хранения данных, мы можем непосредственно наследовать базеацию, и мы можем напрямую использовать объекты запроса, сеанса и приложения. Следовательно, модифицированная категория выглядит следующим образом:
Общедоступный класс CategoryAction Extens BaseAction {частная категория; <pre name = "code"> CategoryService CategoryService; public void setCategoryService (CategoryService CategoryService) {this.categoryService = CategoryService; } public String update () {System.out.println ("--- Обновление ----"); CategoryService.Update (Category); вернуть "индекс"; } public String save () {System.out.println ("---- save -----"); return "index"; } public String Query () {request.put ("CategoryList", CategoryService.Query ()); session.put ("CategoryList", CategoryService.Query ()); Application.put ("CategoryList", CategoryService.Query ()); вернуть "индекс"; } публичная категория getCategory () {return Category; } public void setCategory (категория категория) {this.category = категория; }} Все действия, которые необходимо использовать поля запроса, сеанса и приложения, просто наследуются напрямую, что очень удобно.
3.3 Получите параметры (ModelDriven)
Давайте продолжим смотреть на класс категории выше. Существует категория переменной -член, которая является Pojo. Определение этой переменной и написание методов набора и получения, для того, чтобы страница JSP была передана через параметры, прикрепленные к URL. Параметры - это атрибуты в объекте категории, такие как ID, тип и т. Д., Но параметры в URL должны быть записаны как категория. ID, категория.type и т. Д. Таким образом, стойки автоматически вводят этот параметр записи в объект категории, и тогда мы можем использовать этот объект категории напрямую, но это немного мудро. Мы можем использовать ModelDriven для более легкого решения проблемы.
Общедоступный класс CategoryAction Extens BaseAction реализует ModelDriven <Категория> {Категория частной категории; // Используя интерфейс модели, метод getModel () должен быть реализован. Этот метод подтолкнет возвращенный элемент в верхнюю часть стека @Override Public Category getModel () {Category = New Category (); возвращение категории; } <pre name = "code"> CategoryService CategoryService; public void setCategoryService (CategoryService CategoryService) {this.categoryService = CategoryService; } public String Update () {System.out.println ("---- Update ----"); CategoryService.Update (категория); вернуть "индекс"; } public String save () {System.out.println ("---- Сохранить ----"); вернуть "индекс"; } public String Query () {request.put ("CategoryList", CategoryService.Query ()); session.put ("CategoryList", CategoryService.Query ()); Application.put ("CategoryList", CategoryService.Query ()); вернуть "индекс"; }} Таким образом, нам не нужно включать утомительные параметры, такие как Category.id на странице JSP на стойке регистрации. Посмотрите на модель, основанную на странице JSP:
<%@ page language = "java" import = "java.util.*" pageencoding = "utf-8"%> <%@ taglib uri = "http://java.sun.com/jsp/jstl/core" prefix = "c"%> <! doctpe html public "-//w3c // dtd httm.01.01. <html> <head> <tite> my jsp 'index.jsp' Начальная страница </title> </head> <body> <a href = "$ {pagecontext.request.contextPath} /category_update.action?category.id=2&category.type=gga&category.hot=false"> href = "Category_save.Action? ID = 1 & Type = HAHA & HOT = TRUE"> TEST MODELDRIVEN </a> <a href = "Category_Query.Action"> Запрос всех категорий </a> <br/> <C: Foreach items = "$ {requestScope.categorylist}" var = "Category"> $ {Category.id} | $ {Category.Type} | $ {Category.hot} <br/> </c: foreach> <c: foreach emes = "$ {sessionscope.categorylist}" var = "Категория"> $ {Category.id} | $ {Category.Type} | $ {Category.hot} <br/> </c: foreach> <c: foreach emits = "$ {applicationscope.categorylist}" var = "Категория"> $ {Category.id} | $ {Category.Type} | $ {Category.hot} <br/> </c: foreach> </body> </html> Результатом теста является то, что Catgory может быть получен, и все идентификаторы, тип и горячие атрибуты присваиваются хорошо. Мы видим, что, реализуя интерфейс модели, мы можем легко переносить параметры в URL. В действии нам нужно только реализовать метод GetModel и вернуть новый объект для использования. На этом этапе легко думать, что в столетах определенно будет много таких моделей, которые необходимо получить, поэтому нам также необходимо извлечь эту часть в базеацию.
3.4 Извлечение модели, обработанного в базазакцию
Во -первых, мы добавляем код модели, основанной на базеации следующим образом:
// Поскольку существует множество различных моделей, которые требуют модели, мы используем общий открытый класс Baseaction <T> расширяет действия, реализует запрос, SessionAware, Applicationaware, ModelDriven <T> {Защищенная карта <строка, объект> запрос; Защищенная карта <строка, объект> сеанс; Защищенная карта <строка, объект> приложение; защищенная модель T; @Override public void setApplication (map <string, Object> Application) {this.Application = Application; } @Override public void setSession (map <string, object> session) {this.session = session; } @Override public void setRequest (map <string, объект> запрос) {this.Request = request; } @Override public t getModel () {// Здесь, новый a соответствующий экземпляр, анализируя t, пройденное. Класс clazz = (class) type.getactualtypearguments () [0]; try {model = (t) clazz.newinstance (); } catch (Exception e) {бросить новое runtimeexception (e); } return Model; }} После извлечения код в категории будет уменьшаться и уменьшаться:
// Унаследовать базойксацию и добавление общего открытого класса категория расширяет базой <Категория> {частная категория категория категория; public void setCategoryService (CategoryService CategoryService) {this.categoryService = CategoryService; } public String Update () {System.out.println ("---- Update ----"); CategoryService.Update (MODEL); // Использовать модель непосредственно возвращать «Индекс»; } public String save () {System.out.println ("---- Сохранить ----"); System.out.println (модель); // Использовать модель непосредственно для возврата «Индекс»; } public String Query () {request.put ("CategoryList", CategoryService.Query ()); session.put ("CategoryList", CategoryService.Query ()); Application.put ("CategoryList", CategoryService.Query ()); вернуть "индекс"; }} На данный момент есть еще одна вещь, которая не чувствует себя хорошо, то есть категория переменных участников, которая всегда существовала в категории. Поскольку CategoryAction использует методы в объекте CategoryService, этот объект должен быть создан и может быть введен заданный метод. Это приводит к недостатку: если многие действия должны использовать категорию, то объект и метод установки должны быть созданы в их действиях. Более того, если в действии используются несколько разных объектов обслуживания, все они должны быть созданы, что становится очень сложным.
3.5. Извлечение обслуживания в базеацию
В ответ на вышеупомянутую проблему мы извлекаем все объекты обслуживания в проект в базойкцию, чтобы создать его. Таким образом, после других действий наследуют базеацию, они могут использовать любые услуги, которые хотят использовать:
// I классифицировал контент в базовом общедоступном классе Baseaction <t> расширяет действия. Защищенный счетный счет счетов; public void setCategoryService (CategoryService CategoryService) {this.categoryService = CategoryService; } public void setAccountservice (AccountService) AccountService) {this.Accountservice = accountservice; } // Защищенная карта объекта домена <строка, объект> запрос; Защищенная карта <строка, объект> сеанс; Защищенная карта <строка, объект> приложение; @Override public void setApplication (map <string, Object> Application) {this.Application = Application; } @Override public void setSession (map <string, object> session) {this.session = session; } @Override public void setRequest (map <string, объект> запрос) {this.Request = request; } // Модель защищенная T модель; @Override public t getModel () {parameterizedType type = (parameterizedType) this.getClass (). GetGenericSuperClass (); Класс clazz = (class) type.getactualtypearguments () [0]; try {model = (t) clazz.newinstance (); } catch (Exception e) {бросить новое runtimeexception (e); } return Model; }} Это делает категорию более освежающим: public Class CategoryAction Extends baseaction <Category> {public String update () {System.out.println ("--- Обновление ----"); CategoryService.Update (модель); вернуть "индекс"; } public String save () {System.out.println ("--- Сохранить ----"); System.out.println (модель); вернуть "индекс"; } public String Query () {request.put ("CategoryList", CategoryService.Query ()); session.put ("CategoryList", CategoryService.Query ()); Application.put ("CategoryList", CategoryService.Query ()); вернуть "индекс"; }} Некоторые люди могут спросить, не будет ли это не избыточно, если так много объектов обслуживания вводится в базеат? Это не так, потому что даже если он не записан в базеатровании, контейнер пружины создаст этот объект, который не имеет значения. Напротив, сервисный объект помещается в базеацию и более удобен для разработки других действий. Более того, базоазакну не нужно назначать файлу struts.xml, потому что ни один JSP не будет запрашивать базоазакну, это только для других действий, которые нужно наследовать.
Еще одна вещь, которую нужно забыть: то есть изменить конфигурацию в Beans.xml:
<!-- If it is a prototype type, it is created when used, not automatically when starting--> <bean id="baseAction" scope="prototype"> <property name="categoryService" ref="categoryService"></property> <property name="accountService" ref="accountService"></property> </bean> <bean id="categoryAction" scope="prototype" parent = "baseaction"/>
Добавьте новую базеатчнную фасоль, сопоставьте все объекты обслуживания в проекте в качестве собственности и убейте собственность в оригинальном категории.
В будущем, если мы хотим написать новый XXXAction, мы можем напрямую наследовать базеацию. Если сервис используется в XXXAction, мы можем использовать ее напрямую. Нам просто нужно добавить фасоль, соответствующий XXXAction в файл beans.xml, и настроить прыжок в файле struts.xml.
4. Измените XML на аннотацию
Мы видим, что по мере того, как проект становится больше и больше, в Beans.xml будет все больше конфигураций, и многие конфигурации являются избыточными. Чтобы облегчить разработку, мы теперь изменяем конфигурацию XML на аннотации. Давайте сначала посмотрим на конфигурацию в Beans.xml:
Это те бобы, которые мы написали, когда построили окружающую среду и извлекили их. Они должны быть преобразованы в аннотации. Давайте заменим их пьесу по частям: сначала замените обслуживание, которая имеет три части: BaseService, CategoryService и Accountservice. Замените следующее:
Затем убейте соответствующую часть в Beans.xml. Далее измените часть действия, в основном базеачение, категорию и учетную запись, и замените ее следующим образом:
Затем убейте конфигурацию части действия в Beans.xml и, наконец, добавьте следующую конфигурацию в файл beans.xml, и вы можете использовать аннотацию.
<Контекст: компонент-сканирование Base-package = "cn.it.shop .."/>
Некоторые люди могут спросить, почему обслуживание и действия отличаются при использовании аннотаций? @Service используется в службе, а @Controller используется в действии? На самом деле, это то же самое, просто чтобы отличить их от разных слоев бобов для легкого чтения.
Адрес загрузки исходного кода всего проекта: //www.vevb.com/article/86099.htm
Оригинальный адрес: http://blog.csdn.net/eson_15/article/details/51297698
Вышеуказанное - все содержание второй битвы за SSH Framework Online Mall Project. Я надеюсь, что это будет полезно для каждого обучения, и я надеюсь, что все будут поддерживать wulin.com больше.