Exibir cidade ao selecionar estado

Olá a todos do fórum.

Acho que minha situação deve ser comum mas eu já procurei aqui no fórum por uma resposta e não achei. Se puderem me ajudar.

Eu tenho um formulário de cadastro onde o usuário tem que selecionar o estado e então selecionar a cidade que pertence ao estado selecionado.

segue o código do form abaixo:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ page import="java.util.ArrayList" %>
<%@ page import="classe.modelo.vo.Municipio"%>
<%@ page import="classe.modelo.dao.MunicipioDao"%>
<%! ArrayList<Municipio> listMunicipio = null;%>
<%  listMunicipio = MunicipioDao.listarCategoria(); %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<jsp:include page="menu.jsp" />
        <fieldset>
            <h2> Informações do Usuário</h2>
            <!-- Colocar imagem para cadastro de usuarios           -->
            <!--            <center><img id="photo_compagny" src="images/business_7.jpg" alt="company xhdzy" title="photo_compagny" /></center>
                        <div class="clear"></div><br>-->
            <form method="post" action="ServletUsuario?acao=Cadastrar">
                <fieldset>
                    <legend>Informações pessoais</legend>
                    <br />
                    <table cellpadding=0 cellspacing=0  border="0">
                        <tr>
                            <td>Nome completo: </td>
                            <td><input type="text" name="nome" required="true" size="50"></td>

                        </tr>
                        <tr>
                            <td>Login: </td>
                            <td><input type="text" name="login" required="true" ></td>
                        </tr>
                        <tr>
                            <td>Senha: </td>
                            <td><input type="password" name="senha" required="true"></td>
                        </tr>
                        <tr>
                            <td>Status do Usuário: </td>
                            <td><input type="radio" name="sts" value="AT" />Ativo
                                <input type="radio" name="sts" value="IN" />Inativo</td>
                        </tr>
                        <tr>
                            <td>Endereço de E-Mail: </td>
                            <td><input type="text" name="email" required="true"></td>
                        </tr>
                        <tr>
                            <td>Telefone de Contato: </td>
                            <td><input type="text" name="telefone" required="true"></td>
                        </tr>
                        <tr>
                            <td>Cpf: </td>
                            <td><input type="text" name="cnpjCpf" required="true"></td>
                        </tr>
                        <tr>
                            <td>RG: </td>
                            <td><input type="text" name="rg" required="true"></td>
                        </tr>

                    </table>
                </fieldset>
                <br>
                <fieldset>
                    <legend>Endereço</legend>
                    <table cellpadding=0 cellspacing=0 border="0">
                        <tr>
                            <td>Rua: </td>
                            <td><input type="text" name="rua" required="true" size="50"></td>
                        </tr>
                        <tr>
                            <td>Complemento: </td>
                            <td><input type="text" name="complemento" size="50"></td>
                        </tr>
                        <tr>
                            <td>Número: </td>
                            <td><input type="text" name="numero" size="50"></td>
                        </tr>
                        <tr>
                            <td>Bairro: </td>
                            <td><input type="text" name="bairro" size="50"></td>
                        </tr>
                        <tr>
                           //select com a lista dos estados
                            <td>Estado: </td>
                            <td><select name="uf" required="true">
                                    <option value="0"></option> 
                                    <% for(int i=0;i < listestado.size();i++){%>
                                    <option value="<%=listestado.get(i).getId()%>"><%=listestado.get(i).getDescricao()%></option>
                                    <%} %>
                                </select></td>
                        </tr>
                        //select com a lista de cidades de vários estados já cadastradas no bd
                        <tr>
                            <td>Município: </td>
                            <td><select name="municipio" required="true">
                                    <option value="0"></option> 
                                    <% for(int i=0;i < listmunicipio.size();i++){%>
                                    <option value="<%=listmunicipio.get(i).getId()%>"><%=listmunicipio.get(i).getDescricao()%></option>
                                    <%} %>
                                </select></td>
                        </tr>
                        <tr>
                            <td>Cep: </td>
                            <td><input type="text" name="cep"></td>
                        </tr>
                        <tr>
                            <td  valign="top">Observação: </td>
                            <td height="52" valign="bottom"><textarea name="obs"></textarea></td>
                        </tr>
                    </table>
                </fieldset>
                <table cellpadding=0 cellspacing=0 style="width:100%;height:100%;" border="0">
                    <tr>
                        <td colspan="2" align="center"><input  type="submit" name="salvar" value="Salvar"/></td>
                        <td colspan="2" align="center"><input  type="reset" name="reset" value="Cancelar"/></td>
                        <td colspan="2" align="center"><input  type="button" name="btn" onclick="window.location.href='menu.jsp'" value="Home"/></td>
                    </tr>
                </table>
            </form>
        </fieldset>
</body>
</html>

Como faço para que ao selecionar o estado, o select das cidades contenha somente as cidades pertencente ao estado selecionado?
Eu vi um exemplo com a query dentro do jsp mas isto é errado.

eu fiz isso no meu tcc, mas não lembro de cabeça como, me envia um email (ta no perfil) e eu te envio o codigo que fiz à noite.

nesse post eu coloquei uma possível solução => http://www.guj.com.br/java/261878-select-list-dinamico

o que eu fiz foi ± o seguinte:
no jsp:

<select id="estado" onChange="prencherCidade(this.value);" disabled="true">
                        </select>

no javascript:

function prencherCidade(estado) {
    var xmlHttp = funcaoAjax();
    xmlHttp.onreadystatechange=function() {
        if(xmlHttp.readyState==4) {
            if (xmlHttp.status == 200) {//verifica o status da requisição
                var retorno = eval('(' + xmlHttp.responseText + ')');
                prencheCidade(retorno);
            }
        }
    }
    xmlHttp.open("POST","CINovoParticipante?funcao=2&valor="+estado,true);
    xmlHttp.send(null);
}

no Java:

protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        request.setCharacterEncoding("UTF-8");
        PrintWriter out = response.getWriter();
        String funcao = request.getParameter("funcao");
        if (funcao.equalsIgnoreCase("2")) {
            String valor = request.getParameter("valor");
            carregarCidades(out, valor);
        } 
    }
private void carregarCidades(PrintWriter out, String valor) {
        try {
            int i = 0;
            int idEstado = Integer.parseInt(valor);
            AplNovoParticipante apl = new AplNovoParticipante();
            Estado estado = apl.buscaEstado(idEstado);
            ArrayList<Cidade> cidades = null;
            cidades = apl.buscaCidades(estado);
            JSONArray arrayJsonCidades = new JSONArray();
            JSONObject jsonCidade2 = new JSONObject();
            jsonCidade2.put("nome", "Selecione");
            arrayJsonCidades.put(0, jsonCidade2);
            while (i < cidades.size()) {
                JSONObject jsonCidade3 = new JSONObject();
                jsonCidade3.put("nome", cidades.get(i).getNome());
                jsonCidade3.put("id", cidades.get(i).getIdCidade());
                arrayJsonCidades.put(i + 1, jsonCidade3);
                i++;

            }
            System.out.println(arrayJsonCidades);//imprime array de cidades
            JSONObject retorno = new JSONObject();
            retorno.put("cidades", arrayJsonCidades);
            System.out.println(retorno);
            out.print(retorno);//retorno
        } catch (Exception ex) {
        } finally {
            out.close();
        }
    }

esta é uma das formas que achei na época, cabe lembrar que esta não é a única nem a melhor. Melhor seria por exemplo usar frameworks que facilitam a implementação como spring por exemplo.