??xml version="1.0" encoding="utf-8" standalone="yes"?>
lgQ简单的讄Ҏ如下Q?br />
jsp (gbk) ----> java(ISO-8859-1) -------> mysql(gbk)
转换
q样讄之后Q还有一U情况会出现qQ当你在jsp端提交一个idP然后在java处理端通过id号得到数据库中的gbkQ汉字)数据Q这是就会出Cؕ码,因ؓjava处理的是ISO-8859-1Q你在java到mysql中有了一个ISO-8859-1到gbk的{换,而这些数据本w就是ISO-8859-1,所以{换后出现问题了?br />解决办法Q将在java中处理的gbk数据转换为ISO-8859-1卛_?br />
MQ在jspQjavaQmysql三者之间的~码方式必须l一Q不能错误的转换或者不转换?img src ="http://www.tkk7.com/soochow_hhb/aggbug/78845.html" width = "1" height = "1" />
在实际的pȝ中,要多个类共同协作来完成某一Q务,一般称为复合。在pȝ的设计过E中Q耦合是不可避免的Q是必须的,但是它会带来以下问题Q?br />Q-难以试Q看下面的两个类Q?br />KnightOfTheRoundTable
|
| new
V
HolyGrailQuest
在KnightOfTheRoundTablecM使用了HolyGrailQuestc,q且可能使用不同的QuestcR这两个cȝ功能是骑士去执行不同的Q务,HolyGrail只是代表了一UQ务。这U通过国new的方式,使得knight和quest两个cȝ密的耦合在一赗设计完成后做单元测试,看下面的代码Q?br />KnightOfTheRoundTable knight = new KnightOfTheRoundTable("Bedivere");
HolyGrail grail = knight.embarkOnQuery();
assertNotNull(grail);
assertTrue(grail.isHoly());
在测试KnightOfTheRoundTablecȝ时候,间接的测试了HolyGrailQuestc,但是对于HolyGrailQuestcȝ情况q没有很昑ּ的测试,所以用了最后的两行代码来测试,昑־很笨拙。不知道是否试了所有可能的情况?br />Q-难以l护
如果以后修改了代码,或者增加了/改变了knight的Q务,代码必须改动Q测试代码也要改动,q且改动一个地方,可能会媄响到其他很多地方Qؓ日后的维护工作带来了ȝ
Q-紧耦合
提示Q这U模式引L问题Q主要是因ؓ紧耦合所_所以要解决q种问题的首要方案就是解耦合Q但如何来解耦合呢?Ll看Q?br />Q?Q解耦合——通过接口interface来实?br />因ؓ骑士可能执行不同的Q务,也有不同U类的骑士,所以我们可以将d和骑士抽象ؓ接口Q将具体的实现隐藏在接口之下Q这样就不必在knightcM通过昄?HolyGrailQuest quest = new HolyGrailQuest ()q样的语句来创徏Quest对象Q而可以通过接口Quest quest Q?new HolyGrailQuest()来实现。这样就形成了如下的cdQ?br />
q样Q虽然用了接口Q得层ơ分明,通过接口Quest来实现探险,但是q是只能从事一U探险Q务,而如何才能让骑士从事M一UQ务呢Q请l箋看!
Q?Q给予与获得
骑士执行探险d有两U方式:
W一、让骑士d获得探险dQ前面的实现方式属于q类Q通过new来实玎ͼ
W二Q让骑士被动的获得Q务,即给予骑士某Ҏ险Q务,q样p决了上面的问题(让骑士可以从事Q何一UQ务,只要l他们分配即可)?br />实际实现的方式很单,看如下代码:
public void setQuest(Quest quest){
this.quest = quest;
}
单的代码实现了方式的改变Q这LKnightOfTheRoundTablecM入Q何的QuestdQ都可以接受了?br />到这里可以很明显的看出来Q我们将以前的new方式Q翻转过来,即不是让d获得依赖c,而是被动的获得依赖类Q这是IoC的核心,实际Fowler说得依赖注入也很贴切Q即向类中“注入”它依赖的其他类?br />
好了Q到q里Q应该知道了IoC的基本概念了吧,也知道了IoC的基本功能了吧?br />要想更深入的了解Q请x我的文章?/span>
?/SPAN> ?/SPAN> |
Struts1.1 |
WebWork2 |
Actionc?/SPAN> |
?/SPAN>Struts里面Q每一?/SPAN>Actioncd需要承一个抽象的c?/SPAN>org.apache.struts.action.Action。这个在Java~程中会引来一些问题,是关于多种l承的问题?/SPAN> |
WebWork?/SPAN>ActioncM需要实现接?/SPAN>com.opensymphony.xwork.ActionQ也可以实现其它的接口来实现更多的功能,譬如Q?/SPAN>validateQ验证)Q?/SPAN>localware(国际?/SPAN>){。当Ӟ它也提供了一个类ActionSupport集成了上面的所有功能,我们在开发中可以Ҏ需要选择?/SPAN> |
U程模型 |
Struts ?/SPAN>Action必需?/SPAN>threadQ?/SPAN>safe方式Q它仅仅允许一个实例去处理所有的h。所?/SPAN>action用到的所有的资源都必需l一同步Q这个就引v了线E安全的问题?/SPAN> |
?/SPAN>WebWork中,每个h对应一?/SPAN>ActionQ因此没有线E的安全问题。实际上Servlet容器Ҏ个请求也产生多个对象Q它也没有证明对性能和垃圑֛收生太多的影响?/SPAN> |
Servlet的依?/SPAN> |
Struts处理Action时必需要依?/SPAN>ServletRequest ?/SPAN>ServletResponseQ所有它摆脱不了Servlet容器?/SPAN> |
WebWork?/SPAN>Action不用依赖Web层和其它的容器。它可以通过ActionContextQ直接去讉KRequest?/SPAN>ResponseQ但q个是可选的Q只有在必需的请求下使用?/SPAN> |
试 |
Struts的每?/SPAN>Action都同Web层耦合在一Pq样它的试依赖?/SPAN>Web容器Q单元测试也很难实现。不q有一?/SPAN>Junit的扩展工?/SPAN>Struts TestCase可以实现它的单元试?/SPAN> |
Webwork?/SPAN>action能够通过赋予一定的属性,可以执行单元测试。同时也可以使用一?/SPAN>mock的实例去试Q而不是通过启动web容器来进行测试?/SPAN> |
FormBean |
Struts要求?/SPAN>FormBean对应每一个表单,而且FormBean必需l承抽象c?/SPAN>ActionForm。而?/SPAN>DynaBeans实际上没有太大的意义。不能够很好的处理现有的模型?/SPAN> |
Webwork 能够动态的攉web的数据然后再赋值给bean。它也可以?/SPAN>FormBean的Ş式,FormBean可以是普通的DTO和域对象Q它不用重新Ҏ域对象来生成新的FormBeanQ也不需l承抽象c?/SPAN>ActionForm?/SPAN> |
前端表达式语a |
Struts集成?/SPAN>JSTLQ所以它主要使用JSTL的表辑ּ语言来获取数据。可?/SPAN>JSTL的表辑ּ语言?/SPAN>Collection和烦引属性方面处理显得很弱?/SPAN> |
WebWork的表辑ּ语言使用了功能强大的OGNL。它使用OGNL建立一?/SPAN>OgnlValueStack来搜索数据?/SPAN>Webwork前端也可以?/SPAN>JSTLQ但它同时支持:velocity?/SPAN>freemaker?/SPAN>jspparer?/SPAN>xml?/SPAN> |
cd的{?/SPAN> |
Struts?/SPAN>FormBean把所有的数据都作?/SPAN>StringcdQ它可以使用工具Commons-Beanutilsq行cd转化。但它的转化都是?/SPAN>ClassU别Q而且转化的类型是不可配置的。类型{化时的错误信息返回给用户也是非常困难的?/SPAN> |
WebWork使用OGNLq行cd转化Q提供了所有基本类型的转化功能。类型{化可以直接对一?/SPAN>Classq行Q?/SPAN>ClassU别Q{化,也可以对Class的字D进行类型{化。它使用拦截器可以很Ҏ的将cd转化的错误信息返回给用户Q而且错误信息可以对应C个相应的字段?/SPAN> |
?/SPAN>Action 执行前和后的处理 |
Struts处理Action的时候是Zclass?/SPAN>hierarchiesQ很隑֜action处理前和后进行操作?/SPAN> |
Webwork2 允许您处?/SPAN>Action可以通过拦截器,是在每一?/SPAN>Action处理前或者后q行其它操作。它的拦截器可以在配|文件中动态添加,q样Action和拦截器之间完全解藕Q更好的实现了组件化?/SPAN> |
验证处理 |
Struts的验证是调用FormBean?/SPAN>validator()ҎQ其实就是对FormBean的验证。它一般用框?/SPAN>Commons Validationq行数据验证处理。它使用了一个全局的配|文?/SPAN>validation.xml定义?/SPAN>FormBean的验证信息?/SPAN>Struts?/SPAN>FormBean属性都被认为是StringcdQ所以它在验证时也需要额外的cd转化?/SPAN> |
WebWork使用Xwork的验证框架进行验证处理,它可以通过配置拦截器来ȀzR它可以为每个需要验证的Class指定一?/SPAN>xml验证文gQ也可以Z?/SPAN>Class在不同的情况指定不同?/SPAN>xml验证文g?/SPAN>WebWork证可以给每个ActioncL定对应的验证文gQ也可以l?/SPAN>Action的字D去指定验证文g。通过拦截器来l装Action和其验证文gQ它们之间完全解藕?/SPAN> |
?/SPAN>Action执行的控?/SPAN> |
Struts创徏一?/SPAN>ActionQ如果想控制它的执行序会非常困难。甚至你要重新去?/SPAN>Servlet来实C的这个功能需求?/SPAN> |
在这个方面,WebWork的拦截器栈提供了强大的功能?/SPAN>Action的所有切面功能都有拦截器来实玎ͼ比如Q取?/SPAN>requesth参数、验证处理等Q,q样你就可以用拦截器栈来l织拦截器的执行序。例如:你需要在使用requesth参数来设|?/SPAN>Action属性之前,使用IoC框架讄Action的属性,反之已然。这Ӟ你就可以?/SPAN>package?/SPAN>Action指定一个拦截器栈来实现?/SPAN> |
Feature |
Struts |
WebWork 1.x |
WebWork 2.x |
Action classes |
Struts requires Action classes to extend an Abstract base class. This shows a common problem in Struts of programming to abstract classes instead of interfaces. |
Action classes must implement the webwork.Action Interface. There are other Interfaces which can be implemented for other services, such as storing error messages, getting localized texts, etc. The ActionSupport class implements many of these Interfaces and can act as a base class. WebWork is all written to Interfaces, which allows for plugging in your own implementations. |
An Action must implement the com.opensymphony.xwork.Action Interface, with a series of other Interfaces for other services, like in WebWork 1.x. WebWork2 has its own ActionSupport to implement these Interfaces. |
Threading Model |
Struts Actions must be thread-safe because there will only be one instance to handle all requests. This places restrictions on what can be done with Struts Actions as any resources held must be thread-safe or access to them must be synchronized. |
WebWork Actions are instantiated for each request, so there are no thread-safety issues. In practice, Servlet containers generate many throw-away objects per request, and one more Object does not prove to be a problem for performance or garbage collection. |
ditto |
Servlet Dependency |
Struts Actions have dependencies on Servlets because they get the ServletRequest and ServletResponse (not HttpServletRequest and HttpServletResponse, I've been told) when they are executed. This tie to Servlets (although not Http*) is a defacto tie to a Servlet container, which is an unneeded dependency. Servlets may be used outside a Web context, but it's not a good fit for JMS, for instance. |
WebWork Actions are not tied to the web or any container. WebWork actions CAN choose to access the request and response from the ActionContext, but it is not required and should be done only when ABSOLUTELY neccessary to avoid tieing code to the Web. |
ditto |
Testability |
Many strategies have sprung up around testing Struts applications, but the major hurdle is the fact that Struts Actions are so tightly tied to the web (receiving a Request and Response object). This often leads people to test Struts Actions inside a container, which is both slow and NOT UNIT TESTING. There is a Junit extension : Struts TestCase (http://strutstestcase.sourceforge.net/) |
WebWork actions can be tested by instantiating your action, setting the properties, and executing them |
ditto, but the emphasis on Inversion of Control makes testing even simpler, as you can just set a Mock implementation of your services into your Action for testing, instead of having to set up service registries or static singletons |
FormBeans |
Struts requires the use of FormBeans for every form, necessitating either a lot of extra classes or the use of DynaBeans, which are really just a workaround for the limitation of requiring FormBeans |
WebWork 1.x allows you to have all of your properties directly accessible on your Action as regular Javabeans properties, including rich Object types which can have their own properties which can be accessed from the web page. WebWork also allows the FormBean pattern, as discussed in "WW1:Populate Form Bean and access its value" |
WebWork 2 allows the same features as WebWork 1, but adds ModelDriven Actions, which allow you to have a rich Object type or domain object as your form bean, with its properties directly accessible to the web page, rather than accessing them as sub-properties of a property of the Action. |
Expression Language |
Struts 1.1 integrates with JSTL, so it uses the JSTL EL. This EL has basic object graph traversal, but relatively weak collection and indexed property support. |
WebWork 1.x has its own Expression language which is built for accessing the ValueStack. Collection and indexed property support are basic but good. WebWork can also be made to work directly with JSTL using the Filter described in WW1:Using JSTL seamlessly with WebWork |
WebWork 2 uses XW:Ognl which is a VERY powerful expression language, with additions for accessing the value stack. Ognl supports very powerful collection and indexed property support. Ognl also supports powerful features like projections (calling the same method on each member of a collection and building a new collection of the results), selections (filtering a collection with a selector expression to return a subset), list construction, and lambda expressions (simple functions which can be reused). Ognl also allows access to static methods, static fields, and constructors of classes. WebWork2 may also use JSTL as mentioned in WW1:Using JSTL seamlessly with WebWork |
Binding values into views |
Struts uses the standard JSP mechanism for binding objects into the page context for access, which tightly couples your view to the form beans being rendered |
WebWork sets up a ValueStack which the WebWork taglibs access to dynamically find values very flexibly without tightly coupling your view to the types it is rendering. This allows you to reuse views across a range of types which have the same properties. |
ditto |
Type Conversion |
Struts FormBeans properties are usually all Strings. Struts uses Commons-Beanutils for type conversion. Converters are per-class, and not configurable per instance. Getting a meaningful type conversion error out and displaying it to the user can be difficult. |
WebWork 1.x uses PropertyEditors for type conversion. PropertyEditors are per type and not settable per Action, but field error messages are added to the field error map in the Action to be automatically displayed to the user with the field. |
WebWork2 uses Ognl for type conversion with added converters provided for all basic types. Type converters default to these converters, but type conversion can be specified per field per class. Type conversion errors also have a default error message but can be set per field per class using the localization mechanism in WW2 and will be set into the field error messages of the Action. |
Modular Before & After Processing |
Class hierarchies of base Actions must be built up to do processing before and after delegating to the Action classes, which can lead deep class hierarchies and limitations due to the inability to have multiple inheritance WW:Comparison to Struts#1 |
Class hierarchies |
WebWork 2 allows you to modularize before and after processing in Interceptors. Interceptors can be applied dynamically via the configuration without any coupling between the Action classes and the Interceptors. |
Validation |
Struts calls validate() on the FormBean. Struts users often use Commons Validation for validation. I don't know a lot about this, so I'll put some questions here: |
WebWork1.x calls the validate() method on Actions, which can either do programmatic validations or call an outside validation framework (this is apparently the same as Struts) |
WebWork2 can use the validate() method of WebWork and Struts and / or use the XW:Validation Framework, which is activated using an XWork Interceptor. The Xwork Validation Framework allows you to define validations in an XML format with default validations for a class and custom validations added for different validation contexts. The Xwork Validation Framework is enabled via an Interceptor and is therefore completely decoupled from your Action class. The Xwork Validation Framework also allows you to chain the validation process down into sub-properties using the VisitorFieldValidator which will use the validations defined for the properties class type and the validation context. |
Control Of Action Execution |
As far as I know Struts sets up the Action object for you, and you have very little control over the order of operations. To change them I think |
The ActionFactory chain controls the order in which an Action is constructed and initialised, but this requires writing a class |
The interceptor stacks in WebWork 2 are hugely powerful in this regard. All aspects of Action setup have been moved into Interceptor implementations (ie setting paramters from the web, validation etc), so you can control on a per action basis the order in which they are performed. For example you might want your IOC framework to setup the action before the parameters are set from the request or vice versa - you can thusly control this on a per package or per action basis with interceptor stacks. |
My search criteria for all of these was "framework and java" from the front page on dice.com. I did filter a bunch out for WebWork b/c there's some product called "WebWorks" that folks want to hire for.
In my own experience, these numbers are not as accurate as you might think. Since I gave my original presentation, I've been contacted a number of times to work on projects. It's about even between Struts, Spring MVC, WebWork and JSF. I haven't had a single inquiry to do Tapestry development. The bad part about Struts jobs is there's so many of them, that rates are likely pretty low (i.e. 35-45/hour), whereas the others can get you upwards of 80-90/hour.
依我个h的经验,q些数字不一定就很准?自从我发表第一介l以来,我已l在目中用了好多ơ,包括Struts, Spring MVCQ?WebWorks 和JSFQ?我还没有做Tapestry开发?Struts不好的方面就是太多了Q其工资可能E微低一点(35/45/hour) ,而用其他框架能你提高到80-90/hour?/FONT>
So what do these numbers mean? Do they mean you should tailor your learnings and skills to the most popular frameworks? In a sense, it's important to do so. If nothing else, Struts skills are import so you can migrate all the Struts applications to your favorite framework. However, I don't think these numbers are that important when choosing a framework to start your project with. I think the most important thing in choosing a framework is passion. Which one do you want to work with the most? It's likely that your productivity will be higher if you're enthusiastic about the framework, rather than bored with all the skills you've accumulated using it. Then again, if you're motivated by productivity more than enthusiasm - using your skills to crank out applications quickly is probably a good idea.
那么q些数字意味着我们应该做什么呢Q是不是意味着应该学习那些最行的框Ӟ乍眼看来Q这样做是很重要的?如果没有别的QStruts是很重要的,q且你可以将你所有的Struts应用q移C钟爱的框架中。不q,我认些数字对你选择一U框架开始你的项目来说不是重要的。我惛_选择一U框架时最重要的是passionQ激情)。你最想用哪一个框架工作呢Q或许如果你对一个框架很热情Q你的生产力获得极大的提高Q而不是乏味的使用已经U篏的技术?另外Q如果你׃生力推动而不是激情,那么q用你已U篏的技术去完成目可能是一个好L?/FONT>
You might think that the number of skilled developers for framework X is important too. I don't think it is. I think the most important thing is to hire smart developers. A good developer can come up to speed on any framework in 2 weeks and be highly productive in 4 weeks. If not, the developer isn't that smart or the framework isn't that good.
你可能认为某个框架有l验的开发者的数量也很重要Q我不这么认为,我认为最重要的事情是雇用_明的开发者。一个好的开发h员能在两周时间内使用M框架Qƈ且在四周旉内能熟练q用?如果不是q样的话Q?q个开发h员就不是_明的开发者, 或者这个框架不是优U的?/FONT>
Just for kicks, I did some searching for other web frameworks as well:
Now the question is - what kind of rates are these skills getting? I'd like to know what the average Rails and ASP .NET developers make. In Denver, Java developers seem to make between 65-85/hour when they're experienced contractors