Estou projetando um aplicativo simples baseado na Web. Eu sou novo nesse domínio baseado na Web. Eu precisava de seu conselho sobre os padrões de design, como a responsabilidade deve ser distribuída entre os Servlets, os critérios para criar um novo Servlet, etc.
Na verdade, tenho poucas entidades na minha página inicial e, correspondendo a cada uma delas, temos poucas opções como adicionar, editar e excluir. Anteriormente, eu estava usando um Servlet por opções como Servlet1 para adicionar entidade1, Servlet2 para editar entidade1 e assim por diante e, dessa maneira, acabamos tendo um grande número de servlets.
Agora estamos mudando nosso design. Minha pergunta é como você escolhe exatamente como escolhe a responsabilidade de um servlet. Devemos ter um Servlet por entidade que processará todas as suas opções e encaminhará a solicitação para a camada de serviço. Ou devemos ter um servlet para toda a página que processará a solicitação de página inteira e depois a encaminhará para a camada de serviço correspondente? Além disso, o objeto de solicitação deve ser encaminhado para a camada de serviço ou não.
fonte
Respostas:
Um aplicativo da Web decente consiste em uma mistura de padrões de design. Vou mencionar apenas os mais importantes.
Padrão do Model View Controller
O padrão de design principal (arquitetural) que você deseja usar é o padrão Model-View-Controller . O Controlador deve ser representado por um Servlet que (in) cria / usa diretamente um Modelo e uma Visualização específicos com base na solicitação. O Modelo deve ser representado por classes Javabeanas. Isso geralmente é mais divisível no Modelo de Negócios, que contém as ações (comportamento) e no Modelo de Dados, que contém os dados (informações). A Visualização deve ser representada por arquivos JSP que têm acesso direto ao Modelo ( Dados ) pelo EL (Expression Language).
Depois, há variações baseadas em como as ações e os eventos são tratados. Os populares são:
MVC baseado em solicitação (ação) : este é o mais simples de implementar. O ( Negócios ) Modelo trabalha diretamente com
HttpServletRequest
eHttpServletResponse
objetos. Você precisa reunir, converter e validar os parâmetros de solicitação (principalmente) você mesmo. A View pode ser representada por HTML / CSS / JS simples e não mantém o estado entre solicitações. É assim que, entre outros, o Spring MVC , Struts and Stripes funciona.MVC baseado em componentes : isso é mais difícil de implementar. Mas você acaba com um modelo e uma visualização mais simples, nos quais toda a API Servlet "bruta" é abstraída completamente. Você não precisa reunir, converter e validar os parâmetros de solicitação. O Controller executa esta tarefa e define os parâmetros de solicitação reunidos, convertidos e validados no Modelo . Tudo o que você precisa fazer é definir métodos de ação que funcionem diretamente com as propriedades do modelo. A Visualização é representada por "componentes" no tipo de taglibs JSP ou elementos XML que, por sua vez, geram HTML / CSS / JS. O estado da vistapara os pedidos subsequentes é mantido na sessão. Isso é particularmente útil para eventos de conversão, validação e alteração de valor no servidor. É assim que, entre outros , JSF , Wicket e Play! trabalho.
Como observação lateral, hobbying com uma estrutura MVC doméstica é um exercício de aprendizado muito bom, e eu o recomendo desde que você o mantenha para fins pessoais / privados. Mas quando você se tornar profissional, é altamente recomendável escolher uma estrutura existente em vez de reinventar a sua. Aprender uma estrutura existente e bem desenvolvida leva menos tempo a longo prazo do que desenvolver e manter uma estrutura robusta.
Na explicação detalhada abaixo, restringirei-me a solicitar MVC baseado, pois é mais fácil de implementar.
Padrão do controlador frontal ( padrão do mediador )
Primeiro, a parte Controller deve implementar o padrão Front Controller (que é um tipo especializado de padrão Mediador ). Ele deve consistir em apenas um servlet que fornece um ponto de entrada centralizado de todas as solicitações. Ele deve criar o Modelo com base nas informações disponíveis pela solicitação, como pathinfo ou servletpath, o método e / ou parâmetros específicos. O modelo de negócios é chamado
Action
noHttpServlet
exemplo abaixo .A execução da ação deve retornar algum identificador para localizar a exibição. O mais simples seria usá-lo como nome do arquivo JSP. Mapeie este servlet em um específico
url-pattern
emweb.xml
, por exemplo/pages/*
,*.do
ou mesmo apenas*.html
.Em caso de prefixo-padrões como, por exemplo,
/pages/*
você poderia então invocar URL como http://example.com/pages/register , http://example.com/pages/login , etc e fornecer/WEB-INF/register.jsp
,/WEB-INF/login.jsp
com as ações POST GET apropriado e . As peçasregister
,login
etc, estão disponíveisrequest.getPathInfo()
como no exemplo acima.Quando você usa padrões de sufixo, como
*.do
,*.html
etc, pode chamar URLs como http://example.com/register.do , http://example.com/login.do , etc, e deve alterar o exemplos de código nesta resposta (também oActionFactory
) para extrair as partesregister
elogin
emrequest.getServletPath()
vez disso.Padrão de estratégia
O
Action
deve seguir o padrão de estratégia . Ele precisa ser definido como um tipo de resumo / interface que deve fazer o trabalho com base nos argumentos passados do método abstrato (essa é a diferença com o padrão de comando , em que o tipo de resumo / interface deve fazer o trabalho com base no argumentos passados durante a criação da implementação).Você pode tornar o
Exception
mais específico com uma exceção personalizada comoActionException
. É apenas um exemplo básico de kickoff, o resto é com você.Aqui está um exemplo de um
LoginAction
que (como o próprio nome diz) efetua login no usuário. Por suaUser
vez, é um modelo de dados . O View está ciente da presença doUser
.Padrão de método de fábrica
A
ActionFactory
deve seguir o padrão Factory Method . Basicamente, ele deve fornecer um método criacional que retorne uma implementação concreta de um tipo abstrato / interface. Nesse caso, ele deve retornar uma implementação daAction
interface com base nas informações fornecidas pela solicitação. Por exemplo, o método e pathinfo (o pathinfo é a parte após o contexto e o caminho do servlet na URL da solicitação, excluindo a cadeia de consulta).Por
actions
sua vez, deve haver alguma estática / em todo o aplicativo,Map<String, Action>
que contém todas as ações conhecidas. Cabe a você como preencher este mapa. Codificação rígida:Ou configurável com base em um arquivo de propriedades / configuração XML no caminho de classe: (pseudo)
Ou dinamicamente, com base em uma varredura no caminho de classe, para classes que implementam uma certa interface e / ou anotação: (pseudo)
Lembre-se de criar um "não fazer nada"
Action
para o caso em que não há mapeamento. Deixe, por exemplo, retornar diretamente orequest.getPathInfo().substring(1)
então.Outros padrões
Esses eram os padrões importantes até agora.
Para dar um passo adiante, você pode usar o padrão Facade para criar uma
Context
classe que, por sua vez, agrupa os objetos de solicitação e resposta e oferece vários métodos de conveniência para delegar aos objetos de solicitação e resposta e passar isso como argumento para oAction#execute()
método. Isso adiciona uma camada abstrata extra para ocultar a API Servlet bruta. Você deve basicamente terminar com zeroimport javax.servlet.*
declarações em todas asAction
implementações. Em termos de JSF, é isso que as classesFacesContext
eExternalContext
estão fazendo. Você pode encontrar um exemplo concreto nesta resposta .Depois, há o padrão State para o caso em que você deseja adicionar uma camada de abstração extra para dividir as tarefas de reunir os parâmetros de solicitação, convertê-los, validá-los, atualizar os valores do modelo e executar as ações. Em termos de JSF, é isso que
LifeCycle
está fazendo.Depois, há o padrão Composite para o caso em que você deseja criar uma visualização baseada em componente que pode ser anexada ao modelo e cujo comportamento depende do estado do ciclo de vida baseado em solicitação. Em termos JSF, é isso que
UIComponent
representa.Dessa forma, você pode evoluir pouco a pouco em direção a uma estrutura baseada em componentes.
Veja também:
fonte
web.xml
, então você pode usar umServletContextListener
para isso. Faça com que a fábrica o implemente (e registre-se como<listener>
emweb.xml
) e faça o trabalho de enchimento durante ocontextInitialized()
método.Action
implementação da mesma maneira que nos servlets normais (consulte também o wiki de servlets para obter um exemplo básico, que você pode refatorar ainda mais em algumaValidator
interface). Mas você também pode fazê-lo antes de invocar a ação, mas isso é mais complexo, pois exige que as regras de validação sejam conhecidas por visualização. JSF cobriu isso, oferecendorequired="true"
,validator="customValidatorName"
, etc na marcação XHTML.No padrão de MVC, o Servlet é "C" - controlador.
Sua principal tarefa é fazer a avaliação da solicitação inicial e, em seguida, despachar o processamento com base na avaliação inicial para o trabalhador específico. Uma das responsabilidades do trabalhador pode ser configurar alguns beans da camada de apresentação e encaminhar a solicitação para a página JSP para renderizar HTML. Portanto, apenas por esse motivo, você precisa passar o objeto de solicitação para a camada de serviço.
Porém, eu não começaria a escrever
Servlet
aulas brutas . O trabalho que eles fazem é muito previsível e padronizado, algo que o framework faz muito bem. Felizmente, existem muitos candidatos disponíveis e testados pelo tempo (em ordem alfabética): Apache Wicket , Java Server Faces , Spring , entre outros.fonte
IMHO, não há muita diferença no caso de aplicação web, se você olhar para ela do ângulo de atribuição de responsabilidade. No entanto, mantenha a clareza na camada. Mantenha qualquer coisa puramente para a finalidade da apresentação na camada de apresentação, como o controle e o código específico para os controles da Web. Apenas mantenha suas entidades na camada de negócios e todos os recursos (como adicionar, editar, excluir) etc. na camada de negócios. No entanto, renderizá-los no navegador para serem manipulados na camada de apresentação. Para .Net, o padrão ASP.NET MVC é muito bom em termos de manter as camadas separadas. Examine o padrão MVC.
fonte
Eu usei o framework struts e acho bastante fácil de aprender. Ao usar a estrutura do struts, cada página do seu site terá os seguintes itens.
1) Uma ação usada é chamada toda vez que a página HTML é atualizada. A ação deve preencher os dados no formulário quando a página é carregada pela primeira vez e manipula interações entre a interface da web da web e a camada de negócios. Se você estiver usando a página jsp para modificar um objeto java mutável, uma cópia do objeto java deve ser armazenada no formulário e não no original, para que os dados originais não sejam modificados, a menos que o usuário salve a página.
2) O formulário usado para transferir dados entre a ação e a página jsp. Este objeto deve consistir em um conjunto de getter e setters para atributos que precisam estar acessíveis para o arquivo jsp. O formulário também possui um método para validar dados antes que eles persistam.
3) Uma página jsp que é usada para renderizar o HTML final da página. A página jsp é um híbrido de HTML e tags struts especiais usadas para acessar e manipular dados no formulário. Embora o struts permita que os usuários insiram o código Java nos arquivos jsp, você deve ser muito cauteloso ao fazer isso, pois isso dificulta sua leitura. O código Java nos arquivos jsp é difícil de depurar e não pode ser testado em unidade. Se você estiver escrevendo mais de 4-5 linhas de código java dentro de um arquivo jsp, o código provavelmente deve ser movido para a ação.
fonte
A excelente resposta do BalusC cobre a maioria dos padrões para aplicativos da web.
Alguns aplicativos podem exigir Chain-of-responsável_pattern
Caso de uso para usar este padrão:
Quando o manipulador para processar uma solicitação (comando) é desconhecido e essa solicitação pode ser enviada para vários objetos. Geralmente você define o sucessor como objeto. Se o objeto atual não puder manipular a solicitação ou processá-la parcialmente e encaminhe a mesma solicitação ao objeto sucessor .
Perguntas / artigos úteis sobre SE:
Por que eu usaria uma Cadeia de Responsabilidade em vez de um Decorador?
Usos comuns para cadeia de responsabilidade?
padrão de cadeia de responsabilidade da oodesign
chain_of_responsibility da criação de código-fonte
fonte