Java框架开发技术之SpringMVC

Java框架开发技术之SpringMVC

1. SpringMVC

首先看下Spring的架构图
在这里插入图片描述

从Spring的架构图可以看到,Spring MVC 是Spring的一部分,Spring MVC是一个基于MVC模式开发的表现层框架(与用户打交道),它是类似于 Struts2 的一个 MVC 框架,在实际开发中,接收浏览器的请求响应,对数据进行处理,然后返回页面进行显示,但是上手难度却比 Struts2 简单多了。而且由于 Struts2 所暴露出来的安全问题,SpringMVC 已经成为了大多数企业优先选择的框架。

优点
① 性能高于Struts2;
② Spring MVC可以和Spring实现无缝集成(AOP/IOC);
③ 简单易学,容易上手;
④ 完全支持restful风格的URL;
⑤ 轻量级的框架;
⑥ 使用的人多;
⑦ 支持多种拦截器。

工作流程
在这里插入图片描述
一个http请求过来springMVC是如何处理的?

Spring的MVC框架主要由DispatcherServlet、处理器映射、处理器(控制器)、视图解析器、视图组成。
1 用户向服务器发送请求,请求被Spring 前端控制Servelt DispatcherServlet捕获;
2 DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI)。然后根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器,最后以HandlerExecutionChain对象的形式返回;
3 DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。附注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(…)方法。
4 提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。 在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
HttpMessageConveter:将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息。
数据转换:对请求消息进行数据转换。如String转换成Integer、Double等;
数据格式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等;
数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中。
5 Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象;
6 根据返回的ModelAndView,选择一个适合的ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet;
7 ViewResolver 结合Model和View,来渲染视图;
8 将渲染结果返回给客户端。

SpringMVC运行原理

  1. 客户端请求提交到DispatcherServlet
  2. 由DispatcherServlet控制器查询一个或多个HandlerMapping,找到处理请求的Controller
  3. DispatcherServlet将请求提交到Controller
  4. Controller调用业务逻辑处理后,返回ModelAndView
  5. DispatcherServlet查询一个或多个ViewResoler视图解析器,找到ModelAndView指定的视图
  6. 视图负责将结果显示到客户端

2.配置SpringMVC项目

2.1 在配置文件中配置

① 新建javaweb项目:mvc1

② 手动导包
在这里插入图片描述
③ 新建java类并实现Controller接口,添加未实现的方法处理请求

TestController.java

package com.xixw.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
/**
 * 处理器
 * @author Administrator
 */
public class TestController implements Controller{
	@Override
	public ModelAndView handleRequest(HttpServletRequest arg0,
			HttpServletResponse arg1) throws Exception {
		ModelAndView mv=new ModelAndView();
		//添加数据
		mv.addObject("msg","hello!!");
		//添加页面/WEB-INF/jsp/index.jsp
		mv.setViewName("index");
		//返回一个ModelAndView对象
		return mv;
	}
}

④ 配置web.xml
配置核心控制器(DispatcherServlet)
DispatcherServlet是前置控制器,配置在web.xml文件中。作用是拦截匹配的请求,Servlet拦截匹配规则要自已定义,把拦截下来的请求,依据相应的规则分发到目标Controller来处理。

<!-- 配置核心控制器 -->
  <servlet>
  	<servlet-name>mvc</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  	<load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
  	<servlet-name>mvc</servlet-name>
  	<url-pattern>*.do</url-pattern>
  </servlet-mapping>

⑤ 配置主配置文件(在WEB-INF下面)
新建xml文件([servlet-name]-servlet.xml)

mvc-servlet.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:p="http://www.springframework.org/schema/p"
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.xsd">
<!-- 配置handlermapping对象 -->          
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
<!-- 配置handleAdatper对象 -->         
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
<!-- 配置视图渲染器 -->      
<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!-- 配置处理器 -->
<bean name="/test.do" class="com.xixw.controller.TestController">
</bean>            
</beans>

⑥ 编写jsp页面
/WEB-INF/jsp/index.jsp

<body>
    This is my JSP page. <br>
    ${msg}
</body>

⑦ 将项目加入Tomcat,Run Server
在这里插入图片描述

运行结果
在这里插入图片描述

2.2 使用注解配置

TestController.class
@Controller:负责注册一个bean 到spring 上下文中。
@RequestMapping:注解为控制器指定可以处理哪些 URL 请求。

package com.xixw.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
/**
 * 处理器
 * @author Administrator
 */

