spring实战第四版-第五章学习遇到的一个小问题

我承认,是我spring的渣渣功底导致了如今这不可挽回的局面。。。


这本书第五章主要讲述如何用纯java配置来完成springmvc程序的构建。


主要就是讲,实现了spring的AbstractAnnotationConfigDispatcherServletInitializer类的java类来作为总配置文件,

关于为啥实现它了就能基于java配置要讲一下

因为在Servlet3.0环境中,容器会在类路径中查找javax.servlet.ServletContainerInitializer接口的实现类,找到就用实现类来

配置Servlet容器,而spring提供了这个实现,是SpringServletContainerInitializer类,而后者就被赋予了这种能力,它会

反过来找有没有实现它spring自己的WebApplicationInitializer接口的类,找到则将自己的配置容器的任务交给它,

而前面提到的老长一串的类名,AbstractAnnotationConfigDispatcherServletInitializer就是一个基础的实现,所以我们实现它,稍作修改就可以了。

下面:

package spittr.config;

import javax.servlet.Filter;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;

import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
/*
 * 实现了抽象注解配置DispatcherServlet初始化器 
 **/
public class SpittrWebAppInitializer 
			extends AbstractAnnotationConfigDispatcherServletInitializer{
	//获取系统级配置
	@Override
	protected Class<?>[] getRootConfigClasses() {
		
		return new Class<?>[]{RootConfig.class};
	}
	//获取服务级配置
	@Override
	protected Class<?>[] getServletConfigClasses() {
		return new Class<?>[]{WebConfig.class};
	}
	//获取Servlet接收请求的范围
	@Override
	protected String[] getServletMappings() {
		
		return new String[]{"/"};
	}
	
	@Override
	public Filter[] getServletFilters() {
		CharacterEncodingFilter cd
		=new CharacterEncodingFilter();
		
		cd.setEncoding("UTF-8");
		return new Filter[]{cd};
	}
	
	@Override
	public void onStartup(ServletContext servletContext) throws ServletException {
		
		
		
		super.onStartup(servletContext);
		
	}
}
大概这么个东西,而RootConfig是一个普通的基于java配置的spring配置文件,功能上和application.xml差不多

package spittr.config;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.context.annotation.Bean;
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.web.servlet.config.annotation.EnableWebMvc;

import spittr.Spittle;
import spittr.data.SpittleRepository;

@Configuration
@ComponentScan(basePackages={"spittr"},
//扫描时排除这些内容
excludeFilters={
	@Filter(type=FilterType.ANNOTATION,value=EnableWebMvc.class)	
	,@Filter(type=FilterType.REGEX,pattern="spittr.web.*")
})
public class RootConfig {
	@Bean
	public SpittleRepository spittleRepository(){
		return new SpittleRepository() {
			
			@SuppressWarnings("serial")
			public List<Spittle> findSpittles(long max, int count) {
				return new ArrayList<Spittle>(){
					{
						add(new Spittle("消息1",new Date()));
						add(new Spittle("消息2",new Date(),15.0,65.0));
					}
				};
				
			}

			public Spittle findOne(long spittleId) {
				return new Spittle("傻逼",new Date());
			}
		};
		
		
	}
	/**应该是RootConfig先扫描,因为扫描范围中有spittr.web的范围,所以想装填,但发现没有对应的bean,就报错了*/
	/*@Bean
	public SpitterRepository spitterRepository(){
		return new SpitterRepository() {
			private Map<String,Spitter> spitterList=new HashMap<String,Spitter>();
			public Spitter save(Spitter unsaved) {
				spitterList.put(unsaved.getUsername(),unsaved);
				return unsaved;
			}

			public Spitter findByUsername(String username) {
				System.out.println(spitterList);
				return spitterList.get(username);
			}
		};
	}*/
	
	
	
}
@Configuration 表明这是个java配置类
@ComponentScan是注解扫描,basepackages表明这个包以及它的后代都会被扫描
excludeFilters里的是排除过滤器,即扫描时排除类上有EnableWebMvc注解的bean
和根据正则来判断的,排除spittr.web包下的类,至于为啥排除。。。等会说


,而WebConfig是实现了Spring的WebMvcConfigurerAdapter类的专门服务SpringMvc的一个配置文件

package spittr.config;

import java.util.HashMap;
import java.util.Map;

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.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

import spittr.data.Spitter;
import spittr.data.SpitterRepository;

//配置基于注解的web配置
@Configuration
//作用相当于<mvc:annotation-driven>
@EnableWebMvc
@ComponentScan("spittr.web")
public class WebConfig 
//继承webmvc配置类适配器
extends WebMvcConfigurerAdapter{
	//视图解析Bean 相当于当年的那啥
	
	
	@Bean
	public ViewResolver viewResolver(){
		
		System.out.println("视图解析疯狂奔跑!");
		
		//创建视图解析bean,这个bean我们用过,当年xml就是配置的这个
		//拼接而成的路徑,因此不要忘记路径分隔符等东西
		InternalResourceViewResolver resolver=
				new InternalResourceViewResolver();
		resolver.setPrefix("/WEB-INF/views/");
		resolver.setSuffix(".jsp");
		//设置是否将所有spring上下文中的bean都作为请求属性访问
		resolver.setExposeContextBeansAsAttributes(true);
		return resolver;
	}
	//配置静态资源的处理
	@Override
	public void configureDefaultServletHandling(DefaultServletHandlerConfigurer
			configurer){
		configurer.enable();
	}
	
	@Bean
	public SpitterRepository spitterRepository(){
		System.out.println("spitter");
		return new SpitterRepository() {
			private Map<String,Spitter> spitterList=new HashMap<String,Spitter>();
			public Spitter save(Spitter unsaved) {
				spitterList.put(unsaved.getUsername(),unsaved);
				return unsaved;
			}

			public Spitter findByUsername(String username) {
				System.out.println(spitterList);
				return spitterList.get(username);
			}
		};
	}

}


好,问题来了,spittr.web中的一个类要用到实现SpitterRepository接口的对象。

我刚开始是在WebConfig中添加的Bean,启动报错说找不到,提示NoSuchBean

放在RootConfig就好使了,我知道RootConfig先于WebConfig,因为后者只服务SpringMvc,前者服务整个项目。


想起来RootConfig扫描的时候就扫描到spittr.web中的类了,bean初始化就要找自动装填的实现SpitterRepository接口的对象,但

我把他放在WebConfig里了,环境中找不到这个Bean,于是报错。

所以我在RootConfig中的ComponentScan里添加了过滤,不扫描spittr.web,这样spittr.web中的bean就不会在NoSuchBean的情况下提前初始化了,启动成功。


不过好像还有个懒惰加载的选项。。。。总感觉那个才是首选。。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值