Solucionado (ver solução)

Importante

Você está vendo a versão anterior da nova experiência da Alura que estamos preparando para você. Em breve, ela ganha uma identidade visual novinha totalmente pensada em potencializar seus estudos!

Solucionado
(ver solução)
16
respostas

UTF-8 no OSX - Resolvido Definitivo

Olá,

Gostaria de um apoio para configurar corretamente o "encoding" da minha aplicação. Informo que realizei várias tentativas e não obtive sucesso.

1 - Criei o filtro exatamente como explicado no vídeo; 2 - Adicionei nos Connectors do serve.xml do Tomcat

URIEncoding="UTF-8" useBodyEncodingForURI="true"

3 - Adicionei no formulário

accept-charset="UTF-8"

4 - Adicionei no UsuarioController

@RequestMapping(value= "/usuario", produces = "text/plain;charset=UTF-8")

5 - Adicionei no AppWebConfiguration no resolver

resolver.setContentType("text/html; charset=UTF-8");

6 - Adicionei no ServletSpringMVC no getServletFilters

encodingFilter.setForceEncoding(true);

Nenhuma tentativa acima funcionou.

OBSERVAÇÃO 1 - Se mudo o método de envio do form para GET funciona certinho; 2 - Convertendo na mão funciona também

String nome = new String(usuario.getNome().getBytes("ISO-8859-1"), "UTF-8"); 
usuario.setNome(nome);

Aguardo possíveis ajudas.

Grato,

Edney

16 respostas

Edney, essa string usuario está vindo do banco? o problema popde e deve estar vindo de la, precisando setar a string de conexao com o banco falando que voce quer utf8, alem de verificar se o seu mysql está rodando em utf8

Oi Paulo, o problema não é com o banco não, eu usei essa maneira manual de converter só para testar e confirmar que o problema é que o objeto enviado via post pelo meu formulário já chega no controller com o encode errado. O teste que confirma que o problema é a submissão do formulário via POST foi o fato de eu submeter o formulário via GET e o controller já recebe tudo certinho.

Assim dá erro

<form:form data-toggle="validator" servletRelativeAction="/usuario" role="form" method="POST" accept-charset="UTF-8">

Assim funciona

<form:form data-toggle="validator" servletRelativeAction="/usuario" role="form" method="GET" accept-charset="UTF-8">

dá uma olhada no html que está sendo gerado para os dois e cola aqui pra gente? tanto a tag do form quanto o header falando que é utf8

O html gerado formulário com POST

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>xxx</title>
      <link href="https://fonts.googleapis.com/css?family=Lato:700" rel="stylesheet">
    <link rel="stylesheet" type="text/css" href="/srun/resources/css/normalize.css">
    <link rel="stylesheet" type="text/css" href="/srun/resources/css/bootstrap.min.css">
    <link rel="stylesheet" type="text/css" href="/srun/resources/css/bootstrap-theme.min.css">
    <link rel="stylesheet" type="text/css" href="/srun/resources/css/carousel.css">
      <link rel="stylesheet" type="text/css" href="/srun/resources/css/custom.css">
      <link rel="stylesheet" type="text/css" href="/srun/resources/css/testimonials.css">
      <link rel="stylesheet" type="text/css" href="/srun/resources/css/bootstrap-select.min.css">
      <link rel="stylesheet" type="text/css" href="/srun/resources/css/dataTables.bootstrap.min.css">
      <link rel="stylesheet" type="text/css" href="/srun/resources/css/owlcarouselcss/owl.carousel.min.css">
      <link rel="stylesheet" type="text/css" href="/srun/resources/css/owlcarouselcss/owl.theme.default.min.css">
