Spring实战笔记(四)-SpringMVC

一、什么是SpringMVC

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

二、SpringMVC架构

    1、架构流程图

    eaeb8a8c80344b69fb27bc927d3e9ded59b.jpg

    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、工程结构如下:

        787f914422350de4d3fced105f715f22739.jpg

    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上;<br>
	 * “/”:表示拦截除了JSP的所有请求 <br>
	 * “/*”:表示拦截所有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" %>
<html>
  <head>
    <title>StuSpringMVC</title>
    <link rel="stylesheet" 
          type="text/css" 
          href="<c:url value="/resources/style.css" />" >
  </head>
  <body>
    <h1>Hello SpringMVC</h1>

    <a href="<c:url value="/user" />">UserList</a> | 
    <a href="<c:url value="/user/register" />">Register</a>
  </body>
</html>

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

        c62984d6dd409b002dbf1c01d629afea024.jpg

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

        1、工程目录

        e6c2ddfd04d5b2ac53710e8351074373e3c.jpg

    2、web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
 

	<!-- 设置根上下文配置文件位置 -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/root-context*.xml</param-value>
	</context-param>	
	<!-- 注册ContextLoaderListener -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- 注册DispatcherServlet -->
	<servlet>
		<servlet-name>stuspringmvc-xml</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<!-- DispatcherServlet会根据servlet-name加上-servlet找到一个文件,并基于该文件加载应用上下文。如servlet名字是stuspringmvc-xml,因此DispatcherServlet
		会从/WEB-INF/stuspringmvc-xml-servlet.xml 文件中加载其应用上下文。如果希望指定位置的话,添加如下配置。 -->
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/springmvc-context.xml</param-value>
		</init-param>
		
		<load-on-startup>1</load-on-startup>
	</servlet>
	<!-- 将DispatcherServlet映射到“/” -->
	<servlet-mapping>
		<servlet-name>stuspringmvc-xml</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	
</web-app>

    3、springmvc-context.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"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

	<!-- 配置注解驱动 -->
    <mvc:annotation-driven />

    <!-- 配置组件扫描器 -->
    <context:component-scan base-package="com.caofanqi.controller" >
    	<!-- 扫描带有@Controller注解的类 -->
    	<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
    	<!-- 不扫描带有@Service注解的类 -->
    	<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" />
    </context:component-scan>

	<!-- 配置视图解析器 -->
    <bean
      class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      <property name="prefix" value="/WEB-INF/views/" />
      <property name="suffix" value=".jsp" />
    </bean>
    
    <!-- 静态资源映射1 -->
	<mvc:default-servlet-handler/> 

	<!-- 静态资源映射2 -->
    <mvc:resources mapping="/resources/**" location="WEB-INF/resources/" />

</beans>

    4、root-context.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"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

	<!-- 配置组件扫描器 -->
	<context:component-scan base-package="com.caofanqi">
		<!-- 不扫描带有@Controller注解的类 -->
		<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
	</context:component-scan>

</beans>

    HomeController和home.jsp不变,访问

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

        c62984d6dd409b002dbf1c01d629afea024.jpg

到此,两种模式的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<Product>,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<Product> products() {
		return productService.listProducts();
	}

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

<c:forEach items="${productList}" var="product" >
          <li id="product_<c:out value="product.id"/>">
            <div class="productName"><c:out value="${product.name}" /></div>
            <div>
              <span class="productCreateTime"><c:out value="${product.createTime}" /></span>
              <span class="productPrice"><c:out value="${product.price}" /></span>
            </div>
          </li>
        </c:forEach>

 

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值