﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>语源科技BlogJava-不做浮躁的人</title><link>http://www.blogjava.net/bjwulin/</link><description>正在行走的人...</description><language>zh-cn</language><lastBuildDate>Fri, 17 Apr 2026 07:49:44 GMT</lastBuildDate><pubDate>Fri, 17 Apr 2026 07:49:44 GMT</pubDate><ttl>60</ttl><item><title>ubuntu server下安装apache,mysql,tomcat。</title><link>http://www.blogjava.net/bjwulin/archive/2014/02/19/410032.html</link><dc:creator>不做浮躁的人</dc:creator><author>不做浮躁的人</author><pubDate>Wed, 19 Feb 2014 05:04:00 GMT</pubDate><guid>http://www.blogjava.net/bjwulin/archive/2014/02/19/410032.html</guid><wfw:comment>http://www.blogjava.net/bjwulin/comments/410032.html</wfw:comment><comments>http://www.blogjava.net/bjwulin/archive/2014/02/19/410032.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bjwulin/comments/commentRss/410032.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bjwulin/services/trackbacks/410032.html</trackback:ping><description><![CDATA[一直想用nginx，因为传说很快，可惜对f4f只在商用中支持，所以，暂时放弃，还是继续用用apache。<br />1、安装apache很简单，先例行公事：sudo apt-cache search apache|grep apache，查找到里面的apache2，执行sudo apt-get install apache2，很快就安装完，安装完后执行http://127.0.0.1，如果出现it works,那就表示安装正确。<br />备注：Apache的默认文档根目录是在Ubuntu上的/var/www目录，配置文件是 /etc/apache2/apache2.conf。配置存储的子目录在/etc/apache2目录，apache重启命令：sudo /etc/init.d/apache2 restart<br /><br />2、安装mysql也很简单，先例行公事：sudo apt-cache search mysql|grep server，可以看到里面的mysql-server后面跟着"metapackage depending on the latest version"，因此直接安装mysql-server可以获得最新版本。执行：sudo apt-get install mysql-server mysql-client，安装完后执行mysql -uroot -p，输入默认密码root，即可登录mysql client的操作界面。<br />mysql默认配置文件路径：/etc/mysql/my.cnf<br /><br />3、安装tomcat7，例行公事：sudo apt-cache search tomcat7，然后执行sudo apt-get install tomcat7 tomcat7-admin。安装完毕后，在浏览器输入http://127.0.0.1:8080，出现it works...表示你成功了。<br />备注：tomcat7一般放在/var/lib/tomcat7/webapps。<br /><br />4、整合apache2和tomcat7<br />a、安装mod-jk,sudo apt-get install libapache2-mod-jk <br />b、编辑tomcat配置文件：sudo nano /etc/tomcat7/server.xml ，讲&#8221;&lt;Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /&gt;&#8220;的注释去掉。<br />c、在/etc/apache2/下新建workers.properties，sudo nano /etc/apache2/workers.properties,输入以下内容：<br /><div>worker.list=worker1 <br /><br />worker.worker1.type=ajp13 <br />worker.worker1.host=localhost<br />worker.worker1.port=8009<br />d、编辑jk.conf文件，执行sudo nano /etc/apache2/mods-enabled/jk.conf。将JkWorkersFile修改为：/etc/apache2/workers.properties<br />e、最后配置转发路径，即符合规则的路径由apache转发给tomcat7。编辑000-default.conf文件，执行：sudo nano /etc/apache2/sites-enabled/000-default.conf，在该文件中增加：<br /><div>&lt;VirtualHost *:80&gt;<br />...<br />JkMount /tomcat-test* worker1<br />&lt;/VirtualHost *:80&gt;<br />至此配置都完了。我们用了/tomcat-test*，表示访问这个webapp时转发给worker1进行处理，因此我们还需要做一个tomcat-test应用来进行测试。<br />f、我们在/var/lib/tomcat7/webapps建立一个测试app，依次执行命令：cd /var/lib/tomcat7/webapps，sudo mkdir tomcat-test ， cd tomcat-test ，<br /><div>sudo mkdir test ， cd test ， sudo nano index.jsp，并在index.jsp文件中输入以下内容：</div><div>&lt;HTML&gt;<br />&nbsp;&lt;HEAD&gt;<br />&nbsp; &lt;TITLE&gt;Hello World&lt;/TITLE&gt;<br />&nbsp;&lt;/HEAD&gt;<br />&nbsp;&lt;BODY&gt;<br />&nbsp; &lt;H1&gt;Hello World&lt;/H1&gt;<br />&nbsp; Today is: &lt;%= new java.util.Date().toString() %&gt;<br />&nbsp;&lt;/BODY&gt;<br />&lt;/HTML&gt;</div>在浏览器中输入：http://192.168.1.10:8080/tomcat-test/test/index.jsp，验证是否正常。<br /><br />g、重启tomcat7和apache2，执行命令：sudo /etc/init.d/tomcat7 restart和sudo /etc/init.d/apache2 restart，然后在浏览器中输入：<div>http://192.168.1.10/tomcat-test/test/index.jsp，验证是否正常。</div><br /></div></div><br /><br /><img src ="http://www.blogjava.net/bjwulin/aggbug/410032.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bjwulin/" target="_blank">不做浮躁的人</a> 2014-02-19 13:04 <a href="http://www.blogjava.net/bjwulin/archive/2014/02/19/410032.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>redis 生产环境中的自动启动</title><link>http://www.blogjava.net/bjwulin/archive/2014/02/19/410019.html</link><dc:creator>不做浮躁的人</dc:creator><author>不做浮躁的人</author><pubDate>Wed, 19 Feb 2014 02:39:00 GMT</pubDate><guid>http://www.blogjava.net/bjwulin/archive/2014/02/19/410019.html</guid><wfw:comment>http://www.blogjava.net/bjwulin/comments/410019.html</wfw:comment><comments>http://www.blogjava.net/bjwulin/archive/2014/02/19/410019.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bjwulin/comments/commentRss/410019.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bjwulin/services/trackbacks/410019.html</trackback:ping><description><![CDATA[1、将redis源代码目录下utils下的redis_init_script文件复制到/etc/init.d，将文件名修改为redis_6000（6000表示我分配redis的监听端口号，下面6000都表示redis的端口号），然后修改文件里面的redisport=6000。<br />2、建立需要的文件夹，我们一般需要/etc/redis（用来存放redis的配置文件）以及/var/redis/6000（存放redis的持久文件）。<br />3、将解压的redis目录下的redis.conf拷贝到/etc/redis，并命名为redis_6000.conf，并对以下参数进行修改:<br />&nbsp;&nbsp;&nbsp; daemonize 修改为yes，确保redis以守护进程模式运行。<br />&nbsp;&nbsp;&nbsp; pidfile 修改为/var/run/redis_6000.pid<br />&nbsp;&nbsp;&nbsp; port修改为6000<br />&nbsp;&nbsp;&nbsp; dir修改为/var/redis/6000<br />&nbsp;&nbsp;&nbsp; 确定两个目录都存在。<br />4、执行：/etc/init.d/redis_6000 start启动redis，再执行sudo update-rc.d redis_6000 defaults。<br /><br />完毕。<img src ="http://www.blogjava.net/bjwulin/aggbug/410019.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bjwulin/" target="_blank">不做浮躁的人</a> 2014-02-19 10:39 <a href="http://www.blogjava.net/bjwulin/archive/2014/02/19/410019.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>thymeleaf与spring整合</title><link>http://www.blogjava.net/bjwulin/archive/2014/02/11/409734.html</link><dc:creator>不做浮躁的人</dc:creator><author>不做浮躁的人</author><pubDate>Tue, 11 Feb 2014 08:16:00 GMT</pubDate><guid>http://www.blogjava.net/bjwulin/archive/2014/02/11/409734.html</guid><wfw:comment>http://www.blogjava.net/bjwulin/comments/409734.html</wfw:comment><comments>http://www.blogjava.net/bjwulin/archive/2014/02/11/409734.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bjwulin/comments/commentRss/409734.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bjwulin/services/trackbacks/409734.html</trackback:ping><description><![CDATA[1、使用的是Spring EL而不是Ognl。<br />2、访问上下文的Bean用${@myBean.doSomething()}<br />3、th:field,th:errors,th:errorclass用于form processing。<br />4、要采用SpringTemplateEngine。<br />5、基本配置：<br /><div>&lt;bean id="templateResolver"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.thymeleaf.templateresolver.ServletContextTemplateResolver"&gt;<br />&nbsp; &lt;property name="prefix" value="/WEB-INF/templates/" /&gt;<br />&nbsp; &lt;property name="suffix" value=".html" /&gt;<br />&nbsp; &lt;property name="templateMode" value="HTML5" /&gt;<br />&lt;/bean&gt;<br />&nbsp;&nbsp; &nbsp;<br />&lt;bean id="templateEngine"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.thymeleaf.spring3.SpringTemplateEngine"&gt;<br />&nbsp; &lt;property name="templateResolver" ref="templateResolver" /&gt;<br />&lt;/bean&gt;<br /><br /><div>&lt;bean class="org.thymeleaf.spring3.view.ThymeleafViewResolver"&gt;<br />&nbsp; &lt;property name="templateEngine" ref="templateEngine" /&gt;<br />&nbsp; &lt;property name="order" value="1" /&gt;<br />&nbsp; &lt;property name="viewNames" value="*.html,*.xhtml" /&gt;<br />&lt;/bean&gt;</div></div><br />6、被@ModelAttribute注释的方法会在此controller每个方法执行前被执行，如果@ModelAttribute注释的方法有返回值，则表示在model中存放隐含名称的属性对象，比如返回Account，则相当于model.addAttribute("account",account)，如果@ModelAttribute(value="aname")注释方法，则表示在model中增加aname的属性值。@ModelAttribute注释一个方法的参数则表示从model中或者从Form表单或者url中获取。<br />7、 @RequestMapping("/hello")public void novoid() { }，返回视图为前缀+/hello+后缀，当方法返回Map,ModelMap等时都是相当于Request.setAttribute()。<br />8、&lt;td th:text="${{sb.datePlanted}}"&gt;13/01/2011&lt;/td&gt;双括号表示自动使用转换，常用于格式转换。<br />9、&lt;td th:text="${#strings.arrayJoin(#messages.arrayMsg(#strings.arrayPrepend(sb.features,'seedstarter.feature.')),', ')}"&gt;Electric Heating, Turf&lt;/td&gt;，首先将数组feathers都加上前缀，然后利用messages翻译国际化，最终组合成一个字符串。<br />10、用th:object指定command object，比如：&lt;form action="#" th:action="@{/save}" th:object="${person}" method="post"&gt;，两点限制，第一object只能是model 的直接attribute，不能使${person.baseInfo},第二，th:object的子级标签内不能再使用th:object。inputField使用：&lt;input type="text" th:field="*{datePlanted}" /&gt;。<br />12、checkbox标签：<div>&lt;div&gt;<br />&nbsp; &lt;label th:for="${#ids.next('covered')}" th:text="#{seedstarter.covered}"&gt;Covered&lt;/label&gt;<br />&nbsp; &lt;input type="checkbox" th:field="*{covered}" /&gt;<br />&lt;/div&gt;<br />checkbox array:<br /><div>&lt;ul&gt;<br />&nbsp; &lt;li th:each="feat : ${allFeatures}"&gt;<br />&nbsp;&nbsp;&nbsp; &lt;input type="checkbox" th:field="*{features}" th:value="${feat}" /&gt;<br />&nbsp;&nbsp;&nbsp; &lt;label th:for="${#ids.prev('features')}" th:text="#{${'seedstarter.feature.' + feat}}"&gt;Heating&lt;/label&gt;<br />&nbsp; &lt;/li&gt;<br />&lt;/ul&gt;<br /><br />13、radios:<br /><div>&lt;ul&gt;<br />&nbsp; &lt;li th:each="ty : ${allTypes}"&gt;<br />&nbsp;&nbsp;&nbsp; &lt;input type="radio" th:field="*{type}" th:value="${ty}" /&gt;<br />&nbsp;&nbsp;&nbsp; &lt;label th:for="${#ids.prev('type')}" th:text="#{${'seedstarter.type.' + ty}}"&gt;Wireframe&lt;/label&gt;<br />&nbsp; &lt;/li&gt;<br />&lt;/ul&gt;</div><br />14、dropdownlist or select。<br /><div>&lt;select th:field="*{type}"&gt;<br />&nbsp; &lt;option th:each="type : ${allTypes}" <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; th:value="${type}" <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; th:text="#{${'seedstarter.type.' + type}}"&gt;Wireframe&lt;/option&gt;<br />&lt;/select&gt;<br /><br />15、预处理：&lt;select th:field="*{rows[__${rowStat.index}__].variety}"&gt;而不使用&lt;select th:field="*{rows[rowStat.index].variety}"&gt;，因为spring el不会计算数组索引中的变量或者表达式。<br />16、错误显示：&lt;input type="text" th:field="*{datePlanted}" th:class="${#fields.hasErrors('datePlanted')}? fieldError" /&gt;<br /><div>&lt;ul&gt;<br />&nbsp; &lt;li th:each="err : ${#fields.errors('datePlanted')}" th:text="${err}" /&gt;<br />&lt;/ul&gt;</div><br /><div>&lt;input type="text" th:field="*{datePlanted}" /&gt;<br />&lt;p th:if="${#fields.hasErrors('datePlanted')}" th:errors="*{datePlanted}"&gt;Incorrect date&lt;/p&gt;</div><br /><div>&lt;input type="text" th:field="*{datePlanted}" class="small" th:errorclass="fieldError" /&gt;</div><br /><div>&lt;ul th:if="${#fields.hasErrors('*')}"&gt;<br />&nbsp; &lt;li th:each="err : ${#fields.errors('*')}" th:text="${err}"&gt;Input is incorrect&lt;/li&gt;<br />&lt;/ul&gt;</div>全局错误：<br /><div>&lt;ul th:if="${#fields.hasErrors('global')}"&gt;<br />&nbsp; &lt;li th:each="err : ${#fields.errors('global')}" th:text="${err}"&gt;Input is incorrect&lt;/li&gt;<br />&lt;/ul&gt;</div>在form外显示错误:<br /><div>&lt;div th:errors="${myForm}"&gt;...&lt;/div&gt;<br />&lt;div th:errors="${myForm.date}"&gt;...&lt;/div&gt;<br />&lt;div th:errors="${myForm.*}"&gt;...&lt;/div&gt;<br /><br />&lt;div th:if="${#fields.hasErrors('${myForm}')}"&gt;...&lt;/div&gt;<br />&lt;div th:if="${#fields.hasErrors('${myForm.date}')}"&gt;...&lt;/div&gt;<br />&lt;div th:if="${#fields.hasErrors('${myForm.*}')}"&gt;...&lt;/div&gt;<br /><br />&lt;form th:object="${myForm}"&gt;<br />&nbsp;&nbsp;&nbsp; ...<br />&lt;/form&gt;</div>17、利用功能类转换：#conversions.convert(Object,Class)，#conversions.convert(Object,String)<br />18、渲染模板的片段，常用于ajax，返回一部分文本做替换使用。<br />在ViewBean中指定片段：<br /><div>&lt;bean name="content-part" class="org.thymeleaf.spring3.view.ThymeleafView"&gt;<br />&nbsp; &lt;property name="templateName" value="index" /&gt;<br />&nbsp; &lt;property name="fragmentSpec"&gt;<br />&nbsp;&nbsp;&nbsp; &lt;bean class="org.thymeleaf.standard.fragment.StandardDOMSelectorFragmentSpec"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c:selectorExpression="content" /&gt; <br />&nbsp; &lt;/property&gt;<br />&lt;/bean&gt;</div><br /><div>@RequestMapping("/showContentPart")<br />public String showContentPart() {<br />&nbsp;&nbsp;&nbsp; ...<br />&nbsp;&nbsp;&nbsp; return "content-part";//返回上面定义的bean名称。<br />}<br /><div><div>c:selectorExpression="content"：需要在content节点加上th:fragment。</div>c:selectorExpression="#content" ：完全基于html dom selector，无需th:fragment。<br />在controller中指定片段：<br /><div>@RequestMapping("/showContentPart")<br />public String showContentPart() {<br />&nbsp;&nbsp;&nbsp; ...<br />&nbsp;&nbsp;&nbsp; return "index :: content";<br />}</div><div>"index :: content"和"index ::#content"区别一样。<br />还可以返回带参数的片段：<br /><div>@RequestMapping("/showContentPart")<br />public String showContentPart() {<br />&nbsp;&nbsp;&nbsp; ...<br />&nbsp;&nbsp;&nbsp; return "index :: #content ('myvalue')";<br />}</div></div></div><br /><br /></div><br /><br /></div></div></div><br /><br /><br /><br /><img src ="http://www.blogjava.net/bjwulin/aggbug/409734.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bjwulin/" target="_blank">不做浮躁的人</a> 2014-02-11 16:16 <a href="http://www.blogjava.net/bjwulin/archive/2014/02/11/409734.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>页面布局备忘</title><link>http://www.blogjava.net/bjwulin/archive/2014/02/10/409656.html</link><dc:creator>不做浮躁的人</dc:creator><author>不做浮躁的人</author><pubDate>Mon, 10 Feb 2014 06:00:00 GMT</pubDate><guid>http://www.blogjava.net/bjwulin/archive/2014/02/10/409656.html</guid><wfw:comment>http://www.blogjava.net/bjwulin/comments/409656.html</wfw:comment><comments>http://www.blogjava.net/bjwulin/archive/2014/02/10/409656.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/bjwulin/comments/commentRss/409656.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bjwulin/services/trackbacks/409656.html</trackback:ping><description><![CDATA[一直在用flex做前端，都习惯面向对象的组件模式装配ui，最近想做一些基于网页的以信息展示为主的网站系统，我简称信息发布内核，内核两字表明我只是想做基本功能，不是做一个大而全的内容发布系统。首先得考虑的就是页面的布局模式。页面的布局模式与所选用的页面技术相关，初步计划选择thymeleaf，源于它的natural理念。<br /><br />thymeleaf的eclipse插件：https://github.com/thymeleaf/thymeleaf-extras-eclipse-plugin<br /><br />页面布局分为包含布局和层次布局，包含布局，一般通过th:include以及th:replace来实现，include和replace不一样的是一个包含在host tag里面，一个是指替换host tag，thymeleaf的包含布局和jsp的include不同的方面在于，thymeleaf可以包含某个文件的某一个部分，而jsp的必须包含整个文件。比如：&lt;div th:replace="fragments/header :: header"&gt;...&lt;/div&gt;，fragments/header是指被包含的模板文件，::header的header指被包含模板文件中的被包含部分。可以用this:header或者::header都是指包含本页面的部分。被包含的文件的被包含部分需要加上属性：th:fragment="header"<br /><br />thymeleaf可以基于dom selector来处理包含，而不用显示地调用th:fragment，比如：&lt;div th:include="http://www.thymeleaf.org :: p.notice" &gt;...&lt;/div&gt;，那么将会调用tag p且.class="notice&#8220;的片段，这个最大的好处就是包含别的网站的网页部分。以前的做法有用ajax的，有用iframe的，还有用javabean获取后传给前端的。thymeleaf这种处理方式相对合理。采用dom这种方式，需要templateEngine.addTemplateResolver(urlTemplateResolver());<br /><br />包含语法的模板文件和片段都可以通过表达式来指定，比如&lt;div th:replace="fragments/footer :: ${#authentication.principal.isAdmin()} ? 'footer-admin' : 'footer'"&gt;。<br /><br />thymeleaf包含模板也支持参数包含，比如：<br /><div>&lt;div th:fragment="alert (type, message)"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="alert alert-dismissable" th:classappend="'alert-' + ${type}"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;button type="button" class="close" data-dismiss="alert" aria-hidden="true"&gt;&#215;&lt;/button&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;span th:text="${message}"&gt;Test&lt;/span&gt;<br />&nbsp;&nbsp;&nbsp; &lt;/div&gt;</div>表示alert这个片段有两个参数：type和message，那么调用的时候：<br /><div>&lt;div th:replace="fragments/alert :: alert (type='danger', message=${errorMessage})"&gt;...&lt;/div&gt;</div>参数化片段提高片段的可重用性.<br /><br />题外话，我当年特喜欢infoglue的设计理念，事过好多年，依稀记得slot和param binding两个让我一直很喜欢的理念，现在的thymeleaf都可以做到。继续...<br /><br />能够从spring controller返回片段，比如：<br /><div>if (AjaxUtils.isAjaxRequest(requestedWith)) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return SIGNUP_VIEW_NAME.concat(" :: signupForm");<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; return SIGNUP_VIEW_NAME;</div>当用ajax请求的时候，后端返回的视图为片段的内容。<br /><br />包含布局，由于是在每个页面包含公共代码，因此natural特性没有影响，不过如果一旦需要切换包含另外的公共部分或者改变统一页面布局模式，那么包含布局就显得力不从心。层次布局，目前流行的有Tiles和sitemesh，一般是将布局等公用部分放在parent里面，显示时将每个子页面的具体内容融合到parent里面来对外展现，优点是更好的维护性，缺点是natural不够。<br /><br />本次信息发布内核采用层次布局模式。两层模板展现，父级模板负责布局展现，子级模板负责内容展现。<br />针对spring mvc和thymeleaf做一下扩展：<br />1、定义注释：layout注释可以用在类和方法上。<br /><div>@Target({ElementType.METHOD, ElementType.TYPE})<br />@Retention(RetentionPolicy.RUNTIME)<br />@Documented<br />public @interface Layout {<br />&nbsp;&nbsp;&nbsp; String value() default "";<br />}<br /><br />2、定义interceptor：<br /><div>public class ThymeleafLayoutInterceptor extends HandlerInterceptorAdapter {<br />&nbsp;<br />&nbsp;&nbsp;&nbsp; private static final String DEFAULT_LAYOUT = "layouts/default";<br />&nbsp;&nbsp;&nbsp; private static final String DEFAULT_VIEW_ATTRIBUTE_NAME = "view";<br />&nbsp;<br />&nbsp;&nbsp;&nbsp; private String defaultLayout = DEFAULT_LAYOUT;<br />&nbsp;&nbsp;&nbsp; private String viewAttributeName = DEFAULT_VIEW_ATTRIBUTE_NAME;<br />&nbsp;<br />&nbsp;&nbsp;&nbsp; public void setDefaultLayout(String defaultLayout) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Assert.hasLength(defaultLayout);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.defaultLayout = defaultLayout;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;<br />&nbsp;&nbsp;&nbsp; public void setViewAttributeName(String viewAttributeName) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Assert.hasLength(defaultLayout);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.viewAttributeName = viewAttributeName;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;<br />&nbsp;&nbsp;&nbsp; @Override<br />&nbsp;&nbsp;&nbsp; public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!modelAndView.hasView()) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String originalViewName = modelAndView.getViewName();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (isRedirectOrForward(originalViewName)) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String layoutName = getLayoutName(handler);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; modelAndView.setViewName(layoutName);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; modelAndView.addObject(this.viewAttributeName, originalViewName);<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;<br />&nbsp;&nbsp;&nbsp; private boolean isRedirectOrForward(String viewName) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return viewName.startsWith("redirect:") || viewName.startsWith("forward:");<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;<br />&nbsp;&nbsp;&nbsp; private String getLayoutName(Object handler) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HandlerMethod handlerMethod = (HandlerMethod) handler;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Layout layout = getMethodOrTypeAnnotation(handlerMethod);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (layout == null) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return this.defaultLayout;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return layout.value();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;<br />&nbsp;&nbsp;&nbsp; private Layout getMethodOrTypeAnnotation(HandlerMethod handlerMethod) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Layout layout = handlerMethod.getMethodAnnotation(Layout.class);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (layout == null) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return handlerMethod.getBeanType().getAnnotation(Layout.class);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return layout;<br />&nbsp;&nbsp;&nbsp; }<br />}<br /><br />3：配置interceptor：<br /><div>@Configuration<br />public class WebMvcConfig extends WebMvcConfigurationSupport {<br />&nbsp;&nbsp;&nbsp; @Override<br />&nbsp;&nbsp;&nbsp; protected void addInterceptors(InterceptorRegistry registry) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; registry.addInterceptor(new ThymeleafLayoutInterceptor());<br />&nbsp;&nbsp;&nbsp; }<br />}</div><br />4：测试类：<br /><div>@Controller<br />class SigninController {<br />&nbsp;<br />&nbsp;&nbsp;&nbsp; @Layout(value = "layouts/blank")<br />&nbsp;&nbsp;&nbsp; @RequestMapping(value = "signin")<br />&nbsp;&nbsp;&nbsp; String signin() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return "signin/signin";<br />&nbsp;&nbsp;&nbsp; }<br />}</div>5：测试布局模板页面：<br /><div>&lt;!DOCTYPE html&gt;<br />&lt;html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"&gt;<br />&nbsp;<br />&lt;head&gt;...&lt;/head&gt;<br />&lt;body&gt;<br />&lt;div th:raplace="fragments/header :: header"&gt;<br />&nbsp;&nbsp;&nbsp; Header<br />&lt;/div&gt;<br />&lt;div th:replace="${view} :: content"&gt;<br />&nbsp;&nbsp;&nbsp; Content<br />&lt;/div&gt;<br />&lt;div th:replace="fragments/footer :: footer"&gt;<br />&nbsp;&nbsp;&nbsp; Footer<br />&lt;/div&gt;<br />&lt;/body&gt;<br />&lt;/html&gt;</div><br /><br />6：测试内容模板页面：</div><div>&lt;!DOCTYPE html&gt;<br />&lt;html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"&gt;<br />&nbsp;<br />&lt;head&gt;...&lt;/head&gt;<br />&lt;body&gt;<br />&lt;div class="container" th:fragment="content"&gt;<br />&nbsp;&nbsp;&nbsp; &lt;!-- /* Handle the flash message */--&gt;<br />&nbsp;&nbsp;&nbsp; &lt;th:block th:if="${message != null}"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;div th:replace="fragments/alert :: alert (type=${#strings.toLowerCase(message.type)}, message=${message.message})"&gt; &lt;/div&gt;<br />&nbsp;&nbsp;&nbsp; &lt;/th:block&gt;<br />&nbsp;&nbsp;&nbsp; &lt;p&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Hello &lt;span th:text="${#authentication.name}"&gt;User&lt;/span&gt;!<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Welcome to the Spring MVC Quickstart application!<br />&nbsp;&nbsp;&nbsp; &lt;/p&gt;<br />&lt;/div&gt;<br />&lt;/body&gt;<br />&lt;/html&gt;</div></div><img src ="http://www.blogjava.net/bjwulin/aggbug/409656.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bjwulin/" target="_blank">不做浮躁的人</a> 2014-02-10 14:00 <a href="http://www.blogjava.net/bjwulin/archive/2014/02/10/409656.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>redis学习备忘</title><link>http://www.blogjava.net/bjwulin/archive/2014/02/08/409621.html</link><dc:creator>不做浮躁的人</dc:creator><author>不做浮躁的人</author><pubDate>Sat, 08 Feb 2014 10:51:00 GMT</pubDate><guid>http://www.blogjava.net/bjwulin/archive/2014/02/08/409621.html</guid><wfw:comment>http://www.blogjava.net/bjwulin/comments/409621.html</wfw:comment><comments>http://www.blogjava.net/bjwulin/archive/2014/02/08/409621.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bjwulin/comments/commentRss/409621.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bjwulin/services/trackbacks/409621.html</trackback:ping><description><![CDATA[因为一直用spring，所以上redis，决定用spring-data-redis，该项目希望用maven或者gradle，暂时不打算学习gradle，于是把maven学习了下，并留下学习备忘。<br /><br />spring data redis推荐jedis，因此稍微把jedis稍微看了下，jedis是redis的java客户端。<br /><br />sdr支持低层次的通过连接器connector连接到Redis，支持高层次的友好的模板类RedisTemplate,RedisTemplate是建立在低级别的connection基础之上。RedisConnection接收或返回字节数组需要自身处理连接，比如关闭连接，而RedisTemplate负责处理串行化和反串行化，并且管理对连接进行管理。RedisTemplate提供操作视图，比如(Bound)ValueOperations,<div>(Bound)ListOperations,(Bound)SetOperations,(Bound)ZSetOperations,(Bound)HashOperations。RedisTemplate是线程安全的，能够用于多个实例中。</div><br />RedisTemplate默认选择java-based串行化,也可以切换为其它的串行化方式，或者设置enabledDefaultSerializer为false或者设置串行化器为null，则RedisTemplate用raw byte arrays表示数据。<br /><br />sdr连接到redis通过RedisConnectionFactory来获得有效的RedisConnection。RedisConnection负责建立和处理和redis后端通信。RedisConnection提供getNativeconnection返回用来通信的底层connection。<br /><br />spring配置：<br /><div>&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;beans xmlns="http://www.springframework.org/schema/beans"<br />&nbsp; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br />&nbsp; xmlns:p="http://www.springframework.org/schema/p"<br />&nbsp; xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"&gt;<br />&nbsp; &lt;bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p:host-name="server" p:port="6379" p:use-pool="true"/&gt;<br /><div>&lt;bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"<br />&nbsp;&nbsp;&nbsp; p:connection-factory-ref="jedisConnectionFactory"/&gt;</div>&lt;/beans&gt;<br /><br />使用样例：<br /><div>public class Example {<br /><br />&nbsp; // 注入实际的模板<br />&nbsp; @Autowired<br />&nbsp; private RedisTemplate&lt;String, String&gt; template;//表示键值都是字符串类型。<br /><br />&nbsp; // 注入模板为ListOperations.<br />&nbsp; @Resource(name="redisTemplate")<br />&nbsp; private ListOperations&lt;String, String&gt; listOps;<br /><br />&nbsp; public void addLink(String userId, URL url) {<br />&nbsp;&nbsp;&nbsp; listOps.leftPush(userId, url.toExternalForm());<br />&nbsp; }<br />}</div><br />由于大部分Redis键值对存储都是键值均为字符串，因此sdr做了两个扩展，即StringRedisConnection以及StringRedisTemplate，两个扩展均采用StringRedisSerializer。<br /><br /><div>&lt;bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate"<br />&nbsp;&nbsp;&nbsp; p:connection-factory-ref="jedisConnectionFactory"/&gt;</div><br />代码示例：<br /><div>@Autowired<br />&nbsp; private StringRedisTemplate redisTemplate;<br /><br />&nbsp; public void addLink(String userId, URL url) {<br />&nbsp;&nbsp;&nbsp; redisTemplate.opsForList().leftPush(userId, url.toExternalForm());<br />&nbsp; }<br /><br />RedisTemplate以及其子类都允许开发者通过RedisCallback直接跟Redis通信，在callback中，开发者获得RedisConnection。StringRedisTemplate在callback中可以获得StringRedisConnection，需要强制转换。<br /><br /><div>利用Redis实现Jms的发布和订阅的功能：</div>发布信息：可以通过RedisConnection或者RedisTemplate来实现。<br />redisConnection.publish(byte[] msg,byte[] channel);<br />template.convertAndSend("hello!","world");<br />接收消息：在接受放，可以订阅根据频道名来订阅一个或多个频道或者通过模式匹配。模式匹配非常有用，因为它不仅允许一个命令创建多个订阅，也能监听在订阅创建之后产生的新的频道（只要匹配指定的模式）。<br />在低层面上，RedisConnection提供subscribe和pSubscribe（根据模式匹配）方法，多个频道和模式可以一起作为参数，RedisConnection也提供了getSubscription和isSubscribed方法。当用jedis连接器时，订阅命令是同步的，因此会产生堵塞，会导致该线程一直等待消息，只有当订阅取消的时候，才释放线程，采用unsubcribe或pUnsubscribe来取消同线程的订阅。为了处理订阅消息，需要实现MessageListener callback，每次当新的消息达到时，会调用callback执行onMessage方法，该方法能够获得消息，频道，以及匹配的模式。<br /><br />由于MessageListener的天然堵塞，底层面的消息接收不太被人接受，而且它要求处理连接和线程的管理，为了规避这个问题，sdr提供RedisMessageListenerContainer,它被用来接受从Redis频道传来的消息并注入MessageListener,RedisMessageListenerContainer负责相应接受消息的线程并派发到处理的监听器中。<br /><br /><div>&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;beans xmlns="http://www.springframework.org/schema/beans"<br />&nbsp;&nbsp;&nbsp; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br />&nbsp;&nbsp;&nbsp; xmlns:redis="http://www.springframework.org/schema/redis"<br />&nbsp;&nbsp;&nbsp; xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http://www.springframework.org/schema/redis http://www.springframework.org/schema/redis/spring-redis.xsd"&gt;<br /><br />&nbsp; &lt;!-- the default ConnectionFactory --&gt;<br />&nbsp; &lt;redis:listener-container&gt;<br />&nbsp;&nbsp;&nbsp; &lt;!-- the method attribute can be skipped as the default method name is "handleMessage" --&gt;<br />&nbsp;&nbsp;&nbsp; &lt;redis:listener ref="listener" method="handleMessage" topic="chatroom" /&gt;<br />&nbsp; &lt;/redis:listener-container&gt;<br />&nbsp; <br />&nbsp; &lt;bean id="listener" class="redisexample.DefaultMessageDelegate"/&gt;<br />&nbsp; ...<br />&lt;beans&gt;</div><br />redis对事务提供支持，包括multi,exec,discard命令，这些命令也能用于RedisTemplate，然后redisTemplate不保证用相同的连接在同一个事务执行所有操作。sdr提供SessionCallback接口用于同线程的多操作执行。<br /><br />Redis支持管道（pipelining),管道可以发送多个命令到服务端无需等待反馈然后读取单一步的反馈。管道在你需要一行发送多个命令是提升性能，比如对相同的列表增加多个元素。如果不关注管道操作的结果，则可以调用RedisTemplate标准的excute方法，传递true作为pipeline参数。excutePipelined方法执行RedisCallback或者sessionCallback，然后返回结果。<br /><br /><div>List&lt;Object&gt; results = stringRedisTemplate.executePipelined(new RedisCallback&lt;Object&gt;() {<br />&nbsp;&nbsp;&nbsp; public Object doInRedis(RedisConnection connection) throws DataAccessException {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StringRedisConnection stringRedisConn = (StringRedisConnection)connection;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i=0; i&lt; batchSize; i++) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stringRedisConn.rPop("myqueue");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return null;//必须返回null<br />&nbsp;&nbsp;&nbsp; }<br />});//results为myqueue的value。<br /><br />Redis2.6以及更高的版本支持通过eval和evalsha命令执行lua script。sdr封装代码执行，串行化以及利用代码缓存。scripts能够通过RedisTemplate的execute方法来运行，RedisTemplate用一个可配置的ScriptExecutor来执行提供的代码。缺省的ScriptExecutor通过获取代码的sha1，尝试运行evalsha，失败后执行eval。<br /><br />lua script一般用于原子操作且命令的行为被另外的命令结果所影响。<br /><br />配置：<br /><div>&lt;bean id="script" class="org.springframework.data.redis.core.script.DefaultRedisScript"&gt;<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&lt;property name="location" value="classpath:META-INF/scripts/checkandset.lua"/&gt;<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&lt;property name="resultType" value="java.lang.Boolean"/&gt;<br />&nbsp;&nbsp;&nbsp; &lt;/bean&gt;<br /><br />java代码：<br /><div>@Autowired<br />&nbsp;&nbsp;&nbsp; RedisScript&lt;Boolean&gt; script;<br /><br />&nbsp;&nbsp;&nbsp; public boolean checkAndSet(String expectedValue, String newValue) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return redisTemplate.execute(script, Collections.singletonList("key"),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; expectedValue, newValue);<br />&nbsp;&nbsp;&nbsp; }<br /><br />lua script:<br /><div>-- checkandset.lua<br />local current = redis.call('GET', KEYS[1])<br />if current == ARGV[1]<br />then<br />&nbsp;&nbsp;&nbsp; redis.call('SET', KEYS[1], ARGV[2])<br />&nbsp;&nbsp;&nbsp; return true<br />end<br />return false<br /></div></div></div></div>redis支持类存放在org.springframework.data.redis.support，RedisSet和RedisZSet提供Redis支持的intersection以及union等方法。RedisList可以实现Queue以及Deque来实现FIFO和LiFO。<br />配置：<br /><div>&lt;bean id="queue" class="org.springframework.data.redis.support.collections.DefaultRedisList"&gt;<br />&nbsp;&nbsp;&nbsp; &lt;constructor-arg ref="redisTemplate"/&gt;<br />&nbsp;&nbsp;&nbsp; &lt;constructor-arg value="queue-key"/&gt;<br />&nbsp; &lt;/bean&gt;</div>代码：<br /><div>// injected<br />&nbsp; private Deque&lt;String&gt; queue;<br /><br />&nbsp; public void addTag(String tag) {<br />&nbsp;&nbsp;&nbsp; queue.push(tag);<br />&nbsp; }</div><br />Sdr提供了一个spring3.1 cache abstraction的实现。配置：<div>&lt;bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager" c:template-ref="redisTemplate"/&gt;</div><br /><br /></div><br /><br /><br /></div><img src ="http://www.blogjava.net/bjwulin/aggbug/409621.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bjwulin/" target="_blank">不做浮躁的人</a> 2014-02-08 18:51 <a href="http://www.blogjava.net/bjwulin/archive/2014/02/08/409621.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>maven学习备忘</title><link>http://www.blogjava.net/bjwulin/archive/2014/02/08/409611.html</link><dc:creator>不做浮躁的人</dc:creator><author>不做浮躁的人</author><pubDate>Sat, 08 Feb 2014 05:39:00 GMT</pubDate><guid>http://www.blogjava.net/bjwulin/archive/2014/02/08/409611.html</guid><wfw:comment>http://www.blogjava.net/bjwulin/comments/409611.html</wfw:comment><comments>http://www.blogjava.net/bjwulin/archive/2014/02/08/409611.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bjwulin/comments/commentRss/409611.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bjwulin/services/trackbacks/409611.html</trackback:ping><description><![CDATA[对于我来说，maven解决依赖是很有用，至于其构建，编译，打包等自动化对于我这样的小队伍来说，反而有些繁琐，团队小了，技术架构相对稳定，每个应用的jars基本上都通用，所以常常是直接把一个老项目复制为一个新项目，然后改变一些参数...<br /><br />于是，一直在排斥maven，不愿意学习，于是对于maven始终是菜鸟，现在越来越多的项目都开始用maven，于是，不愿意还是maven小白，选择学习，选择备忘这个学习过程。<br /><br /><div>eclipse indigo安装m2e，选择安装路径为：http://download.eclipse.org/releases/indigo，然后选择m2e，新的m2e版本不能在indigo安装，安装完后，在eclipse 的reference里面设置maven的installations以及user setting，改变里面的setting文件为安装目录\conf\settings.xml文件，并改变该文件中的本地仓库路径&lt;localRepository&gt;。</div><br />下载mvn，然后设定系统path，设置MAVEN_OPTS的值为：-Xms128m -Xmx512m等就不用啰嗦了。先看一个命令，入个门：<br /><div>mvn archetype:create -DgroupId=com.studio -DartifactId=helloWorld -DpackageName=com.studymaven<br />archetype是mvn的一个插件（plugin),create是archetype的一个任务（task）。-D后面的是这个任务的参数。groupId一般是开发组织的Id，artifactId是本项目的具体名称.<br /><br />mvn插件有哪些任务，可以用mvn help:describe -Dplugin=archetype，help是插件，describe是help的任务，整个命令显示archetype的所有任务信息，如要查看详细的参数信息，则加入-Dfull参数。<br /><br />mvn的命令支持简写，比如mvn compile=mvn compile:compile，另外常用的简写命令有：mvn compile ，mvn test-compile，mvn test，mvn package，mvn install 将应用发布到本地仓库，mvn deploy 复制最终的包至远程仓库，共享给其它开发人员和项目供其他项目使用。<br /><br /><div>maven采用坐标精确定位每一个构建（artifect)，也就是通过一些参数精确找到合适的jar包。</div><br />mvn archetype:generate命令可以以提示的方式填写create任务的参数，生成完毕后，可以通过m2e导入到eclipse，或者直接在eclipse中建立maven project，选择maven-archetype-quickstart。<br /><br />当用eclipse建立项目后，可以选择项目的pom.xml，然后run as，选择合适的命令，如果没有合适的命令，则可以通过选择Maven buid&#8230; 自定义Maven运行命令，在弹出对话框中的Goals一项中输入我们想要执行的命令。<br /><br />最后一点，我们更多时候需要源代码包，那么可以选择需要源代码的jar，然后右键，然后maven，然后Download source即可。<br /> </div><img src ="http://www.blogjava.net/bjwulin/aggbug/409611.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bjwulin/" target="_blank">不做浮躁的人</a> 2014-02-08 13:39 <a href="http://www.blogjava.net/bjwulin/archive/2014/02/08/409611.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>flex mobile开发的一些注意点</title><link>http://www.blogjava.net/bjwulin/archive/2014/02/07/409562.html</link><dc:creator>不做浮躁的人</dc:creator><author>不做浮躁的人</author><pubDate>Thu, 06 Feb 2014 16:20:00 GMT</pubDate><guid>http://www.blogjava.net/bjwulin/archive/2014/02/07/409562.html</guid><wfw:comment>http://www.blogjava.net/bjwulin/comments/409562.html</wfw:comment><comments>http://www.blogjava.net/bjwulin/archive/2014/02/07/409562.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bjwulin/comments/commentRss/409562.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bjwulin/services/trackbacks/409562.html</trackback:ping><description><![CDATA[1、如果View的destructionPolicy设置为never，那么该视图的上层视图被弹出后，runtime会从内存中取得该view的实例。但是如果pop这个view，这个view将会从内存中移除，或者Push这个view，也会导致新建一个View实例。<br />2、每个View都有createReturnObject()，复写该方法，可以为上一个视图展现提供数据，上一个视图可以采用：navigator.poppedViewReturnedObject.object来得到数据。<br />3、如果需要在应用程序运行期间保存数据，则需要设置应用的persistNavigatorState属性，并且编写navigatorStateLoading 和 navigatorStateSaving两个时间的处理方法。<br />4、flex mobile不能使用mx Alert，也不能使用spark Alert，官方建议使用SkinnablePopUpContainer。<br />5、可以用fx:Component className="AlertMsg"嵌套定义组件类。通过new AlertMsg()来生成实例。<br /><img src ="http://www.blogjava.net/bjwulin/aggbug/409562.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bjwulin/" target="_blank">不做浮躁的人</a> 2014-02-07 00:20 <a href="http://www.blogjava.net/bjwulin/archive/2014/02/07/409562.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>flex mobile适应设备尺寸</title><link>http://www.blogjava.net/bjwulin/archive/2014/02/06/409558.html</link><dc:creator>不做浮躁的人</dc:creator><author>不做浮躁的人</author><pubDate>Thu, 06 Feb 2014 11:26:00 GMT</pubDate><guid>http://www.blogjava.net/bjwulin/archive/2014/02/06/409558.html</guid><wfw:comment>http://www.blogjava.net/bjwulin/comments/409558.html</wfw:comment><comments>http://www.blogjava.net/bjwulin/archive/2014/02/06/409558.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bjwulin/comments/commentRss/409558.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bjwulin/services/trackbacks/409558.html</trackback:ping><description><![CDATA[源于移动设备的dpi不同，可能导致一个设备上运行展现正常的界面，到另外一个设备上惨不忍睹。<br /><br />flex sdk4.5及以上在Application及其子类上提供了ApplicationDpi，并支持3种类型的dpi：160,240,320，基本上可以涵盖目前已有的设备的dpi。<br /><br />如果设定Application的applicationDpi，flex runtime会针对矢量图以及文本自动做dpi自适应，由于矢量图绘制会产生痕迹，所以最好在设计时按照低dpi（比如160，Adobe官方建议)来设计，在dpi=240的设备上，runtime会自动将矢量图放到为1.5倍。<br /><br />对于位图来说，放大会导致痕迹，因此flex sdk提供了MultiDPIBitmapSource类，允许用户针对160,240,320分别提供位图。mobile app的splash不能采用MultiDPIBitmapSource，最好使用大位图，让runtime自动缩小它。<br /><br />在skin中，判断applicationDpi：<br /><div>switch (applicationDPI) { <br />case DPIClassification.DPI_320: { <br />upBorderSkin = skins.assets320.TransparentRoundedButton_up; <br />downBorderSkin = skins.assets320.TransparentRoundedButton_down; <br />break; <br />}</div><br /><br />在css中，采用@media：<br />@media (application-dpi: 160) {<br /><div>&nbsp;Button { fontSize: 20; } <br />}</div><br />要提供良好体验的splash，需要扩展SplashScreen类，重写getImageClass方法，比如：<br /><div>override mx_internal function getImageClass(dpi:Number, aspectRatio:String):Class { <br />if (dpi == DPIClassification.DPI_160) <br />return SplashImage160; <br />else if (dpi == DPIClassification.DPI_240) <br />return SplashImage240; <br />else if (dpi == DPIClassification.DPI_320) <br />return SplashImage320; return null; <br />} <br />}</div><br /><img src ="http://www.blogjava.net/bjwulin/aggbug/409558.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bjwulin/" target="_blank">不做浮躁的人</a> 2014-02-06 19:26 <a href="http://www.blogjava.net/bjwulin/archive/2014/02/06/409558.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>flex mobile性能优化点</title><link>http://www.blogjava.net/bjwulin/archive/2014/02/06/409550.html</link><dc:creator>不做浮躁的人</dc:creator><author>不做浮躁的人</author><pubDate>Thu, 06 Feb 2014 07:27:00 GMT</pubDate><guid>http://www.blogjava.net/bjwulin/archive/2014/02/06/409550.html</guid><wfw:comment>http://www.blogjava.net/bjwulin/comments/409550.html</wfw:comment><comments>http://www.blogjava.net/bjwulin/archive/2014/02/06/409550.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bjwulin/comments/commentRss/409550.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bjwulin/services/trackbacks/409550.html</trackback:ping><description><![CDATA[<div>这个mobile开发，一般原生开发也许是最合适的方式，但是涉及到跨平台的问题，有精力的团队一般都会逐个基于移动操作系统进行开发。但是我追求短小，精悍，快速。于是我希望能够跨平台，基于html5开发是一个不错的选择，但是终究因为团队更熟悉flex，于是决定采用flex mobile development来进入移动互联的开发。<br /><br />flex是个双刃剑，我见过用的好的，做出来的效果不比原生差，也见过做的不好的，那效果，那性能真的不敢恭维，我的团队一直在台式机的flex app开发上，很少关于客户端app的性能优化，于是写此日志作为备忘，大部分都是网络的共享观点，不过经过我验证后得以收纳：<br /><br />1、组件尽量使用为移动开发优化的，皮肤尽量使用简洁的，一般最好通过graphic以及fxg语法来绘制，不要过多嵌入位图。<br />2、itemRenderer最好用As3的，mobile theme里面有LabelItemRenderer以及IconItemRenderer，里面需要重载的方法有createChildren,measure,drawBackground,layoutContent以及数据的setter。相比Flex ItemRenderer，mobile的ItemRenderer的updateDisplayList分割成drawBackground和LayoutContent。IconItemRenderer使用flex ContentCache高速缓存下载下来的图形图像。<br />3、用styleableTextField，该类只可以在As3中使用，不能在mxml中使用，性能在mobile中比Label和RichText性能高不少。<br />4、让flex ItemRender保持矩形形状并且设置OpaqueBackground为一个单一颜色。<br />5、如果在flex ItemRenderer中绘制自己的背景，则需要将autoDrawBackground为false。<br />6、flex ItemRenderer如果外观保持静态，可以设置cacheAsBitmap为true。<br />7、flex ItemRenderer尽量少使用双向绑定。<br />8、布局定位组件，尽量使用容器组件的layout属性来达到布局目的，尽量少地嵌入容器组件，减少容器组件层次等。<br />9、优先考虑ConstraintLayout布局方式，减少动态布局。<br />10、使用Group和Graphics fxg来代替BorderContainer。<br />11、flex mobile中不要使用CreationComplete来初始化view的外观，直接覆盖data的setter方法，尽量避免使用双向绑定以及绑定表达式。<br />12、建议在View的ViewActivate中调用远程异步服务以及处理子组件的初始化等工作，避免用户体验中的&#8221;停顿&#8220;。<br />13、用IncludeIn或ExcludeFrom以state的方式隐藏或显示组件。<br />14、如果一个View来回被用户所切入，那么最好指定该View的destructionPolicy为never，即在内存中一直保留该view的实例。<br />15、使用BitmapImage代替Image进行图像嵌入工作。<br />16、使用RectangularDropShadow代替DropShadowFilter<br />17、使用图像的多个尺寸备份，而不是使用大图+缩放或者图形圆滑技术来适应不同分辨率和dpi。<br />18、尽量使用png图形，而不是采用jpg或者gif.<br />19、对于简单图形，可以采用graphics或者rect fill等，对于复杂一点的图形建议采用Adobe Illustrator来绘制fxg矢量图形。<br />20、尽量使用css，利用mobile theme已有的皮肤，因为这些皮肤已经高度优化。<br />21、如果mobile theme的css样式不足，则需要用as3来编写皮肤或者扩展已有组件的皮肤。</div><img src ="http://www.blogjava.net/bjwulin/aggbug/409550.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bjwulin/" target="_blank">不做浮躁的人</a> 2014-02-06 15:27 <a href="http://www.blogjava.net/bjwulin/archive/2014/02/06/409550.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ubuntu server下安装redis</title><link>http://www.blogjava.net/bjwulin/archive/2014/01/16/409029.html</link><dc:creator>不做浮躁的人</dc:creator><author>不做浮躁的人</author><pubDate>Thu, 16 Jan 2014 07:04:00 GMT</pubDate><guid>http://www.blogjava.net/bjwulin/archive/2014/01/16/409029.html</guid><wfw:comment>http://www.blogjava.net/bjwulin/comments/409029.html</wfw:comment><comments>http://www.blogjava.net/bjwulin/archive/2014/01/16/409029.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/bjwulin/comments/commentRss/409029.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bjwulin/services/trackbacks/409029.html</trackback:ping><description><![CDATA[我是新手，中间遇到的过程做备忘，可能都是很浅显的问题。<br /><br />空白的ubuntu server，一步一步来。<br /><br />1、首先在ubuntu server里面安装openssh server，通过tasksel命令调出task，选择openssh server进行安装。<br />2、我一般用windows办公，直接用putty，通过ip和port连接服务器，注意一点的就是connection的seconds between keepalives设置时间稍微长一些，毕竟通信过程有延迟。<br />3、用wget下载redis的稳定版本，然后用tar解压，进入到解压目录。执行make，提示make没有安装。<br />4、用sudo apt-get install make和sudo apt-get install gcc安装两个编译器。<br />5、在redis解压目录下，执行make，如果提示&#8220;<span style="color: red;">error: jemalloc/jemalloc.h: No such file or directory</span>&#8221;，则可以先执行指令：make distclean<br />6、make完后，一般建议make test，我在make test时提示&#8220;You need tcl 8.5 or newer in order to run the Redis test&#8221;<br />7、wget<a href="http://prdownloads.sourceforge.net/tcl/tcl8.6.0-src.tar.gz" target="_blank"> http://prdownloads.sourceforge.net/tcl/tcl8.6.0-src.tar.gz</a>,下载后，进入安装目录，进入unix，然后执行"./configure",然后make，然后make install<span style="color: red;">（告诉我没有权限建立文件，在make前加上sudo）。</span><br />8、然后跑到redis的解压目录下，再进行"make test"，很多很多ok，哈哈。<br />9、然后make install，这样以后执行命令不用上全路径<br />10、开发环境中启动：redis-server --port 6000,命令行客户端：redis-cli -h 192.168.1.10 -p 6000，然后就可以用redis的各种命令交互了。<br /><br />总结：我是老白，不过ubuntu server基于debian,真心很好用，debian的更新周期太长，所以ubuntu还是不错的。<br /><br />每次启动redis，总是报告：Unable&nbsp;to&nbsp;set&nbsp;the&nbsp;max&nbsp;number&nbsp;of&nbsp;files&nbsp;limit<br />解决方案：<br /><div>1.打开/etc/security/limits.conf，里面有很详细的注释，找到如下设置(如果没有就插入)<br />* soft nofile 51200<br />* hard nofile 51200<br />2.编辑/etc/pam.d/common-session，加入一行<br />session required pam_limits.so<br />3.编辑/etc/profile，加入<br />ulimit -SHn 51200<br />重启服务器，再次登陆，查看句柄数，已经正确设置为51200。</div><img src ="http://www.blogjava.net/bjwulin/aggbug/409029.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bjwulin/" target="_blank">不做浮躁的人</a> 2014-01-16 15:04 <a href="http://www.blogjava.net/bjwulin/archive/2014/01/16/409029.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>