</head>
</head>
<body>
.
.
.
<form id="command" data-toggle="validator" role="form" accept-charset="UTF-8" action="/srun/usuario" method="POST">
                          <div class="form-group has-feedback">
                            <label for="email" class="control-label">Nome Completo</label>
                            <input type="text" class="form-control" id="nome" placeholder="Nome" name="nome"  data-error="Nome não pode ser vazio" required>
                            <span class="glyphicon form-control-feedback" aria-hidden="true"></span>
                            <div class="help-block with-errors"></div>
                        </div>
                          <div class="form-group has-feedback">
                            <label for="email">Email</label>
                            <div class="input-group">
                              <span class="input-group-addon">@</span>
                              <input type="email" class="form-control" id="email" placeholder="Email" name="email" data-error="Email inválido" required>
                            </div>
                            <span class="glyphicon form-control-feedback" aria-hidden="true"></span>
                            <div class="help-block with-errors"></div>
                        </div>

                        <div class="form-group">

                            <div class="form-inline row">
                                <div class="form-group has-feedback col-md-3">
                                    <label for="password" class="control-label">Password</label>
                                    <input type="password" data-minlength="6" class="form-control" id="password" placeholder="Senha" name="senha" required>
                                    <div class="help-block">Mínimo de 6 caracteres</div>
                                  </div>
                                  <div class="form-group has-feedback col-md-3">
                                    <label for="passwordconfirm" class="control-label">Confirmar</label>
                                    <input type="password" class="form-control" id="passwordconfirm" data-match="#password" 
                                    data-match-error="Confirmação não confere com a senha" placeholder="Confirmar Senha" data-error="Confirmação não pode ser vazio" required>
                                    <div class="help-block with-errors"></div>
                                  </div>

                        <button type="submit" class="btn btn-warning-custom">Cadastrar <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span></button>
                      <div>
<input type="hidden" name="_csrf" value="b70f6921-fac8-4cea-ba72-9b2427cb438c" />
</div></form>
.
.
.

O html gerado com o método GET no form

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>xxx</title>
     <link href="https://fonts.googleapis.com/css?family=Lato:700" rel="stylesheet">
    <link rel="stylesheet" type="text/css" href="/srun/resources/css/normalize.css">
    <link rel="stylesheet" type="text/css" href="/srun/resources/css/bootstrap.min.css">
    <link rel="stylesheet" type="text/css" href="/srun/resources/css/bootstrap-theme.min.css">
    <link rel="stylesheet" type="text/css" href="/srun/resources/css/carousel.css">
      <link rel="stylesheet" type="text/css" href="/srun/resources/css/custom.css">
      <link rel="stylesheet" type="text/css" href="/srun/resources/css/testimonials.css">
      <link rel="stylesheet" type="text/css" href="/srun/resources/css/bootstrap-select.min.css">
      <link rel="stylesheet" type="text/css" href="/srun/resources/css/dataTables.bootstrap.min.css">
        <link rel="stylesheet" type="text/css" href="/srun/resources/css/owlcarouselcss/owl.carousel.min.css">
      <link rel="stylesheet" type="text/css" href="/srun/resources/css/owlcarouselcss/owl.theme.default.min.css">
</head>
</head>
<body>
.
.
.
<form id="command" data-toggle="validator" role="form" accept-charset="UTF-8" action="/srun/usuario" method="GET">
                          <div class="form-group has-feedback">
                            <label for="email" class="control-label">Nome Completo</label>
                            <input type="text" class="form-control" id="nome" placeholder="Nome" name="nome"  data-error="Nome não pode ser vazio" required>
                            <span class="glyphicon form-control-feedback" aria-hidden="true"></span>
                            <div class="help-block with-errors"></div>
                        </div>
                          <div class="form-group has-feedback">
                            <label for="email">Email</label>
                            <div class="input-group">
                              <span class="input-group-addon">@</span>
                              <input type="email" class="form-control" id="email" placeholder="Email" name="email" data-error="Email inválido" required>
                            </div>
                            <span class="glyphicon form-control-feedback" aria-hidden="true"></span>
                            <div class="help-block with-errors"></div>
                        </div>

                        <div class="form-group">

                            <div class="form-inline row">
                                <div class="form-group has-feedback col-md-3">
                                    <label for="password" class="control-label">Password</label>
                                    <input type="password" data-minlength="6" class="form-control" id="password" placeholder="Senha" name="senha" required>
                                    <div class="help-block">Mínimo de 6 caracteres</div>
                                  </div>
                                  <div class="form-group has-feedback col-md-3">
                                    <label for="passwordconfirm" class="control-label">Confirmar</label>
                                    <input type="password" class="form-control" id="passwordconfirm" data-match="#password" 
                                    data-match-error="Confirmação não confere com a senha" placeholder="Confirmar Senha" data-error="Confirmação não pode ser vazio" required>
                                    <div class="help-block with-errors"></div>
                                  </div>

                        <button type="submit" class="btn btn-warning-custom">Cadastrar <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span></button>
                      <div>
