springMVC-入门-01

入门

springMVC是处在控制层的一个地位,最原始的东西是servlet,后来发展出了struts框架,现在是使用SpringMVC,但是这几个都是处理控制层的框架。

SpringMVC与struts2的区别

springMVCstruts2都是controller层的一个框架,对于MVC的框架主要作用就是以下的几个方面。

  • 拦截请求地址
  • 将请求地址映射到某一个处理器
  • 获得结果
  • 将结果进行渲染,返回给视图

springMVCstruts2的具体比较信息如下:

对比项目 SpringMVC Struts2 优势
国内市场情况 有大量用户,一般新项目启动都会选用springmvc 有部分老用户,老项目组,由于习惯了,一直在使用 国内情况,springmvc的使用率已经超过Struts2
框架入口 基于servlet 基于filter 本质上没太大优势之分,只是配置方式不一样
框架设计思想 控制器基于方法级别的拦截,处理器设计为单实例 控制器基于类级别的拦截, 处理器设计为多实例 由于设计本身原因,造成了Struts2,通常来讲只能设计为多实例模式,相比于springmvc设计为单实例模式,Struts2会消耗更多的服务器内存
参数传递 参数通过方法入参传递 参数通过类的成员变量传递 Struts2通过成员变量传递参数,导致了参数线程不安全,有可能引发并发的问题
与spring整合 与spring同一家公司,可以与spring无缝整合 需要整合包 Springmvc可以更轻松与spring整合

使用springMVC的一个小案例

controller层

package top.twolovelypig.controller;
@Controller
public class HelloWorld {
	@RequestMapping("welcome")
	public String hello() {
		return "success";
	}
}
  • 在浏览器中只需要输入http:localhost:8080/项目名称/welcome就会跳转到这里,这里返回的是一个字符串,其实这个字符串就是返回的jsp页面的名称,只是在下面的springMVC配置文件中配置了视图解析器,也就是加上了前缀和后缀。最终返回的内容其实是 前缀+success+后缀

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>01springMVC</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
  
  <!-- 配置前端控制器 -->
  <servlet>
  	<servlet-name>springmvc</servlet-name>
  	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  	<!-- 加载spring核心配置文件 -->
  	<init-param>
  		<param-name>contextConfigLocation</param-name>
  		<param-value>classpath:springmvc.xml</param-value>
  	</init-param>
  </servlet>
  <!-- 配置拦截路径 -->
  <servlet-mapping>
  	<servlet-name>springmvc</servlet-name>
  	<url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>
  • 上面有一步是加载springMVC的核心配置文件,如果是使用默认的文件名以及路径可以使用配置,默认的路径是在WEB-INF下面,默认的文件名是servlet-name里面的值-servlet.xml,比如在上面的web.xml中配置的的值是springmvc,那么默认的配置文件名就是springmvc-servlet.xml
  • 配置拦截路径的时候这里使用的是 / ,也就是拦截一切请求,即所有的请求都是交给springMVC来处理,也就是再controller中使用RequestMapping这种注解形式的路径,如果配置的是*.action,那么就是所有的以action结尾的请求都会被拦截交给springMVC来处理。
  • 如果是使用的eclipse并且配置了sts插件或者是使用的sts,那么上面web.xml中的配置可以一键生成,使用alt+/展开提示,找到有dispatcher的那个就可以了,生成好需要修改的有spring配置文件的路径以及

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"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

	<!-- 配置@Controller处理器,包扫描器 -->
	<context:component-scan base-package="top.twolovelypig.controller"/>
    <!-- 配置视图解析器 -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/views/"></property>
		<property name="suffix" value=".jsp"></property>
	</bean>
</beans>

RequestMapping的配置(不使用对象)

多级路径

不使用通配符

上面controller层的代码如下:

package top.twolovelypig.controller;
@Controller
public class HelloWorld {
	@RequestMapping("welcome")
	public String hello() {
		return "success";
	}
}

这里配置RequestMapping可以配置多级,下面的几种形式都是可以的

package top.twolovelypig.controller;
@Controller
@RequestMapping("HelloWorld")
public class HelloWorld {
	@RequestMapping("welcome")
	public String hello() {
		return "success";
	}
}

像这种形式访问路径就是http://localhost:8080/项目名称/Helloworld/welcome,还可以是下面的这种形式。

package top.twolovelypig.controller;
@Controller
@RequestMapping("HelloWorld")
public class HelloWorld {
	@RequestMapping("welcome/abc")
	public String hello() {
		return "success";
	}
}

此时访问路径是http://localhost:8080/项目名称/Helloworld/welcome/abc