@Controller
@RequestMapping("/test")
public class TestController{

	@RequestMapping("/test.do")
	public ModelAndView handleRequest(HttpServletRequest arg0,
			HttpServletResponse arg1) throws Exception {
		ModelAndView mv=new ModelAndView();
		//添加数据
		mv.addObject("msg", "helloworld!!");
		//添加页面(WEB-INF/jsp/index.jsp)
		mv.setViewName("index");
		return mv;
	}
}

mvc.servlet.xml

<!-- 配置注解扫描 -->
<context:component-scan base-package="com.xixw.controller">
</context:component-scan>
<!-- 配置视图渲染器 -->
<bean id="viewResolver"
	class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
 value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>

运行结果
在这里插入图片描述
在这里插入图片描述

3.基于MVC表现层框架所做的工作

3.1 如何将URL和java类或者方法映射起来?

将请求URL和类中的方法进行映射使用@RequestMapping,如果省略了method则代表可以处理任何方式的请求。

@RequestMapping(value=“设置映射的URL”,method={ 指定请求的方式 })

3.2 如何将请求的参数封装?

参数的封装:请求的参数都是默认封装到处理的方法的参数列表中
(1)普通的参数
在处理方法入参处使用 @RequestParam 可以把请求参数传递给请求方法。
请求的参数名必须要和处理的方法参数名称保持一致;如果不一致必须手动进行匹配,在方法的参数上添加如下注解,但不建议这样做。

@RequestParam(“请求的参数名”)

(2)对象参数(常用的方式)
请求的参数名必须要和方法参数的对象中的属性名保持一致。

(3)模板传参(restful风格)

  • 普通的get请求

http://localhost:8080/mvc3/deleteUser.do?uid=3

  • 映射格式

@RequestMapping("/deleteUser/{uid}.do")

  • restful风格URL

http://localhost:8080/mvc3/deleteUser/3.do

3.3 如何将请求处理后的结果返回给客户端?

(1)乱码的解决
① post请求:配置编码过滤器
web.xml

<!-- 配置编码过滤器 -->
  <filter>
  	<filter-name>EncodingFilter</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>EncodingFilter</filter-name>
  	<url-pattern>*.do</url-pattern>
  </filter-mapping>

② get请求

(2)页面跳转的方式

① 使用ModelAndView对象来进行页面跳转(必须配置视图渲染器)

通过mv.setViewName(“页面地址”)(地址后缀不需要写)的方法来设置要跳转的页面进行页面跳转(请求转发的方式)
返回的数据封装的方式:通过**mv.addObject(“name”, name)**将数据保存起来。
注意:在底层还是将数据保存在request中,相当于request.setAttrubite(“name”,name);

② 使用Servlet的API进行跳转(没有视图渲染器)

请求转发
request.getRequestDispatcher(“index.jsp”).forward(request, response);
重定向
response.sendRedirect(“index.jsp”);
返回的数据封装方式:可以将数据保存在某一个存储空间中。

③ 使用springmvc方式进行跳转(没有视图渲染器)

请求转发
return “forward:跳转的页面”;
注意:默认就是请求转发所以一般将forward:省略
重定向
return “redirect:跳转的页面”;

④ 使用springmvc方式进行跳转(有视图渲染器)

请求转发
return “跳转的页面”;
注意:只要是经过视图渲染器都不能使用重定向进行页面跳转。
返回的数据封装:都可以封装到ModelMap对象中,map.addAttribute(键,值);
注意:对象不能自己创建,使用的时候必须声明在参数列表中。

3.4 如何将响应的数据渲染到页面?

使用JSTL及EL表达式。

4.实现一个文件上传的示例

4.1 上传单个文件

① 添加文件上传的包
在这里插入图片描述

② 编写上传文件的页面
新建JSP页面,使用form表单进行文件上传:file_upload.jsp

<body>
     <h2>文件上传</h2>  
     <form action="upload.do" method="post" enctype="multipart/form-data">
     	请选择文件:<input type="file" name="file"><br>
     	普通参数:<input type="text" name="test"><br>
     	<input type="submit" value="提交">
     </form>
</body>

③ 编写处理器方法
新建Java类,控制器的类:FileUploadController.java

package com.xixw;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

