SpringMvc json中文变成?的解决办法 设置mvc编码

SpringMvc处理json中文乱码解决方案
当前端发送ajax请求到后端获取商品数据时,发现商品名称中的中文显示为问号。问题定位在后端,尝试通过设置servletResponse编码未成功。解决方法包括在请求映射注解中添加字符编码,配置SpringMVC的StringHttpMessageConverter,或者实现WebMvcConfigurer并添加messageConverter。

场景描述:
前端发送ajax请求向后台查询商品数据,得到数据后将商品信息加入到页面中。

$.ajax({
                url: url,
                type: "get",
                data: dataObject,
                //traditional: true,
                dataType: "json",
                success: function (data) {
                    console.log(data);
                },
                error: function () {

                }
            });

出现了商品名称中的中文变成?的现象。猜测是编码问题。
通过浏览器控制台得知接收到的json数据的中文就是问号,问题发生在后端。
编写filter设置servletResponse的编码,没能解决问题

import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(value="/*")//拦截所有请求和响应
@Component
public class ServletFilter implements Filter {


    @Override
   //初始化方法
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //统一处理请求和响应的乱码
        servletRequest.setCharacterEncoding("UTF-8");
        servletResponse.setCharacterEncoding("UTF-8");
        //过滤完之后需要放行请求和响应
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    //销毁方法
    public void destroy() {

    }
}

解决方法:

1.在请求映射的注解中添加 produces="application/json;charset=utf-8" 如:

    @ResponseBody
    @GetMapping(value="/product/{index}/{count}"
            ,produces = "application/json;charset=utf-8"
    )
    public String getProductBySearch(@RequestParam(required = false) String product_name/* 产品名称 */,
       JSONObject object = new JSONObject();
       //object.put(...,...);
       return object,toJSONString();
    }

这种方法需要改动多个请求映射的注解
2.在springMVC里配置StringHttpMessageConverter

<mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                    <value>application/json;charset=UTF-8</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

3.写配置类,实现WebMvcConfigurer,添加messageConverter

