En la sección anterior , "El primer proyecto de Battle of SSH Framework Online Mall: Integración de Struts2, Hibernate4.3 y Spring4.2", hemos construido el entorno de desarrollo para Struts2, Hibernate y Spring y los integramos con éxito. Esta sección completa principalmente algunas adiciones básicas, eliminación, modificación y búsqueda, así como la extracción de servicio, DAO y acción.
1. Extracción de la capa de servicio
En la sección anterior, simplemente escribimos los métodos de guardado y actualización en la capa de servicio. Aquí comenzamos a mejorar el código en esta parte y luego extraemos el código en la capa de servicio.
1.1 Mejorar la capa de servicio de categorías
El funcionamiento de la base de datos no es más que agregar, eliminar, modificar y verificar. Primero, mejoremos la interfaz y la implementación de la capa CategorialService:
// Interfaz CategyService Interfaz Public Interface CategyService extiende BaseService <Cateatory> {public void save (categoría de categoría); // Insertar la actualización pública void (categoría de categoría); // Actualizar public void eliminar (int id); // eliminar la categoría pública get (int id); // Obtener una categoría Lista pública <Catexy> Query (); // Obtener toda la categoría} Implementación específica de la interfaz CategoryService:
CategyServiceImpl de clase pública extiende BaseServiceImpl <Catexatory> Implementa CategyService {private sessionFactory sessionFactory; // La primavera inyectará públicamente setSessionFactory (sessionFactory sessionFactory) {this.sessionFactory = sessionFactory; } Sesión protegida getSession () {// Get Session desde el hilo actual, si no, cree una nueva sesión de retorno SessionFactory.getCurrentSession (); } @Override public void save (categoría de categoría) {getSession (). Save (categoría); } @Override public void Update (categoría de categoría) {getSession (). Update (categoría); } @Override public void Delete (int id) { /*El primer método tiene una desventaja, es decir, debe consultarlo una vez antes de eliminarlo. Object obj = getSession (). Get (categoría.class, id); if (obj! = null) {getSession (). eliminar (obj); }*/ String hql = "Eliminar categoría mientras id =: id"; getSession (). CreateQuery (HQL) // .SetInTeger ("id", id) // .executeUpdate (); } @Override Public Category get (int id) {return (categoría) getSession (). Get (category.class, id); } @Override Public List <Cateatory> QUERY () {String hql = "de la categoría"; return getSession (). CreateQuery (HQL) .list (); }} 1.2 Implementación de extracción de capa de servicio
Después de completar el servicio de categoría, extraeremos la implementación básica de la capa de servicio. La idea es la siguiente: extraemos una interfaz base BaseService y el BaseServiceImpl, y al desarrollar más tarde, si se necesita un nuevo servicio, solo necesita hacer dos pasos: primero defina una nueva interfaz XXXService hereda la interfaz Baseservice, que puede agregar nuevos métodos abstractos a esta interfaz; Luego, defina una nueva clase de implementación XXXServiceImpl hereda BaseServiceImpl e implementa la interfaz XXXService. Esto hace que sea más fácil mantener el proyecto.
Primero creemos la interfaz BaseService basada en la interfaz de Servicio de categoría anterior:
// Interfaz básica BaseService, use la interfaz pública genérica BaseService <T> {public void save (t t); Actualización pública vacía (T t); Public void eliminar (int id); Public t get (int id); Lista pública <t> QUERY (); } Luego cree la clase de implementación de interfaz Baseservice BaseServiceImpl de acuerdo con la clase de implementación de CategyServiceImpl:
/ ** * @Description TODO (Extracción de módulos públicos) * @author eson_15 * */ @supplesswarnings ("sin verificar") clase pública BaseServiceImpl <T> Implementa BaseService <T> {Clazz de clase privada; // El tipo de operación actual se almacena en el clazz, es decir, el genérico T Private SessionFactory SessionFactory; Public BaseServiceImpl () {// Se puede eliminar la siguiente información de impresión. Aquí está el sistema.out.println ("Esto representa el objeto que actualmente llama al constructor" + esto); System.out.println ("Obtenga la información de la clase principal del actual este objeto" + this.getClass (). GetsuperClass ()); System.out.println ("Obtenga la información de la clase principal del actual este objeto (incluida la información genérica)" + this.getClass (). GetGenericsuperClass ()); // Obtenga el tipo de parámetro del tipo de parametrizado genérico tipo = (parameterizedType) this.getClass (). GetGenericsuperClass (); clazz = (class) type.getActualTyPearGuments () [0]; } public void setSessionFactory (sessionFactory sessionFactory) {this.sessionFactory = sessionFactory; } Sesión protegida getSession () {// Get Session desde el hilo actual, si no, cree una nueva sesión de retorno SessionFactory.getCurrentSession (); } @Override public void save (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 () + "como c donde 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 (); }} Una vez completada la extracción, podemos reescribir la interfaz CategoryService y la clase de implementación de CategyServiceImpl. como sigue:
// La interfaz CategyService hereda la interfaz de interfaz de Basservice, la interfaz pública CategyService extiende BaseService <Cateatory> { / * * Simplemente agregue el nuevo método requerido por la categoría misma. El método público ya está en BaseService * /} / ** * @Description TODO (la lógica comercial del módulo en sí) * @author eson_15 * * / public class CategyServiceImpl extiende BasesServiceImpl <Catexatory> Implementa la categoría de categoría { / * * solo implementa el nuevo método agregado en la interfaz de servicio de categoría. El método público se ha implementado en BaseServiceImpl */} Como se puede ver en el código, el servicio recientemente agregado solo necesita heredar la interfaz BaseService y luego agregar la lógica comercial requerida por el servicio a la interfaz. El ServiceImpl recientemente agregado solo necesita heredar BaseServiceImpl e implementar la lógica comercial recientemente agregada.
Pero no olvide el punto importante: es modificar los frijoles en el archivo de configuración de Spring frijoles.xml .
<
Mata la propiedad en el servicio de categorías original, luego agregue la propiedad principal para indicar la herencia del servicio Basservice; Luego, configure el servicio BaseService y configure el SessionFactory en el BaseService. Además, una cosa a tener en cuenta: establecer la propiedad de la inyente perezosa en verdad, porque BasesService es una clase genérica, y las clases genéricas no pueden ser instanciadas. En este punto, se realiza la extracción de la capa de servicio.
2. Agregue una cuenta en la capa de servicio
La capa de servicio acaba de extraer, por lo que ahora es muy simple escribir un servicio de cuenta:
Primero escriba una interfaz de servicio de cuentas para heredar BaseService:
El servicio de cuentas de interfaz pública extiende BasesService <COPATY> {// Tenga en cuenta que los genéricos en BaseService ahora son cuentas / * * Simplemente agregue el nuevo método requerido por el servicio de cuentas en sí, y el método público ya está en BaseService * /} Luego, escriba una clase de implementación de cuentas de servicio para heredar la clase de implementación de BaseServiceImpl e implementar la interfaz de servicios de cuentas:
Public ClasserServiceImpl extiende BaseServiceImpl <Coence> Implementa AccountService { / * * Simplemente implementa los métodos recientemente agregados en la interfaz de cuentas de servicio. El método público se ha implementado en BaseServiceImpl */// Administrar la función de inicio de sesión, y se mejorará más tarde} Finalmente, agregue la siguiente configuración al archivo beans.xml:
<bean id = "cuento" parent = "basesService" />
De esta manera, se ha escrito un nuevo servicio. Si necesita agregar un servicio en el futuro, seguirá este proceso, lo cual es muy conveniente.
3. Extracción de acción
3.1 Almacene los datos en la acción en el dominio (solicitud, sesión, aplicación, etc.)
Sabemos que en acción, puede obtener directamente un objeto ActionContext a través de ActionContext.getContext (), y luego obtener el objeto de dominio correspondiente a través del objeto; También puede inyectar el objeto de dominio correspondiente implementando la interfaz xxxAware. Primero veamos estos dos métodos:
La categoría de clase pública extiende ActionSupport implementa request AWare, SessionAWare, ApplicationAware {Categoría de categoría privada; Categoría privada Categoría de categoría; public void setCategoryService (categoryService CategoryService) {this.CategoryService = CategyService; } public String Update () {System.out.println ("----- Update ----"); categoryService.Update (categoría); devolver "índice"; } public String Save () {System.out.println ("---- save ----"); devolver "índice"; } Public String Query () {// Solución 1, use el mapa correspondiente para reemplazar el objeto incorporado original, de modo que no haya dependencia con JSP, pero la cantidad de código es relativamente grande // ActionContext.getContext (). Put ("CategyList", CategyService.query ()); // colóquelo en el campo de solicitud // ActionContext.getContext (). GetSession (). PUT ("CategyList", CategyService.Query ()); // Ponlo en el campo de sesión // ActionContext.getContext (). GetApplication (). PUT ("CategyList", CategyService.Query ()); // colóquelo en el dominio de la aplicación // Solución 2, implementa la interfaz correspondiente (request AWare, SessionAWare, ApplicationAware), y permita que el mapa correspondiente inyecte request.put ("CategyList", categoryService.query ()); session.put ("CategyList", categoryService.query ()); Application.put ("CategyList", CategyService.Query ()); devolver "índice"; } Categoría pública getCategory () {categoría de retorno; } public void setCategory (categoría de categoría) {this.category = category; } mapa privado <cadena, objeto> solicitud; mapa privado <cadena, objeto> sesión; mapa privado <cadena, objeto> aplicación; @Override public void setApplication (map <string, objeto> aplicación) {this.application = application; } @Override public void setSession (map <string, object> session) {this.session = session; } @Override public void setRequest (map <string, object> request) {this.request = request; }} Sigue siendo la clase de categoría que integra los tres marcos principales en la sección anterior. Agregamos un método de consulta a este método. En este método, almacenamos los resultados de la consulta en el dominio de solicitud, el dominio de la sesión y el dominio de la aplicación. El primer método es usar directamente ActionContext para implementarlo. No se requiere interfaz, pero el código es grande; El segundo método implementa las interfaces SoldingWare, SessisionAWare y ApplicationAware, y tres métodos abstractos para implementar la solicitud, sesión y aplicación de inyección de interfaz, y luego asignarla a las variables de miembro correspondientes, de modo que los resultados de la consulta se puedan almacenar en el dominio en el método de consulta. Este volumen de código parece ser más grande que el primer método ... pero podemos extraerlo y leerlo primero.
Agregamos una nueva conexión de consulta a index.jsp para probar si se pueden mostrar los resultados de la consulta:
<%@ page lenguaje = "java" import = "java.util.*" PageEncoding = "utf-8"%> <%@ taglib uri = "http://java.sun.com/jsp/jstl/core" prefix = "c"%> < <html> <fead> <title> my jsp 'index.jsp' página inicial </title> </head> <body> <a href = "$ {pageContext.request.contextPath} /category_update.action?categy.id=2&category.type=gga &category.hot=false"> Access Update </ae> href = "category_save.action"> Access Save </a> <a href = "category_query.action"> consulta todas las categorías </a> <br/> <c: foreach elementos = "$ {requestscope.categoryList}" var = "categoría"> $ {categoría.id} | $ {Category.Type} | $ {category.hot} <br/> </c: foreach> <c: foreach elementos = "$ {sessionscope.categorylist}" var = "category"> $ {category.id} | $ {Category.Type} | $ {category.hot} <br/> </c: foreach> <c: foreach elementos = "$ {aplicationsCope.CategoryList}" var = "categoría"> $ {category.id} | $ {Category.Type} | $ {categoría.hot} <br/> </c: foreach> </body> </html> 3.2 Extraer base
Como se mencionó en este momento, el segundo método tiene un volumen de código más grande, pero podemos extraer una capacidad de basura para manejar específicamente las operaciones relacionadas con estos dominios.
Public Class BasAction extiende ActionSupport implementa request AWare, SessionAWare, ApplicationAWee {Map protegido <String, Object> Solicitud; mapa protegido <cadena, objeto> sesión; mapa protegido <cadena, objeto> aplicación; @Override public void setApplication (map <string, objeto> aplicación) {this.application = application; } @Override public void setSession (map <string, object> session) {this.session = session; } @Override public void setRequest (map <string, object> request) {this.request = request; }} Entonces, si nuestra propia acción necesita usar estos objetos de dominio para almacenar datos, podemos heredar directamente la base de bases, y podemos usar directamente objetos de solicitud, sesión y aplicación. Por lo tanto, la categoría modificada es la siguiente:
CategoryAction de clase pública extiende Baseaction {categoría de categoría privada; <preame = "Código"> Categoría privada CategyService; public void setCategoryService (categoryService CategoryService) {this.CategoryService = CategyService; } public String Update () {System.out.println ("--- Update ----"); categoryService.Update (categoría); devolver "índice"; } public string save save () {System.out.println ("---- save -----"); return "índice"; } public String Query () {request.put ("categoryList", categoryService.query ()); session.put ("CategyList", categoryService.query ()); Application.put ("CategyList", CategyService.Query ()); devolver "índice"; } Categoría pública getCategory () {categoría de retorno; } public void setCategory (categoría de categoría) {this.category = category; }} Todas las acciones que necesitan usar campos de solicitud, sesión y aplicación se heredan directamente, lo cual es muy conveniente.
3.3 Obtener parámetros (ModelDriven)
Sigamos observando la clase de categoría anterior. Hay una categoría de variable miembro, que es un POJO. Definir esta variable y escribir los métodos establecer y obtener es que la página JSP se transfiera a través de los parámetros adjuntos a la URL. Los parámetros son atributos en el objeto de categoría, como ID, tipo, etc., pero los parámetros en la URL deben escribirse como categoría.id, categoría. Type, etc. De esta manera, los puntales inyectarán automáticamente este parámetro de escritura en el objeto de categoría, y luego podemos usar este objeto de categoría directamente, pero esto es un poco espumoso. Podemos usar ModelDiven para resolver el problema más fácilmente.
CategoryAction de clase pública extiende Baseaction implementa ModelDriven <Cateatory> {Categoría de categoría privada; // Usando la interfaz ModelDiven, se debe implementar el método getModel (). Este método empujará el elemento devuelto a la parte superior de la categoría pública de pila @Override getModel () {category = new Category (); categoría de devolución; } <preame = "Código"> Categoría privada CategyService; public void setCategoryService (categoryService CategoryService) {this.CategoryService = CategyService; } public String Update () {System.out.println ("----- Update ----"); categoryService.Update (categoría); devolver "índice"; } public String Save () {System.out.println ("---- save ----"); devolver "índice"; } public String Query () {request.put ("categoryList", categoryService.query ()); session.put ("CategyList", categoryService.query ()); Application.put ("CategyList", CategyService.Query ()); devolver "índice"; }} De esta manera, no necesitamos incluir los parámetros tediosos como la categoría de categoría en la página JSP de recepción. Mire la parte impulsada por modelos de la página JSP:
<%@ page lenguaje = "java" import = "java.util.*" PageEncoding = "utf-8"%> <%@ taglib uri = "http://java.sun.com/jsp/jstl/core" prefix = "c"%> < <html> <fead> <title> my jsp 'index.jsp' página inicial </title> </head> <body> <a href = "$ {pageContext.request.contextPath} /category_update.action?categy.id=2&category.type=gga &category.hot=false"> Access Update </ae> href = "category_save.action? id = 1 & type = jAHA & HOT = true"> Test ModelDriven </a> <a href = "category_query.action"> consulta todas las categorías </a> <br/> <c: elementos de foreach = "$ {requestscope.categoryList}" var = "categoría"> $ {{{{{} | | | $ {Category.Type} | $ {category.hot} <br/> </c: foreach> <c: foreach elementos = "$ {sessionscope.categorylist}" var = "category"> $ {category.id} | $ {Category.Type} | $ {category.hot} <br/> </c: foreach> <c: foreach elementos = "$ {aplicationsCope.CategoryList}" var = "categoría"> $ {category.id} | $ {Category.Type} | $ {categoría.hot} <br/> </c: foreach> </body> </html> El resultado de la prueba es que se puede obtener Catgory y todos los atributos ID, tipo y calto se asignan bien. Podemos ver que al implementar la interfaz ModelDriven, podemos llevar fácilmente los parámetros en la URL. En acción, solo necesitamos implementar el método GetModel y devolver un nuevo objeto para usar. En este punto, es fácil pensar que definitivamente habrá muchos de estos modelos en puntales que deben obtenerse, por lo que también necesitamos extraer esta parte en Baseaction.
3.4 Extracto Modelo impulsado a Baseaction
Primero, agregamos el código de la parte de ModelDiven a Baseaction, de la siguiente manera:
// Debido a que hay muchos modelos diferentes que requieren ModelDengiven, utilizamos la Basa de Basa de clase pública genérica <T> extiende las acciones de ActionSupport SoldingAware, SessionAWare, ApplicationAware, ModelDriven <T> {mapa protegido <cadena, objeto> request; mapa protegido <cadena, objeto> sesión; mapa protegido <cadena, objeto> aplicación; modelo t protegido; @Override public void setApplication (map <string, objeto> aplicación) {this.application = application; } @Override public void setSession (map <string, object> session) {this.session = session; } @Override public void setRequest (map <string, object> request) {this.request = request; } @Override public t getModel () {// Aquí, nueva una instancia correspondiente analizando la t. Class clazz = (class) type.getActualTyPearGuments () [0]; intente {model = (t) clazz.newinstance (); } catch (Exception e) {Throw New RuntimeException (e); } modelo de retorno; }} Después de la extracción, el código en categoría disminuirá y disminuirá:
// Heredar BASACACT y agregar CategyAction de clase pública genérica extiende Baseaction <Cateatory> {Categoría privada CategyService; public void setCategoryService (categoryService CategoryService) {this.CategoryService = CategyService; } public String Update () {System.out.println ("----- Update ----"); categoryService.Update (modelo); // Use el modelo devuelve directamente "índice"; } public String Save () {System.out.println ("---- save ----"); System.out.println (modelo); // use el modelo directamente para devolver "índice"; } public String Query () {request.put ("categoryList", categoryService.query ()); session.put ("CategyList", categoryService.query ()); Application.put ("CategyList", CategyService.Query ()); devolver "índice"; }} En este punto, hay otra cosa que no se siente bien al respecto, que es el servicio de categorías variables miembros, que siempre ha existido en la categoría. Debido a que la categoría usa métodos en el objeto CategoryService, este objeto debe crearse y se puede inyectar un método establecido. Esto lleva a una desventaja: si muchas acciones necesitan usar CategoryService, entonces el método de objeto y conjunto debe crearse en sus acciones. Además, si se usan varios objetos de servicio diferentes en una acción, todos deben crearse, lo que se vuelve muy complicado.
3.5 Servicio de extracción a Baseaction
En respuesta al problema anterior, extraemos todos los objetos de servicio en el proyecto en Baseaction para crearlo. De esta manera, después de que otras acciones hereden la base de bases, pueden usar cualquier servicio que quieran usar:
// Clasifiqué el contenido en Baseaction public class Baseaction <T> Extiende ActionSupport implementa request AWare, SessionAWare, ApplicationAware, ModelDriven <T> {// Categoría de servicio protegida por objeto CategyService; servicio de cuentas protegido Reserva de cuentas; public void setCategoryService (categoryService CategoryService) {this.CategoryService = CategyService; } public void setAcCountService (AccountService) AccountService) {this.accountService = AccountService; } // Mapa protegido del objeto de dominio <cadena, objeto> request; mapa protegido <cadena, objeto> sesión; mapa protegido <cadena, objeto> aplicación; @Override public void setApplication (map <string, objeto> aplicación) {this.application = application; } @Override public void setSession (map <string, object> session) {this.session = session; } @Override public void setRequest (map <string, object> request) {this.request = request; } // modelo T protegido con modelado; @Override public t getModel () {parameterizedType type = (parameterizedType) this.getClass (). GetGenericsuperClass (); Class clazz = (class) type.getActualTyPearGuments () [0]; intente {model = (t) clazz.newinstance (); } catch (Exception e) {Throw New RuntimeException (e); } modelo de retorno; }} Esto hace que la categoría sea más refrescante: la clase pública CategyAction extiende Baseaction <Cateatory> {public String Update () {System.out.println ("--- Update ----"); categoryService.Update (modelo); devolver "índice"; } public String Save () {System.out.println ("--- Save ----"); System.out.println (modelo); devolver "índice"; } public String Query () {request.put ("categoryList", categoryService.query ()); session.put ("CategyList", categoryService.query ()); Application.put ("CategyList", CategyService.Query ()); devolver "índice"; }} Algunas personas pueden preguntar, ¿no será redundante si tantos objetos de servicio se inyectan en la base de bases? Esto no es cierto, porque incluso si no está escrito en Baseaction, el contenedor de resorte creará este objeto, lo que no importa. Por el contrario, el objeto de servicio se coloca en Baseaction y es más conveniente para el desarrollo de otras acciones. Además, Baseaction no necesita ser asignada al archivo Struts.xml, porque ningún JSP solicitará Baseaction, es solo para otras acciones que heredan.
Otra cosa para olvidar: es modificar la configuración en frijoles.xml:
< parent = "Baseaction"/>
Agregue un nuevo frijol de base, coincida con todos los objetos de servicio en el proyecto como propiedad y mate la propiedad en la categoría original.
En el futuro, si queremos escribir una nueva XXXACTION, podemos heredar directamente BASEACTION. Si se usa un servicio en xxxaction, podemos usarlo directamente. Solo necesitamos agregar un bean correspondiente a xxxaction en el archivo beans.xml y configurar el salto en el archivo struts.xml.
4. Cambiar XML a la anotación
Podemos ver que a medida que el proyecto se vuelve cada vez más grande, habrá más y más configuraciones en frijoles.xml, y muchas configuraciones son redundantes. Para facilitar el desarrollo, ahora cambiamos la configuración de XML en anotaciones. Primero veamos la configuración en frijoles.xml:
Estos son los frijoles que escribimos cuando construimos el entorno y los extraíamos. Estos deben convertirse en anotaciones. Vamos a reemplazarlos por pieza por pieza: reemplace primero la parte del servicio, que tiene tres partes: BaseService, CategoryService y cuentas de cuentas. Reemplace de la siguiente manera:
Luego mata la parte correspondiente en frijoles. Xml. A continuación, modifique la parte de acción, principalmente BasAction, CategoryAction y Responding, y reemplácela de la siguiente manera:
Luego, mata la configuración de la parte de acción en frijoles.xml y finalmente agregue la siguiente configuración al archivo beans.xml, y puede usar la anotación.
<context: componente-scan base-paquete = "cn.it.shop .."/>
Algunas personas pueden preguntar, ¿por qué el servicio y la acción son diferentes cuando se usan anotaciones? @Service se usa en el servicio y @Controller se usa en la acción? De hecho, es lo mismo, solo para distinguirlos de diferentes capas de frijoles para una fácil lectura.
La dirección de descarga del código fuente de todo el proyecto: //www.vevb.com/article/86099.htm
Dirección original: http://blog.csdn.net/eson_15/article/details/51297698
Lo anterior es todo el contenido de la segunda batalla del proyecto SSH Framework Online Mall. Espero que sea útil para el aprendizaje de todos, y espero que todos apoyen más a Wulin.com.