Springmvc架构原理解析

Springmvc架构原理解析

第一步:发起请求到前端控制器(DispatcherServlet)
第二步:前端控制器请求HandlerMapping查找 Handler可以根据xml配置、注解进行查找
第三步:处理器映射器HandlerMapping向前端控制器返回Handler
第四步:前端控制器调用处理器适配器去执行Handler
第五步:处理器适配器去执行Handler
第六步:Handler执行完成给适配器返回ModelAndView
第七步:处理器适配器向前端控制器返回ModelAndViewModelAndView是springmvc框架的一个底层对象,包括 Model和view
第八步:前端控制器请求视图解析器去进行视图解析 根据逻辑视图名解析成真正的视图(jsp)
第九步:视图解析器向前端控制器返回View
第十步:前端控制器进行视图渲染视图渲染将模型数据(在ModelAndView对象中)填充到request域
第十一步:前端控制器向用户响应结果

组件:

  1. 前端控制器DispatcherServlet(不需要程序员开发) 作用接收请求,响应结果,相当于转发器,中央处理器。
    有了DispatcherServlet减少了其它组件之间的耦合度。
  2. 处理器映射器HandlerMapping(不需要程序员开发) 作用:根据请求的url查找Handler
  3. 处理器适配器HandlerAdapter 作用:按照特定规则(HandlerAdapter要求的规则)去执行Handler
  4. 处理器Handler(需要程序员开发)
    注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler
  5. 视图解析器View resolver(不需要程序员开发) 作用:进行视图解析,根据逻辑视图名解析成真正的视图(view)
  6. 视图View(需要程序员开发jsp) View是一个接口,实现类支持不同的View类型(jsp、freemarker、pdf…)

SpringMVC学习笔记

一、SpringMVC基础入门,创建一个HelloWorld程序

  1. 首先,导入SpringMVC需要的jar包。
  2. 添加Web.xml配置文件中关于SpringMVC的配置
 <servlet>
    <servlet-name>springDispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 配置DispatcherServlet的初始化參數:设置文件的路径和文件名称 -->
    <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>springDispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

3.在src下添加springmvc-servlet.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!-- scan the package and the sub package -->
<context:component-scan base-package="test.SpringMVC"/>

<!-- don't handle the static resource -->
<mvc:default-servlet-handler />

<!-- if you use annotation you must configure following setting -->
<mvc:annotation-driven />

<!-- configure the InternalResourceViewResolver -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" 
        id="internalResourceViewResolver">
    <!-- 前缀 -->
    <property name="prefix" value="/WEB-INF/jsp/" />
    <!-- 后缀 -->
    <property name="suffix" value=".jsp" />
</bean>

4.在WEB-INF文件夹下创建名为jsp的文件夹,用来存放jsp视图。创建一个hello.jsp,在body中添加“Hello World”。
5.建立包及Controller,如下所示
6.编写Controller代码

@Controller
@RequestMapping("/mvc")
public class mvcController {
@RequestMapping("/hello")
public String hello(){        
    return "hello";
}
}

7.启动服务器,键入 http://localhost:8080/项目名/mvc/hello

二、配置解析

  1. Dispatcherservlet DispatcherServlet是前置控制器,配置在web.xml文件中的。拦截匹配的请求,Servlet拦截匹配规则要自已定义,把拦截下来的请求,依据相应的规则分发到目标Controller来处理,是配置spring
    MVC的第一步。
  2. InternalResourceViewResolver 视图名称解析器
  3. 以上出现的注解 @Controller 负责注册一个bean 到spring 上下文中 @RequestMapping 注解为控制器指定可以处理哪些 URL 请求

三、SpringMVC常用注解

  • @Controller 负责注册一个bean 到spring 上下文中

  • @RequestMapping 注解为控制器指定可以处理哪些 URL 请求

  • @RequestBody
    该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上
    ,再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上

  • @ResponseBody
    该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区

  • @ModelAttribute 在方法定义上使用 @ModelAttribute 注解:Spring MVC
    在调用目标处理方法前,会先逐个调用在方法级上标注了@ModelAttribute 的方法 在方法的入参前使用

  • @ModelAttribute 注解:可以从隐含对象中获取隐含的模型数据中获取对象,再将请求参数 绑定到对象中,再传入入参将方法入参对象添加到模型中

  • @RequestParam 在处理方法入参处使用 @RequestParam 可以把请求参 数传递给请求方法

  • @PathVariable 绑定 URL 占位符到入参

  • @ExceptionHandler 注解到方法上,出现异常时会执行该方法

  • @ControllerAdvice
    使一个Contoller成为全局的异常处理类,类中用@ExceptionHandler方法注解的方法可以处理所有Controller发生的异常

