SpringMVC——SpringMVC简介、SpringMVC入门程序、返回值类型、参数绑定

说明:部分内容节选网络,只做学习总结使用,侵删

SpringMVC简介

什么是Spring MVC ?

  1. Spring MVC是一个基于MVC架构的用来简化web应用程序开发的应用开发框架,它是Spring的一部分,它和Struts2一样都属于表现层的框架。
    MVC(Model模型 View 视图 Controller 控制器):这是一种软件架构思想,是一种开发模式,将软件划分为三种不同类型的模块,分别是模型,视图,和控制器。
    • 模型:用于封装业务逻辑处理(java类);
    • 视图:用于数据展现和操作界面(Servlet);
    • 控制器:用于协调视图和模型(jsp);
  2. 处理流程:视图将请求发送给控制器,由控制器选择对应的模型来处理;模型将处理结果交给控制器,控制器选择合适的视图来展现处理结果;
  3. 优点:方便测试和代码的维护,分工协作等

SpringMVC工作原理

系统分层

系统分为:

  • 表现层(UI):数据的展现,操作页面,请求转发。
  • 业务层(服务层):封装业务处理逻辑
  • 持久层(数据访问层):封装数据访问逻辑

各层之间的关系: 表现层通过接口调用业务层,业务层通过接口调用持久层,这样,当下一层发生变化改变,不影响上一层的数据。 MVC是一种表现层的架构思想:

在这里插入图片描述

SpringMVC五大组件

前端控制器 (DispatcherServlet)
映射处理器(HandlerMapping)
处理器(Controller)
模型和视图(ModelAndView)
视图解析器(ViewResolver)

SpringMVC具体工作流程

在这里插入图片描述

  • 文字说明:

首先,用户浏览器发送请求,这个请求被前端控制器(或者说中央处理器)DispatcherServlet接收到,调用处理器映射器HandlerMapping,它会根据具体的请求找到相应的处理器Handler(由xml配置文件或者注解查找),封装成处理器对象及处理器拦截器(有则生成)返回给前端处理器。前端处理器拿到这个处理器对象,会去调用处理器适配器HandlerAdapter,处理器适配器根据适配调用具体的处理器(Controller–Handler),处理器处理这个请求,然后返回一个ModelAndView对象给处理器适配器HandlerAdapter,处理器适配器再接着返回给前端处理器,前端处理器则负责将ModelAndView交给视图解析器ViewReslover去解析,返回一个具体的view给前端处理器,前端处理器拿到view,渲染视图(将数据模型填充到视图中),响应给用户浏览器。

  • 总结:
  1. DispatcherServlet 前端控制器
    负责分发请求,springmvc框架提供
    程序员不用写
  2. HandlerMapping 处理器映射器
    负责根据请求路径查找处理器,springmvc框架提供
    程序员不用写
  3. HandlerAdpater 处理器适配器
    负责适配处理器,调用处理器相应功能方法,springmvc框架提供
    系统架构师可以自定义,程序员不用写
  4. Handler处理器 也叫后端控制器 程序员写
  5. ModelAndView 模式和视图的综合体
    springmvc框架提供
    程序员不用写
  6. ViewResoler 视图解析器
    负责将逻辑视图解析成真正的视图,springmvc框架提供
    程序员不用写
  7. View视图 (jsp html pdf img)程序员自定义视图

Controller和Handler的区别?

controller指定的是类(控制器),handler指定的类中的一个方法(处理器)。

SpringMVC入门程序

@Controller和@RequestMapping

  • @Controller 注解控制器

负责注册一个bean 到spring 上下文中
用@Controller注释的类叫控制器,是用来处理请求的类

  • @RequestMapping 请求映射注解

用来注释请求的url地址和请求的提交方式
value属性的值用来配置请求URL
method可以用来限制请求方式,默认支持:DELETE POST GET PUT TRACE等