</div></form>
.
.
.

Eliminei alguns campos do formulário para simplificar .

caramba, nao consigo nem chutar uma possibilidade. ja to querendo culpar a versao do springmvc. é a ultima?

nao tem filtro nenhum, certo?

e faça um debug no chrome e veja se está sendo enviado utf8 ou latin1, pra tentar descobrir quem ta errado: front ou back

outra coisa

voce tem esse filtro?

 <filter>
     <filter-name>EncodingFilter</filter-name>
     <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
     <init-param>
         <param-name>encoding</param-name>
         <param-value>UTF-8</param-value>
     </init-param>
     <init-param>
         <param-name>forceEncoding</param-name>
         <param-value>true</param-value>
     </init-param>
 </filter>

public class ServletSpringMVC extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
        encodingFilter.setEncoding("UTF-8");
        encodingFilter.setForceEncoding(true);

        return new Filter[] {encodingFilter};
    }

form com GET

Request URL:http://localhost:8080/srun/usuario?nome=T%C3%AAnis+cora%C3%A7%C3%A3o+d%C3%BAvida&email=acneubarth%40hotmail.com&senha=123456&idade=45&telefone=33&camisa=XP
Request Method:GET
Status Code:302 Found
Remote Address:[::1]:8080
Response Headers
view source
Cache-Control:no-cache, no-store, max-age=0, must-revalidate
Content-Language:pt-BR
Content-Length:0
Date:Thu, 23 Feb 2017 14:35:31 GMT
Expires:0
Location:/srun/usuario-list
Pragma:no-cache
Server:Apache-Coyote/1.1
X-Content-Type-Options:nosniff
X-Frame-Options:DENY
X-XSS-Protection:1; mode=block
Request Headers
view source
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:pt-BR,pt;q=0.8,en-US;q=0.6,en;q=0.4
Cache-Control:no-cache
Connection:keep-alive
Cookie:JSESSIONID=3511028A9CE004203B02364BFE279527
Host:localhost:8080
Pragma:no-cache
Referer:http://localhost:8080/srun/usuario-form
Upgrade-Insecure-Requests:1
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Query String Parameters
view source
view URL encoded
nome:Tênis coração dúvida
email:acneubarth@hotmail.com
senha:123456
idade:45
telefone:33
camisa:XP

form com POST

Request URL:http://localhost:8080/srun/usuario
Request Method:POST
Status Code:302 Found
Remote Address:[::1]:8080
Response Headers
view source
Cache-Control:no-cache, no-store, max-age=0, must-revalidate
Content-Language:pt-BR
Content-Length:0
Date:Thu, 23 Feb 2017 14:41:30 GMT
Expires:0
Location:/srun/usuario-list
Pragma:no-cache
Server:Apache-Coyote/1.1
X-Content-Type-Options:nosniff
X-Frame-Options:DENY
X-XSS-Protection:1; mode=block
Request Headers
view source
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip, deflate, br
Accept-Language:pt-BR,pt;q=0.8,en-US;q=0.6,en;q=0.4
Cache-Control:no-cache
Connection:keep-alive
Content-Length:176
Content-Type:application/x-www-form-urlencoded
Cookie:JSESSIONID=3511028A9CE004203B02364BFE279527
Host:localhost:8080
Origin:http://localhost:8080
Pragma:no-cache
Referer:http://localhost:8080/srun/usuario-form
Upgrade-Insecure-Requests:1
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Form Data
view source
view URL encoded
nome:Tênis coração dúvida
email:edneydasilvasouza@gmail.com
senha:123456
idade:23
telefone:1232075712
camisa:XP
_csrf:97ad30cb-4ca0-4464-ac7e-469d3999d5b3

