springMvc02 基于注解版本的

1.springMvc基于注解版(maven项目)

1.1 先引入springMvc和Servlet3.0的依赖包

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>cn.hxl</groupId>
  <artifactId>SpringMvc</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
   <dependencies>
      <!-- springmvc依赖 -->
      <dependency>
      	<groupId>org.springframework</groupId>
      	<artifactId>spring-webmvc</artifactId>
      	<version>4.3.13.RELEASE</version>
      </dependency>
      <dependency>
      	<groupId>javax.servlet</groupId>
      	<artifactId>servlet-api</artifactId>
      	<version>3.0-alpha-1</version>
      	 <!--防止冲突   于tomcat中的servlet冲突  -->
      	<scope>provided</scope>
      </dependency>
   </dependencies>
   <!-- 编译maven编译war的插件 -->
  <build>
      <plugins>
        <plugin>
        	<groupId>org.apache.maven.plugins</groupId>
        	<artifactId>maven-war-plugin</artifactId>
        	<version>2.6</version>
        	<configuration>
        	<!--不需要war  -->
        	    <failOnMissingWebXml>false</failOnMissingWebXml>
        	</configuration>
        </plugin>
      </plugins>
  </build>
</project>

1.2 我们了解一下springMvc启动的原理

引入springMvc的依赖包,springMvc中的spring-web中就会找到 METAINF/services/javax.servlet.ServletContainerInitializer中可以找springMvc启动时 绑定的servlet启动类 org.springframework.web.SpringServletContainerInitializer

在这里插入图片描述

2.查看org.springframework.web.SpringServletContainerInitializer的如何实现的

package org.springframework.web;

import java.lang.reflect.Modifier;
import java.util.LinkedList;
import java.util.List;
import java.util.ServiceLoader;
import java.util.Set;
import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.HandlesTypes;

import org.springframework.core.annotation.AnnotationAwareOrderComparator;

@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {



	@Override
	public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
			throws ServletException {

		List<WebApplicationInitializer> initializers = new LinkedList<WebApplicationInitializer>();

		if (webAppInitializerClasses != null) {
			for (Class<?> waiClass : webAppInitializerClasses) {
				// Be defensive: Some servlet containers provide us with invalid classes,
				// no matter what @HandlesTypes says...
				if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
						WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
					try {
						initializers.add((WebApplicationInitializer) waiClass.newInstance());
					}
					catch (Throwable ex) {
						throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
					}
				}
			}
		}

		if (initializers.isEmpty()) {
			servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
			return;
		}

		AnnotationAwareOrderComparator.sort(initializers);
		servletContext.log("Spring WebApplicationInitializers detected on classpath: " + initializers);

		for (WebApplicationInitializer initializer : initializers) {
			initializer.onStartup(servletContext);
		}
	}

}

2.1.实现了sevlet中的ServletContainerInitializer接口 重写了onStartup() Modifier 是查找方法的修饰符(抽空看一下) 主要查找出WebApplicationInitializer的实现类来继续调用onStartup()实现初始化

2.2.SpringServletContainerInitializer绑定的是@HandlesTypes({WebApplicationInitializer.class}) springMvc绑定的启动类 * 项目启动时会加载WebApplicationInitializer类以及其的实现类

*2.2.1.AbstractContextLoaderInitializer 容器初始化启动的加载的文件 * 创建一个根容器 将此容器加到servletContext的上下文中

package org.springframework.web.context;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.context.ApplicationContextInitializer;
import org.springframework.web.WebApplicationInitializer;
public abstract class AbstractContextLoaderInitializer implements WebApplicationInitializer {

	protected final Log logger = LogFactory.getLog(getClass());


	@Override
	public void onStartup(ServletContext servletContext) throws ServletException {
		registerContextLoaderListener(servletContext);
	}

	
	protected void registerContextLoaderListener(ServletContext servletContext) {
		//创建一个根容器
		WebApplicationContext rootAppContext = createRootApplicationContext();
		if (rootAppContext != null) {
			//如何根容器不为null  将根容器加到  ContextLoaderListener  容器的监听类中
			ContextLoaderListener listener = new ContextLoaderListener(rootAppContext);
			//将此容器转化为spring的容器
			listener.setContextInitializers(getRootApplicationContextInitializers());
			//注册监听器为项目启动时加载
			servletContext.addListener(listener);
		}
		else {
			logger.debug("No ContextLoaderListener registered, as " +
					"createRootApplicationContext() did not return an application context");
		}
	}

	protected abstract WebApplicationContext createRootApplicationContext();

	protected ApplicationContextInitializer<?>[] getRootApplicationContextInitializers() {
		return null;
	}

}

* 2.2.2.AbstractDispatcherServletInitializer 容器实现DispatcherServlet的初始化的抽象类,主要针对于DispatcherServlet registerDispatcherServlet(servletContext); 注册dispatcherServlet

