个人建议重新练习一遍搭建的过程,如果感觉麻烦你可以直接复制上一个工程,但是需要修改pom.xml中的一点信息
<groupId>com.hanpang.springmvc</groupId> <artifactId>springmvc-demo02</artifactId> <version>0.0.1-SNAPSHOT</version>
看下面的代码,我设置了相同的路径,那么会有说明错误呢?请自己查看控制台信息
package com.hanpang.web; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; @Controller//告知其是一个控制器 @RequestMapping("/cms") public class Demo05Controller { @RequestMapping(value="/user") public ModelAndView test01() { System.out.println("用于获取用户信息"); return null; } @RequestMapping(value="/user") public ModelAndView test02() { System.out.println("用于修改用户信息"); return null; } }
错误信息如下:
Caused by: java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'demo05Controller' method public org.springframework.web.servlet.ModelAndView com.hanpang.web.Demo05Controller.test02() to {[/cms/user]}: There is already 'demo05Controller' bean method public org.springframework.web.servlet.ModelAndView com.hanpang.web.Demo05Controller.test01() mapped.
在一个控制器名字叫demo05Controller的中有一个映射路径"/cms/user"对应了两个方法,属于模糊映射
如果出现了这样的情况或者需求,如何处理呢? 我们可以设置requestMethod来区别相同路径的不同处理方式
可以通过设置method设置可以处理,个人推荐这种方式.
package com.hanpang.web; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; @Controller//告知其是一个控制器 @RequestMapping("/cms") public class Demo05Controller { @RequestMapping(value="/user",method=RequestMethod.GET) public ModelAndView test01() { System.out.println("用于获取用户信息"); return null; } @RequestMapping(value="/user",method=RequestMethod.POST) public ModelAndView test02() { System.out.println("用于修改用户信息"); return null; } }
启动正常,区分你的请求方式执行相应的方法
HTTP Method Conversion A key principle of REST is the use of the Uniform Interface. This means that all resources (URLs) can be manipulated using the same four HTTP methods: GET, PUT, POST, and DELETE. For each method, the HTTP specification defines the exact semantics. For instance, a GET should always be a safe operation, meaning that is has no side effects, and a PUT or DELETE should be idempotent, meaning that you can repeat these operations over and over again, but the end result should be the same. While HTTP defines these four methods, HTML only supports two: GET and POST. Fortunately, there are two possible workarounds: you can either use JavaScript to do your PUT or DELETE, or simply do a POST with the 'real' method as an additional parameter (modeled as a hidden input field in an HTML form). This latter trick is what Spring’s HiddenHttpMethodFilter does. This filter is a plain Servlet Filter and therefore it can be used in combination with any web framework (not just Spring MVC). Simply add this filter to your web.xml, and a POST with a hidden _method parameter will be converted into the corresponding HTTP method request.
来自官网的处理方案
REST的一个关键原则是使用统一接口。这意味着所有资源(url)都可以使用相同的4个HTTP方法进行操作:GET、PUT、POST和DELETE。对于每个方法,HTTP规范定义了精确的语义。例如,GET应该始终是一个安全的操作,这意味着没有副作用,PUT或DELETE应该是幂等的,这意味着您可以一次又一次地重复这些操作,但是最终结果应该是相同的。虽然HTTP定义了这四种方法,但是HTML只支持两种方法:GET和POST。幸运的是,有两种可能的解决方案:要么使用JavaScript进行PUT或DELETE,要么使用“real”方法作为附加参数(将其建模为HTML表单中的隐藏输入字段)。后一种技巧是Spring的HiddenHttpMethodFilter所做的。这个过滤器是一个普通的Servlet过滤器,因此它可以与任何web框架(不仅仅是Spring MVC)结合使用。只需将这个过滤器添加到您的web中。xml,以及带有隐藏方法参数的POST将被转换成相应的HTTP方法请求。
Spiring Web MVC 中提供了八种请求方式,但是常用的是官方推荐的四种,分别是
(1) 测试代码如下
package com.hanpang.web; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; @Controller//告知其是一个控制器 @RequestMapping("/cms") public class Demo05Controller { @RequestMapping(value="/user",method=RequestMethod.GET) public ModelAndView test01() { System.out.println("用于获取用户信息"); return null; } @RequestMapping(value="/user",method=RequestMethod.POST) public ModelAndView test02() { System.out.println("用于添加用户信息"); return null; } @RequestMapping(value="/user",method=RequestMethod.PUT) public ModelAndView test03() { System.out.println("用于修改用户信息"); return null; } @RequestMapping(value="/user",method=RequestMethod.DELETE) public ModelAndView test04() { System.out.println("用于删除用户信息"); return null; } }
(2) 配置HiddenHttpMethodFilter过滤器
package com.hanpang.config; import javax.servlet.Filter; import org.springframework.web.filter.HiddenHttpMethodFilter; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class[] {WebConfig.class}; } @Override protected Class<?>[] getServletConfigClasses() { return null; } @Override protected String[] getServletMappings() { return new String[] {"/"}; } //看这里重写方法,新增过滤器 @Override protected Filter[] getServletFilters() { HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter(); return new Filter[] {hiddenHttpMethodFilter}; } }
<?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_ID" version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" > <filter> <filter-name>httpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>httpMethodFilter</filter-name> <!-- 请注意这里Servlet过滤器 --> <servlet-name>mvc</servlet-name> </filter-mapping> <servlet> <servlet-name>mvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>mvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>default.jsp</welcome-file> </welcome-file-list> </web-app>
(3)使用Postman测试
POST是真正的请求方式,传递一个"_method"名的参数,赋值为PUT或者DELETE(不区分大小写),看控制台执行的方法