springmvc项目中无法访问@controller中的方法,报错404

本文介绍了一种常见的前端向后端发送AJAX请求时出现404错误的原因及解决方案。通过添加@ResponseBody注解,成功将接口返回值从视图路径更改为实际数据。

项目场景:

提示:关于前端发送JSON格式的数据


问题描述

提示:在前端往后端发送AJAX时,发现无法访问到后端@controller中的接口,出现404报错

@Controller    
@RequestMapping("/json")  
public class JsonController {    
    @RequestMapping("/test2")
    public String addUser(@RequestBody UserVo userVo){
        System.out.println(userVo);
        return "ok";
    }

原因分析:

提示:接口的返回值为String,这代表返回的为视图或者相对路径的接口,而我的项目中不存在ok的视图或“ok“的接口方法,所以出现了404。而在项目 中我想要的是返回”ok"字符串的值,如果要想返值的话,就必须加上@ResponseBody注解,这样才代表返回的为数据。



解决方案:

解决方法:在具体的接口上加上@ResponseBody注解即可
@Controller   
@RequestMapping("/json") 
public class JsonController {
    @RequestMapping("/test2")
    @ResponseBody     //增加这个注解,让其返回值为数据
    public String addUser(@RequestBody UserVo userVo){
        System.out.println(userVo);
        return "ok";
    }

<think>我们正在解决用户关于SpringMVC@Controller注解返回值无法进行视图解析的问题。用户提供的引用内容展示了@Controller的基本用法和视图解析机制,以及可能出现的异常处理方式。现在,我们需要系统地分析视图解析失败的原因和解决方案。根据引用[1][2][3]:-@Controller注解的控制器方法通常返回字符串,该字符串对应视图名称(如"success"),视图解析器会将其解析为具体视图路径(如/WEB-INF/pages/success.jsp)-视图解析器配置示例(引用[3]):```xml<beanid="viewResolver"class="org.springframework.web.servlet.view.InternalResourceViewResolver"><propertyname="prefix"value="/WEB-INF/pages/"/><propertyname="suffix"value=".jsp"/></bean>```-若返回值为void,则需手动处理请求(引用[4]),如转发、重定向或直接输出常见视图解析问题及解决方案:###一、视图解析失败的症状1.**返回视图名称但显示404页面**-控制台无报错,但浏览器显示4042.**控制台报错"Couldnotresolveview"**-明确提示找不到视图3.**返回字符串被直接输出到响应体**-浏览器显示的是视图名称字符串(如"success")而非渲染后的页面###二、根本原因分析(附解决方案)####原因1:视图解析器未配置或配置错误-**检测点**:检查Spring配置文件中是否声明了`InternalResourceViewResolver`-**解决方案**:确保正确配置前缀(prefix)和后缀(suffix)```xml<!--正确配置示例(XML)--><beanclass="org.springframework.web.servlet.view.InternalResourceViewResolver"><propertyname="prefix"value="/WEB-INF/views/"/><!--实际路径需匹配项目结构--><propertyname="suffix"value=".jsp"/></bean>```>**关键细节**:>-路径区分大小写(Linux环境下)>-使用`classpath:`前缀访问资源(如`value="classpath:/templates/"`)####原因2:视图文件路径错误-**检测点**:物理文件是否存在于解析后的路径?示例:返回`"home"`→解析为`/WEB-INF/views/home.jsp`→检查该文件是否存在-**解决方案**:1.核对视图解析器前缀/后缀2.核对项目目录结构3.使用绝对路径测试(临时方案):```java@GetMapping("/test")publicStringtest(){return"/WEB-INF/views/home.jsp";//绕过视图解析器直接指定完整路径}```####原因3:方法意外添加了@ResponseBody-**现象**:返回的视图名称字符串被直接输出到响应体-**根源**:方法或类被错误添加了`@ResponseBody`(或类被误标为`@RestController`)-**解决方案**:```java@Controller//确保类注解是@Controller而非@RestControllerpublicclassMyController{@GetMapping("/page")publicStringshowPage(){return"page";//正常返回视图名称}//避免在需要视图解析的方法上使用@ResponseBody//@ResponseBody//如果存在则删除//publicStringapi(){...}}```####原因4:请求处理方法返回void但未手动处理-**场景**:方法返回void且未调用转发/重定向(引用[4]示例)-**解决方案**:二选一1.**改为返回视图名称字符串**```java@RequestMapping("/voidFix")publicStringfixVoid(){return"targetPage";}```2.**手动处理请求**(适用于需要直接操作响应时)```java@RequestMapping("/manual")publicvoidmanualHandle(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{//方案1:转发request.getRequestDispatcher("/WEB-INF/views/target.jsp").forward(request,response);//方案2:重定向(注意路径不带上下文)response.sendRedirect(request.getContextPath()+"/other-url");}```###三、调试视图解析流程启用SpringMVC日志可追踪解析过程:```properties#application.propertieslogging.level.org.springframework.web.servlet=DEBUG```典型成功日志:```DEBUGo.s.w.s.v.InternalResourceViewResolver-Viewname'home'resolvedtoInternalResourceViewDEBUGo.s.w.s.DispatcherServlet-Renderingview[org.springframework.web.servlet.view.JstlView]```###四、进阶:多视图解析器冲突当配置多个视图解析器时,需通过`order`属性控制优先级:```xml<beanclass="org.springframework.web.servlet.view.XmlViewResolver"p:order="1"/><!--高优先级--><beanclass="org.springframework.web.servlet.view.InternalResourceViewResolver"p:order="2"/><!--低优先级(必须设更高order值)-->```>**原理**:InternalResourceViewResolver应设为最低优先级,因为它的`resolveViewName()`永远返回非null值。###五、SpringBoot的特殊配置SpringBoot自动配置的视图解析规则:```properties#默认前缀:classpath:/templates/#默认后缀:.htmlspring.mvc.view.prefix=/WEB-INF/views/spring.mvc.view.suffix=.jsp```>**注意**:若使用Thymeleaf等模板引擎,需移除JSP解析器配置。---###修复流程图```mermaidgraphTDA[视图解析失败]-->B{检查控制台日志}B-->|有错误|C[根据错误信息修复]B-->|无错误|D[检查视图解析器配置]D-->E[核对前缀/后缀与实际路径]E-->F[检查物理文件是否存在]F-->G[检查方法是否含@ResponseBody]G-->H[检查类注解是否为@RestController]H-->I[确认返回void时是否手动处理]I-->J[启用DEBUG日志追踪]```§§相关问题§§1.SpringBoot中如何配置Thymeleaf视图解析器替代JSP?2.如何为同一个SpringMVC应用配置多套视图解析规则?3.视图解析器如何处理国际化(i18n)视图?4.当使用JSP和JSONAPI混合开发时,如何避免视图解析冲突?5.InternalResourceViewResolver与ResourceBundleViewResolver有什么区别?</think>### 解决 Spring MVC `@Controller` 返回值视图解析问题 在 Spring MVC 中使用 `@Controller` 时,视图解析失败通常由以下原因引起。以下将结合您的引用内容进行系统分析并提供解决方案: --- #### 一、核心问题分析 1. **视图解析器未正确配置** - 未配置 `ViewResolver` 或路径错误(引用[3]) - 示例配置: ```xml <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/pages/"/> <property name="suffix" value=".jsp"/> </bean> ``` - **错误现象**: 返回 `"login"` → 期望路径 `/WEB-INF/pages/login.jsp`,但实际未解析[^3] 2. **返回值类型处理错误** - 返回 `String` 但期望视图时,未经过视图解析器 - 返回 `void` 时未手动处理响应(引用[4]) 3. **注解使用冲突** - 意外添加 `@ResponseBody` 导致跳过视图解析 - 错误使用 `@RestController`(本质是 `@Controller` + `@ResponseBody`) --- #### 二、解决方案指南 ##### 场景1:返回视图名称但未解析 **问题代码**: ```java @Controller public class LoginController { @GetMapping("/login") public String getLogin() { return "login"; // 期望解析为 /WEB-INF/pages/login.jsp } } ``` **修复步骤**: 1. **检查视图解析器配置** 确保 `prefix` 和 `suffix` 与实际路径匹配: ```xml <!-- 正确示例 --> <property name="prefix" value="/WEB-INF/views/"/> <!-- 路径末尾必须有/ --> <property name="suffix" value=".jsp"/> ``` 2. **验证物理文件存在** ```bash src └── main └── webapp └── WEB-INF └── views └── login.jsp # 必须存在 ``` 3. **启用调试日志** 在 `application.properties` 中添加: ```properties logging.level.org.springframework.web.servlet=DEBUG ``` 查看日志确认解析路径: ``` DEBUG ViewResolver= - View name 'login' resolved to /WEB-INF/views/login.jsp ``` ##### 场景2:返回 `void` 时未处理响应 **问题代码**: ```java @GetMapping("/void") public void handleVoid() { // 无任何响应处理 } ``` **解决方案**(引用[4]): ```java @GetMapping("/void") public void handleVoid(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { // 方案1:手动转发(跳过视图解析器) request.getRequestDispatcher("/WEB-INF/pages/target.jsp").forward(request, response); // 方案2:直接输出内容 response.setContentType("text/html"); response.getWriter().println("<h1>Hello World</h1>"); // 方案3:重定向 response.sendRedirect("/new-url"); } ``` ##### 场景3:意外添加 `@ResponseBody` **错误示例**: ```java @Controller public class HybridController { @ResponseBody // 导致跳过视图解析 @GetMapping("/page") public String getPage() { return "home"; // 直接输出字符串"home" } } ``` **修复**:移除 `@ResponseBody` 注解 --- #### 三、最佳实践 1. **统一视图解析规则** ```java // 返回逻辑视图名 → 自动拼接物理路径 @GetMapping("/dashboard") public String dashboard() { return "admin/dashboard"; // → /WEB-INF/views/admin/dashboard.jsp } ``` 2. **显式转发/重定向** ```java // 手动控制跳转(无需视图解析器) @GetMapping("/redirect") public String redirect() { return "redirect:/new-url"; // 重定向 } @GetMapping("/forward") public String forward() { return "forward:/internal-page"; // 服务器转发 } ``` 3. **混合使用策略** ```java @Controller public class MultiController { // 返回视图 @GetMapping("/page") public String page() { return "page"; } // 返回JSON数据 @ResponseBody @GetMapping("/data") public Data getData() { ... } } ``` --- #### 四、调试流程图 ```mermaid graph TD A[控制器返回字符串] --> B{是否含 redirect/forward?} B -->|是| C[执行重定向或转发] B -->|否| D[视图解析器处理] D --> E[拼接 prefix + 视图名 + suffix] E --> F{物理文件是否存在?} F -->|是| G[渲染视图] F -->|否| H[抛出 404 错误] ``` --- #### 五、常见错误总结 | **问题现象** | **根本原因** | **解决方案** | |----------------------------|------------------------------|--------------------------------| | 返回字符串被直接输出 | 类/方法添加了 `@ResponseBody` | 移除 `@ResponseBody` | | 控制台报错 View not found | 视图文件缺失或路径错误 | 检查 `prefix/suffix` 和物理路径 | | 返回 void 时浏览器无响应 | 未手动处理 HttpServletResponse | 添加转发/重定向/直接输出逻辑 | | 重定向后 URL 不变 | 使用转发(forward)而非重定向 | 改用 `redirect:` 前缀 | > **关键原则**: > - 需要 HTML 页面渲染 → 返回字符串 + 正确视图解析器配置 > - 需要直接控制响应 → 使用 `HttpServletResponse` 或返回 `void` > - 避免在视图控制器中使用 `@ResponseBody`
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值