SpringMVC详解一、@RequestMapping注解与Controller接收参数

1SpringMVC的概述

2SpringMVC的核心DispatcherServlet程序

3SpringMVC的示例程序

4、视图解析器

5@RequestMapping注解详解标注在方法上

6Controller中如何接收请求参数


1SpringMVC的概述

Spring MVC框架是一个开源的Java平台,为开发强大的基于JavaWeb应用程序提供全面的基础架构支持非常容易和非常快速。

Spring web MVC框架提供了MVC(模型 - 视图 - 控制器)架构和用于开发灵活和松散耦合的Web应用程序的组件。 MVC模式导致应用程序的不同方面(输入逻辑,业务逻辑和UI逻辑)分离,同时提供这些元素之间的松散耦合。

· 模型(Model)封装了应用程序数据,通常它们将由POJO类组成。

· 视图(View)负责渲染模型数据,一般来说它生成客户端浏览器可以解释HTML输出。

· 控制器(Controller)负责处理用户请求构建适当的模型,并将其传递给视图进行渲染。

这里的控制器和servlet功能是一样的 ,

Servlet:接收请求参数→封装成JavaBean对象模型,只不过这里spring帮我们封装好了

2、SpringMVC的核心DispatcherServlet程序

官方给的一个图:


说明:图片的下方可以看出:Servlet引擎是在tomcat里面,所有配置dispatcherServlet不是在spring容器中进行配置,而是在web.xml中进行配置

1、所有的请求进来都是进入到前端控制器FrontController(也就是dispatcherServlet帮我们接收所有的请求)

2、然后再把这些请求转给(delegate request 委托请求)不同的Controller控制器(handler request),并创建模型(create model)(delegate rendering of response 委托渲染响应模型),重新返回给前端控制器.

3、前端控制器将模型交给视图(view template ) 进行渲染响应,渲染完之后返回给前端控制器( return control) ,并由前端控制器返回给客户端

注意:Servlet 不需要加@controller注解,加@controller注解是在黄色的这个位置

springmvc中所有的请求都是经过dispatcherservlet的,并响应回去

3SpringMVC的第一个Hello示例程序

3.1SpringMVC——Hello world程序的步骤:

1、创建一个动态的web工程


2、导入SpringMVC的包

commons-logging-1.1.3.jar

log4j-1.2.17.jar

spring-aop-4.0.0.RELEASE.jar

spring-beans-4.0.0.RELEASE.jar

spring-context-4.0.0.RELEASE.jar

spring-core-4.0.0.RELEASE.jar

spring-expression-4.0.0.RELEASE.jar

spring-web-4.0.0.RELEASE.jar

spring-webmvc-4.0.0.RELEASE.jar

2、创建工程需要的配置文件:

(1) log4j.properties


# Global logging configuration
log4j.rootLogger=INFO, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

(2) 创建SpringMVC的配置文件

<?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 http://www.springframework.org/schema/context/spring-context-4.0.xsd">

	<context:component-scan base-package="com.tcent"></context:component-scan>
	
</beans>

(3) 配置web.xml

<servlet>
		<servlet-name>springDispatcherServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
		<!-- 	给Spring的核心组件,告诉它,springMVC的配置文件在哪 -->
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:springmvc.xml</param-value>
		</init-param>
		<!-- load-on-startup表示当前这个Servlet程序,当Web服务器一启动的时候,就创建和初始化 -->
		<load-on-startup>1</load-on-startup>
	</servlet>
	<!-- Map all requests to the DispatcherServlet for handling -->
	<servlet-mapping>
		<servlet-name>springDispatcherServlet</servlet-name>
		<!-- / 拦截全部请求。/支持restful风格 -->
		<url-pattern>/</url-pattern>
	</servlet-mapping>

这里 有两点很重要:

1)原来的servlet程序是在第一次访问的时候进行创建并且初始化,后面的每次访问只调用service()方法,但是,你只要一加上这个配置load-on-startup ,就会在web工程已启动就给你创建出来并进行初始化,好处就是我们做好初始化之后,你后面的访问速度就会比较快,就跟数据库连接池一样,我先把连接都准备好,你一进来我就直接给你,就不会产生等你每次访问,我就给你创建这么慢,就提升了访问速度。

