法会
天天喝咖啡的我,竟目睹这样的场景,之前真是井底之蛙,没敢去大海看看。这是我所见到的:
有一天,山泉水大神(spring 3.0)在舍卫山(servlet 3.0)下,和一群很硬的javaConfig小弟,有千八百号人马。
到了要上阵战场(war)的时间,spring 3.0大神抄起炸(jar)药包,指挥各路人马,进入舍卫附近的雄猫(tomcat)城,
去打仗了。
号令完毕便回到了原处。胜仗后,大神收好家伙,冲上82的爪哇咖啡,坐在垫(@)上。
善现
这时WebApplicationInitializer从众javaConfig小弟众站了起来,他偏袒右肩,右膝著地,抱拳恭敬地对大神说:
“大神!您善于教导每一个开发者,善于管理每一个java咖啡豆。”
“大神,开发者发愿要远离xml研磨咖啡,通过虔诚的硬叩(硬编码)方式抵达舍卫之巅获得上好的java咖啡豆。
请问我们应该怎么硬叩?我们应该如何戒掉xml研磨咖啡?
山泉水大神对WebApplicationInitializer说:“说得好,说得好!WebApplicationInitializer啊!如同你所说的,
我善于教导每一个开发者,善于管理每一个java咖啡豆。现在你仔细听啊!
开发者发心喝山泉水硬叩(使用spring 3.0)之后,应该要这样做,应该要这样戒掉xml研磨咖啡。”
WebApplicationInitializer说:“是的大神!我们很高兴能聆听您说法!”
大乘
山泉水大神对WebApplicationInitializer说:“各位大开发者们!我们应该要这样戒掉xml研磨咖啡。
一切的泉水豆(spring bean)不能再给到xml研磨,我们都要令他们硬叩成java咖啡豆,
使他们永远不再堕入食品不安全(类型不安全)、杂质太多(配置繁杂)、烘焙不够(使用java代码不自由)的痛苦轮回。”
“虽然我度化了无数开发者,让他们喝到xml研磨泉水豆的咖啡,但实际上我并不认为自己让开发者真正获得了java咖啡。”
“WebApplicationInitializer啊,如果一个开发者还有只喝你的硬叩咖啡、戒掉xml研磨咖啡、
xml研磨咖啡和javaConfig咖啡都喝、javaConfig咖啡好不好喝的主观想法,他就不是个开发者了。”
妙行
接着大神又说:“WebApplicationInitializer啊,开发者在喝java咖啡时,不要老喝老咖啡(稳定安全的旧代码),
咖啡是会过期变质的,应该更换掉老咖啡,喝新鲜的咖啡。
为什么呢?
如果开发者能够少喝老咖啡,那么身体也会更健康。
(没有绝对安全的代码,很多都会存在漏洞)”
“WebApplicationInitializer啊,我们在雄猫(tomcat)城战胜web.xml取得战利品怎样?”
public class MyWebAppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) {
XmlWebApplicationContext appContext = new XmlWebApplicationContext();
appContext.setConfigLocation("/WEB-INF/spring/spring-mvc.xml");
ServletRegistration.Dynamic dispatcher =
container.addServlet("dispatcher", new DispatcherServlet(appContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
“不好,XmlWebApplicationContext他自作聪明,急着喝咖啡,把泉水豆都用xml研磨了。
(spring bean还是配置在xml文件中)
他这样喝的咖啡和以前xml咖啡没有差别,五十步笑百步而已。”
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
“WebApplicationInitializer啊,那先让AnnotationConfigWebApplicationContext来替代他吧”
“好的,这可是大神麾下的猛将,教导开发者使用神兵(@Configuration、@Bean等注解方式)自己硬叩出
AppConfig、DispatcherConfig等口味(code way)的咖啡。”
@Configuration
public class AppConfig {
@Bean(name="helloBean")
public HelloWorld helloWorld() {
return new HelloWorldImpl();
}
}
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.xxx.springmvc")
public class DispatcherConfig{
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
public class MyWebAppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) {
// Create the 'root' Spring application context
AnnotationConfigWebApplicationContext rootContext =
new AnnotationConfigWebApplicationContext();
rootContext.register(AppConfig.class);
// Manage the lifecycle of the root application context
container.addListener(new ContextLoaderListener(rootContext));
// Create the dispatcher servlet's Spring application context
AnnotationConfigWebApplicationContext dispatcherContext =
new AnnotationConfigWebApplicationContext();
dispatcherContext.register(DispatcherConfig.class);
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher =
container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
“WebApplicationInitializer啊,你这DispatcherConfig是加了mvc咖啡伴侣的。无添加的咖啡你了解吗?”
“大神,我了解。就像下面这样。”
public class MyServlet extends HttpServlet {
private static final long serialVersionUID = 577211309543842236L;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
out.print("doGet");
/**
* todo
*/
out.close();
out = null;
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
out.print("doPost");
/**
* todo
*/
out.close();
out = null;
}
}
public class MyWebAppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) {
ServletRegistration.Dynamic myServlet=
servletContext.addServlet("myServlet", new MyServlet());
myServlet.addMapping("/myServlet");
}
}
“WebApplicationInitializer啊,开发者少喝了老咖啡是对身体健康的,但太多添加的咖啡也会使人不健康的。
这些添加都是为了中和咖啡的苦和酸(为了开发便捷),苦和酸都是与咖啡的萃取技术(开发者本身的能力)有关,
技术越好咖啡越香醇可口。细细品味咖啡的苦和酸,才能知道香醇不是咖啡伴侣可以替代的。
(开发者技术的历练是不能依赖框架的)
开发者应该学会山泉水的思想去硬叩,而不单单是喝山泉水咖啡。”
如理
“WebApplicationInitializer啊,还有什么办法让咖啡更纯?”
“大神,我觉得是过滤(filter)以及照看(Listener)好咖啡豆”
public class TestFilter implements Filter {
private static final Set<String> ALLOWED_PATHS = Collections.unmodifiableSet(new HashSet<>(
Arrays.asList( "/login", "/logout", "/register")));
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("init-----------filter");
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
String path = request.getRequestURI().substring(request.getContextPath().length()).replaceAll("[/]+$", "");
boolean allowedPath = ALLOWED_PATHS.contains(path);
if (allowedPath) {
System.out.println("这里是不需要处理的url进入的方法");
chain.doFilter(req, res);
} else {
System.out.println("这里是需要处理的url进入的方法");
System.out.println(((HttpServletRequest) req).getRequestURI());
//chain.doFilter(req, res);
}
}
@Override
public void destroy() {
System.out.println("destroy----------filter");
}
}
public class MyListener implements ServletContextListener {
@Override
public final void contextInitialized(ServletContextEvent sce) {
//执行初始化操作
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
//执行销毁操作
}
}
public class MyWebAppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) {
/**编码过滤器*/
FilterRegistration.Dynamic characterEncodingFilter = container
.addFilter("encodingFilter", new CharacterEncodingFilter());
characterEncodingFilter.setInitParameter("encoding", "UTF-8");
characterEncodingFilter.setInitParameter("forceEncoding", "true");
characterEncodingFilter.addMappingForUrlPatterns(null, false, "/*");
/**自定义过滤器*/
FilterRegistration.Dynamic testFilter = container
.addFilter("testFilter", new TestFilter());
testFilter.addMappingForUrlPatterns(null, false, "/*");
/**监听器*/
container.addListener(ConfigListener.class);
}
}
“WebApplicationInitializer啊,你能以过滤(filter)、照看方式(listener)以及喝纯咖啡(servlet)
来判断他是不是开发的大神?”
“不能啊!我无法以过滤(filter)、照看方式(listener)以及喝纯咖啡(servlet)来评断一个人。
因为我们看的只是他的表面,最终制作的咖啡好不好,需要去喝才知道。”
山泉水大神告诉WebApplicationInitializer说:“凡是所有咖啡,都是我们主观所品尝的味道。
如果能尝到咖啡的原始芳香,便能够接近大神。”(所有的编码思想,都是我们主观所理解的那样,
没了复制粘贴可能就忘了,如果能理解清楚源码思想并且可以加以利用,这才是真大神。)
正信
WebApplicationInitializer向山泉水大神说:“大神!大家听了这些话,他们会相信吗?”
山泉水大神对WebApplicationInitializer说:“WebApplicationInitializer啊!你不要那么悲观。在我逝去五百年之后
(后续的spring版本),使用javaConfig硬叩的开发者们,都还能从这些话产生信心(后续的版本会继续推荐javaConfig)
,你应当相信我的话是真实不虚的(spring源码的思想都很值得我们学习)。”
“听到这些章句(编码)而获到好咖啡的人,他一定知道:这些章句(编码)不只是由一个、两个、三四五个大神们
所积累出来的成果,而是由数不尽的千千万万大神们所共同积累的智慧。”
“WebApplicationInitializer啊!大神们所培育的咖啡树,是所有开发者的one piece。”
“为什么呢?开发者们面对任何java咖啡时,不再乱喝肥宅咖啡、乱喝不健康的咖啡、乱喝不合时间的咖啡,
不再只喝而不会制作自己喜欢的咖啡,这就真正获得了java咖啡。”
“如果开发者们用泉水豆来获得咖啡,用主观味觉去品尝咖啡,即是着了咖啡的香气而已
(开发者使用spring框架时,如果只是觉得好用就用,这就像为了框架而用框架)。
因为为了自己的味觉,不自觉就添加了很多糖、奶之类的,影响了咖啡原有的香醇以及身体健康
(框架不是那么容易使用的,都是需要学习的,而且不同框架之前还需要整合,这就会影响了开发)。
所以我们不使自己的味觉陷于甜蜜的口感享受,更不要为了自己的主观口感去伤害身体。
所以我常说:你们这些小弟早就应该听懂我所说的纯正咖啡了。”
“例如,咖啡粉渣是为了烹煮出香醇的咖啡,煮完之后咖啡粉渣便可以抛去了。
好的咖啡粉煮过或者氧化变味了都应该舍弃了,更何况是不好的咖啡豆呢?”
(使用框架是为了节约开发成本,核心代码开发出来,框架就可以用更高效的代码替代)。
结后语:
这篇文章纯属娱乐,下篇会正式把spring的javaConfig技术做介绍。