@Controller
public class FileUploadController {
	@RequestMapping("/upload.do")
	public String upload(@RequestParam MultipartFile file,String test,HttpServletRequest request) throws IOException{
		//进行文件上传
		//获取输入流
		InputStream is=file.getInputStream();
		//获取上传的文件的目标路径
		String path=request.getRealPath("upload");		
		//获取上传的文件的名称
		String name=file.getOriginalFilename();	
		File f=new File(path+"/"+name);
		//创建一个输出流
		OutputStream os=new FileOutputStream(f);
		//将输入流中的数据通过输出流写入到目标文件中
		IOUtils.copy(is, os);
		//关闭流
		is.close();
		os.close();
//跳转到index.jsp页面
		return "index.jsp";
	}
}

④ 在主配置文件中添加文件上传的配置
mvc.xml

<!-- 配置註解掃描 -->
<context:component-scan base-package="com.xixw">
</context:component-scan>
<!-- 配置文件上传 -->
	<bean id="multipartResolver"
	class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
	<!-- one of the properties available; the maximum file size in bytes -->
	<property name="maxUploadSize" value="1000000"/>
	</bean>

⑤ 配置web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 
	xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  <display-name></display-name>	
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  
  <!-- 配置编码过滤器 -->
  <filter>
  	<filter-name>EncodingFilter</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>EncodingFilter</filter-name>
  	<url-pattern>*.do</url-pattern>
  </filter-mapping>
  <!-- 配置核心控制器 -->
  <servlet>
  	<servlet-name>mvc</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  	<!-- 指定配置文件的路徑 -->
	<init-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:mvc.xml</param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
  	<servlet-name>mvc</servlet-name>
  	<url-pattern>*.do</url-pattern>
  </servlet-mapping>
</web-app>

⑥ 进行测试

4.2 上传多个文件

注意:上传多个文件使用数组。

FileUploadController.java

/**
 * 处理文件上传
 * @author Administrator
 */
@Controller
public class FileUploadController {
	@RequestMapping("/upload.do")
	public String upload(@RequestParam MultipartFile[] files,String test,HttpServletRequest request) throws IOException{
		//进行文件上传
		//获取输入流
		for (MultipartFile file : files) {
			InputStream is=file.getInputStream();
			//获取上传的文件的目标路径
			String path=request.getRealPath("upload");		
			//获取上传的文件的名称
			String name=file.getOriginalFilename();	
			File f=new File(path+"/"+name);
			//创建一个输出流
			OutputStream os=new FileOutputStream(f);
			//将输入流中的数据通过输出流写入到目标文件中
			IOUtils.copy(is, os);
			//关闭流
			is.close();
			os.close();
		}
		return "index.jsp";
	}
}

fileUpload.jsp

 <body>
    <h2>文件上传</h2>
    <form action="upload.do" method="post" enctype="multipart/form-data">
    	请选择问件:<input type="file" name="files"><br>
    	请选择问件:<input type="file" name="files"><br>
    	请选择问件:<input type="file" name="files"><br>
    	普通参数:<input type="text" name="test"><br>
    	<input type="submit" value="提交">
    </form>
  </body>

测试
在这里插入图片描述
结果
在这里插入图片描述

5.使用Spring MVC返回JSON数据

5.1 JSON简单语法

JSON是javaScript中的对象,是最常用的数据交互格式。

① JSON中的对象表示
对象使用 { } 括起来,其中数据是以键值对的形式出现,键必须是字符串类型,值的数据类型没有要求(数值、字符串、函数、对象、数组等)。

{“键”:“值”,“键”:“值”}
{“name”:“张三”,“age”:“18”,“password”:“123456”,“study”:“function(){}}”}

② JSON中的数组表示
JSON中的数组是用 [ ] 括起来的数据。

[ {“键”:“值”,“键”:“值”},{“键”:“值”,“键”:“值”},{“键”:“值”,“键”:“值”}]
{“status”:1,“msg”:“ok”,“data”:[{“name”:“张三”,“age”:“18”},{“name”:“张三”,“age”:“18”},{“name”:“张三”,“age”:“18”}]}

5.2 使用Spring MVC返回JSON数据

① 导入需要的JSON包
在这里插入图片描述
② 编写用户实体类
UserVo.java

package com.xixw.vo;
/**
 * 用户实体类
 * @author Administrator
 */
public class UserVo {
	private int id;//用户id
	private String name;//用户名
	private String password;//用户密码
	//get/set方法
}

③ 编写处理器方法(新建Java类,控制器的类)
JsonController.java

package com.xixw.controller;

