虽然一直用,因为基本不会遇到问题。
这里弄清楚一下
对tomcat,有4种
/* wildcardWrappers
*. extensionWrappers
/ defaultWrapper
其他 exactWrappers
优先级是
1.精确匹配最优先,exactWrappers
2.前缀匹配,wildcardWrappers /*
3.扩展名匹配,extensionWrappers *.
4.显示welcome
5.使用默认的servlet来处理,defaultWrapper /
到这里,就能区分开/*和/的区别了
例子,springmvc里,定义了/*来处理所有的请求给springmvc的DispatcherServlet,也定义了一个@RequestMapping为index.jsp,web目录里面也放一个index.jsp
如果输入http://xxxx/index.jsp,那么请求会被/*给拦截给springmvc,因为rule2比rule3优先。
如果springmvc的servlet里定义的是/, index.jsp就不会被拦截给springmvc,因为rule3比rule5高。
同时,我们还可能会碰到这样的问题
springmvc里面定义/*拦截,然后@RequestMapping定义为index,做一个viewResolver,指向WEB-INF/views/login.jsp。这个时候,如果访问index,会出现什么结果?
a。index会被springmvc拦截,然后去访问 WEB-INF/views/login.jsp
b。 结果WEB-INF/views/login.jsp又被springmvc再次拦截了(rule2比rule3优先级高)
结果导致出现
No mapping found for HTTP request with URI [/xiu_template/WEB-INF/views/login.jsp] in DispatcherServlet with name 'spring.mvc'
出来不了我们想要的东西。
解决法子,最简单的自然是定义springmvc为比如url-pattern *.html,然后访问index.html,然后去WEB-INF/views/login.jsp,然后去的*.jsp的servlet。是没有问题的。
如果就是不想用扩展名的的方法咋办?? url-pattern是没有exclude的。
其实,只要在web.xml里面多顶一个前缀匹配就ok了。default的名字,是固定的。tomcat还可以写为jsp,因为真正的名字是jsp(可以通过serveletcontext找到getServletRegistrations后知道里面注册的servelet是org.apache.jasper.servlet.JspServlet,名字是jsp)。
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/WEB-INF/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/resources/*</url-pattern>
</servlet-mapping>
追到这里,就不由想到难道springmvc就不能处理jsp或者static的东西了?查了一下,发现早就有一个
<mvc:default-servlet-handler/>来对应这个事情,定义了这个,拦截了后不能mapping的就给这个default了。
这下才算是完满了。 web.xml里面清爽了。
default-servlet-handler自动发现server(tomcat)的默认serlet,交个它来出来自己搞不定的事情。
那是不是说定义了这个东西,事情就算完了?我发现如果网站在default-servlet-handler和spring-security搭配起容易出问题。
2015年12月14日星期一
2015年11月27日星期五
context:property-placeholder vs PropertySourcesPlaceholderConfigurer
spring各个版本还不一样,目前最新的是
3.1前,property-placeholder 解析为 PlaceholderConfigurerSupport
3.1后,property-placeholder 解析为PropertySourcesPlaceholderConfigurer
关于父子容器
父亲里面定义的property-placeholder,儿子里面@Value读不到。
要想多个 property-placeholder,需要设置ignore-unresolvable="true" ,顺序靠order,但是是以order小的优先。比如order1先加载了keyA=valueA,order2里面如果有keyA=valueAA,order2里面的keyA=valueAA不会加载,所以内容仍然是order1里的valueA。
property-placeholder定义的内容进不了Environment,所以env.getProperty是拿不着东西,就算@Value拿到了也不行。
挺乱。
结论就是,不要再使用 property-placeholder了,以后要用 @PropertySource
@PropertySource自己并不会注册PropertySourcesPlaceholderConfigurer ,所以需要自己定义一个PropertySourcesPlaceholderConfigurer bean
@PropertySource的父子容器是
父亲定义的,儿子可以读取,@Value可以读,env可以读。
同一个容器里的多个 @PropertySource,就拼先后顺序了。
3.1前,property-placeholder 解析为 PlaceholderConfigurerSupport
3.1后,property-placeholder 解析为PropertySourcesPlaceholderConfigurer
关于父子容器
父亲里面定义的property-placeholder,儿子里面@Value读不到。
要想多个 property-placeholder,需要设置ignore-unresolvable="true" ,顺序靠order,但是是以order小的优先。比如order1先加载了keyA=valueA,order2里面如果有keyA=valueAA,order2里面的keyA=valueAA不会加载,所以内容仍然是order1里的valueA。
property-placeholder定义的内容进不了Environment,所以env.getProperty是拿不着东西,就算@Value拿到了也不行。
挺乱。
结论就是,不要再使用 property-placeholder了,以后要用 @PropertySource
@PropertySource自己并不会注册PropertySourcesPlaceholderConfigurer ,所以需要自己定义一个PropertySourcesPlaceholderConfigurer bean
@PropertySource的父子容器是
父亲定义的,儿子可以读取,@Value可以读,env可以读。
同一个容器里的多个 @PropertySource,就拼先后顺序了。
2015年11月13日星期五
spring的豆知识
http://docs.spring.io/spring-javaconfig/docs/1.0.0.M4/reference/html/ch06s02.html
<
context:annotation-config
/>,
@AnnotationDrivenConfigAnnotationConfigApplicationContext来实现的。有了它可以使用
@Configuration,@Bean然后
@Resource 、@PostConstruct、@PreDestroy
@PersistenceContext
@Autowired
@Required
有
@Autowired
就有了注入功能。不用再写ref=xxx了。自身并不创建bean。
<context:component-scan>@ComponentScan,包含了
component-scan所有的功能,另外加上了扫描到的
Component
的自动创建注册功能。@Component(以及后代
@Repository,@Service,@Controller,@RestController)都创建起来了。
这里
@Configuration其实已经注解了@Component了,它其实也是
@Component的后代。
<mvc:annotation-driven />
@EnableWebMvc,
@RequestMapping起作用了。提供了mvc里面的req到controller的mapping功能,没有它req
dispatch不到controller,也就是找不着
dispatch的对象。它对应JavaConfig里的@EnableWebMvc。当然相关的Mvc的配置也跟着就被调用了,如WebMvcConfigurerAdapter.configureContentNegotiation。
WebApplicationInitializer(AbstractAnnotationConfigDispatcherServletInitializer)相关的是启动时会被扫描,然后加载配置类,是完全拥有自己的Container(ServletContext)的。
配置类,
如果Initialize加载,就去配置Initializer里面创建的上下文ConfigWebApplicationContext属性,然后上下文属性在作用到里面创建的servlet(DispatcherServlet),当然一个ConfigWebApplicationContext可以创建多个servlet,也就是同一份配置,应用到了多个servlet,这些servlet共享一个上下文,也就是同一个Container里面的不同servlet共享bean了。
如果是被web.xml里面指定的servlet的ComponeScan扫描到,就去配置当前servlet的上下文,这里不会再次创建上下文,所以@Configure的类只是对已有的配置进行再配置。如果同一个servlet扫描到多个@Configure怎么办?我认为是后面的进一步补充前面的。
配置类里想要知道 自己被应用到哪些SerletContext了?我没找到方法。
另外,这些配置是不会被子container给继承的,比如root containter定义了
<mvc:annotation-driven />,它的child仍然需要定义。
http://techidiocy.com/annotation-config-vs-component-scan-spring-core/
http://www.cnblogs.com/fangqi/archive/2012/11/04/2748579.html
http://stackoverflow.com/questions/7414794/difference-between-contextannotation-config-vs-contextcomponent-scan
2015年9月29日星期二
http://www.toptal.com/angular-js/top-18-most-common-angularjs-developer-mistakes
http://www.toptal.com/angular-js/top-18-most-common-angularjs-developer-mistakes
2015年9月22日星期二
angular的动画,nganimate
https://docs.angularjs.org/api/ngAnimate,白话顺一遍 。
有几个方式来实现
1. css动画,CSS-based Animations
A。用
有几个方式来实现
1. css动画,CSS-based Animations
A。用
css 的transition
例子
/* The starting CSS styles for the enter animation */ .fade.ng-enter { transition:
opacity
0.5s linear 0s; opacity:0;这是动画开始属性 } /* The finishing CSS styles for the enter animation */ .fade.ng-enter.ng-enter-active { opacity:1;这是动画结束属性 }
transition的设置是:http://www.htmq.com/css3/transition.shtml
第一个是要trans的属性名(opacity),
第二个是要持续多长时间(0.5s),
第三个是用的算法(linear),
第四个是delay多久才执行(0s)。
B.用keyframe来实现
例子
.fade.ng-enter {
animation: fadeIn 1s;
},这里的fadeIn一般用别人的,animation.css里面定义了不少keyframe。
用keyframe方法不需要实现-active来表示结束。
CSS Staggering Animations这个好像没啥用,因为staggering指定的值,
可以用transtion的第四个值指定啊
JavaScript-based Animations类型的,没jquery的话,自己好像比较难搞。
2015年9月20日星期日
去掉debug log信息
search了一下,知道目前有一个gulp-strip-debug可以用来去掉 console, alert, and debugger,但是这个不是我想要的,因为我自己封装了一个logger。
再找,说gulp-uglify自己就带的有参数,
所以可以
.pipe($.uglify({ compress: {global_defs: {DEBUG: false}}})).on('error', conf.errorHandler('Uglify'))
来传递进去。这样在做production的时候,就会去删掉debug的代码。挺好。但是问题是,岂不是代码里到处都是if (DEBUG)。继续找
最后看到了gulp-defeatureify,直接设置去掉哪些功能,雖然它主要是給ember用的,但是仍然可以給angular用。
.pipe($.defeatureify({enableStripDebug: true, debugStatements: ['log.debug', 'log.debug.apply']}))
這樣,所有的log.debug代碼就都給去掉了。
再找,说gulp-uglify自己就带的有参数,
drop_console
可以去掉debugger,也并不是我想要的。另外http://lisperator.net/uglifyjs/compress里面可以定义变量,然后压缩的时候就会去掉里面的代码,这个的确是不错,我用的是gulp-uglify,它后面是call的uglifyjs,看https://www.npmjs.com/package/gulp-uglify所以可以
.pipe($.uglify({ compress: {global_defs: {DEBUG: false}}})).on('error', conf.errorHandler('Uglify'))
来传递进去。这样在做production的时候,就会去删掉debug的代码。挺好。但是问题是,岂不是代码里到处都是if (DEBUG)。继续找
最后看到了gulp-defeatureify,直接设置去掉哪些功能,雖然它主要是給ember用的,但是仍然可以給angular用。
.pipe($.defeatureify({enableStripDebug: true, debugStatements: ['log.debug', 'log.debug.apply']}))
這樣,所有的log.debug代碼就都給去掉了。
要留意的是,它删不掉这样的
self(this).log.debug('xxxx')
也就是, debugStatements里面设置的,必须是点[.]下去的的。
2015年9月11日星期五
调试gulp
1。要安装gulp-intercept
npm install gulp-intercept --save-dev
2。执行node-inspector
C:\Users\Jacky>node-inspector
Node Inspector v0.12.3
Visit http://127.0.0.1:8080/?ws=127.0.0.1:8080&port=5858 to start debugging.
3。windows上调试gulp,需要到应用的目录下
node-debug "C:\Users\Jacky\AppData\Roaming\npm\node_modules\gulp\bin\gulp.js" styles,这个会发现node-inspector,然后连接上node-inspector后启动chrome
unix上面 执行node-debug $(which gulp) styles
4。在chrome里面单步就可以了。
虽然这样可以调试gulp了,但是gulp的那一堆的pipe却是不行的,要想查看pipe里面的内容,需要用到gulp-print,gulp-debug,或者gulp-intercept,
gulp-print只能打印出filename
gulp-debug可以打印出filename以外的内容,但是仍然打印不出文件的内容自身
gulp-intercept才是最强,可以打印出所有的内容。
测试代码如下
.pipe(wiredep(_.extend({}, conf.wiredep)))
//.pipe($.print()) //only can print filename
/*.pipe($.print(function(filepath) { //custom print filename
return "built: " + filepath;
})
)
.pipe($.intercept(function(file){
//https://www.npmjs.com/package/vinyl
//console.log('file: ' + JSON.stringify(file));
console.log('file.cwd: ' + file.cwd );
console.log('file.base ' + file.base );
console.log('file.path: ' + file.path );
console.log('file.history: ' + file.history );
console.log('file.relative : ' + file.relative);
console.log('file.dirname : ' + file.dirname);
console.log('file.basename : ' + file.basename);
console.log('file.extname : ' + file.extname);
//https://nodejs.org/api/fs.html#fs_class_fs_stats
console.log('file.stat: ' + JSON.stringify(file.stat));
//console.log('file.contents.type: ' + file._contents.type);
//console.log('file.contents: ' + file.contents.toString() );
return file;})
)*/
//.pipe($.debug({title: 'zyz debug:', minimal: false}))
npm install gulp-intercept --save-dev
2。执行node-inspector
C:\Users\Jacky>node-inspector
Node Inspector v0.12.3
Visit http://127.0.0.1:8080/?ws=127.0.0.1:8080&port=5858 to start debugging.
3。windows上调试gulp,需要到应用的目录下
node-debug "C:\Users\Jacky\AppData\Roaming\npm\node_modules\gulp\bin\gulp.js" styles,这个会发现node-inspector,然后连接上node-inspector后启动chrome
unix上面 执行node-debug $(which gulp) styles
4。在chrome里面单步就可以了。
虽然这样可以调试gulp了,但是gulp的那一堆的pipe却是不行的,要想查看pipe里面的内容,需要用到gulp-print,gulp-debug,或者gulp-intercept,
gulp-print只能打印出filename
gulp-debug可以打印出filename以外的内容,但是仍然打印不出文件的内容自身
gulp-intercept才是最强,可以打印出所有的内容。
测试代码如下
.pipe(wiredep(_.extend({}, conf.wiredep)))
//.pipe($.print()) //only can print filename
/*.pipe($.print(function(filepath) { //custom print filename
return "built: " + filepath;
})
)
.pipe($.intercept(function(file){
//https://www.npmjs.com/package/vinyl
//console.log('file: ' + JSON.stringify(file));
console.log('file.cwd: ' + file.cwd );
console.log('file.base ' + file.base );
console.log('file.path: ' + file.path );
console.log('file.history: ' + file.history );
console.log('file.relative : ' + file.relative);
console.log('file.dirname : ' + file.dirname);
console.log('file.basename : ' + file.basename);
console.log('file.extname : ' + file.extname);
//https://nodejs.org/api/fs.html#fs_class_fs_stats
console.log('file.stat: ' + JSON.stringify(file.stat));
//console.log('file.contents.type: ' + file._contents.type);
//console.log('file.contents: ' + file.contents.toString() );
return file;})
)*/
//.pipe($.debug({title: 'zyz debug:', minimal: false}))
订阅:
博文 (Atom)