2url-pattern/拦截所有请求,而且支持restful风格。这里不要写成/*了,/*的权限太高了,而且也不支持restful风格

2、创建jsp页面

4.1WebContent/index.jsp

<body>

<a href="${ pageContext.request.contextPath }/hello">hello(访问服务器。转发到WebContent/jsp/target.jsp页面)</a>

</body>

4.2、在WebContent/jsp/target.jsp

<body>

请求转发进来

</body>

5、编写一个类HelloController(当然也可以叫HelloHandler这都是习惯命名)

/**
 *  @Controller 表示当前类是一个控制器
 */
@Controller
public class HelloController {
	/**
	 * @RequestMapping("/hello") <br/>
	 *  	表示在SpringMVC中注册一个控制器,请求地址是http://ip:port/工程名/hello
	 * @return
	 */
	@RequestMapping("/hello")
	public String hello() {
		System.out.println("这是SpringMVC的hello程序");
		// "/jsp/target.jsp" 返回值表示要跳转的地址
		// /打头,表示绝对路径:到http://ip:port/工程名/		映射到WebContent目录
		// "/jsp/target.jsp" 整个表示http://ip:port/工程名/jsp/target.jsp页面
		// SpringMVC默认跳转使用的是转发
		return "/jsp/target.jsp";
	}
	
}

 SpringMVC默认跳转使用的是转发

注意:@RequestMapping(“/hello”)表示请求映射,相当于我们之前的servlet

<servlet-mapping>
		<servlet-name>xxx</servlet-name>
		<url-pattern>/hello</url-pattern>
	</servlet-mapping>

的作用一样,也是表示到工程名后面跟的hello,就能访问塔hello

表示在SpringMVC中注册一个控制器,请求地址是http://ip:port/工程名/hello

3.2SpringMVC.xml配置文件的另一种存放方式

原来的方案

1、编写一个SpringMVC配置文件,

2、通过dispatcherServlet的初始化参数告诉SpringMVC它的配置文件在哪里。

<!-- The front controller of this Spring Web application, responsible for handling all application requests -->
	<servlet>
		<servlet-name>springDispatcherServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
		<!-- 	给Spring的核心组件,告诉它,springMVC的配置文件在哪 -->
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:springmvc.xml</param-value>
		</init-param>
		<!-- load-on-startup表示当前这个Servlet程序,当Web服务器一启动的时候,就创建和初始化 -->
		<load-on-startup>1</load-on-startup>
	</servlet>
	<!-- Map all requests to the DispatcherServlet for handling -->
	<servlet-mapping>
		<servlet-name>springDispatcherServlet</servlet-name>
		<!-- / 拦截全部请求。/支持restful风格 -->
		<url-pattern>/</url-pattern>
	</servlet-mapping>

另一种方案是

1、web.xml配置文件所在的目录下创建一个SpringMVC配置文件。

2、这个配置文件名的命名规则是你springMVC前端控制器的servlet-name的值-servlet.xml

servlet-name<servlet-name>springDispatcherServlet</servlet-name>


取代如下一段代码:

<init-param>
		<!-- 	给Spring的核心组件,告诉它,springMVC的配置文件在哪 -->
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:springmvc.xml</param-value>
		</init-param>

原先的和现在的对比:


4、视图解析器

配置SpringMVC提交的视图解析器:

<!-- 配置Spring的视图解析器 -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<!-- prefix配置返回的视图的前缀 -->
		<property name="prefix" value="/jsp/"/>
		<!-- suffix配置返回的视图的后缀 -->
		<property name="suffix" value=".jsp"/>
	</bean>

视图解析器工作原理


5@RequestMapping注解详解标注在方法上

@RequestMapping给个方法配置一个访问地址。就比如web学习的Servlet程序,在web.xml中配置了访问地址之后,它们之间就有一个访问映射关系。

5.1value属性**重点**

@RequestMapping(value="/hello")

表示映射 当前这个请求方法 的访问地址。

 

/ 表示到http://ip:port/工程名/ 映射到代码的WebContent目录

 

/hello 就表示到http://ip:port/工程名/hello

此处的value单个属性可以省略

5.2params属性

params是要求此请求的参数匹配

params="username"表示请求地址必须带有username参数

params="username=abc"表示请求参数中必须要有username,而且值还必须是abc

 

params="username!=abc"表示1、请求参数中不能有username参数。2、有username参数,但值不能等于abc

 

params="!username"表示请求地址不能带有username参数

params= {"username!=abc","!password"}params可以有多个值,每个值之间是&&关系

以上条件表示要求:

(请求地址中不能有username参数 || username参数值不能等于 abc && 不能有password参数)

