在第一次完成spirngmvc代码的基础上:
开始时代码
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <body> <h2>Hello World!</h2> <%--href="some"时是到发布的项目目录下找:访问网址是http://localhost/springmvc/some href="/some"是直接到服务器下找:访问网址是http://localhost/some--%> <a href="some.do">请求</a> </body> </html>
web.xml
<!--中央调度器--> <servlet> <servlet-name>springmvc</servlet-name> <!--写的那个servlet--> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <!--servlet的映射路径 :是jsp通过这个路径请求后,再通过springmvc找servlet-class是谁--> <!--写”/“会把所有的静态请求都交给中央调度器,所以如果ggg.html也会给handler,会发生找不到404的错误,不建议使用--> <!--如果写”/*“的话,会把所有的请求都交给中央调度器,包括动态index.jsp,所以不能使用--> <!--用*.do或者*.go可以解决这个问题:1.让提交请求的路径后面加上.do 例如:<a href="some.do"> 2.在注册的时候也写上"/请求路径.do" 3.<url-pattern>*.do</url-pattern> 即所有后缀为.do的请求都可以被中央调度器接收了,不加就不用接收了--> <!----> <url-pattern>*.do</url-pattern> </servlet-mapping>
springmvc.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!--注册处理器:bean的id必须以"/"开头,因为id是一个路径--> <!--<bean id="/some.do" class="com.abc.handler.SomeHandler"/>--> <!--注册组件扫描器--> <context:component-scan base-package="com.abc.handler"/> <!--一开始只设置注册组件扫描器,和在handler上加一个注解@Controller,运行点击请求报错404。因为请求会通过xml给中央调度器,中央调度器servlet会根据/some,再找SomeHandler, 但是现在虽然扫描到base-package="com.abc.handler",但是你配置处理器SomeHandler具体的名字(你还没有告诉系统),还有该处理器内方法的名字(一个处理器内可以有好几个名字), --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean> </beans>
SomeHandler.java
import org.springframework.stereotype.Controller; import org.springframework.web.servlet.ModelAndView; /*import org.springframework.web.servlet.mvc.Controller;*/ /* * @Service:service * @Controller:处理器 * @Respostory:dao * 和@Component:功能相同,意义不同 * * */ //0. /*1.用注解不需要实现Controller接口了 2.用接口时导入的包删掉,改为注解的包 3.不用接口了,handleRequest方法不用重写了,方法名随意写,返回值类型不变 4. */ @Controller public class SomeHandler { public ModelAndView doFirst(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception { ModelAndView mv = new ModelAndView(); //setViewName:响应视图叫什么名字,这个名字应该写相对于webapp路径下的名称(发布到服务器时项目的根目录) mv.setViewName("welcome"); mv.addObject("message","helloSpringMvc"); return mv; } }
一开始只设置注册组件扫描器,和在handler上加一个注解@Controller,就运行点击请求报错404。因为请求会通过xml给中央调度器,中央调度器servlet会根据/some,再找SomeHandler,
但是现在虽然扫描到base-package="com.abc.handler",但是你配置处理器SomeHandler具体的名字(你还没有告诉系统),还有该处理器内方法的名字(一个处理器内可以有好几个名字),
接着我在SomeHandler处理器内@Controller后面加上("/some.do"),如下
@Controller("/some.do") public class SomeHandler {...
结果报错:
HTTP Status 500 – Internal Server Error
Type 异常报告
消息 No adapter for handler [com.abc.handler.SomeHandler@3bdc7430]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler
中央调度器调度的时候需要包含一个的适配器支持这个处理器。这个时候是因为适配器找不到SomeHandler.java类中的方法doFirst(),这个时候适配器适配不了这个handler,因为没有正确的方法响应了
这个时候应该给出方法的路径,需要在方法上进行配置:
@RequestMapping("/some.do") 请求映射(根据请求的路径/some.do可以映射到doFirst方法):如果是/some.do的时候就找到doFirst方法了
修改后代码如下:
@Controller public class SomeHandler { //请求映射:如果是/some.do的时候就找到doFirst方法了 @RequestMapping("/some.do") public ModelAndView doFirst(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception { ModelAndView mv = new ModelAndView(); //setViewName:响应视图叫什么名字,这个名字应该写相对于webapp路径下的名称(发布到服务器时项目的根目录) mv.setViewName("welcome"); mv.addObject("message","helloSpringMvc"); return mv; } }
点击,成功访问。
(为什么不加注解的时候可以找到对应的方法呢,因为那个时候的代码如下:
public class SomeHandler implements Controller{ @Override public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception { ModelAndView mv = new ModelAndView(); //setViewName:响应视图叫什么名字,这个名字应该写相对于webapp路径下的名称(发布到服务器时项目的根目录) mv.setViewName("welcome"); mv.addObject("message","helloSpringMvc"); return mv; } }
SomeHandler实现了Servlet类中的Controller接口,并用了特定的方法名 handleRequest,而现在两者都没有了)。
接着又出现下一个问题,如果有两个handler里方法前面都加上了注解@RequestMapping("/some.do"),那么中央调度器会在handler对象里根据/some.do找出两个不同处理器中的两个方法,
会报错:to { /some.do}: There is already 'someHandler' bean method,加了namespace解决,代码:
@Controller @RequestMapping("/sss") public class xxxHandler { //此时这个some在这个sss命名空间起作用了 @RequestMapping("/some.do") public ModelAndView aaa(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception { return null; } }
@Controller @RequestMapping("/some") //命名空间 public class SomeHandler { //请求映射:如果是/some.do的时候就找到doFirst方法了 //此时这个some在这个规定的/some命名空间起作用, @RequestMapping("/some.do") public ModelAndView doFirst(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception { ModelAndView mv = new ModelAndView(); //setViewName:响应视图叫什么名字,这个名字应该写相对于webapp路径下的名称(发布到服务器时项目的根目录) mv.setViewName("welcome"); mv.addObject("message","helloSpringMvc"); return mv; } }
给handler类加一个限制,起一个命名空间,为了避免方法的路径重复。
另外要把index.jsp里的请求路径修改为:<a href="${pageContext.request.contextPath}/some/some.do">请求</a>,不加会404报错。
现在改需求:现在是/some.do可以访问dofirst()方法,我想再发个fistdo请求也使用dofirst()方法由它来响应。
其实@RequestMapping("/some.do"),方法的path里value()是string[]类型,所以可以写成这样实现@RequestMapping({"/some.do","first.do"})
用注解实现一个方法给多个请求响应,实现多个请求访问一个handler类里的不同响应方法:
@Controller @RequestMapping("/some") //命名空间,相当于该类的代名词为some public class SomeHandler { //请求映射:如果是/some.do的时候就找到doFirst方法了 //此时这个some在这个规定的/some命名空间起作用, @RequestMapping({"/some.do","first.do"}) public ModelAndView doFirst(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception { ModelAndView mv = new ModelAndView(); //setViewName:响应视图叫什么名字,这个名字应该写相对于webapp路径下的名称(发布到服务器时项目的根目录) mv.setViewName("welcome"); mv.addObject("message","helloSpringMvc"); return mv; } //一个处理类内可以定义多个处理方法 @RequestMapping("/doSecond.do") public ModelAndView doSecond(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception { ModelAndView mv = new ModelAndView(); //setViewName:响应视图叫什么名字,这个名字应该写相对于webapp路径下的名称(发布到服务器时项目的根目录) mv.setViewName("welcome"); mv.addObject("message","hello"); return mv; } }