四、自动匹配参数

//match automatically
@RequestMapping("/person")
public String toPerson(String name,double age){
    System.out.println(name+" "+age);
    return "hello";
}

五、自动装箱

1.编写一个Person实体类

package test.SpringMVC.model;
public class Person {
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
private String name;
private int age;
}

2.在Controller里编写方法

//boxing automatically
@RequestMapping("/person1")
public String toPerson(Person p){
    System.out.println(p.getName()+" "+p.getAge());
    return "hello";
}

六、使用InitBinder来处理Date类型的参数

//the parameter was converted in initBinder
@RequestMapping("/date")
public String date(Date date){
    System.out.println(date);
    return "hello";
}

//At the time of initialization,convert the type "String" to type "date"
@InitBinder
public void initBinder(ServletRequestDataBinder binder){
    binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),
            true));
}

七、向前台传递参数

//pass the parameters to front-end
@RequestMapping("/show")
public String showPerson(Map<String,Object> map){
    Person p =new Person();
    map.put("p", p);
    p.setAge(20);
    p.setName("jayjay");
    return "show";
}

前台可在Request域中取到"p"

八、使用Ajax调用

//pass the parameters to front-end using ajax
@RequestMapping("/getPerson")
public void getPerson(String name,PrintWriter pw){
    pw.write("hello,"+name);        
}
@RequestMapping("/name")
public String sayHello(){
    return "name";
}

前台用下面的Jquery代码调用

      $(function(){
          $("#btn").click(function(){
              $.post("mvc/getPerson",{name:$("#name").val()},function(data){
                  alert(data);
              });
          });
      });

九、在Controller中使用redirect方式处理请求

//redirect
@RequestMapping("/redirect")
public String redirect(){
return “redirect:hello”;
}

十、文件上传

1.需要导入两个jar包
2.在SpringMVC配置文件中加入

<!-- upload settings -->
<bean id="multipartResolver"  class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize" value="102400000"></property>
</bean>

3.方法代码

@RequestMapping(value="/upload",method=RequestMethod.POST)
public String upload(HttpServletRequest req) throws Exception{
    MultipartHttpServletRequest mreq = (MultipartHttpServletRequest)req;
    MultipartFile file = mreq.getFile("file");
    String fileName = file.getOriginalFilename();
    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");        
    FileOutputStream fos = new FileOutputStream(req.getSession().getServletContext().getRealPath("/")+
            "upload/"+sdf.format(new Date())+fileName.substring(fileName.lastIndexOf('.')));
    fos.write(file.getBytes());
    fos.flush();
    fos.close();
    
    return "hello";
}

4.前台form表单

  <form action="mvc/upload" method="post" enctype="multipart/form-data">
      <input type="file" name="file"><br>
      <input type="submit" value="submit">
  </form>

文件上传示例

1)拷贝jar包
commons-fileupload-1.2.1.jar
commons-io-2.0.jar
严重: Servlet /SpringMVC_06_FileUpload threw load() exception
java.lang.ClassNotFoundException: org.apache.commons.fileupload.FileItemFactory
2)配置文件上传解析器

<!-- 配置文件上传解析器
id必须是"multipartResolver",否则,会报错误:
java.lang.IllegalArgumentException: Expected MultipartHttpServletRequest: is a MultipartResolver
configured?
-->
<bean id="multipartResolver"
 class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8"></property>
<property name="maxUploadSize" value="1024000"></property>
</bean>

3)上传页面

	<%@ 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="testUpload" method="post" enctype="multipart/form-data">
文件: <input type="file" name="file"/><br><br>
描述: <input type="text" name="desc"/><br><br>
<input type="submit" value="提交"/>
</form>
</body>
</html>

4)控制器方法

