Solucionado (ver solução)
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

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software