/**
	 * params="username"表示当前请求地址必须要有username参数。<br/>
	 * params = "username=wzg168"表示当前请求地址必须要有username参数。而且值必须是wzg168<br/>
	 * params = "username!=wzg168"表示当前请求地址不能包含username参数,或有了username参数的话,值必须不等于wzg168
	 * params = "!username"表示当前请求地址不能包含请求参数username。
	 * @return
	 */
	@RequestMapping(value = "/param", params = {"abc","xxx=ccc"})
	public String param() {
		System.out.println("这是param方法");
		return "param";
	}

5.3headers属性

可以限定请求头中的内容:

/**
	 * headers = "User-Agent=Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
	 * 表示限定浏览器必须是谷歌浏览器,而且版本还是Chrome/58.0.3029.110
	 * @return
	 */
	@RequestMapping(value = "/header", headers = "User-Agent=Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36")
	public String header() {
		System.out.println("这是header方法");
		return "param";
	}

多个参数时,value不可省略

5.4method属性(*次重点*)

form标签页面内容:

<form action="${ pageContext.request.contextPath }/method" method="post">
			<input type="submit" />
		</form>

代码:

/**
	 * method=RequestMethod.GET 表示当前请求必须是GET请求才允许访问<br/>
	 * method=RequestMethod.POST 表示当前请求必须是POST请求才允许访问<br/>
	 */
	@RequestMapping(value="/method",method=RequestMethod.POST)
	public String method() {
		System.out.println("这是method方法");
		return "param";
	}

5.5@RequestMapping标注在Controller类上

@RequestMapping(value = "/hello")

public String hello()

它原来的请求访问地址是:http://ip:port/工程名/hello

当我们在Controller控制器上添加一个@RequestMapping注解,并赋于value属性值的时候。

比如:

@RequestMapping(value="/person")

@Controller

public class HelloController {

这个时候,HelloController中的所有方法必须都在原有请求地址路径前面加上/person

比如:

@RequestMapping(value = "/hello")

public String hello()

它原来的访问地址是:http://ip:port/工程名/hello

Controller控制器上加了@RequestMapping(value="/person")之后,那么访问地址是:

 

http://ip:port/工程名/Controller地址/方法上的地址

http://ip:port/工程名/person/hello

5.6、通配符在@RequestMapping中的使用(不常用)

1、绝对匹配

@RequestMapping(value = "/fun")
	public String fun() {
		System.out.println("这是绝对匹配");
		return "target";
	}

/fun 表示http://ip:port/工程名/fun

2、? 问号 匹配资源路径

? 问号表示一个任意字符

@RequestMapping(value = "/fu?")
	public String fun1() {
		System.out.println("这是fun1方法 ,fu?");
		return "target";
	}

表示请求地址是:http://ip:port/工程名/fu[a-Z0-9_]

3、* 星号 匹配资源路径

* 星号 可以匹配多个任意字符

@RequestMapping(value = "/fu*")
	public String fun2() {
		System.out.println("这是fun2方法 ,fu*");
		return "target";
	}

注:当一个路径同时匹配多个规则的时候,调用方法的优先顺序是:

绝对匹配--->>>>?问号匹配---->>>>*星号匹配

匹配的精度越高,越优先

4、? 问号 匹配一层目录

? 问号表示一个任意字符

