Servlet único que recebe todas as requisições

Noite…

Estou com um projeto que utiliza servlet e jsp e queria a opinião de quem já utilizou algum mecanismo em um servlet para receber diversas requisições de mais de uma tela ou funcionalidade.
Na verdade é mais uma questão de design da aplicação. É comum ter um único servlet que receba, por exemplo, as requisições de diversos cadastros? E esse servlet seja “inteligente” para distribuir as chamadas para os métodos específicos?

Vi algo sobre front controller mas não saberia como aplicar!

Oque vc está querendo aplicar me parece ser um controlador.
Uma Servlet que vai receber as requisições e despachar para as respectivas classes que cuidam das regras de negócio.
Veja a apostila fj21 da caelum , no capítulo chamada MVC se não me engano (e se a apostila não foi alterada) tem uma explicação boa de como fazer seu próprio controlador.

O caminho é esse mesmo. O padrão Command é muito usado, para que você possa encaminhar a requisição para o serviço apropriado sem precisar fazer uma tonelada de if’s.

Usa um framework.

Sergio Possari,

como o mapleplayer falou, a caelum tem uma apostila de programação web que é muito boa para isso, quando precisei fazer meu projeto para a aula de Java ela me ajudou muito, a lógica que ele usaram foi a seguinte:

1 - Criaram um servlet e toda requisição era enviada para esse servlet,

2 - Colocaram dois parâmetros a mais o controller e a ação a ser tomada, por exemplo para inserir um produto, Controller: ProdutoController e Ação : inserir, dai você pode colocar uns if no seu código para ir para esses métodos ou usar reflexão (eu usei e acho o melhor jeito)

Tenha em mente dois padrões: Front Controller e Intercepting Filter.
Mas veja que, como alguns já falaram, alguns frameworks MVC já podem fazer isso pra você (implementando estes e outros padrões), e você pode ganhar também em mais aspectos: segurança, binding, etc etc etc.

Pessoal,

nesse semestre em meu trabalho de faculdade eu utilizei exatamente esse controlador que a apostila da caelum ensina, durante a apresentação me foi questionado se o fato de ter um único servlet, responsável por redirecionar as requisição, não poderia acarretar uma perda de desempenho, algum problema de gargalo caso o número de acessos fosse grande.
alguém já pensou nessa questão? Qual a opinião de vocês?

Não existe problema de desempenho, o servidor cria uma thread para cada solicitação utlizando o mesmo servlet.

Correto, mas também é preciso tomar cuidado para não abusar de variáveis de instância sincronizadas dentro dos métodos de tratamento de requisição, senão você cria um gargalo nessa variável.

Olá, só adicionando uma observação: não seria bem criar uma nova thread, mas sim alocar uma de possivelmente um pool de threads de tamanho limitado. Pois daí evitaria estouros de recurso…

Correto, mas também é preciso tomar cuidado para não abusar de variáveis de instância sincronizadas dentro dos métodos de tratamento de requisição, senão você cria um gargalo nessa variável.[/quote]

fois a respeito desse gargalo que o meu professor questinou… então, pode-se dizer que implementando o controlador corretamente não há risco de gargalo?

Cara que faz isso é o servidor automaticamente. Mas existe riscos sim você não pode usar nada sincronizado, pode ter problemas com estouro de memória se colocar muitos objetos na sessão.

Boa tarde… desviando um pouco do rumo que a discussão tomou…

Eu li os links que vocês passaram, de fato entendi a proposta do pattern… mas entre o “entender” e o “fazer” ainda existe uma grande lacuna.
Digamos que eu tenha um servlet, chamado “ServletController”, ele receberá todas as minhas requisições, TODAS.

Mas não vejo outra maneira de implementar isso sem encher o “ServletController” de if ou como mostra a apostila da caelum (reflexão).
Veja:

if(origemRequest == “material”) {
if(operacao == “listar”) {
…chama o que seria um Command ou Helper (pelo que eu entendi vendo a documentação), que faria o processamento, buscar as informações da base, etc…
}
} else if(origemRequest == “item”) {
if(operacao == “cadastrar”) {
… chama o Command/Helper… etc…
}
}
dispatch()…

Dessa forma eu estaria atendendo ao Front Controller?
Eu queria fazer algo sem precisar fazer incluir ou alterar os if/else, como eu vi na documentação:

// Use a helper object to gather parameter
// specific information.
RequestHelper helper = new RequestHelper(request);
Command cmdHelper= helper.getCommand();
// Command helper perform custom operation
page = cmdHelper.execute(request, response);

Só que não faço a mínima idéia de como ficaria o código.
O que é o RequestHelper e o Command no exemplo, são classes da própria API do Servlet?

São muitas dúvidas, eu sei…

Obrigado!

Command é um design pattern

O Struts 1.3 faz exatamente o que você quer, sem usar ifs…

Você pode baixar o fonte na url http://struts.apache.org/download.cgi#struts1310.

Tipicamente, para se livrar dos ifs, o pessoal utiliza a capacidade de reflection do java, e um mecanismo de mapeamento para recuperar a instância correta.

Por exemplo, nós podemos fazer algo assim, no java.

package xxx;
public interface MinhaInterface {

	void doSomething();

}
package yyy;
import xxx.MinhaInterface;

public class MinhaImplementacao implements MinhaInterface{

	public void doSomething() {
	
		System.out.println("Done!");
	}

Um arquivo de configuração: myprops.properties

algumacoisa=yyy.MinhaImplementacao

Meu código que consegue instanciar a classe MinhaImplementacao com base no arquivo de configuração

package zzz;
import xxx.MinhaInterface;
public class FacoTudo {
	static Properties p = new Properties();
	public static void getInstance(String nome) throws Exception {
		p.load(new FileReader("myprops.properties"));
		String classname = p.getProperty(nome);
		Class c = Class.forName(classname);
		MinhaInterface i = (MinhaInterface)c.newInstance();
		i.doSomething(); //vai fazer o que MinhaImplementação faz, se chamar getInstance("algumacoisa")
	}
}

Nota: é claro que esse código é absurdamente simplista e não contém nenhuma segurança. É só para ilustrar o conceito…