使用通配符

对于目录还可以使用通配符形式,主要有以下几种类型

  • *,一个星号表示是任意字符,比如下面的代码

    package top.twolovelypig.controller;
    @Controller
    public class HelloWorld {
    	@RequestMapping("welcome/*/abc")
    	public String hello() {
    		return "success";
    	}
    }
    

    这里表示请求路径中开始是welcome,最后是abc,在这之间的可以是任意字符,下面这些请求路径都是合法的。

    • http://localhost:8080/项目名/welcome/asheib/abc
    • http://localhost:8080/项目名/welcome/asgerhre/abc
  • ** 中间含有两个星号表示的是任意目录,也就是中间可以有任意层级,如果welcome与abc之间是两个星号的话下面的请求路径都是合法的

    • http://localhost:8080/项目名/welcome/asheib/asg/agre/agr/abc
    • http://localhost:8080/项目名/welcome/asheib/asg/agre/abc
  • ? 这里使用的问号表示是单个字符,还是上面的代码示例,如果welcome与abc之间是一个问号来表示那么下面的请求路径是合法的

    • http://localhost:8080/项目名/welcome/a/abc
    • http://localhost:8080/项目名/welcome/k/abc

配置提交方式

RequestMapping中还可以配置其余参数,比如下面的代码

@Controller
public class HelloWorld {
	@RequestMapping(value="welcome", method=RequestMethod.POST)
	public String hello() {
		return "success";
	}
}

这里配置了method是post提交方式,也就是除了映射路径要对之外,提交的还必须是post方式才可以,比如下面的提交方式就是不行的。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="welcome">hello</a>
</body>
</html>

因为超链接默认是get提交方式,与我们配置吃不符合,所以不能被拦截。

此时就需要使用form提交,并且手动配置提交方式为post提交。

<body>
<a href="welcome">hello</a>
<form action="welcome" method="post">
	<input type="submit">
</form>
</body>

在form当中手动配置了method属性为post,此时就可以被拦截到。

配置提交参数

除了提交方式之外还可以配置提交的参数。

@Controller
public class HelloWorld {
	@RequestMapping(value="welcome", method=RequestMethod.POST, params= {"name", "age"})
	public String hello() {
		return "success";
	}
}

提交参数是通过params来设置的,这里配置了name和age,也就是提交参数中必须要name属性和age属性,否则就不会被拦截到。如果还是之前那个空的form来提交就不会被拦截到,此时需要将那个form修改为如下形式

<body>
<a href="welcome">hello</a>
<form action="welcome" method="post">
    <input name="name">
	<input name="age">
	<input type="submit">
</form>
</body>

还可以更严格一点是配置值,比如在controller中配置如下形式

@Controller
public class HelloWorld {
	@RequestMapping(value="welcome", method=RequestMethod.POST, params= {"name=hello", "age"})
	public String hello() {
		return "success";
	}
}

此时就算form当中有name参数但是如果name的值如果不是hello也是不行的,所以需要修改这种形式才可以被正确拦截到。

除了这些之外还可以配置其余参数,比如请求头之类的。

配置@PathVariable动态获取参数

如果是get请求之前是可以在请求路径后面加上加上问号来传递参数到后台,然后在后台可以通过request.getParamater()来获取传递过去的参数,在springMVC中可以通过@PathVariable来动态传递参数

jsp页面

<body>
<a href="welcome/hello/神奇">hello</a>
</body>

a标签吃一个get请求,这里的welcome是我们请求的路径,后面两个是我们传递的参数。

后台controller

@Controller
public class HelloWorld {
	@RequestMapping(value="welcome/{name}/{age}")
	public String hello(@PathVariable("name") String name, @PathVariable("age") String age) {
		System.out.println(name);
		System.out.println(age);
		return "success";
	}
}

可以看到在这里我们在welcome后面拼接了两个参数,大括号里面的是参数名,使用这种方式需要注意的是需要与@PathVariable注解结合起来使用,比如我们接受的第一个参数是name,在方法的形参前面的@PathVariable注解就需要写name,当然也可以在第二个参数位置写,位置可以不按照顺序,但是名称需要对应起来。

用@requestParam获取参数

上面说的参数是通过在路径后面拼接地址的方式来传递参数,如果不是在路径后面拼接,而是通过form表单来提交的话就可以通过@RequestParam来获取参数。

jsp页面

<form action="testParam" method="post">
	<input type="text" name="uname" value="hello"> 
	<input type="submit">
</form>

这样提交方式是post或者get都是可以的。

controller

