SpringMVC学习之路 第一篇
今天我们开始学习SpringMVC框架。 本文涉及以下内容: 1. SpringMVC的入门案例。 2. SpringMVC入门案例的分析 。 3. SpringMVC请求参数的绑定 。 4. SpringMVC自定义类型转换器 。 5. 获取Servlet原生的API 。 6. SpringMVC常用注解 。
1.1 入门案例的项目结构图如下:
1.2 在pom.xml中导入需要的包:
maven.compiler的版本从1.7修改为1.8 spring-webmvc
spring-web 提供了核心 HTTP 集成,包括一些便捷的 servlet 过滤器, Spring HTTP 调用,用于集成其它 web 框架的基础结构以及技术(Hessian,Burlap)。 spring-webmvc 是 Spring MVC 的一个实现。spriing-webmvc 依赖于 spring-web,这样包含它就会间接地添加 spring-web。不必显示添加 spring-web。 如果你不使用 Spring MVC ,但想要借助其它 Spring 支持的 web 相关技术的优势,那么你只需依赖 spring-web 。
< properties>
< project.build.sourceEncoding> UTF-8</ project.build.sourceEncoding>
< maven.compiler.source> 1.8</ maven.compiler.source>
< maven.compiler.target> 1.8</ maven.compiler.target>
< spring.version> 5.0.2.RELEASE</ spring.version>
</ properties>
< dependencies>
< dependency>
< groupId> org.springframework</ groupId>
< artifactId> spring-context</ artifactId>
< version> ${spring.version}</ version>
</ dependency>
< dependency>
< groupId> org.springframework</ groupId>
< artifactId> spring-webmvc</ artifactId>
< version> ${spring.version}</ version>
</ dependency>
</ dendencies>
1.3 编写index.jsp部分:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
< html>
< head>
< title> Title</ title>
</ head>
< body>
< h3> 入门程序</ h3>
< a href = " hello" > 入门程序</ a>
</ body>
</ html>
1.4 编写成功后的跳转页面success.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
< html>
< head>
< title> Title</ title>
</ head>
< body>
< h3> 入门成功</ h3>
</ body>
</ html>
1.5 编写控制器类HelloController:
@Controller
public class HelloController {
@RequestMapping ( path = "/hello" )
public String sayHello ( ) {
System. out. println ( "hello startmvc" ) ;
return "success" ;
}
}
1.6 编写web.xml:
< url-pattern>/< /url-pattern>:
“/”:会匹配到 /toIndex 这种类型的 url ,不会匹配到模式为 *.jsp 这样的后缀型 url。 (一般就用这个)。 “/*”:会匹配所有路径型的和后缀型的url。 < load-on-startup>1< /load-on-startup>:
当值为0或者大于0时,表示容器在应用启动时就加载这个servlet; 当是一个负数时或者没有指定时,则指示容器在该servlet被选择时才加载。 正数的值越小,启动该servlet的优先级越高。 contextConfigLocation:
在web.xml中定义contextConfigLocation参数,Spring会使用这个参数去加载所有逗号分隔的xml文件,如果没有这个参数,Spring默认加载WEB-INF/applicationContext.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>
1.7 编写配置文件springmvc.xml:
<?xml version="1.0" encoding="UTF-8"?>
< beans xmlns = " http://www.springframework.org/schema/beans"
xmlns: mvc= " http://www.springframework.org/schema/mvc"
xmlns: context= " http://www.springframework.org/schema/context"
xmlns: xsi= " http://www.w3.org/2001/XMLSchema-instance"
xsi: schemaLocation= "
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd" >
< context: component-scan base-package = " fang" />
< bean id = " internalResourceViewResolver" class = " org.springframework.web.servlet.view.InternalResourceViewResolver" >
< property name = " prefix" value = " /WEB-INF/pages/" />
< property name = " suffix" value = " .jsp" />
</ bean>
</ beans>
1.9 配置TomCat服务器:
Server选项: Deployment选项:
Application context:可以设置访问路径,也可以不需要。
2.1 SpringMVC框架基于组件方式执行流程
2.2 RequestMapping注解:
用于建立请求 URL 和处理请求方法之间的对应关系。 源码@Target({ElementType.METHOD, ElementType.TYPE}),说明可以作用在方法上或者类上。 value:用于指定请求的 URL。它和 path 属性的作用是一样的。 method:用于指定请求的方式。 params:用于指定限制请求参数的条件。它支持简单的表达式。要求请求参数的 key 和 value 必须和配置的一模一样。
例如:
@Controller
@RequestMapping ( "/user" )
public class HelloController {
@RequestMapping ( value= "/hello" , method = { RequestMethod. GET} , params = { "name=123" } )
public String sayHello ( ) {
System. out. println ( "hello startmvc" ) ;
return "success" ;
}
}
3.1 基本类型和String类型作为参数
ParamController中testParam函数的参数保持和jsp文件发送的参数一致时,参数会自动封装到testParam函数的参数中。
编写params.jsp文件,添加如下内容:< a href = " param/testParam?username=fang" > 请求参数绑定</ a>
编写ParamController类:@Controller
@RequestMapping ( "/param" )
public class ParamController {
@RequestMapping ( "/testParam" )
public String testParam ( String username) {
System. out. println ( username) ;
return "success" ;
}
}
3.2 POJO 类型作为参数
表单中的内容可以直接封装到Account类中。 POST请求时中文会出现乱码,后面会介绍用过滤器解决方法。
编写Account类(domain/Account.java),省略get等方法:public class Account implements Serializable {
private String username;
private String password;
private Double money;
}
修改params.jsp中的内容,提交表单: < form action= "param/saveAccount" method= "post" >
姓名:< input type= "text" name= "username" > < br>
密码:< input type= "text" name= "password" > < br>
金额:< input type= "text" name= "money" > < br>
< input type= "submit" value= "提交" >
< / form>
添加ParamController中的内容如下:@RequestMapping ( "/saveAccount" )
public String testParam ( Account account) {
System. out. println ( account) ;
return "success" ;
}
3.3 POJO 类中包含其他类的引用参数
编写User类,忽略get等方法:public class User implements Serializable {
private String uname;
private Integer age;
}
修改Account类,添加User类的引用,忽略get等方法:public class Account implements Serializable {
private String username;
private String password;
private Double money;
private User user;
}
修改param.jsp中的内容:< form action = " param/saveAccount" method = " post" >
姓名:< input type = " text" name = " username" > < br>
密码:< input type = " text" name = " password" > < br>
金额:< input type = " text" name = " money" > < br>
用户姓名:< input type = " text" name = " user.uname" > < br>
用户年龄:< input type = " text" name = " user.age" > < br>
< input type = " submit" value = " 提交" >
</ form>
ParamController直接用前面的testParam即可。
3.4 解决中文乱码问题:
< 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-mapping>
3.5 POJO 类中包含集合类型参数
修改Account类,添加Map和List:public class Account implements Serializable {
private String username;
private String password;
private Double money;
private List< User> list;
private Map< String, User> map;
}
添加params.jsp如下:< form action = " param/saveAccount" method = " post" >
姓名:< input type = " text" name = " username" > < br>
密码:< input type = " text" name = " password" > < br>
金额:< input type = " text" name = " money" > < br>
用户姓名:< input type = " text" name = " list[0].uname" > < br>
用户年龄:< input type = " text" name = " list[0].age" > < br>
用户姓名:< input type = " text" name = " map[' one' ].uname" > < br>
用户年龄:< input type = " text" name = " map[' one' ].age" > < br>
< input type = " submit" value = " 提交" >
</ form>
ParamController类直接用前面的testParam方法就可以啦。
4.1 修改User类如下(忽略get等方法):
form表单提交的都是字符串类型。基本类型可以自动转换。如需要转换成Date类型,格式必须是1994/03/12。不然就需要自定义类型转换器了。 如果我想要编辑的格式为1994-03-12,就需要自定义类型转换器。
public class User implements Serializable {
private String uname;
private Integer age;
private Date date;
}
4.2 在params.jsp中添加内容如下:
< form action = " param/saveUser" method = " post" >
用户姓名:< input type = " text" name = " uname" > < br>
用户年龄:< input type = " text" name = " age" > < br>
用户生日:< input type = " text" name = " date" >
< input type = " submit" value = " 提交" >
</ form>
4.3 编写ParamController类中的testParam(User user)方法(方法名可以一样,参数不一样就行):
@RequestMapping ( "/saveUser" )
public String testParam ( User user) {
System. out. println ( user) ;
return "success" ;
}
4.4 编写自定义类型转换器类,(utils/StringToDateConterver.java):
public class StringToDateConterver implements Converter < String, Date> {
@Override
public Date convert ( String source) {
if ( source == null) {
throw new RuntimeException ( "空参数" ) ;
}
DateFormat df = new SimpleDateFormat ( "yyyy-MM-dd" ) ;
try {
return df. parse ( source) ;
} catch ( ParseException e) {
throw new RuntimeException ( "转换错误" ) ;
}
}
}
4.5 在springmvc.xml中编写自定义的类型转换器配置项:
< bean id = " conversionService" class = " org.springframework.context.support.ConversionServiceFactoryBean" >
< property name = " converters" >
< set>
< bean class = " fang.utils.StringToDateConterver" />
</ set>
</ property>
</ bean>
< mvc: annotation-driven conversion-service = " conversionService" />
到这里就可以啦,输入日期格式时输入1994-03-12,也可以封装到User类中了。
###### 5.1 如果需要获取Servlet原生的API,可以直接添加参数,就可以直接用了。
在pom.xml中导入servlet-api的包:
< dependency>
< groupId> javax.servlet</ groupId>
< artifactId> servlet-api</ artifactId>
< version> 2.5</ version>
< scope> provided</ scope>
</ dependency>
在ParamController中编写调用方法:
@RequestMapping ( "/testServlet" )
public String testParam ( HttpServletRequest request, HttpServletResponse response) {
System. out. println ( request) ;
System. out. println ( response) ;
return "success" ;
}
6.1 RequestParam
把请求中指定名称的参数给控制器中的形参赋值。 主要用在发送的参数和Controller类中函数的参数不一致时使用。 value:请求参数中的名称。 required:请求参数中是否必须提供此参数。默认值:true。表示必须提供,如果不提供将报错。
编写anno.jsp文件:<%@ page contentType="text/html;charset=UTF-8" language="java" %>
< html>
< head>
< title> Title</ title>
</ head>
< body>
< a href = " anno/testRequestParam?name=fang" > RequestParam</ a>
</ body>
</ html>
编写AnnoController类如下:@Controller
@RequestMapping ( "/anno" )
public class AnnoController {
@RequestMapping ( "/testRequestParam" )
public String testRequestParam ( @RequestParam ( name= "name" ) String username) {
System. out. println ( username) ;
return "success" ;
}
}
6.2 RequestBody
作用:
用于获取请求体内容。直接使用得到是 key=value&key=value…结构的数据。 get 请求方式不适用。 属性:
required:是否必须有请求体。默认值是:true。当取值为 true 时,get 请求方式会报错。如果取值为 false,get 请求得到是 null。
在anno.jsp中添加如下:< form action = " anno/testRequestBody" method = " post" >
用户姓名:< input type = " text" name = " username" /> < br/>
用户年龄:< input type = " text" name = " age" /> < br/>
< input type = " submit" value = " 提交" />
</ form>
编写AnnoController中内容:@RequestMapping ( "/testRequestBody" )
public String testRequestBody ( @RequestBody String body) {
System. out. println ( body) ;
return "success" ;
}
6.3 PathVaribale
作用:
用于绑定 url 中的占位符。例如:请求 url 中 /delete/{id},这个{id}就是 url 占位符。 url 支持占位符是 spring3.0 之后加入的。是 springmvc 支持 rest 风格 URL 的一个重要标志。 属性:
value:用于指定 url 中占位符名称。 required:是否必须提供占位符。
添加内容到anno.jsp中:< a href = " anno/testPathVariable/10" > testPathVariable</ a>
在AnnoController类中添加如下代码:@RequestMapping ( "/testPathVariable/{sid}" )
public String testPathVariable ( @PathVariable ( "sid" ) String id) {
System. out. println ( id) ;
return "success" ;
}
6.4 RequestHeader(很少用)
作用:
属性:
value:提供消息头名称 required:是否必须有此消息头 注:
在anno.jsp添加:< a href = " anno/testRequestHeader" > RequestHeader</ a>
在AnnoController添加如下:@RequestMapping ( "/testRequestHeader" )
public String testRequestHeader ( @RequestHeader ( "Accept" ) String header) {
System. out. println ( header) ;
return "success" ;
}
6.5 CookieValue(很少用)
作用:
用于把指定 cookie 名称的值传入控制器方法参数。 属性:
value:指定 cookie 的名称。 required:是否必须有此 cookie。
在anno.jsp添加:< a href = " anno/testCookieValue" > CookieValue</ a>
在AnnoController添加如下:@RequestMapping ( "/testCookieValue" )
public String testCookieValue ( @CookieValue ( "JSESSIONID" ) String cookieValue) {
System. out. println ( cookieValue) ;
return "success" ;
}
6.6 ModelAttribute
作用:
该注解是 SpringMVC4.3 版本以后新加入的。它可以用于修饰方法和参数。 出现在方法上,表示当前方法会在控制器的方法执行之前,先执行。它可以修饰没有返回值的方法,也可以修饰有具体返回值的方法。 出现在参数上,获取指定的数据给参数赋值。 属性:
value:用于获取数据的 key。key 可以是 POJO 的属性名称,也可以是 map 结构的 key。 应用场景:
当表单提交数据不是完整的实体类数据时,保证没有提交数据的字段使用数据库对象原来的数据。 例如:
我们在编辑一个用户时,用户有一个创建信息字段,该字段的值是不允许被修改的。在提交表单数据是肯定没有此字段的内容,一旦更新会把该字段内容置为 null,此时就可以使用此注解解决问题。 会先执行带有ModelAttribute注解的函数,还可以传参数。两种方式均可以实现。
6.6.1 基于 Map 的应用场景示例 :ModelAttribute 修饰方法带返回值
添加内容到anno.jsp如下:< form action = " anno/testModelAttribute" method = " post" >
用户姓名:< input type = " text" name = " uname" /> < br/>
用户年龄:< input type = " text" name = " age" /> < br/>
< input type = " submit" value = " 提交" />
</ form>
编写AnnoController类中内容如下:@RequestMapping ( "/testModelAttribute" )
public String testModelAttribute ( User user) {
System. out. println ( "testModelAttribute执行了..." ) ;
System. out. println ( user) ;
return "success" ;
}
@ModelAttribute
public User showUser ( String uname) {
System. out. println ( "showUser执行了..." ) ;
User user = new User ( ) ;
user. setUname ( uname) ;
user. setAge ( 20 ) ;
user. setDate ( new Date ( ) ) ;
return user;
}
6.6.2 基于 Map 的应用场景示例 :ModelAttribute 修饰方法带返回值
编写AnnoController类中内容如下:@RequestMapping ( value= "/testModelAttribute" )
public String testModelAttribute ( @ModelAttribute ( "userData" ) User user) {
System. out. println ( "testModelAttribute执行了..." ) ;
System. out. println ( user) ;
return "success" ;
}
@ModelAttribute
public void showUser ( String uname, Map< String, User> map) {
System. out. println ( "showUser执行了..." ) ;
User user = new User ( ) ;
user. setUname ( uname) ;
user. setAge ( 20 ) ;
user. setDate ( new Date ( ) ) ;
map. put ( "userData" , user) ;
}
6.7 SessionAttribute
作用:
属性:
value:用于指定存入的属性名称 type:用于指定存入的数据类型。
编写anno.jsp代码:< a href = " anno/testSessionAttributes" > testSessionAttributes</ a>
< a href = " anno/getSessionAttributes" > getSessionAttributes</ a>
< a href = " anno/delSessionAttributes" > delSessionAttributes</ a>
编写AnnoController代码,在类上加入了SessionAttributes注解:@Controller
@RequestMapping ( "/anno" )
@SessionAttributes ( { "msg" } )
public class AnnoController {
@RequestMapping ( "/testSessionAttributes" )
public String testSessionAttributes ( Model model) {
System. out. println ( "testSessionAttributes..." ) ;
model. addAttribute ( "msg" , "美美" ) ;
return "success" ;
}
@RequestMapping ( "/getSessionAttributes" )
public String getSessionAttributes ( ModelMap modelMap) {
System. out. println ( "getSessionAttributes..." ) ;
String msg = ( String) modelMap. get ( "msg" ) ;
System. out. println ( msg) ;
return "success" ;
}
@RequestMapping ( "/delSessionAttributes" )
public String delSessionAttributes ( SessionStatus status) {
System. out. println ( "getSessionAttributes..." ) ;
status. setComplete ( ) ;
return "success" ;
}
}
编写success.jsp:<%@ page contentType="text/html;charset=UTF-8" language="java" %>
< html>
< head>
< title> Title</ title>
</ head>
< body>
< h3> 入门成功</ h3>
</ body>
</ html>