package com.atguigu.springmvc.crud.handlers;
 
import java.io.IOException;
import java.io.InputStream;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
 
@Controller
public class UploadHandler {
 
@RequestMapping(value="/testUpload",method=RequestMethod.POST)
public String testUpload(@RequestParam(value="desc",required=false) String desc, @RequestParam("file") MultipartFile multipartFile) throws IOException{                
System.out.println("desc : "+desc);
System.out.println("OriginalFilename : "+multipartFile.getOriginalFilename());
InputStream inputStream = multipartFile.getInputStream();
System.out.println("inputStream.available() : "+inputStream.available());
System.out.println("inputStream : "+inputStream);

return "success"; //增加成功页面: /views/success.jsp
}
}

9.3 思考多个文件上传?

十一、使用@RequestParam注解指定参数的name

@Controller
@RequestMapping("/test")
public class mvcController1 {
@RequestMapping(value="/param")
public String testRequestParam(@RequestParam(value=“id”) Integer id,
@RequestParam(value=“name”)String name){
System.out.println(id+" "+name);
return/hello”;
}
}

十二、RESTFul风格的SringMVC

1.RestController

@Controller
@RequestMapping("/rest")
public class RestController {
@RequestMapping(value="/user/{id}",method=RequestMethod.GET)
public String get(@PathVariable(“id”) Integer id){
System.out.println(“get”+id);
return/hello”;
}
@RequestMapping(value="/user/{id}",method=RequestMethod.POST)
public String post(@PathVariable("id") Integer id){
    System.out.println("post"+id);
    return "/hello";
}

@RequestMapping(value="/user/{id}",method=RequestMethod.PUT)
public String put(@PathVariable("id") Integer id){
    System.out.println("put"+id);
    return "/hello";
}

@RequestMapping(value="/user/{id}",method=RequestMethod.DELETE)
public String delete(@PathVariable("id") Integer id){
    System.out.println("delete"+id);
    return "/hello";
}
}

2.form表单发送put和delete请求
在web.xml中配置
HiddenHttpMethodFilter org.springframework.web.filter.HiddenHttpMethodFilter HiddenHttpMethodFilter /*
在前台可以用以下代码产生请求

<form action="rest/user/1" method="post">
    <input type="hidden" name="_method" value="PUT">
    <input type="submit" value="put">
</form>

<form action="rest/user/1" method="post">
    <input type="submit" value="post">
</form>

<form action="rest/user/1" method="get">
    <input type="submit" value="get">
</form>

<form action="rest/user/1" method="post">
    <input type="hidden" name="_method" value="DELETE">
    <input type="submit" value="delete">
</form>

十三、返回json格式的字符串

1.导入以下jar包
2.方法代码

@Controller
@RequestMapping("/json")
public class jsonController {
@ResponseBody
@RequestMapping("/user")
public  User get(){
    User u = new User();
    u.setId(1);
    u.setName("jayjay");
    u.setBirth(new Date());
    return u;

处理请求数据

4.1请求处理方法签名

  • 1)Spring MVC 通过分析处理方法的签名,HTTP请求信息绑定到处理方法的相应人参中。
  • 2)Spring MVC 对控制器处理方法签名的限制是很宽松的,几乎可以按喜欢的任何方式对方法进行签名。
  • 3)必要时可以对方法及方法入参标注相应的注解( @PathVariable 、@RequestParam、@RequestHeader
    等)、
  • 4)Spring MVC 框架会将 HTTP 请求的信息绑定到相应的方法入参中,并根据方法的返回值类型做出相应的后续处理。

4.2 @RequestParam注解

  • 1)在处理方法入参处使用 @RequestParam 可以把请求参数传递给请求方法
  • 2)value:参数名
  • 3)required:是否必须。默认为 true, 表示请求参数中必须包含对应的参数,若不存在,将抛出异常
  • 4)defaultValue: 默认值,当没有传递参数时使用该值
4.2.1 实验代码

1)增加控制器方法

/**
 * @RequestParam 注解用于映射请求参数
 *         value 用于映射请求参数名称
 *         required 用于设置请求参数是否必须的
 *         defaultValue 设置默认值,当没有传递参数时使用该值
 */