package org.springframework.web.servlet.support;
  import java.util.EnumSet;
  import javax.servlet.DispatcherType;
  import javax.servlet.Filter;
  import javax.servlet.FilterRegistration;
  import javax.servlet.FilterRegistration.Dynamic;
  import javax.servlet.ServletContext;
  import javax.servlet.ServletException;
  import javax.servlet.ServletRegistration;              
  import org.springframework.context.ApplicationContextInitializer;
  import org.springframework.core.Conventions;
  import org.springframework.util.Assert;
  import org.springframework.util.ObjectUtils;
  import org.springframework.web.context.AbstractContextLoaderInitializer;
  import org.springframework.web.context.WebApplicationContext;
  import org.springframework.web.servlet.DispatcherServlet;
  import org.springframework.web.servlet.FrameworkServlet;
               
  public abstract class AbstractDispatcherServletInitializer extends
           AbstractContextLoaderInitializer {
                      	public static final String DEFAULT_SERVLET_NAME = "dispatcher";
    	@Override
    	public void onStartup(ServletContext servletContext) throws ServletException {
    		super.onStartup(servletContext);
    		registerDispatcherServlet(servletContext);
    	}

	protected void registerDispatcherServlet(ServletContext servletContext) {
		//  servletName=dispatcher
		String servletName = getServletName();
		//非空校验
		Assert.hasLength(servletName, "getServletName() must not return empty or null");
        //创建  WebApplicationContext  web的上下文
		WebApplicationContext servletAppContext = createServletApplicationContext();
		//非空判断
		Assert.notNull(servletAppContext,
				"createServletApplicationContext() did not return an application " +
				"context for servlet [" + servletName + "]");
        //创建dispatcherServlet     new DispatcherServlet(servletAppContext)
		FrameworkServlet dispatcherServlet = createDispatcherServlet(servletAppContext);
		//设置初始化参数  预留方法
		dispatcherServlet.setContextInitializers(getServletApplicationContextInitializers());
        //注册  dispatcherServlet 成为一个servlet服务
		ServletRegistration.Dynamic registration = servletContext.addServlet(servletName, dispatcherServlet);
		//非空判断
		Assert.notNull(registration,
				"Failed to register servlet with name '" + servletName + "'." +
				"Check if there is another servlet registered under the same name.");
        /**
         * 注册初始化参数   
         *  LoadOnStartup=1
         *  ServletMapping 映射的路径
         *  异步支持
         */
		registration.setLoadOnStartup(1);
		registration.addMapping(getServletMappings());
		registration.setAsyncSupported(isAsyncSupported());
         //获取所有的过滤器   注册为filter服务
		Filter[] filters = getServletFilters();
		if (!ObjectUtils.isEmpty(filters)) {
			for (Filter filter : filters) {
				registerServletFilter(servletContext, filter);
			}
		}

		customizeRegistration(registration);
	}
	protected String getServletName() {
		return DEFAULT_SERVLET_NAME;
	}
	protected abstract WebApplicationContext createServletApplicationContext();

	protected FrameworkServlet createDispatcherServlet(WebApplicationContext servletAppContext) {
		return new DispatcherServlet(servletAppContext);
	}

	protected ApplicationContextInitializer<?>[] getServletApplicationContextInitializers() {
		return null;
	}
	protected abstract String[] getServletMappings();
	protected Filter[] getServletFilters() {
		return null;
	}

	protected FilterRegistration.Dynamic registerServletFilter(ServletContext servletContext, Filter filter) {
    		String filterName = Conventions.getVariableName(filter);
    		Dynamic registration = servletContext.addFilter(filterName, filter);
    		if (registration == null) {
    			int counter = -1;
    			while (counter == -1 || registration == null) {
    				counter++;
    				registration = servletContext.addFilter(filterName + "#" + counter, filter);
    				Assert.isTrue(counter < 100,
    						"Failed to register filter '" + filter + "'." +
    						"Could the same Filter instance have been registered already?");
    			}
    		}
    		registration.setAsyncSupported(isAsyncSupported());
    		registration.addMappingForServletNames(getDispatcherTypes(),false, getServletName());
        		return registration;
        	}


	private EnumSet<DispatcherType> getDispatcherTypes() {
		return (isAsyncSupported() ?
				EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.ASYNC) :
				EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE));
	}
	protected boolean isAsyncSupported() {
		return true;
	}

	protected void customizeRegistration(ServletRegistration.Dynamic registration) {
	}

}

