Na seção anterior , "O Projeto Mall Online da Framework Online da Battle of SSH: Integração de Struts2, Hibernate4.3 e Spring4.2", construímos o ambiente de desenvolvimento para Struts2, Hibernate e Spring e os integraram com sucesso. Esta seção completa principalmente algumas adições básicas, exclusão, modificação e pesquisa, bem como a extração de serviço, DAO e ação.
1. Extração da camada de serviço
Na seção anterior, simplesmente escrevemos os métodos de salvar e atualizar na camada de serviço. Aqui começamos a melhorar o código nesta parte e, em seguida, extraímos o código na camada de serviço.
1.1 Melhorar a camada de categoryservice
A operação do banco de dados nada mais é do que adicionar, excluir, modificar e verificar. Primeiro, vamos melhorar a interface e a implementação da camada CategoryService:
// CategoryService Interface Public Interface CategoryService estende BaseService <Categoria> {public void salvar (categoria categoria); // Insira a atualização pública void (categoria de categoria); // Atualize public void Exclete (int id); // excluir categoria pública get (int id); // Obtenha uma categoria Lista Pública <Categoria> Query (); // Obtenha toda a categoria} Implementação específica da interface CategoryService:
classe pública CategoryServiceImpl estende o BasEServiceImpl <Categoria> implementa a categoryService {private SessionFactory SessionFactory; // A primavera injetará o público de void público (sessionFactoryFactory) {this.SessionFactory = SessionFactory; } sessão protegida getSession () {// Obtenha sessão do thread atual, se não, crie uma nova sessão de retorno sessionFactory.getCurrentSession (); } @Override public void save (categoria categoria) {getSession (). Save (categoria); } @Override public void update (categoria categoria) {getSession (). Update (categoria); } @Override public void Delete (int id) { /*O primeiro método tem uma desvantagem, ou seja, você deve consultá -lo uma vez antes de excluí -lo. Objeto obj = getSession (). Get (category.class, id); if (obj! = null) {getSession (). delete (obj); }*/ String hql = "Excluir categoria enquanto id =: id"; getSession (). CreateEquery (HQL) // .SetInteger ("ID", ID) // .ExecuteUpdate (); } @Override Public Category get (int id) {return (category) getSession (). Get (category.class, id); } @Override Public List <Category> query () {string hql = "da categoria"; retorno getSession (). CreateEquery (HQL) .List (); }} 1.2 Implementação de extração da camada de serviço
Depois de concluir a categoria Service, extrairemos a implementação básica da camada de serviço. A idéia é a seguinte: extraímos uma interface básica BasEserSerService e o BaseServiceImpl e, ao desenvolver posteriormente, se for necessário um novo serviço, você só precisará fazer duas etapas: primeiro definir uma nova interface XXXService herda a interface BasEService, que pode adicionar novos métodos de resumo a essa interface; Em seguida, defina uma nova classe de implementação XXXServiceImpl herda BaseServiceImpl e implementa a interface XXXService. Isso facilita a manutenção do projeto.
Vamos primeiro criar a interface BaseService com base na interface de categoryservice acima:
// BASIC BASIC INTERFACE BASESERVICE, Use o BasEstice genérico de interface pública <T> {public void Save (T t); Atualização de vazio público (T t); Public Void Exclete (int id); public t get (int id); Lista pública <t> query (); } Em seguida, crie a classe de implementação da interface BaseService BasEServiceImpl de acordo com a classe de implementação da categoryServiceImpl:
/ ** * @Description TODO (Extração de módulos públicos) * @Author Eson_15 * */ @suppresswarnings ("desmarcado") Classe pública BasEserServiceImpl <T> implementa BaseService <t> {classe privada clazz; // O tipo de operação atual é armazenado no clazz, ou seja, o genérico T Private SessionFactory Factory; public BaseServiceImpl () {// As três informações de impressão a seguir podem ser removidas. Aqui está o System.out.println ("Isso representa o objeto que atualmente chama o construtor" + this); System.out.println ("Obtenha as informações da classe pai do atual esse objeto" + this.getClass (). GetSuperclass ()); System.out.println ("Obtenha as informações da classe pai do atual esse objeto (incluindo informações genéricas)" + this.getclass (). GetGenericsuperclass ()); // Obtenha o tipo de parâmetro do genérico parametrizype type = (parametreizadoType) this.getclass (). GetGenericsuperclass (); clazz = (classe) type.getActualTyPearguments () [0]; } public void SetSessionFactory (SessionFactory SessionFactory) {this.SessionFactory = SessionFactory; } sessão protegida getSession () {// Obtenha sessão do thread atual, se não, crie uma nova sessão de retorno sessionFactory.getCurrentSession (); } @Override public void Save (t T) {getSession (). Salvar (t); } @Override public void update (t) {getSession (). Update (t); } @Override public void Delete (int id) {System.out.println (clazz.getSimplename ()); String hql = "exclate" + clazz.getSimplename () + "como c onde c.id =: id"; getSession (). CreateEquery (HQL) // .SetInteger ("ID", ID) // .ExecuteUpdate (); } @Override public t get (int id) {return (t) getSession (). Get (clazz, id); } @Override Public List <T> query () {String hql = "de" + clazz.getSimplename (); retorno getSession (). CreateEquery (HQL) .List (); }} Após a conclusão da extração, podemos reescrever a interface CategoryService e a classe de implementação CategoryServiceImpl. do seguinte modo:
// A interface da categoria Service herda a interface pública BaseService Interface CategoryService estende o BasEService <Categoria> { / * * Basta adicionar o novo método exigido por categoryService. O método público já está no BaseService * /} / ** * @Description TODO (a lógica de negócios do próprio módulo) * @author eSon_15 * * / Classe pública CategoryServiceImpl estende BaseServiceImpl <Categoria> Implementa a categoria de categoria. O método público foi implementado no BaseServiceImpl */} Como pode ser visto no código, o serviço recém -adicionado só precisa herdar a interface BaseService e, em seguida, adicionar a lógica de negócios exigida pelo serviço à interface. O recém -adicionado ServiceImpl só precisa herdar BasEServiceImpl e implementar a lógica de negócios recém -adicionada.
Mas não se esqueça do ponto importante: é modificar os grãos no arquivo de configuração da primavera Beans.xml .
<!-Classes genéricas não podem ser instanciadas, então adicione propriedades preguiçosas-> <bean id = "baseserservice" lazy-init = "true"> <propriedade name = "sessionFactory" ref = "sessionFactory"/> </ Bean> <bean id = "categoryService" Parent = "BasEserviice"/>
Mate a propriedade na categoryservice original e adicione a propriedade pai para indicar a herança do BaseService; Em seguida, configure o BaseService e configure o SessionFactory para o BaseService. Além disso, uma coisa a ser observada: defina a propriedade preguiçosa-init como TRUE, porque o BaseService é uma classe genérica, e as classes genéricas não podem ser instanciadas. Neste ponto, a extração da camada de serviço está realizada.
2. Adicione uma conta na camada de serviço
A camada de serviço acaba de ser extraída, então agora é muito simples escrever um serviço de conta:
Primeiro, escreva uma interface de serviço de conta para herdar o BasESerService:
Public Interface AccountService estende BaseService <Counct> {// Observe que os genéricos no BaseService agora estão em conta / * * Basta adicionar o novo método exigido pelo próprio serviço de conta, e o método público já está no BaseService * /} Em seguida, escreva uma classe de implementação do AccountServiceImpl para herdar a classe de implementação BasEServiceImpl e implemente a interface de serviço de conta:
Classe pública AccountServiceImpl estende o BasEServiceImpl <Count> implementa o serviço de conta { / * *, basta implementar os métodos recém -adicionados na interface da conta. O método público foi implementado no BaseServiceImpl */// Gerenciar a função de login e será melhorado posteriormente} Por fim, adicione a seguinte configuração ao arquivo beans.xml:
<bean id = "AccountService" Parent = "BaseService" />
Dessa maneira, um novo serviço foi escrito. Se você precisar adicionar um serviço no futuro, seguirá esse processo, o que é muito conveniente.
3. Extração de ação
3.1 Armazene os dados na ação no domínio (solicitação, sessão, aplicação etc.)
Sabemos que, em ação, você pode obter diretamente um objeto ActionContext através do ActionContext.getContext () e, em seguida, obter o objeto de domínio correspondente através do objeto; Você também pode injetar o objeto de domínio correspondente implementando a interface XXXXAWARE. Vamos primeiro olhar para esses dois métodos:
Categoria de classe pública Ações estende o ACTIONSupport implementa requestware, sessionAWare, ApplicationAware {categoria privada categoria; CategoryService CategoryService; public void setCategoryService (categoryService CategoryService) {this.categoryService = categoryService; } public string update () {System.out.println ("---- Update ----"); categoryService.Update (categoria); retornar "índice"; } public string save () {System.out.println ("---- SALVA ----"); retornar "índice"; } public string query () {// Solução 1, use o mapa correspondente para substituir o objeto interno original, para que não haja dependência no JSP, mas a quantidade de código é relativamente grande // ActionContext.getContext (). Put ("categoryList", categoryService.Query ()); // coloque -o no campo de solicitação // actionContext.getContext (). GetSession (). Put ("categoryList", categoryservice.query ()); // coloque -o no campo da sessão // actionContext.getContext (). GetApplication (). Put ("categoryList", categoryService.Query ()); // coloque -o no domínio do aplicativo // Solução 2, implemente a interface correspondente (requestAware, sessionAWare, ApplicationAware) e deixe o mapa correspondente injeção request.put ("categoryList", categoryService.Query ()); session.put ("categoryList", categoryService.Query ()); Application.put ("categoryList", categoryService.Query ()); retornar "índice"; } categoria pública getCategory () {Categoria de retorno; } public void setCategory (categoria categoria) {this.category = category; } mapa privado <string, objeto> solicitação; mapa privado <string, objeto> sessão; mapa privado <string, objeto> aplicativo; @Override public void Stapplication (map <string, object> Application) {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; }} Ainda é a classe de categoria que integra as três principais estruturas na seção anterior. Adicionamos um método de consulta a esse método. Neste método, armazenamos os resultados da consulta no domínio da solicitação, no domínio da sessão e no domínio do aplicativo. O primeiro método é usar diretamente o ActionContext para implementá -lo. Nenhuma interface é necessária, mas o código é grande; O segundo método implementa as interfaces RequestAware, SessionAcare e ApplicationAware e três métodos abstratos de implementação da solicitação, sessão e aplicação de injeção de interface e, em seguida, atribuem -a às variáveis de membros correspondentes, para que os resultados da consulta possam ser armazenados no domínio no método de consulta. Esse volume de código parece ser maior que o primeiro método ... mas podemos extraí -lo e lê -lo primeiro.
Adicionamos uma nova conexão de consulta ao index.jsp para testar se os resultados da consulta podem ser exibidos:
<%@ página linguagem = "java" import = "java.util. <html> <head> <title> meu jsp 'index.jsp' página de partida </title> </ad Head> <body> <a href = "$ {PageContext.request.contextpath} /category_update.action?category.id=2&category.type=GGA&sactdate.hottate?category.id=2&category.type=GGA. href = "category_save.action"> Access Salvar </a> <a href = "category_query.action"> consulta todas as categorias </a> <br/> <c: foreach itens = "$ {requestscope.categoryList}" var = "categoria"> $ {categoria.id} | $ {category.type} | $ {category.hot} <br/> </c: foreach> <c: foreach itens = "$ {sessionscope.categoryList}" var = "category"> $ {category.id} | $ {category.type} | $ {category.hot} <br/> </c: foreach> <c: foreach itens = "$ {applicationscope.categoryList}" var = "categoria"> $ {category.id} | $ {category.type} | $ {category.hot} <br/> </c: foreach> </body> </html> 3.2 Extrair basal
Como mencionado agora, o segundo método possui um volume de código maior, mas podemos extrair uma base para lidar especificamente em operações relacionadas a esses domínios.
A classe pública Baseaction estende o ACTIONSupport implementa o requestAware, sessionAWare, ApplicationAWare {mapa protegido <string, object> request; mapa protegido <string, objeto> sessão; mapa protegido <string, objeto> aplicativo; @Override public void Stapplication (map <string, object> Application) {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; }} Então, se nossa própria ação precisar usar esses objetos de domínio para armazenar dados, podemos herdar diretamente o Baseaction e podemos usar diretamente objetos de solicitação, sessão e aplicativo. Portanto, a categoria Modificada é a seguinte:
A categoria de classe pública estende o Baseaction {categoria privada categoria; <pré -nome = "code"> categoryservice categoryService privado; public void setCategoryService (categoryService CategoryService) {this.categoryService = categoryService; } public string update () {System.out.println ("--- update ----"); categoryservice.update (categoria); retornar "índice"; } public string save () {System.out.println ("---- SALVAR -----"); retornar "index"; } public string query () {request.put ("categoryList", categoryservice.query ()); session.put ("categoryList", categoryService.Query ()); Application.put ("categoryList", categoryService.Query ()); retornar "índice"; } categoria pública getCategory () {Categoria de retorno; } public void setCategory (categoria categoria) {this.category = category; }} Todas as ações que precisam usar os campos de solicitação, sessão e aplicativo são herdados diretamente diretamente, o que é muito conveniente.
3.3 Obtenha parâmetros (Modeldriven)
Vamos continuar olhando para a classe de categorias acima. Existe uma categoria de variável de membro, que é um pojo. Definir essa variável e escrever os métodos definidos e obtidos é que a página JSP seja passada através dos parâmetros anexados ao URL. Os parâmetros são atributos no objeto de categoria, como ID, tipo, etc., mas os parâmetros no URL devem ser escritos como category.id, category.type, etc. Dessa maneira, os struts injetarão automaticamente esse parâmetro de gravação no objeto de categoria e, em seguida, podemos usar esse objeto de categoria diretamente, mas isso é um pouco mais importante. Podemos usar o Modeldriven para resolver o problema com mais facilidade.
A categoria de classe pública estende o Baseaction implementa Modeldriven <Category> {categoria privada categoria; // Usando a interface Modeldriven, o método getModel () deve ser implementado. Este método levará o item retornado para a parte superior da categoria pública da pilha @Override getModel () {category = new Category (); categoria de retorno; } <pré -nome = "code"> categoryservice categoryService privado; public void setCategoryService (categoryService CategoryService) {this.categoryService = categoryService; } public string update () {System.out.println ("---- Update ----"); categoryService.Update (categoria); retornar "índice"; } public string save () {System.out.println ("---- SALVA ----"); retornar "índice"; } public string query () {request.put ("categoryList", categoryservice.query ()); session.put ("categoryList", categoryService.Query ()); Application.put ("categoryList", categoryService.Query ()); retornar "índice"; }} Dessa forma, não precisamos incluir os parâmetros tediosos como a categoria.id na página JSP da recepção. Veja a parte Modeldriven da página JSP:
<%@ página linguagem = "java" import = "java.util. <html> <head> <title> meu jsp 'index.jsp' página de partida </title> </ad Head> <body> <a href = "$ {PageContext.request.contextpath} /category_update.action?category.id=2&category.type=GGA&sactdate.hottate?category.id=2&category.type=GGA. href = "category_save.action? id = 1 & type = haha & hot = true"> test modeldriven </a> <a href = "category_query.action"> consulta todas as categorias </a> <br/> <c: foreach itens = "$ {requestscope.categylist}" var = "category"> $ {$ {requestscope.cateirl} "var =" category "> $ {category.type} | $ {category.hot} <br/> </c: foreach> <c: foreach itens = "$ {sessionscope.categoryList}" var = "category"> $ {category.id} | $ {category.type} | $ {category.hot} <br/> </c: foreach> <c: foreach itens = "$ {applicationscope.categoryList}" var = "categoria"> $ {category.id} | $ {category.type} | $ {category.hot} <br/> </c: foreach> </body> </html> O resultado do teste é que o Catgory pode ser obtido e todos os atributos de ID, tipo e quentes são bem atribuídos. Podemos ver que, implementando a interface Modeldriven, podemos transportar facilmente parâmetros na URL. Em ação, precisamos apenas implementar o método getModel e retornar um novo objeto a ser usado. Neste ponto, é fácil pensar que definitivamente haverá muitos desses modelos em suportes que precisam ser obtidos; portanto, também precisamos extrair essa parte da base.
3.4 Extrair Model -Driven To Baseaction
Primeiro, adicionamos o código da parte do Model -Driven à Baseaction, como segue:
// Como existem muitos modelos diferentes que requerem o Modeldriven, usamos a classe pública genérica BaseAction <T> estende o Ações do suporte a implementos RequestAware, SessionAcare, ApplicationAware, Modeldriven <T> {mapa protegido <string, objeto> request; mapa protegido <string, objeto> sessão; mapa protegido <string, objeto> aplicativo; modelo t protegido; @Override public void Stapplication (map <string, object> Application) {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 () {// aqui, novo uma instância correspondente analisando o T passado. Classe clazz = (classe) type.getActualTyPearguments () [0]; tente {model = (t) clazz.newInstance (); } catch (Exceção e) {lança nova RunTimeException (e); } Modelo de retorno; }} Após a extração, o código na categoryAction diminuirá e diminuirá:
// herdam a base de bases e adicionam a categoria de classe pública genérica estende a base <category> {categoryService CategoryService; public void setCategoryService (categoryService CategoryService) {this.categoryService = categoryService; } public string update () {System.out.println ("---- Update ----"); categoryService.Update (Model); // Use o modelo retornar diretamente "índice"; } public string save () {System.out.println ("---- SALVA ----"); System.out.println (modelo); // Use o modelo diretamente para retornar "índice"; } public string query () {request.put ("categoryList", categoryservice.query ()); session.put ("categoryList", categoryService.Query ()); Application.put ("categoryList", categoryService.Query ()); retornar "índice"; }} Neste ponto, há outra coisa que não se sente bem com isso, que é a categoria Variável de membros, que sempre existiu na categoriaActionAction. Como a categoryAction usa métodos no objeto CategoryService, esse objeto deve ser criado e um método de conjunto pode ser injetado. Isso leva a uma desvantagem: se muitas ações precisarem usar o Service de Categorias, o método do objeto e do conjunto deverá ser criado em suas ações. Além disso, se vários objetos de serviço diferentes forem usados em uma ação, todos precisam ser criados, o que se torna muito complicado.
3.5 Extrair serviço para Baseation
Em resposta ao problema acima, extraímos todos os objetos de serviço no projeto para o Baseaction para criá -lo. Dessa forma, depois de outras ações herdarem bases, elas podem usar o serviço que desejam usar:
// Classifiquei o conteúdo na classe pública Baseaction Baseaction <T> estende o ACTIONSupport implementa o requestAware, sessionAWare, ApplicationAlare, Modeldriven <T> {// Service Object Protected CategoryService CategoryService; SERVIÇÃO DE CONTATOS DE CONTANTES DE PROTECIDA; public void setCategoryService (categoryService CategoryService) {this.categoryService = categoryService; } public void SetAccountService (AccountService) service) {this.accountService = service; } // mapa protegido pelo objeto de domínio <string, object> request; mapa protegido <string, objeto> sessão; mapa protegido <string, objeto> aplicativo; @Override public void Stapplication (map <string, object> Application) {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 modelddriven; @Override public t getModel () {parameterledType type = (parameterledType) this.getclass (). GetGenericsuperclass (); Classe clazz = (classe) type.getActualTyPearguments () [0]; tente {model = (t) clazz.newInstance (); } catch (Exceção e) {lança nova RunTimeException (e); } Modelo de retorno; }} Isso torna a categoryAction mais refrescante: a classe pública CategoryActionActionações estende o BaseAction <Category> {public String update () {System.out.println ("--- Update ----"); categoryService.Update (Model); retornar "índice"; } public string save () {System.out.println ("--- salvar ----"); System.out.println (modelo); retornar "índice"; } public string query () {request.put ("categoryList", categoryservice.query ()); session.put ("categoryList", categoryService.Query ()); Application.put ("categoryList", categoryService.Query ()); retornar "índice"; }} Algumas pessoas podem perguntar: não será redundante se tantos objetos de serviço forem injetados em bases? Isso não é verdade, porque mesmo que não esteja escrito no Baseation, o contêiner de mola criará esse objeto, o que não importa. Pelo contrário, o objeto de serviço é colocado em bases e é mais conveniente para o desenvolvimento de outras ações. Além disso, o Baseaction não precisa ser atribuído ao arquivo struts.xml, porque nenhum JSP solicitará bases, é apenas para outras ações herdadas.
Outra coisa a esquecer: isso é modificar a configuração em beans.xml:
<!-Se for um tipo de protótipo, é criado quando usado, não automaticamente ao iniciar-> <bean id = "Baseaction" scope = "prototype"> <propriedade name = "categoryService" ref = "categoryService"> </property> <nome da propriedade "" pai = "baseAction"/>
Adicione um novo feijão de bases, combine todos os objetos de serviço no projeto como propriedade e mate a propriedade na categoria original.
No futuro, se queremos escrever uma nova XXXACACTION, podemos herdar diretamente o Baseaction. Se um serviço for usado no xxxaction, podemos usá -lo diretamente. Só precisamos adicionar um feijão correspondente a xxxaction no arquivo beans.xml e configurar o salto no arquivo struts.xml.
4. Altere XML para anotação
Podemos ver que, à medida que o projeto fica cada vez maior, haverá cada vez mais configurações no Beans.xml, e muitas configurações são redundantes. Para facilitar o desenvolvimento, agora alteramos a configuração do XML em anotações. Vamos primeiro olhar para a configuração em beans.xml:
Estes são os grãos que escrevemos quando construímos o meio ambiente e os extraímos. Estes precisam ser convertidos em anotações. Vamos substituí -los por peça: primeiro substitua a peça de serviço, que possui três partes: BaseService, CategoryService e AccountService. Substitua o seguinte:
Em seguida, mate a parte correspondente em Beans.xml. Em seguida, modifique a parte da ação, principalmente bases, categoriaAction e AccountAction e substitua -a da seguinte forma:
Em seguida, mate a configuração da parte da ação no beans.xml e, finalmente, adicione a seguinte configuração ao arquivo beans.xml e você pode usar a anotação.
<Contexto: componente-Scan Base-Package = "CN.it.shop .."/>
Algumas pessoas podem perguntar: por que o serviço e a ação são diferentes ao usar anotações? @Service é usado no serviço e o @Controller é usado na ação? De fato, é o mesmo, apenas para distingui -los de diferentes camadas de feijão para facilitar a leitura.
O endereço de download do código -fonte de todo o projeto: //www.vevb.com/article/86099.htm
Endereço original: http://blog.csdn.net/eson_15/article/details/51297698
O exposto acima é o conteúdo inteiro da segunda batalha do projeto de shopping on -line da estrutura do SSH. Espero que seja útil para o aprendizado de todos, e espero que todos apoiem mais o wulin.com.