@RequestMapping(value="/testRequestParam")
public String testRequestParam(
@RequestParam(value="username") String username,
@RequestParam(value="age",required=false,defaultValue="0") int age){
System.out.println("testRequestParam - username="+username +",age="+age);
return "success";
}

2)增加页面链接

testRequestParam

4.3 @RequestHeader 注解

1)使用 @RequestHeader 绑定请求报头的属性值
2)请求头包含了若干个属性,服务器可据此获知客户端的信息,通过 @RequestHeader 即可将请求头中的属性值绑定到处理方法的入参中

4.3.1 实验代码

//了解: 映射请求头信息 用法同 @RequestParam

@RequestMapping(value="/testRequestHeader")
public String testRequestHeader(@RequestHeader(value="Accept-Language") String al){
System.out.println("testRequestHeader - Accept-Language:"+al);
return "success";
}
<a href="springmvc/testRequestHeader">testRequestHeader</a>

4.4 @CookieValue 注解

1)使用 @CookieValue 绑定请求中的 Cookie 值
2)@CookieValue 可让处理方法入参绑定某个 Cookie 值

4.4.1实验代码

1)增加控制器方法

//了解:@CookieValue: 映射一个 Cookie 值. 属性同 @RequestParam
@RequestMapping("/testCookieValue")
public String testCookieValue(@CookieValue("JSESSIONID") String sessionId) {
System.out.println("testCookieValue: sessionId: " + sessionId);
return "success";
}

2)增加页面链接

<a href="springmvc/testCookieValue">testCookieValue</a>

4.5 使用POJO作为参数

1)使用 POJO 对象绑定请求参数值
2)Spring MVC 会按请求参数名和 POJO 属性名进行自动匹配,自动为该对象填充属性值。支持级联属性。如:dept.deptId、dept.address.tel 等

4.5.1实验代码

1)增加控制器方法、表单页面

/**
 * Spring MVC 会按请求参数名和 POJO 属性名进行自动匹配, 自动为该对象填充属性值。
 * 支持级联属性
 *                 如:dept.deptId、dept.address.tel 等
 */
@RequestMapping("/testPOJO")
public String testPojo(User user) {
System.out.println("testPojo: " + user);
return "success";
}
<!-- 测试 POJO 对象传参,支持级联属性 -->
<form action=" testPOJO" method="POST">
username: <input type="text" name="username"/><br>
password: <input type="password" name="password"/><br>
email: <input type="text" name="email"/><br>
age: <input type="text" name="age"/><br>
city: <input type="text" name="address.city"/><br>
province: <input type="text" name="address.province"/>
<input type="submit" value="Submit"/>
</form>	

2)增加实体类

package com.atguigu.springmvc.entities;
 
public class Address {
 
private String province;
private String city;
 
//get/set
  
}	package com.atguigu.springmvc.entities;
 
public class User {
private Integer id ;
private String username;
private String password;
 
private String email;
private int age;
 
private Address address;
 
//get/set 
}

3)执行结果:

4)如果中文有乱码,需要配置字符编码过滤器,且配置其他过滤器之前,
如(HiddenHttpMethodFilter),否则不起作用。(思考method=”get”请求的乱码问题怎么解决的)


	<!-- 配置字符集 -->
	<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>
		<init-param>
			<param-name>forceEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>encodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

处理响应数据

5.1 SpringMVC 输出模型数据概述

5.1.1提供了以下几种途径输出模型数据
1)ModelAndView: 处理方法返回值类型为 ModelAndView 时, 方法体即可通过该对象添加模型数据
2)Map 及 Model: 入参为 org.springframework.ui.Model、
org.springframework.ui.ModelMap 或 java.uti.Map 时,处理方法返回时,Map 中的数据会自动添加到模型中。

5.2处理模型数据之 ModelAndView

#5.2.1ModelAndView介绍

1)控制器处理方法的返回值如果为 ModelAndView, 则其既包含视图信息,也包含模型
数据信息。
2)添加模型数据:
MoelAndView addObject(String attributeName, Object attributeValue)
ModelAndView addAllObject(Map<String, ?> modelMap)
3)设置视图:
void setView(View view)
void setViewName(String viewName)

5.2.2 实验代码

1)增加控制器方法