import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.xixw.vo.UserVo;
/**
 * 处理json数据的处理器
 * @author Administrator
 */
@Controller
public class JsonController {
	/*
	 * 返回的是对象
	 */
	@RequestMapping("/getUser.do")
	@ResponseBody  //处理器中的方法默认返回的是页面,该注解指定方法返回的是数据而非页面
	public UserVo getUser(){
		UserVo user=new UserVo();
		user.setId(10);
		user.setName("小明");
		user.setPassword("123456");
		return user;
	}
	/*
	 * 返回的是数组
	 */
	@RequestMapping("/getUsers.do")
	@ResponseBody
	public List<UserVo> getUsers(){
		List<UserVo> users=new ArrayList<UserVo>();
		UserVo user=new UserVo();
		user.setId(10);
		user.setName("小红");
		user.setPassword("123");
		users.add(user);
		user=new UserVo();
		user.setId(11);
		user.setName("小绿");
		user.setPassword("123");
		users.add(user);
		user=new UserVo();
		user.setId(12);
		user.setName("小蓝");
		user.setPassword("123");
		users.add(user);
		return users;	
	}
}

④ 配置web.xml

<!-- 配置编码过滤器 -->
  <filter>
  	<filter-name>EncodingFilter</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>EncodingFilter</filter-name>
  	<url-pattern>*.do</url-pattern>
  </filter-mapping>
  
  <!-- 配置核心控制器 -->
  <servlet>
  	<servlet-name>mvc</servlet-name>
  	<servlet-class>org.springframework.web.servlet.DispatcherServlet </servlet-class>
  	<!-- 指定配置文件的路径 -->
  	<init-param>
  		<param-name>contextConfigLocation</param-name>
  		<param-value>classpath:mvc.xml</param-value>
  	</init-param>
  	<load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
  	<servlet-name>mvc</servlet-name>
  	<url-pattern>*.do</url-pattern>
  </servlet-mapping>

⑤ 在主配置文件中配置Json转换器
mvc.xml

<!-- 配置注解扫描 -->
<context:component-scan base-package="com.xixw">
</context:component-scan>
<!-- 配置json转换器 -->
<bean id="stringConverter" class="org.springframework.http.converter.StringHttpMessageConverter">
	<property name="supportedMediaTypes">
		<list>
			<value>text/plain;charset=UTF-8</value>
		</list>
	</property>
</bean>
<bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
	<property name="messageConverters">
	<list>
	    <ref bean="stringConverter"/>
		<ref bean="jsonConverter"/>
	</list>	
	</property>
</bean>

⑥ 测试能否返回json数据
返回的是对象
在这里插入图片描述

返回的是数组
在这里插入图片描述

5.3 进一步优化(封装Json数据)

封装一个返回数据的类:DataResult.java

package com.xixw.util;
/**
 * 封装一个数据返回的类
 * @author Administrator
 */
public class DataResult {
	private int status;//返回的状态码
	private String msg;//对状态码的描述
	private Object obj;//返回的数据
	//get/set方法
}

修改处理器:返回DataResult对象

package com.xixw.controller;

import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.xixw.util.DataResult;
import com.xixw.vo.UserVo;
/**
 * 处理json数据的处理器
 * @author Administrator
 */
@Controller
public class JsonController {

	@RequestMapping("/getUser.do")
	@ResponseBody  //处理器中的方法默认返回的是页面,该注解指定方法返回的是数据而非页面
	public DataResult getUser(){
		DataResult dr=new DataResult();
		UserVo user=new UserVo();
		user.setId(10);
		user.setName("小明");
		user.setPassword("123456");
		dr.setStatus(1);
		dr.setMsg("ok");
		dr.setObj(user);
		return dr;
	}
	
	@RequestMapping("/getUsers.do")
	@ResponseBody
	public DataResult getUsers(){
		DataResult dr=new DataResult();
		List<UserVo> users=new ArrayList<UserVo>();
		UserVo user=new UserVo();
		user.setId(10);
		user.setName("小红");
		user.setPassword("123");
		users.add(user);
		user=new UserVo();
		user.setId(11);
		user.setName("小绿");
		user.setPassword("123");
		users.add(user);
		user=new UserVo();
		user.setId(12);
		user.setName("小蓝");
		user.setPassword("123");
		users.add(user);
		dr.setStatus(1);
		dr.setMsg("ok");
		dr.setObj(users);
		return dr;	
	}
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值