@RequestMapping(value="testParam")
	public String testParam(@RequestParam("uname") String name) {
		System.out.println(name);
		return "success";
	}

在jsp页面中input的name属性是uname,这里@RequestParam也必须是uname,最终是将传过来的值赋值到name参数中。

SpringMVC处理各种参数的逻辑

  • 前端发起一个请求,也就是给定一个路径
  • 在controller中使用@RequestMapping映射找到对应的处理方法
  • 在方法中使用注解获取传递过来的参数

将参数封装为对象

上面所讲的从前端带过来参数是直接获取的,但是如果参数有很多的时候一个一个的获取显然是不现实的,所以可以直接将参数封装到一个对象之中,SpringMVC将参数封装到对象之中是很简单的,只需要满足下面几个条件即可。

  • 表单中name属性必须与对象的属性名一致
  • 如果有级联关联,除了保证name属性值与对象的属性名一致外还需要保证级联性

具体案例

Student对象

package top.twolovelypig.entity;

public class Student {

	private int id;
	private String name;
	private Address address;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Address getAddress() {
		return address;
	}
	public void setAddress(Address address) {
		this.address = address;
	}
	@Override
	public String toString() {
		return this.id + "," + this.name + "," + this.address.getHomeAddress() + "," + this.address.getSchoolAddress();
	}
}

Address对象

package top.twolovelypig.entity;

public class Address {
	private String homeAddress;
	private String schoolAddress;

	public String getHomeAddress() {
		return homeAddress;
	}

	public void setHomeAddress(String homeAddress) {
		this.homeAddress = homeAddress;
	}

	public String getSchoolAddress() {
		return schoolAddress;
	}

	public void setSchoolAddress(String schoolAddress) {
		this.schoolAddress = schoolAddress;
	}

}


jsp页面

<form action="testObject" method="post">
	id:<input type="text" name="id" value="">
	name:<input type="text" name="name" value="">
	homeAddress:<input type="text" name="address.homeAddress" value="">
	schoolAddress:<input type="text" name="address.schoolAddress" value="">
	<input type="submit">
</form>

可以看到form表单中name属性值与实体中属性名一致,而且student类中包含address,所以对于address类中的属性还需要加上arrdess前缀。

controller

@RequestMapping(value="testObject")
	public String testParam(Student student) {
		System.out.println(student);
		return "success";
	}

在controller层中直接通过对象来接受值即可。

在springMVC中使用原生态的servlet-api

在servlet中的api中有一些方法是比较好用的,比如说HttpServletRequest和HttpServletResponse等,对于这些servlet-api如果想要在SpringMVC中使用也是很简单的,就是直接将这些作为参数传入SpringMVC的方法之中即可。比如:

@RequestMapping(value="testObject")
	public String testParam(HttpServletRequest request, HttpServletResponse response,Student student) {
		String name = request.getParameter("name");
		System.out.println("通过request获取的name" + name);
		System.out.println(student);
		return "success";
	}

配置过滤器增加对put与delete请求的支持

四种请求

这里的是四中请求方式其实对应的是增删改查四种操作

  • get 获取的意思,也就是对应的是 查询
  • post 提交的意思,也就是对应的是 新增
  • delete 删除的意思,也就是对应的是 删除
  • put 对应的是 修改

一般的浏览器其实是只支持get和post请求,也就是并不支持put以及delete请求,所以此处需要通过过滤器来实现将不支持的两种请求方式变得支持。

但是springMVC中使用这个过滤器的时候有两个条件需要先满足

  • 我们使用的是post提交方式
  • 含有隐藏域,形式为或者是

只有满足了这两个要求过滤器才会去执行。

过滤器的配置

在web.xml中需要配置一个过滤器,主要是记住过滤器的类名是HiddenHttpMethodFilter

 <filter>
  	<filter-name>filtermethod</filter-name>
  	<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
  </filter>
  <filter-mapping>
  	<filter-name>filtermethod</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>

表单配置

上面已经说过如果是使用delete或者put提交方式,那么在表单中需要使用使用post提交,并且需要有隐藏域,该隐藏域需要满足两个条件,一个是name=“_method”,一个是value=“DELETE”或者value=“PUT”(delete或者put需要大写),也就是如下形式:

<form action="路径" method="post">
    <input type="hidden" name="_method" value="DELETE">
</form>

由于映射是可以重复的,所以如果有相同的映射路径时可以通过method=RequestMethod.POST或者method=RequestMethod.DELETE来区别不同的映射路径。

上一篇:设计模式七大原则之依赖倒转原则


下一篇:C# 参数可选特性