Spring MVC 02:MVC的使用与接收参数
示例程序:HelloWorld(xml形式)
1.新建一个maven工程 : webapp
2.配置pom.xml依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.2.13.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.13.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.13.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.13.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.2.13.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.2.13.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.2.13.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.0</version>
</dependency>
<!--jsp的支持-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
3.在Java目录下写Controller:HelloWorldController
package cn.silverCorridors;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HelloWorldController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
System.out.println("Hello,Spring MVC world"); // 控制台输出信息
return new ModelAndView("/Jsp/HelloWorld.jsp"); // 向browser返回这个目录下的jsp文件
}
}
4.注册处理器:在resources目录下配置SpringMVC.xml
<beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:context = "http://www.springframework.org/schema/context"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc = "http://www.springframework.org/schema/mvc"
xsi:schemaLocation = "
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<bean name="/hello" class="cn.silverCorridors.HelloWorldController"></bean>
</beans>
5.配置中央调度器web.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<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>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
在<servlet/>中添加<Load-on-startup/>的作用是,,标记是否在Web服务器(这里是Tomcat) 启动时会创建这个 Servlet 实例,即是否在 Web 服务器启动时调用执行该 Servlet 的 init()方法,而不是在真正访问时才创建。它的值必须是一个整数。
- 当值大于等于 0 时,表示容器在启动时就加载并初始化这个 servlet,数值越小,该 Servlet的优先级就越高,其被创建的也就越早;
- 当值小于 0 或者没有指定时,则表示该 Servlet 在真正被使用时才会去创建。
- 当值相同时,容器会自己选择创建顺序。
对于<url-pattern/>,可以写为 / ,建议写为*.do 的形式。
6.在webapp下新建一个Jsp文件夹,创建HelloWorld.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
Hello,Spring MVC World JSP!
输出结果

示例程序:HelloWorld(annotation形式)
注册组件扫描器: 指定处理器所在的包
注册视图解析器:ResourceViewResolver,指定视图所在位置
<beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:context = "http://www.springframework.org/schema/context"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc = "http://www.springframework.org/schema/mvc"
xmlns:p = "http://www.springframework.org/schema/p"
xsi:schemaLocation = "
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<!--扫描包-->
<context:component-scan base-package="cn.silverCorridors"></context:component-scan>
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 配置视图 前缀:prefix 后缀:suffix-->
<property name="prefix" value="/Jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
- @Controller:表示当前类为处理器
- @RequestMapping:表示当前方法为处理器方法。该方法要对 value 属性所指定的 URI 进行处理与响应。被注解的方法的方法名可以随意。通过@RequestMapping 注解可以定义处理器对于请求的映射规则。该注解可以注解在方法上,也可以注解在类上,但意义是不同的。value 属性值常以“/”开始,也可不加“/”。
在类上使用@RequestMapping(掌握)
@RequestMapping 的 value 属性用于定义所匹配请求的 URI。但对于注解在方法上与类上,其 value 属性所指定的 URI,意义是不同的。
一个@Controller 所注解的类中,可以定义多个处理器方法。当然,不同的处理器方法所匹配的 URI 是不同的。这些不同的 URI 被指定在注解于方法之上的@RequestMapping 的value 属性中。但若这些请求具有相同的 URI 部分,则这些相同的 URI,可以被抽取到注解在类之上的@RequestMapping 的 value 属性中。此时的这个 URI 表示模块的名称。URI 的请求是相对于 Web 的根目录。
换个角度说,要访问处理器的指定方法,必须要在方法指定 URI 之前加上处理器类前定义的模块名称。
Model 中的数据存储在 request 作用域中,SringMVC 默认采用转发的方式跳转到视图,本次请求结束,模型中的数据被销毁。若有多个请求路径均可匹配该处理器方法的执行,则@RequestMapping 的 value 属性中可以写上一个数组。
package cn.silverCorridors;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
@RequestMapping(value = "/helloworld2") // 类级别注解
public class HelloWorld2 {
//@RequestMapping(value = "/helloworld2/hello2")
@RequestMapping(value = "/hello2",method = {RequestMethod.POST,RequestMethod.GET},params = {"a=5"}) // method:设置可接受访问请求的类型,params设置参数(访问时必须要加参数)
public String sayHello() {
System.out.println("Hello, Spring MVC world2");
return "HelloWorld"; // 前缀 后缀不用写,视图解析器帮你找
}
//@RequestMapping(value = "/helloworld2/hello3")
@RequestMapping(value = "/hello3")
public String sayHello2() {
System.out.println("Hello, Spring MVC world3");
return "HelloWorld"; // 前缀 后缀不用写,视图解析器帮你找
}
}
问题:利用PostMan发送POST请求中的中文乱码
package cn.silverCorridors;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/param")
public class Parameters {
// /param/test1?a=5&b=6&c=888.0
@RequestMapping("/test1")
public String test1(String a, String b, String c) {// 获取请求访问中的参数,自动匹配
System.out.println("test1()");
System.out.println("a=" + a);
System.out.println("b=" + b);
System.out.println("c=" + c);
return "HelloWorld";
}
// /param/test2?a=5&b=6&c=888.0
@RequestMapping("/test2")
public String test2(Pabc pabc) {// 自动组装
System.out.println("test2()");
System.out.println(pabc);
return "HelloWorld";
}
// /param/test3?a=5&b=true&c=888.6
@RequestMapping("/test3")
public String test2(Integer a, Boolean b, Double c) {// 自动组装
System.out.println("test2()");
System.out.println("a = " + a);
System.out.println("b = " + b);
System.out.println("c = " + c);
return "HelloWorld";
}
// /param/test4?a=5&b=6&c=888.0&pd.d1=aaa&pd.d2=bbb
@RequestMapping("/test4")
public String test4(Pabc1 pabc) {// 自动组装
System.out.println("test4()");
System.out.println(pabc);
return "HelloWorld";
}
}


可以看到输出结果中出现了中文的乱码问题。
解决办法:通过filter实现URI编码转换
在web.xml中添加filter、filterMapping
<filter>
<filter-name>characterEncodingFilter</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>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern><!-- 所有目录下都执行这个filter -->
</filter-mapping>
问题解决:

请求中写集合对象的格式: List/Map的例子
/param/test4?a=5&b=6&c=888.0&pd.d1=aaa&pd.d2=b56b&listPd[0].d1=d1d1&listPd[0].d2=aabb&listPd[1].d1=5656&listPd[1].d2=132421&MapPd[one].d1=asdf&MapPd[one].d2=aaadf
自定义转换器
例如在请求方法中我们需要传递一个Date类型的数据
@RequestMapping("/test6")
public String test5(Date a) {
System.out.println("test6()");
System.out.println(a);
return "HelloWorld";
}
在postman里发送请求发现只能按照特定格式输入

我们通过配置Converter来解决这个问题
Converter格式:
package cn.silverCorridors;
import org.springframework.core.convert.converter.Converter;
// S为转换前,T为转换后
public class SpringToDateConverter implements Converter<S,T> {
@Override
public T convert(S s) {
return null;
}
}
具体的类:SpringToDateConverter
public class SpringToDateConverter implements Converter<String,Date> {
@Override
public Date convert(String s) {
if (null == s){
throw new RuntimeException("s cannot be null.");
}
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
try {
return df.parse(s);
} catch (ParseException e) {
e.printStackTrace();
throw new RuntimeException("Parse Error!");
}
}
}
将Converter配置到SpringMVC.xml
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="cn.silverCorridors.SpringToDateConverter"></bean>
</set>
</property>
</bean>
<!-- 通知给MVC配置了conversion-->
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
此时配置成功