/**
 * 目标方法的返回类型可以是ModelAndView类型
 *                 其中包含视图信息和模型数据信息
 */
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
System.out.println("testModelAndView");
String viewName = "success";
ModelAndView mv = new ModelAndView(viewName );
mv.addObject("time",new Date().toString()); //实质上存放到request域中 
return mv;
}

2)增加页面链接

<a href="springmvc/testModelAndView">testModelAndView</a>

3)增加成功页面,显示数据
time: ${requestScope.time }
视图和视图解析器
1)请求处理方法执行完成后,最终返回一个 ModelAndView 对象。对于那些返回 String,View 或 ModeMap 等类型的处理方法,Spring MVC 也会在内部将它们装配成一个 ModelAndView 对象,它包含了逻辑名和模型对象的视图
2)Spring MVC 借助视图解析器(ViewResolver)得到最终的视图对象(View),最终的视图可以是 JSP ,也可能是 Excel、JFreeChart等各种表现形式的视图
3)对于最终究竟采取何种视图对象对模型数据进行渲染,处理器并不关心,处理器工作重点聚焦在生产模型数据的工作上,从而实现 MVC 的充分解耦

6.3 视图

1)视图的作用是渲染模型数据,将模型里的数据以某种形式呈现给客户,主要就是完成转发或者是重定向的操作.
2)为了实现视图模型和具体实现技术的解耦,Spring 在 org.springframework.web.servlet 包中定义了一个高度抽象的 View 接口:

3)视图对象由视图解析器负责实例化。由于视图是无状态的,所以他们不会有线程安全的问题

6.4 常用的视图实现类

在这里插入图片描述

6.5 JstlView

1)若项目中使用了JSTL,则SpringMVC 会自动把视图由InternalResourceView转为 JstlView (断点调试,将JSTL的jar包增加到项目中,视图解析器会自动修改为JstlView)

2)若希望直接响应通过 SpringMVC 渲染的页面,可以使用 mvc:view-controller 标签实现

6.5.1 实验代码

1)增加jstl标签 jar包(断点调试,这时的View对象就是JstlView)

6.6 视图解析器

1)SpringMVC 为逻辑视图名的解析提供了不同的策略,可以在 Spring WEB 上下文中配置一种或多种解析策略,并指定他们之间的先后顺序。每一种映射策略对应一个具体的视图解析器实现类。
2)视图解析器的作用比较单一:将逻辑视图解析为一个具体的视图对象。
3)所有的视图解析器都必须实现 ViewResolver 接口:

6.7 常用的视图解析器实现类

1)程序员可以选择一种视图解析器或混用多种视图解析器
2)每个视图解析器都实现了 Ordered 接口并开放出一个 order 属性,可以通过 order 属性指定解析器的优先顺序,order 越小优先级越高。
3)SpringMVC 会按视图解析器顺序的优先顺序对逻辑视图名进行解析,直到解析成功并返回视图对象,否则将抛出 ServletException 异常
4)InternalResourceViewResolver
①JSP 是最常见的视图技术,可以使用 InternalResourceViewResolve作为视图解析器:

6.8mvc:view-controller标签

1)若希望直接响应通过 SpringMVC 渲染的页面,可以使用 mvc:view-controller 标签实现

<mvc:view-controller path="/success" view-name=“success”/>
2)请求的路径:
http://localhost:8080/SpringMVC_02_View/success
3)配置mvc:view-controller会导致其他请求路径失效
解决办法:

mvc:annotation-driven/ 6.9 重定向

1)关于重定向
①一般情况下,控制器方法返回字符串类型的值会被当成逻辑视图名处理
②如果返回的字符串中带 forward: 或 redirect: 前缀时,SpringMVC 会对他们进行特殊处理:将 forward: 和 redirect: 当成指示符,其后的字符串作为 URL 来处理
③redirect:success.jsp:会完成一个到 success.jsp 的重定向的操作
④forward:success.jsp:会完成一个到 success.jsp 的转发操作
2)定义页面链接
testRedirect
3)定义控制器方法
@RequestMapping("/testRedirect")
public String testRedirect(){
System.out.println(“testRedirect”);
return “redirect:/index.jsp”;
//return “forward:/index.jsp”;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值