* 2.2.3.AbstractAnnotationConfigDispatcherServletInitializer 容器配置DispatcherServlet的注解的类 集成AbstractDispatcherServletInitializer 创建带有@Component @Configuration的父子容器类

     package org.springframework.web.context.support;
    import org.springframework.util.ObjectUtils;
    import org.springframework.web.context.WebApplicationContext;
    import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
    
    public abstract class AbstractAnnotationConfigDispatcherServletInitializer
    		extends AbstractDispatcherServletInitializer {/**
	 * 创建一个AnnotationConfigWebApplicationContext 
	 * getRootConfigClasses   将spring的信息注册进去
	 * 
	 * @return
	 */
	@Override
	protected WebApplicationContext createRootApplicationContext() {
		Class<?>[] configClasses = getRootConfigClasses();
		if (!ObjectUtils.isEmpty(configClasses)) {
			AnnotationConfigWebApplicationContext rootAppContext = new AnnotationConfigWebApplicationContext();
			rootAppContext.register(configClasses);
			return rootAppContext;
		}
		else {
			return null;
		}
	}

	/**
	 * 创建一个AnnotationConfigWebApplicationContext 
	 *   getServletConfigClasses  将dispatcherservlet的配置注册进去
	 *   
	 * @return
	 */
	@Override
	protected WebApplicationContext createServletApplicationContext() {
		AnnotationConfigWebApplicationContext servletAppContext = new AnnotationConfigWebApplicationContext();
		Class<?>[] configClasses = getServletConfigClasses();
		if (!ObjectUtils.isEmpty(configClasses)) {
			servletAppContext.register(configClasses);
		}
		return servletAppContext;
	}
	protected abstract Class<?>[] getRootConfigClasses();
	protected abstract Class<?>[] getServletConfigClasses();
	}

1.3 进入正题,我们使用注解需要继承AbstractAnnotationConfigDispatcherServletInitializer 重新写里面的方法

package cn.itcast;

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

import cn.itcast.myMvcConfig.Appconfig;
import cn.itcast.myMvcConfig.RootConfig;
/**
 * 继承抽象的注解的dispatcherServlet的初始化容器
 * @author hxl
 *
 */
public class MyAnocationDispatcherServletInitialer extends AbstractAnnotationConfigDispatcherServletInitializer {
    
	@Override
	//创建根容器(spring的配置文件)
	protected Class<?>[] getRootConfigClasses() {
		return new Class<?>[]{RootConfig.class};
	}

	@Override
	//创建springmvc容器(mvc的配置文件)
	protected Class<?>[] getServletConfigClasses() {
		return new Class<?>[]{Appconfig.class};
	}

	@Override
	//映射的路径   /拦截所有请求  包括静态资源  不包括jsp页面
	 //   /*  包括jsp文件
	protected String[] getServletMappings() {
		return new String[]{"/"};
	}

}

spring父容器的配置类

package cn.itcast.myMvcConfig;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
/**
 * spring 父容器只扫描service和dao
 * 不扫描controller
 * 
 * @author hxl
 *
 */
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
@ComponentScan(value="cn.itcast",excludeFilters={
		@Filter(type=FilterType.ANNOTATION,classes={Controller.class})})
public class RootConfig {


}

springMvc子容器的配置类

package cn.itcast.myMvcConfig;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import cn.itcast.intercepter.MyInterCptor;
/**
 * spring mvc 只扫描Contrller  子容器  
 * 
 * useDefaultFilters=false  禁用默认的扫描规则
 * @author hxl
 *
 */
@EnableWebMvc
//相当于mvc:annocation-driven  开启springmvc的高级配置
/**
 * 实现web
 * @author hxl
 *  实现WebMvcConfigurer重新方法即可配置springmvc的各种配置
 *  包括静态资源  上传下载    路径映射
 *  WebMvcConfigurerAdapter 和WebMvcConfigurer一样,只不过为我们
 *  提供了空的实现,方便我们只配置自己想要的实现
 */
@ComponentScan(value="cn.itcast",includeFilters={
		@Filter(type=FilterType.ANNOTATION,classes={Controller.class})}
 ,useDefaultFilters=false)
public class Appconfig extends WebMvcConfigurerAdapter{
   //定制功能  
   //视图解析器
	@Override
	public void configureViewResolvers(ViewResolverRegistry registry) {
		//super.configureViewResolvers(registry);
		registry.jsp();//==jsp("/WEB-INF/", ".jsp");
		//registry.jsp("/WEB-INF/jsp/",".jsp");
	}
	//静态资源访问  相当于 <rerources>
	@Override
	public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
		//super.configureDefaultServletHandling(configurer);
		configurer.enable();
	}
	//拦截器  相当于  inctecptor
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		//super.addInterceptors(registry);
		registry.addInterceptor(new MyInterCptor()).addPathPatterns("/**");
	}
}

简单请求和视图解析器测试

package cn.itcast.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import cn.itcast.service.UserService;

@Controller
public class UserController {
    @RequestMapping("/hello")
    @ResponseBody
	public String hello(){
		return "hello";
	}
    
    @RequestMapping("/sucess")
    //视图解析器  返回jsp页面  跳转到WEB-INF/jsp/success.jsp
	public String sucess(){
		return "success";
	}
}

过滤器配置类

package cn.itcast.intercepter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
/**
 * 自定义拦截器
 * @author hxl
 *
 */
public class MyInterCptor implements HandlerInterceptor {
    //发放执行之前
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("preHandle=======");
		//此处返回false直接结束,返回true执行request请求流程
		return true;
	}
    //方法执行正确后执行
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("postHandle=======");
	}
    //页面相应之后执行
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("afterCompletion=======");
	}

}

配置完成之后如果能正常访问ok,以上我的拙略之见,如有不对欢迎雅正。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值