@Configuration
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        WebMvcConfigurer.super.configureMessageConverters(converters);
        StringHttpMessageConverter converter = new StringHttpMessageConverter();
        converter.setDefaultCharset(StandardCharsets.UTF_8);
        converters.add(converter);
    }
}
<think>好的,用户问为什么有了Servlet还要用Spring MVC来替代,Servlet相比有什么缺点,以及Spring MVC怎么解决的。首先,我需要回顾Servlet和Spring MVC的基本概念和它们之间的关系。Servlet是Java处理Web请求的基础技术,但直接使用Servlet开发复杂的应用可能会比较繁琐,需要处理很多底层细节,比如请求分发、参数解析、视图渲染等。而Spring MVC是基于Servlet的一个框架,提供了更高层次的抽象,简化了开发流程。 用户可能是在学习Java Web开发时,对这两者的关系不太清楚,或者在实际项目中遇到了使用Servlet的痛点,想了解Spring MVC的优势。需要明确的是,Spring MVC并不是完全替代Servlet,而是构建在Servlet之上,利用Servlet API,但通过封装和扩展,提供了更便捷的开发模式。 接下来要分析Servlet的缺点。首先,Servlet的配置比较繁琐,每个Servlet都需要在web.xml中配置URL映射,当应用规模大时,管理起来麻烦。其次,处理请求参数时,需要手动从HttpServletRequest中获取参数,进行类型转换,容易出错。第三,视图解析和渲染需要自己处理,比如转发到JSP或者生成JSON响应,代码重复且不够灵活。另外,Servlet在实现MVC架构时,需要开发者自行设计控制器、模型和视图的分层,缺乏统一的规范,可能导致代码结构混乱。 Spring MVC如何解决这些问题呢?首先,它通过注解(如@Controller、@RequestMapping)简化了控制器的配置,无需在XML中逐个注册,提高了开发效率。其次,提供了强大的参数绑定机制,自动将请求参数转换为方法参数,支持各种数据类型的转换,减少了样板代码。视图解析方面,Spring MVC支持多种视图技术,如JSP、Thymeleaf、FreeMarker等,并且可以轻松配置视图解析器,简化视图层的开发。此外,Spring MVC天然集成Spring框架,可以利用依赖注入、AOP等特性,方便管理组件和增强功能。 用户可能存在的深层需求是希望了解如何选择技术栈,或者在项目中如何权衡使用Servlet和Spring MVC。需要强调Spring MVC在开发效率、维护性、扩展性上的优势,特别是在中大型项目中的价值。同时,也要指出Servlet作为基础技术的重要性,Spring MVC是基于Servlet的,理解Servlet有助于更好地使用和调试Spring MVC。 可能的误区是认为Spring MVC完全取代了Servlet,但实际上它是对Servlet的增强。需要澄清两者的关系,Spring MVC的核心DispatcherServlet本身就是一个Servlet,负责请求的分发和处理,但通过框架提供的各种组件,简化了开发流程。此外,对于非常简单的应用,直接使用Servlet可能更轻量,但复杂度上升后,Spring MVC的优势会更明显。 总结回答时需要结构清晰,先解释Servlet的缺点,再说明Spring MVC的解决方案,最后强调两者的适用场景和关系,帮助用户全面理解。</think>在 Java Web 开发中,Servlet 是处理 HTTP 请求和响应的基础技术,而 Spring MVC 是基于 Servlet 的框架,通过封装和扩展解决了 Servlet 在开发复杂应用时的诸多痛点。以下是具体对比和解决方案: --- ### **1. Servlet 的局限性** #### **(1)开发效率低** - **手动处理请求分发**:每个 Servlet 需在 `web.xml` 中配置 URL 映射,导致配置冗余。 ```xml <!-- web.xml 中配置多个 Servlet --> <servlet> <servlet-name>UserServlet</servlet-name> <servlet-class>com.example.UserServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>UserServlet</servlet-name> <url-pattern>/user</url-pattern> </servlet-mapping> ``` - **重复代码多**:获取请求参数、转换数据类型、渲染视图等操作需手动实现。 #### **(2)缺乏 MVC 分层支持** - **职责混乱**:Servlet 既处理业务逻辑,又直接操作响应(如 `response.getWriter().write()`),违反单一职责原则。 ```java public class UserServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { // 处理业务逻辑 String userId = request.getParameter("id"); User user = userService.findById(userId); // 直接渲染视图 response.getWriter().write("<html><body>User: " + user.getName() + "</body></html>"); } } ``` #### **(3)参数绑定复杂** - **手动解析参数**:需从 `HttpServletRequest` 中逐个提取参数并转换类型。 ```java int age = Integer.parseInt(request.getParameter("age")); // 可能抛出 NumberFormatException ``` #### **(4)视图管理困难** - **硬编码视图路径**:转发到 JSP 或模板引擎时需手动拼接路径。 ```java request.getRequestDispatcher("/WEB-INF/views/user.jsp").forward(request, response); ``` --- ### **2. Spring MVC 的解决方案** #### **(1)简化配置** - **注解驱动**:通过 `@Controller` 和 `@RequestMapping` 自动映射 URL,无需 XML 配置。 ```java @Controller public class UserController { @GetMapping("/user") public String getUser(Model model, @RequestParam("id") String userId) { User user = userService.findById(userId); model.addAttribute("user", user); return "user"; // 自动解析为视图名(如 user.jsp) } } ``` #### **(2)清晰的 MVC 分层** - **职责分离**: - **控制器(Controller)**:处理请求,调用业务逻辑。 - **模型(Model)**:封装数据。 - **视图(View)**:渲染页面(如 JSP、Thymeleaf)。 ```java @GetMapping("/user/{id}") public String getUser(@PathVariable String id, Model model) { User user = userService.findById(id); model.addAttribute("user", user); // 数据传递到视图 return "user"; // 视图名称(由视图解析器处理) } ``` #### **(3)自动参数绑定** - **支持多种参数类型**:自动将请求参数、路径变量、表单数据等绑定到方法参数。 ```java // 自动将请求参数转换为对象 @PostMapping("/user") public String createUser(@ModelAttribute User user) { userService.save(user); return "redirect:/users"; } ``` #### **(4)灵活的视图解析** - **视图解析器**:统一管理视图路径,支持多种模板引擎。 ```java // 配置 Thymeleaf 视图解析器 @Bean public ThymeleafViewResolver thymeleafViewResolver() { ThymeleafViewResolver resolver = new ThymeleafViewResolver(); resolver.setTemplateEngine(templateEngine()); resolver.setCharacterEncoding("UTF-8"); return resolver; } ``` #### **(5)集成 Spring 生态** - **依赖注入(DI)**:通过 `@Autowired` 管理组件依赖。 - **AOP 支持**:统一处理日志、事务、安全等横切关注点。 - **数据验证**:结合 `@Valid` 注解自动校验参数。 ```java @PostMapping("/user") public String createUser(@Valid @ModelAttribute User user, BindingResult result) { if (result.hasErrors()) { return "error"; } userService.save(user); return "redirect:/users"; } ``` --- ### **3. 核心对比:Servlet vs Spring MVC** | **场景** | **Servlet** | **Spring MVC** | |-------------------------|--------------------------------------------|---------------------------------------------| | **请求分发** | 手动配置 `web.xml`,每个 URL 对应一个 Servlet | 通过 `@RequestMapping` 自动映射到控制器方法 | | **参数绑定** | 手动从 `request` 中提取并转换类型 | 自动绑定到方法参数(支持对象、JSON、文件上传)| | **视图渲染** | 硬编码 JSP 路径或直接输出响应流 | 通过视图解析器统一管理,支持多种模板引擎 | | **异常处理** | 需在 `try-catch` 中处理异常 | 全局异常处理器(`@ExceptionHandler`) | | **代码复用** | 重复编写参数解析、视图跳转代码 | 拦截器(`HandlerInterceptor`)和 AOP 切面 | --- ### **4. 实际案例** #### **Servlet 实现用户查询** ```java public class UserServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { String userId = request.getParameter("id"); User user = userService.findById(userId); request.setAttribute("user", user); request.getRequestDispatcher("/WEB-INF/views/user.jsp").forward(request, response); } } ``` #### **Spring MVC 实现相同功能** ```java @Controller public class UserController { @GetMapping("/user") public String getUser(@RequestParam("id") String userId, Model model) { User user = userService.findById(userId); model.addAttribute("user", user); return "user"; // 视图解析器自动查找 /WEB-INF/views/user.jsp } } ``` --- ### **5. 总结** - **Servlet 的定位**:是 Java Web 的底层标准,适合简单场景或学习底层原理。 - **Spring MVC 的优势**: - **开发效率**:通过注解和自动化减少冗余代码。 - **可维护性**:清晰的 MVC 分层和组件化设计。 - **扩展性**:无缝集成 Spring 生态(安全、事务、数据访问等)。 - **适用场景**: - 小型工具类应用:可直接使用 Servlet。 - 中大型企业应用:优先选择 Spring MVC
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值