é. estou sem ideias. mas eu iria debugar o chrome e ver o que está sendo enviado para tentar isolar o problema. e depois ate tiraria esse filtro dai.

caramba, no front ta certo! tente entao tirar esse seu filtro do spring.

vc percebeu que não tem um valor

content-type:text/html;charset=UTF-8

no site do alura aparece essa propriedade e na minha requisição ela não existe, estranho não?

pois é, mas o seu front parece que está certo, ja que voce debugou. to perdido mesmo. tente sem os filtros.

e esse header ai do response é para a renderizacao da pagina, nao para o request que voce recebera os dados, entao acho que nao resolveria

cara, problemas com encoding sao sempre os mais complciados de achar, e é uma virgula em algum lugar que ta fazendo o post ser convertido em latin1

solução!

Olá Paulo, consegui resolver o problema. De qualquer forma obrigado pelo seu apoio.

Encontrei artigo explicando o problema.

https://wiki.apache.org/tomcat/FAQ/CharacterEncoding#Q1

A partir de uma certa versão do Tomcat os filtros foram incorporados no core, então bastaria fazer as configurações corretas sem a necessidade de criar um filtro particular. O que ocorre é que o tomcat estava convertendo uma vez e meu filtro estava convertendo mais uma vez. Então voltei nos vídeos do curso e percebi que o professor Paulo Alves Jr colocou ISO-8859-1 no jsp da tag

<%@ tag language="java" pageEncoding="ISO-8859-1"%>

fiz o mesmo e funcionou perfeitamente.

antes estava assim

<%@ tag language="java" pageEncoding="UTF-8"%>

Obrigado mais uma vez pela atenção dada.

Grato, Edney

Alarme falso, fiz um clean no projeto e o problema voltou.

Neste link comenta que devo colocar a configuração do Encode antes de qualquer outro filtro, porém não sei como fazer isso pois os meus filtros não são mapeados por xml e sim programaticamente, ou seja, na classe java como faço para ele chamar o filtro do Encode antes de qualquer outro filtro ?

https://wiki.apache.org/tomcat/FAQ/CharacterEncoding#Q1

oi Edney

Voce pode mapear os filtros no web.xml dentro de WEB-INF e colocar na ordem que quiser:

 <filter>
     <filter-name>EncodingFilter</filter-name>
     <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
     <init-param>
         <param-name>encoding</param-name>
         <param-value>UTF-8</param-value>
     </init-param>
     <init-param>
         <param-name>forceEncoding</param-name>
         <param-value>true</param-value>
     </init-param>
 </filter>

Resolvido definitivamente,

Eu não tenho um arquivo web.xml, todas as minhas configurações são feitas em classes java.

Por isso descobri como colocar para chamar o filtro do Encode antes do filtro do security.

@Override
    protected void beforeSpringSecurityFilterChain(ServletContext servletContext) {
        FilterRegistration.Dynamic characterEncodingFilter = servletContext.addFilter("encodingFilter", new CharacterEncodingFilter());
        characterEncodingFilter.setInitParameter("encoding", "UTF-8");
        characterEncodingFilter.setInitParameter("forceEncoding", "true");
        characterEncodingFilter.addMappingForUrlPatterns(null, false, "/*");
    }

Está funcionando perfeitamente agora.

Grato, Paulo