Spring实战笔记(四)-SpringMVC

原文链接: https://my.oschina.net/caofanqi/blog/3009435

一、什么是SpringMVC

        SpringMVC是Spring框架的一部分,是一个表现层框架,它是基于模型视图-控制器(Model-View-Controller,MVC)模式实现,能够帮助我们构建想Spring框架那样灵活和松耦合的Web应用程序。

二、SpringMVC架构

    1、架构流程图

    Spring实战笔记(四)-SpringMVC_第1张图片

    2、流程说明:

             ①用户发送请求至 前端控制器DispatcherServlet(是一个单实例的Servlet将请求委托给应用程序的其他组件来执行实际的处理)。

             ②前端控制器DispatcherServlet收到请求后调用处理器映射器HandlerMapping,来确定请求的下一站是哪里。

             处理器映射器HandlerMapping根据请求的Url找到具体的处理器,生成处理器对象Handler及处理器拦截器HandlerIntercepter(如果有则生成)一并返回给前端控制器DispatcherServlet。

             ④前端控制器DispatcherServlet通过处理器适配器HandlerAdapter调用处理器Controller。

             执行处理器(Controller,也叫后端控制器)。

             执行完后返回ModelAnView。

             处理器映射器HandlerAdapter将处理器Controller执行返回的结果ModelAndView返回给前端控制器DispatcherServlet。

             前端控制器DispatcherServlet将ModelAnView传给视图解析器ViewResolver。

             视图解析器ViewResolver解析后返回具体的视图View。

             前端控制器DispatcherServlet对视图View进行渲染视图(即:将模型数据填充至视图中)

             前端控制器DispatcherServlet响应用户。

    3、组件说明:

         ①DisPatcherServlet(前端控制器):用户请求到达前端控制器,它相当于MVC模式中的C(Controller),DispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,DispatcherServlet的存在降低了组件之间的耦合性。作用:作为接受请求,相应结果,相当于转发器,中央处理器,减少其他组件之间的耦合度。

        ②HandlerMapping(处理器映射器):HandlerMapping负责根据用户请求找到Handler(处理器),SpringMVC提供了不同的映射器实现实现不同的映射方式,例如:配置文件方式、实现接口方式、注解方式等。作用:根据请求的Url 查找Handler。

        ③HandLer(处理器):Handler是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下,Handler对具体的用户请求进行处理。由于Handler设计到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发Handler。注意:编写Handler时按照HandlerAdpter的要求去做,这样才可以去正确执行Handler。

        ④HandlerAdapter(处理器适配器):通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。作用:按照特定的规则(HandlerAdapter要求的规则)去执行Handler。

        ⑤ViewResolver(视图解析器):ViewResolver负责将处理结果生成View视图,ViewResolver首先根据逻辑视图名解析成物理视图名,即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面的展示给用户。作用:进行视图解析,根据逻辑视图名解析成真正的视图(view)。

        ⑥View视图:View是一个接口,实现类支持不同的View类型(jsp、freemarker、pdf)。

三、基于JavaConfig的SpringMVC入门程序

        1、工程结构如下:

        Spring实战笔记(四)-SpringMVC_第2张图片

    2、配置DispacherServlet,ApiWebInitializer

package com.caofanqi.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

/**
 * 配置DispatcherServlet:扩展AbstractAnnotationConfigDispatcherServletInitializer的任意类都会
 * 自动地配置DispatcherServlet和Spring应用上下文 ,Spring的应用上下文会位于应用程序的Servlet上下文之中。
 * 
 * 注:使用AbstractAnnotationConfigDispatcherServletInitializer配置DispatcherServlet是传统web.xml方式的替代方案。
 * 需要Servlet3.0以上才支持
 */
public class ApiWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

	/**
	 * 将一个或多个路径映射到DispatcherServlet上;
* “/”:表示拦截除了JSP的所有请求
* “/*”:表示拦截所有Url包括JSP */ @Override protected String[] getServletMappings() { return new String[] { "/" }; } /** * 返回的带有@Configuration注解的类将会用来配置DispatcherServlet加载应用上下文时的bean。 * 加载包含Web组件的bean,如控制器、视图解析器以及处理器映射器。 */ @Override protected Class[] getServletConfigClasses() { return new Class[] { WebConfig.class }; } /** * 返回的带有@Configuration注解的类将会用来配置ContextLoaderListtener创建的应用上下文bean。 * 这些bean通常是驱动应用后端中间层和数据层组件。 */ @Override protected Class[] getRootConfigClasses() { return new Class[] { RootConfig.class }; } }

       3、WebConfig

package com.caofanqi.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@EnableWebMvc // JavaConfig 启用SpringMVC
@ComponentScan("com.caofanqi.controller")
public class WebConfig extends WebMvcConfigurerAdapter {

	/**
	 * 配置JSP视图解析器
	 */
	@Bean
	public ViewResolver viewResolver() {
		InternalResourceViewResolver resolver = new InternalResourceViewResolver();
		resolver.setPrefix("/WEB-INF/views/");
		resolver.setSuffix(".jsp");
		return resolver;
	}