	@RequestMapping(value = "/?/fun")
	public String fun3() {
		System.out.println("这是fun3方法 ,/?/fun");
		return "target";
	}


5、* 星号 匹配一层目录

* 星号 可以匹配多个任意字符

@RequestMapping(value = "/*/fun")
	public String fun4() {
		System.out.println("这是fun4方法 ,/*/fun");
		return "target";
	}

6** 星星号 匹配多层目录

@RequestMapping(value = "/**/fun")
	public String fun5() {
		System.out.println("这是fun5方法 ,/**/fun");
		return "target";
	}

6Controller中如何接收请求参数

6.1、原生API参数类型

6.1.1HttpServletRequest

@RequestMapping(value = "/param1")
	public String param1(HttpServletRequest request) {
		System.out.println("这是param1方法");
		System.out.println(request);
		return "param";
	}

6.1.2HttpSession

@RequestMapping(value = "/param2")
	public String param2(HttpServletRequest request, HttpSession session) {
		System.out.println("这是param2方法");
		System.out.println(request);
		System.out.println(session);
		return "param";
	}

6.1.3HttpServletResponse

@RequestMapping(value = "/param3")
	public String param3(HttpServletRequest request, HttpSession session,
			HttpServletResponse response) {
		System.out.println("这是param3方法");
		System.out.println(response);
		System.out.println(request);
		System.out.println(session);
		return "param";
	}

6.2普通类型传入参数(注入)

通过request对象获取(不推荐)

@RequestMapping(value="/param4")
	public String param4(HttpServletRequest request) {
		System.out.println("这是param4方法");
		System.out.println(request.getParameter("username"));
		return "param";
	}

我们在Controller的目标方法上直接设置方法的参数。就可以直接传入请求参数的值。

@RequestMapping(value="/param5")
	public String param5(String username) {
		System.out.println("这是param5方法");
		System.out.println(username);
		return "param";
	}


通过方法传入参数可以结合@RequestMapping注解params属性传值使用,并进行接受。

要求:参数名必须和方法的参数名相匹配。

6.3、普通类型数组的参数

@RequestMapping(value = "/param6")
	public String param6(String[] hobbies) {
		System.out.println("这是param6方法");
		if (hobbies != null) {
			for (String string : hobbies) {
				System.out.println(string);
			}
		}
		return "param";
	}

注:当然也可以使用String hobbies直接接收一个字符串,中间它会用逗号隔开,但自己使用的时候还要解析,有点自找麻烦的感觉,推荐还是使用String[] hobbies这种形式

6.4普通类型使用@RequestParam入参


@RequestMapping(value = "/param7")
	public String param7(@RequestParam(value = "username") String user) {
		System.out.println("这是param7方法");
		System.out.println(user);
		return "param";
	}

注意:请求参数名username和方法参数名的区别user,这里也就相当于起别名

 

@RequestParam(value = "username") String user 表示SpringMVC会自动将请求过来的参数username的值。注入到方法参数user中。

默认情况下。@RequestParam(value = "username")中要求username参数必须要有值(required=true)。否则就会报如下错误:


required:属性设置当前要求的username参数是否客户端必须传递。默认值是true表示必须传递。

如果没有传递就报错。

也可以手动修改为false。允许不传递值。则默认值是null

defaultValue:属性设置当客户端没有传递值的时候。设置的默认值。

6.5@RequestHeader获取请求头入参

@RequestMapping(value = "/param8")
	public String param8(@RequestHeader(value = "User-Agent") String userAgent,
			@RequestHeader(value = "Host") String host) {
		System.out.println("这是param8方法");
		System.out.println(userAgent);
		System.out.println(host);
		return "param";
	}


6.6@CookieValue获取Cookie值入参

@CookieValue注解获取cookie的值注入。

value中填写的是cookiekey

@RequestMapping(value = "/param9")
	public String param9(@CookieValue(value = "JSESSIONID") String jsessionid) {
		System.out.println("这是param9方法");
		System.out.println(jsessionid);
		return "param";
	}

6.7、一个Pojo对象类型的参数

创建Person对象:

public class Person {

	private Integer id;
	private String name;
	private String phone;
	private Integer age;

创建一个表单:

<form action="${ pageContext.request.contextPath }/param10">
			id:<input type="text" name="id" /><br/>
			name:<input type="text" name="name" /><br/>
			phone:<input type="text" name="phone" /><br/>
			age:<input type="text" name="age" /><br/>
			<input type="submit" />
		</form>

这里的name值必须和pojo属性一致,才能通过表单注入值到对象

Controller中的方法代码:

@RequestMapping(value="/param10")
	public String param10(Person person) {
		System.out.println("这是param10方法");
		System.out.println(person);
		return "param";
	}

要求:pojo对象自动入参的要求是客户端传递的参数名必须跟pojo对象的属性名对应上。

6.8、对象中套对象(级联属性)

比如Person对象中套有book对象。只需要传递参数。子对象名.属性名就可以自动的注入到Person对象的book对象的属性中。

public class Book {

	private String name;
	private BigDecimal price;

public class Person {

	private Integer id;
	private String name;
	private String phone;
	private Integer age;
	private Book book;

表单:

<form action="${ pageContext.request.contextPath }/param10">
			id:<input type="text" name="id" /><br/>
			name:<input type="text" name="name" /><br/>
			phone:<input type="text" name="phone" /><br/>
			age:<input type="text" name="age" /><br/>
			book.name:<input type="text" name="book.name" /><br/>
			book.price:<input type="text" name="book.price" /><br/>
			<input type="submit" />
		</form>

常用spring开发jar包即额外包下载



猜你喜欢

转载自blog.csdn.net/mxcsdn/article/details/80719258