步骤

  1. 新建动态web项目0420springmvc_001
  2. 添加jar包到WebContent/WEB-INF/lib目录下,build path
    在这里插入图片描述
  1. 在项目的src下添加springmvc-servlet.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!-- beans是springmvc配置文件的根标签 -->
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 			       xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
		http://www.springframework.org/schema/beans/spring-beans-4.3.xsd 
		http://www.springframework.org/schema/mvc 
		http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd 
		http://www.springframework.org/schema/context 
		http://www.springframework.org/schema/context/spring-context-4.3.xsd ">
		
	<!-- 配置mvc的注解驱动 :不用自己配置处理器映射器、配置处理器适配器 -->
	<mvc:annotation-driven />
	<!-- 配置全局注解扫描 :不用自己配置处理器(Controller) -->
    <!-- 等会所有的controller都放在com.xx.controller"这个包下-->
	<context:component-scan base-package="com.xx.controller"></context:component-scan>
	
</beans>
  1. 修改web.xml文件,配置拦截器
<!-- 配置DispatcherServlet -->
<servlet>
    <servlet-name>springmvc</servlet-name>
    <!--所有的请求都交给DispatcherServlet中央处理器去处理-->
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--我们把springmvc-servlet.xml放到项目的src目录下,需要在这里进行配置-->
    <!--它默认是去WebContent目录下去找-->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:springmvc-servlet.xml</param-value>
    </init-param>
</servlet>

<servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

关于url-pattern的设置一般有以下几种方式:

配置springmvc的DispatcherServlet拦截的请求
/所有的请求都交给DispatcherServlet进行处理,但是不包括*.jsp,支持RESTful风格的请求
/*所有的请求都交给DispatcherServlet进行处理,包括 *.jsp
*.do所有以.do结尾的请求都交给DispatcherServlet进行处理 *.action所有以.action结尾的请求都交给DispatcherServlet进行处理

  1. 新建测试类 com.xx.controller.PrintDateController.java
package com.xx.controller;

import java.io.IOException;
import java.util.Date;

import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class PrintDateController {

	@RequestMapping(value="/printDate")
	public String printDate(HttpServletResponse response) throws IOException{
		// 打印当前日期到网页
		response.getWriter().println(new Date());
		return null;
	}
}
  1. 发布项目到tomcat服务器,启动服务器,打开浏览器在地址栏输入:http://localhost/0420springmvc_001/printDate
    在这里插入图片描述

Controller方法的返回值类型

返回类型总共有三种:

  1. ModelAndView
  2. String
  3. void

Controller返回值类型是ModelAndView

当Handler的返回值类型是ModelAndView时,中央处理器收到这个返回值,会把它交给视图解析器进行解析,随后渲染页面,响应请求。

  • 先在springmvc-servlet.xml配置ViewResolver视图解析器
<!-- 配置ViewResolver -->
<bean
      class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <!-- prefix:表示页面的前缀 -->
    <property name="prefix" value="/WEB-INF/jsp/" />
    <!-- suffix:表示页面后缀 -->
    <property name="suffix" value=".jsp" />
</bean>

这样做的目的是给所有的逻辑视图加上前缀和后缀,变成一个完整的全限定名。

  • 新建com.xx.controller.testReturnController.class, 下面所有的示例都写在这个类中,用@RequestMapping注解
@Controller
public class testReturnController {

	// value只有一个值时可以省略value=
	@RequestMapping("/modelAndView")
	public ModelAndView modelAndView() {
		// 创建ModelAndView对象
		ModelAndView mav = new ModelAndView();
		// 设置逻辑视图,全限定名是配置好的/WEB-INF/jsp/hello.jsp
		mav.setViewName("hello");
		// 可以存值,存储数据的范围与用法跟request.setAttribute("h","i am hello")一样
		mav.addObject("h", "i am hello");
		return mav;
	}

}
  • 新建WEB-INF/jsp/hello.jsp
<body>
i am hello.jsp
<hr/>
<!-- 取出mav里面存的值 -->
${h}
</body>
  • 在浏览器中访问:http://localhost/0420springmvc_001/modelAndView

在这里插入图片描述

Controller返回值类型是String

当Controller的返回值类型是String时,可以实现三种功能:

  1. 请求转发
  2. 重定向
  3. 返回逻辑视图名

请求转发

@RequestMapping("/returnStringForward")
public String returnStringForward(){
	// 转发到WEB-INF/jsp/hello.jsp
	 return "forword:WEB-INF/jsp/hello.jsp";
}

重定向

@RequestMapping("returnStringRediredct")
public String returnStringRediredct(){
	// 重定向到index.jsp
	return "redirect:index.jsp"
}

注意,转发可以访问到任何资源,但是重定向只能访问到WebContent目录下的资源。

返回逻辑视图名

@RequestMapping("/returnStringModelView")
public String returnStringModelView(){
	// hello是逻辑视图名,真正的视图是/WEB-INF/jsp/hello.jsp
    return "hello";
}

Controller返回值类型是void

当返回值的类型是void,可以实现以下三种功能:

  1. 转发
  2. 重定向
  3. javabean—》json

转发与重定向

@RequestMapping("/voidF")
public void returnVoidF(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {
	// 请求转发到index.jsp,这种写法和普通的servlet写法无异
	request.getRequestDispatcher("index.jsp").forward(request, response);
}

@RequestMapping("/voidR")
public void returnVoidR(HttpServletResponse response) throws IOException {
	// 请求重定向到index.jsp
	response.sendRedirect("index.jsp");
}

实体类对象解析为JSON数据返回

重点来了,怎么把一个实体类转化成一个json格式的数据返回是关键。
步骤:

  1. 添加jar包,SpringMvc解析JSON所依赖的jar包
    在这里插入图片描述
  2. 新建实体类,这里用com.xx.entity.User来举例:
package com.xx.entity;

public class User {

	private Integer id;
	private String username;
	private String password;

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public User() {
		super();
		// TODO Auto-generated constructor stub
	}

}

  1. 编写Handler:
@RequestMapping("/returnVoidJ")
public void returnVoidJ(HttpServletResponse response) throws IOException {
	User user = new User();
	user.setId(1);
	user.setUsername("Bob");
	user.setPassword("123456abcde");
	// 将实体类解析为JSON数据
	String userJson = JSONObject.fromObject(user).toString();
	response.getWriter().println(userJson);
}
  • 测试:
    在这里插入图片描述

参数绑定

参数绑定指的是将请求参数的值绑定到controller方法参数的过程。
SpringMVC支持的参数绑定类型包括:

  1. Servlet默认的数据类型
    HttpServletRequest HttpServletResponse HttpSession

  2. Model或者ModelMap

  3. java基础数据类型
    byte short int long float double boolean char

  4. Java基础数据类型的封装类型
    Byte Short Integer Long Float Double Boolean Charactor

  5. String

  6. JavaBean

  7. javaBean的封装类型

  8. Java数组类型

我们一一来演示:

Servlet默认的数据类型

code和name假设是表单提交上来的参数。
你可以把Handler当做一个普通的Servlet来用,Servlet能做的事情它都可以做。我们可以拿到 HttpServletRequest,HttpServletResponse,HttpSession,并且调用它们各自的方法。

@RequestMapping("/paramBindingDefaultType")
public void paramBindingDefaultType(HttpServletRequest request, HttpServletResponse response, HttpSession session)
		throws IOException {
	
	String code = request.getParameter("code");
	String name = request.getParameter("name");
	session.setAttribute("code", code);
	session.setAttribute("name", name);
	response.sendRedirect("index.jsp");

}

Model或者ModelMap

Model和ModelMap都可以用来以键值对的形式保存数据,作用范围和request一样
Model是接口,ModelMap是它的实现类。

@RequestMapping("/paramBindingModel")
public String paramBindingModel(HttpServletRequest request, Model model) {

	String code = request.getParameter("code");
	String name = request.getParameter("name");
	model.addAttribute("code", code);
	model.addAttribute("name", name);
	// 转发到index.jsp,在里面用${code}、${name}取值
	return "forward:index.jsp";
	
}

java基础数据类型、java基础数据的封装类型、String类型

比如现在有一个添加商品的页面:

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>商品新增页面</title>
</head>
<body>
	<h1 align="center">商品新增页面</h1>
	<form action="paramBingBasicType" method="post" align="center"
		style="text-align: center;">
		<table border="1" width="500px" height="300px" align="center">
			<tr>
				<td>商品编号:</td>
				<td><input type="text" name="code" size="25" /></td>
			</tr>
			<tr>
				<td>商品名称:</td>
				<td><input type="text" name="name" size="25" /></td>
			</tr>
			<tr>
				<td>商品价格:</td>
				<td><input type="text" name="price" size="25" /></td>
			</tr>
			<tr>
				<td>商品数量:</td>
				<td><input type="text" name="count" size="25" /></td>
			</tr>
			<tr>
				<td>商品状态:</td>
				<td><input type="radio" name="status" size="25" value="0"
					checked="checked" />上架&nbsp;&nbsp; <input type="radio"
					name="status" size="25" value="1" />下架&nbsp;&nbsp;</td>
			</tr>

			<tr>
				<td>商品描述:</td>
				<td><textarea rows="5" cols="25" name="description"></textarea>
				</td>
			</tr>

			<tr>
				<td>生产日期:</td>
				<td><input type="date" name="product_date" size="25" /></td>
			</tr>

			<tr>
				<td colspan="2"><input type="submit" value="保存" /></td>
			</tr>

		</table>
	</form>

</body>
</html>

这张表单里面有code,name,price,count,status,description,product_date这些参数,表单提价到控制器paramBingBasicType去处,我们在这个接收一下这些参数(不包括product_date,它是date类型,SpringMVC默认不对日期类型进行处理,所以我们在开发时需要对日期类型进行处理。)

@RequestMapping("/paramBingBasicType")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
public String paramBingBasicType(String code,String name,double price,int count,Integer status,String description){
	// 只要我们这样定义方法,表单上的参数就可以自动绑定到这些变量上,我们不需要做任何处理
	// 这些变量的类型要和表单上的参数类型符号,变量名要和参数名一致(不一致也可以,但要另做处理)
	// 打印一下看看:
	System.out.println(code+"\t"+name+"\t"+price+"\t"+status+"\t"+description);

}

这是我们提交的表单:
在这里插入图片描述
点击保存后,控制台:

001	product1	30.0	2	0	test

JavaBean

实际开发中我们一般把上面这些参数封装成实体类去取值。所以我们要新建实体类Product.java,属性和绑定参数一致(类型和变量名都要一样),需要注意的是要对date类型做处理,在属性定义的上面加上注解,这样就可以正确映射到表单上的product_date参数:

@DateTimeFormat(pattern="yyyy-MM-dd")
private Date product_date;

还是上面的那张表单,我们现在来用Javabean来绑定参数,注意要更改将表单上action="bindingJavaBean",把数据提交给bindingJavaBean处理:

@RequestMapping("/bindingJavaBean")
public void bindingJavaBean(Product product) {
	// 我们什么都不用做,SpringMVC会自动帮我们把实体类对象product和表单上的参数绑定起来
	// 打印一下看看
	System.out.println(product.getCode());
	System.out.println(product.getName());
	System.out.println(product.getProduct_date());

}

访问表单:
在这里插入图片描述
表单提交给bindingJavaBean,控制台打印:

002
product2
Mon Apr 22 00:00:00 CST 2019

JavaBean的封装类型

  • 新建Order类封装User类:
package com.xx.entity;

public class Order {

	private String order_code;
	private User user;

	public String getOrder_code() {
		return order_code;
	}

	public void setOrder_code(String order_code) {
		this.order_code = order_code;
	}

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

	public Order() {
		super();
		// TODO Auto-generated constructor stub
	}
}

  • 比如我现在有一个根据用户名查询订单的界面,这里要注意订单编号和所属用户的name值order_codeuser.username,前者没什么好说的,后者:user是Oreder的属性,username又是user的属性。
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1 align="center">查询用户订单信息</h1>
	<form action="paramBindingPackObjectType" method="post">
		<table border="1px" width="350px" height="200px" align="center"
			style="text-align: center;">
			<tr>
				<td>订单编号:</td>
				<td><input type="text" name="order_code" size="25" /></td>
			</tr>
			<tr>
				<td>所属用户:</td>
				<td><input type="text" name="user.username" size="25"></td>
			</tr>
			<tr>
				<td colspan="2"><input type="submit" value="查询" /></td
			</tr>
		</table>
	</form>
</body>
</html>
  • Handler,显然,Order类是User类的封装类,我们就可以通过Order类拿到请求的信息存到模型里,转发到index.jsp页面,在jsp页面用${order.order_code}${order.user.username}就可以取到。
@RequestMapping("/paramBindingPackObjectType")
public String paramBindingPackObjectType(Order order, Model model) {

	model.addAttribute("order", order);
	return "forward:index.jsp";
	
}

java数组类型

SpringMVC同样也支持java数组类型的绑定,比如我要实现一个批量删除用户信息的需求,就可以通过数组拿到这一批用户的id值。

  • batchDeleteUser.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
  <h1 align="center">批量删除用户信息</h1>
 <form action="paramBindingListType" method="post">
     
        <table border="1px" width="300px" height="400px" style="text-align: center;" align="center">
            <tr>
              <td>全选</td>
              <th>用户ID</th>
              <th>用户名</th>
              <th>用户密码</th>
           
            </tr>
            
            <tr>
              <td><input type="checkbox" name="ids" value="1"/></td>
              <td>1</td>
              <td>张三</td>
              <td>admin</td>
             
            </tr>
            <tr>
             <td> <input type="checkbox" name="ids" value="2"/></td>
              <td>2</td>
              <td>李四</td>
              <td>admin4</td>
             
            </tr>
            <tr>
             <td> <input type="checkbox" name="ids" value="3"/></td>
              <td>3</td>
              <td>王五</td>
              <td>wangw</td>
              
            </tr>
            <tr>
             <td> <input type="checkbox" name="ids" value="4"/></td>
              <td>4</td>
              <td>赵6</td>
              <td>zhao6</td> 
            </tr>
            
         <tr>
            <td colspan="4"><input type="submit" value="批量删除"/></td>
         </tr>
       </table>
   </form>
</body>
</html>
  • 数据提交到控制器paramBindingArrayType,用数组接收ids要和表单上的name一样。
@RequestMapping("/paramBindingArrayType")
public String paramBindingArrayType(int[] ids) {
	if(ids.length!=0){
		for (int i = 0; i < ids.length; i++) {
			System.out.println(ids[i]);
		}
	}
	return "forward:index.jsp";
}

测试一下:
在这里插入图片描述

  • 控制台:
    在这里插入图片描述

SpringMVC不支持类表类型的参数绑定

虽然这样,但是我们可以把列表封装起来,比如新建一个UserVO:

package com.xx.entity;

import java.util.List;

public class UserVO {
	
	private List<User> users;

	public List<User> getUsers() {
		return users;
	}

	public void setUsers(List<User> users) {
		this.users = users;
	}

	public UserVO() {
		super();
		// TODO Auto-generated constructor stub
	}
}

  • 这是批量更改用户信息的jsp(注意name的写法):
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
  <form action="paramBindingListType" method="post">
     
        <table border="1px" width="300px" height="400px" style="text-align: center;" align="center">
            <tr>
            
              <th>用户ID</th>
              <th>用户名</th>
              <th>用户密码</th>
           
            </tr>
            
            <tr>
             
              <td><input type="text" name="users[0].id" size="25" value="1" readonly="readonly"/></td>
              <td><input type="text" name="users[0].username" size="25" value="zhang3"/></td>
              <td><input type="password" name="users[0].password" size="25" value="zhang3"></td>
             
            </tr>
            <tr>
          
              <td><input type="text" name="users[1].id" size="25" value="2" readonly="readonly"/></td>
              <td><input type="text" name="users[1].username" size="25" value="li4"/></td>
              <td><input type="password" name="users[1].password" size="25" value="li4"></td>
             
            </tr>
            <tr>
           
              <td><input type="text" name="users[2].id" size="25" value="3" readonly="readonly"/></td>
              <td><input type="text" name="users[2].username" size="25" value="wang5"/></td>
              <td><input type="password" name="users[2].password" size="25" value="wang5"></td>
              
            </tr>
            <tr>
            
              <td><input type="text" name="users[3].id" size="25" value="4" readonly="readonly"/></td>
              <td><input type="text" name="users[3].username" size="25" value="zhao6"/></td>
              <td><input type="password" name="users[3].password" size="25" value="zhao6"></td>
             
            </tr>
        
         <tr>
            <td colspan="3"><input type="submit" value="批量修改"/></td>
         </tr>
       </table>
       
   
   </form>
</body>
</html>
  • Handler:
@RequestMapping("/paramBindingListType")
public String paramBindingListType(UserVO userVO, Model model) {

	List<User> users = userVO.getUsers();
	
	model.addAttribute("users", users);

	for (User user : users) {
		System.out.println(user.getId() + " " + user.getUsername() + " " + user.getPassword());
	}
	
	return "forward:index.jsp";
}

测试:
在这里插入图片描述

  • 控制台:
    在这里插入图片描述
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值