	/**
	 * 配置静态资源处理1:
	 * 此时会注册一个默认的Handler:DefaultServletHttpRequestHandler,这个Handler也是用来处理静态文件的,它会尝试映射/*。
	 * 当DispatcherServelt映射/时(/和/*是有区别的),并且没有找到合适的Handler来处理请求时,就会交给DefaultServletHttpRequestHandler
	 * 来处理。注意:这里的静态资源是放置在web根目录下,而非WEB-INF 下。 例如:在WebRoot目录下有一个图片:1.png
	 * 我们知道Servelt规范中web根目录(WebRoot)下的文件可以直接访问的,但是由于DispatcherServlet配置了映射路径是:/,
	 * 它几乎把所有的请求都拦截了,从而导致1.png 访问不到,这时注册一个DefaultServletHttpRequestHandler
	 * 就可以解决这个问题。其实可以理解为DispatcherServlet破坏了Servlet的一个特性(根目录下的文件可以直接访问),
	 * DefaultServletHttpRequestHandler是帮助回归这个特性的。
	 */
	@Override
	public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
		configurer.enable();
	}

	/**
	 * 配置静态资源处理2: addResoureHandler指的是对外暴露的访问路径,addResourceLocations指的是文件放置的目录
	 * 此方法用来专门注册一个Handler,来处理静态资源的,例如:图片,js,css等。举例:
	 * 当请求http://localhost:8090/stuspringmvc/resources/1.png时,会把/WEB-INF/resources/1.png返回。
	 */
	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		super.addResourceHandlers(registry);
		registry.addResourceHandler("/resources/**").addResourceLocations("/WEB-INF/resources/");
	}
}

    4、RootConfig

package com.caofanqi.config;

import java.util.regex.Pattern;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.core.type.filter.RegexPatternTypeFilter;

@Configuration
@ComponentScan(basePackages = { "com.caofanqi" }, excludeFilters = {
		@Filter(type = FilterType.CUSTOM, value = RootConfig.WebPackage.class) })
public class RootConfig {

	/**
	 * 通过excludeFilters过滤指定包不进行装载到容器(因为WebConfig中已经扫描了)
	 */
	public static class WebPackage extends RegexPatternTypeFilter {

		public WebPackage() {
			super(Pattern.compile("com\\.caofanqi\\.controller"));
		}
	}
}

    5、HomeController

package com.caofanqi.controller;

import static org.springframework.web.bind.annotation.RequestMethod.GET;

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

@Controller // 声明为一个控制器
@RequestMapping(value = "/") // @RequestMapping可以加载类上,表示该类所有的方法路径前面都要包括该value
public class HomeController {

	@RequestMapping(method = GET) // 处理对/的get请求
	public String home() {

		return "home"; // 视图名为home
	}

}

    6、home.jsp

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>

  
    StuSpringMVC
    " >
  
  
    

Hello SpringMVC

">UserList | ">Register

    启动项目,访问http://localhost:8090/stuspringmvc/  如下所示:

        Spring实战笔记(四)-SpringMVC_第3张图片

四、基于web.xml的SpringMVC入门程序

        1、工程目录

        Spring实战笔记(四)-SpringMVC_第4张图片

    2、web.xml



 

	
	
		contextConfigLocation
		/WEB-INF/spring/root-context*.xml
		
	
	
		org.springframework.web.context.ContextLoaderListener
	

	
	
		stuspringmvc-xml
		org.springframework.web.servlet.DispatcherServlet
		
		
			contextConfigLocation
			/WEB-INF/spring/springmvc-context.xml
		
		
		1
	
	
	
		stuspringmvc-xml
		/
	
	

    3、springmvc-context.xml




	
    

    
    
    	
    	
    	
    	
    

	
    
      
      
    
    
    
	 

	
    

    4、root-context.xml




	
	
		
		
	

    HomeController和home.jsp不变,访问

http://localhost:8090/stuspringmvc/  如下所示:

        Spring实战笔记(四)-SpringMVC_第5张图片

到此,两种模式的SpringMVC入门已经完成。

五、传递模型数据到视图中

        类上注解为:

@Controller
@RequestMapping("/products")
public class ProductController {
     ...
}

        1、我们可以在方法的参数列表上添加一个Model(也可使用ModelAndView,Map),然后视图可以根据指定的key获取value,如下所示:

	@RequestMapping(method = RequestMethod.GET)
	public String products(Model model) {
		model.addAttribute("productList", productService.listProducts());
		return "products";
	}

        2、如果不指定key的话,key会根据值的对象类型推断确定,比如List,key会推断为productList,如下所示:

	@RequestMapping(method = RequestMethod.GET)
	public String products(Model model) {
		model.addAttribute(productService.listProducts());
		return "products";
	}

        3、还有一种,不返回视图名称,也不显示地设定模型,当处理器方法返回对象或集合时,这个值会放到模型中,模型的key会根据其类型推断得出,逻辑视图的名称将会根据请求路径推断得出。比如这个方法是处理“/products”的GET请求,视图名称将会是products(去掉开头的/)。如下所示:

	@RequestMapping(method = RequestMethod.GET)
	public List products() {
		return productService.listProducts();
	}

        上面几种方式都可以将数据放入模型中,当视图是JSP时,数据模型会作为请求属性放到请求(request)中。可以使用JSTL的标签来渲染列表:


          
  • ">
  •  

    转载于:https://my.oschina.net/caofanqi/blog/3009435

    你可能感兴趣的:(Spring实战笔记(四)-SpringMVC)