form action="b.jsp"
name:input type=text name=name
input type=submit
/form
b.jsp页面内容:
%@ page language="java" import="java.util.*" pageEncoding="GB2312"%
%
String name=request.getParameter("name");
%
body
%=name%
/body
现象:中文乱码,比如“??????”
解决方法如下:
方法一:
1. 在b.jsp中把pageEncoding="GB2312"改为pageEncoding="ISO8859-1"
虽然这样b.jsp页面显示的内容还是乱码,但是不是那种“??????”的乱码,而是一些特殊字符
2. 然后在浏览器中查看菜单中修改成GB2312的编码,这时乱码就显示中文了。
3. 但是这种方法是不可行的。
方法二:
1. 在b.jsp中把String name=request.getParameter("name");修改为
String name=new String(request.getParameter("name").getBytes("ISO-8859-1"),"GB2312");
2. 这时再在页面上显示,则就是中文了。
方法三:
1. 有人说修改get/post的传值方式,但是这是有前提的,如果只是把get方式修改成post方式,页面结果还是乱码!
2. 前提你必须配置了过滤器,若果你只是配置了过滤器,则传值方式必须是:post方式才不是乱码,如果是get方式照样是乱码!
3. 过滤器的配置,我想大家都能有,我就不说了
方法四:
1. 有人说配置tomcat的配置文件server.xml里这句:
Connector URIEncoding="GB2312"
port="8080" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" redirectPort="8443" acceptCount="100"
connectionTimeout="20000" disableUploadTimeout="true" /
加上这句:URIEncoding="GB2312"
2. 虽然可以但是有前提的,若果你过滤器没有配置,则只是配置了server.xml文件,这样只有在表单是get传值时候才可以!当是post方式时,照样是乱码!
*这时我们就可以看出在tomcat5中的post与get传值方式是不一样的*
*有人要问有没有一种方法让传值使用get方式或post方式都好用呢,下面就是我推荐的方法五*
方法五:
1. 其实很简单,就是同时实现方法三又实现方法四!
2. 就是先配置过滤器,又配置server.xml文件,都设置成GB2312的编码
3. 这样无论是post还是get方式的表单传值,中文都不会是乱码!
五、应用Spring中的切面
Spring生来支持AOP,首先来看几个概念:
1、切面(Aspect):切面是系统中抽象出来的的某一个功能模块,上文已经有过介绍,这里不再多说。
2、通知(Advice):通知是切面的具体实现。也就是说你的切面要完成什么功能,具体怎么做就是在通知里面完成的。这个名称似乎有点让人费解,等后面看了代码就明白了。
3、切入点(Pointcut):切入点定义了通知应该应用到系统的哪些地方。Spring只能控制到方法(有的AOP框架可以控制到属性),也就是说你能在方法调用之前或者之后选择切入,执行额外的操作。
4、目标对象(Target):目标对象是被通知的对象。它可以是任何类,包括你自己编写的或者第三方类。有了AOP以后,目标对象就只需要关注自己的核心业务,其他的功能,比如日志,就由AOP框架支持完成。
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/webkaifa/)5、代理(Proxy):简单的讲,代理就是将通知应用到目标对象后产生的对象。Spring在运行时会给每个目标对象生成一个代理对象,以后所有对目标对象的操作都会通过代理对象来完成。只有这样通知才可能切入目标对象。对系统的其他部分来说,这个过程是透明的,也就是看起来跟没用代理一样。
我为了简化,只介绍这5个概念。通过这几个概念应该能够理解Spring的切面编程了。如果需要深入了解Spring AOP的话再去学习其他概念也很快的。
下面通过一个实际的例子来说明Spring的切面编程。继续上文Greeting的例子,我们想在Speaker每次说话之前记录Speaker被调用了。
首先创建一个LogAdvice类:
代码片段12:
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/webkaifa/)public class LogAdvice implements MethodBeforeAdvice
{
public void before(Method arg0, Object[] arg1, Object arg2)throws Throwable
{
System.out.println("Speaker called!");
}
}
这里涉及到一个类,MethodBeforeAdvice,这个类是Spring类库提供的,类似的还有AfterReturningAdvice等等,从字面就能理解它们的含义。先不急着理解这个类,我稍后解释。我们继续看如何把这个类应用到我们的系统中去。
代码片段13:
bean id="Speaker" class="Speaker"/
bean id="Greeting" class="Greeting"
property name="speaker"
ref bean="SpeakerProxy"/
bean id="LogAdvice" class="LogAdvice"/
bean id="SpeakerProxy" class="org.springframework.aop.framework.ProxyFactoryBean"
property name="proxyInterfaces"
ISpeaker
property name="interceptorNames"
LogAdvice
property name="target"
ref local="Speaker"/
一、Spring诞生
Spring是一个开源框架,目前在开源社区的人气很旺,被认为是最有前途的开源框架之一。她是由Rod Johnson创建的,她的诞生是为了简化企业级系统的开发。说道Spring就不得不说EJB,因为Spring在某种意义上是EJB的替代品,她是一种轻量级的容器。用过EJB的人都知道EJB很复杂,为了一个简单的功能你不得不编写多个Java文件和部署文件,他是一种重量级的容器。也许你不了解EJB,你可能对“轻(重)量级”和“容器”比较陌生,那么这里我简单介绍一下。
1、什么是容器
“萜鳌保 飧龈拍罾 盼液镁谩4友 癟omcat开始就一直对此感到困惑。感性的来讲,容器就是可以用来装东西的物品。那么在编程领域就是指用来装对象(OO的思想,如果你连OO都不了解,建议你去学习OO先)的对象。然而这个对象比较特别,它不仅要容纳其他对象,还要维护各个对象之间的关系。这么讲可能还是太抽象,来看一个简单的例子:
代码片断1:
public class Container
{
public void init()
{
Speaker s = new Speaker();
Greeting g = new Greeting(s);
}
}
可以看到这里的Container类(容器)在初始化的时候会生成一个Speaker对象和一个Greeting对象,并且维持了它们的关系,当系统要用这些对象的时候,直接问容器要就可以了。这就是容器最基本的功能,维护系统中的实例(对象)。如果到这里你还是感到模糊的话,别担心,我后面还会有相关的解释。
2、轻量级与重量级
所谓“重量级”是相对于“轻量级”来讲的,也可以说“轻量级”是相对于重量级来讲的。在Spring出现之前,企业级开发一般都采用EJB,因为它提供的事务管理,声明式事务支持,持久化,分布计算等等都“简化”了企业级应用的开发。我这里的“简化”打了双引号,因为这是相对的。重量级容器是一种入侵式的,也就是说你要用EJB提供的功能就必须在你的代码中体现出来你使用的是EJB,比如继承一个接口,声明一个成员变量。这样就把你的代码绑定在EJB技术上了,而且EJB需要JBOSS这样的容器支持,所以称之为“重量级”。
相对而言“轻量级”就是非入侵式的,用Spring开发的系统中的类不需要依赖Spring中的类,不需要容器支持(当然Spring本身是一个容器),而且Spring的大小和运行开支都很微量。一般来说,如果系统不需要分布计算或者声明式事务支持那么Spring是一个更好的选择。
二、几个核心概念
在我看来Spring的核心就是两个概念,反向控制(IoC),面向切面编程(AOP)。还有一个相关的概念是POJO,我也会略带介绍。
1、POJO
我所看到过的POJO全称有两个,Plain Ordinary Java Object,Plain Old Java Object,两个差不多,意思都是普通的Java类,所以也不用去管谁对谁错。POJO可以看做是简单的JavaBean(具有一系列Getter,Setter方法的类)。严格区分这里面的概念没有太大意义,了解一下就行。
2、IoC
IoC的全称是Inversion of Control,中文翻译反向控制或者逆向控制。这里的反向是相对EJB来讲的。EJB使用JNDI来查找需要的对象,是主动的,而Spring是把依赖的对象注入给相应的类(这里涉及到另外一个概念“依赖注入”,稍后解释),是被动的,所以称之为“反向”。先看一段代码,这里的区别就很容易理解了。
代码片段2:
public void greet()
{
Speaker s = new Speaker();
s.sayHello();
}
代码片段3:
public void greet()
{
Speaker s = (Speaker)context.lookup("ejb/Speaker");
s.sayHello();
}
代码片段4:
public class Greeting
{
public Speaker s;
public Greeting(Speaker s)
{
this.s = s;
}
public void greet()
{
s.sayHello();
}
}
我们可以对比一下这三段代码。其中片段2是不用容器的编码,片段3是EJB编码,片段4是Spring编码。结合代码片段1,你能看出来Spring编码的优越之处吗?也许你会觉得Spring的编码是最复杂的。不过没关系,我在后面会解释Spring编码的好处。
这里我想先解释一下“依赖注入”。根据我给的例子可以看出,Greeting类依赖Speaker类。片段2和片段3都是主动的去获取Speaker,虽然获取的方式不同。但是片段4并没有去获取或者实例化Speaker类,而是在greeting函数中直接使用了s。你也许很容易就发现了,在构造函数中有一个s被注入(可能你平时用的是,传入)。在哪里注入的呢?请回头看一下代码片段1,这就是使用容器的好处,由容器来维护各个类之间的依赖关系(一般通过Setter来注入依赖,而不是构造函数,我这里是为了简化示例代码)。Greeting并不需要关心Speaker是哪里来的或是从哪里获得Speaker,只需要关注自己分内的事情,也就是让Speaker说一句问候的话。
3、AOP
AOP全称是Aspect-Oriented Programming,中文翻译是面向方面的编程或者面向切面的编程。你应该熟悉面向过程的编程,面向对象的编程,但是面向切面的编程你也许是第一次听说。其实这些概念听起来很玄,说到底也就是一句话的事情。
现在的系统往往强调减小模块之间的耦合度,AOP技术就是用来帮助实现这一目标的。举例来说,假如上文的Greeting系统含有日志模块,安全模块,事务管理模块,那么每一次greet的时候,都会有这三个模块参与,以日志模块为例,每次greet之后,都要记录下greet的内容。而对于Speaker或者Greeting对象来说,它们并不知道自己的行为被记录下来了,它们还是像以前一样的工作,并没有任何区别。只是容器控制了日志行为。如果这里你有点糊涂,没关系,等讲到具体Spring配置和实现的时候你就明白了。
假如我们现在为Greeting系统加入一个Valediction功能,那么AOP模式的系统结构如下:
GRETTING
VALEDITION
日志 安全 事务
这些模块是贯穿在整个系统中的,为系统的不同的功能提供服务,可以称每个模块是一个“切面”。其实“切面”是一种抽象,把系统不同部分的公共行为抽取出来形成一个独立的模块,并且在适当的地方(也就是切入点,后文会解释)把这些被抽取出来的功能再插入系统的不同部分。
从某种角度上来讲“切面”是一个非常形象的描述,它好像在系统的功能之上横切一刀,要想让系统的功能继续,就必须先过了这个切面。这些切面监视并拦截系统的行为,在某些(被指定的)行为执行之前或之后执行一些附加的任务(比如记录日志)。而系统的功能流程(比如Greeting)并不知道这些切面的存在,更不依赖于这些切面,这样就降低了系统模块之间的耦合度。
三、Spring初体验
这一节我用一个具体的例子Greeting,来说明使用Spring开发的一般流程和方法,以及Spring配置文件的写法。
首先创建一个Speaker类,你可以把这个类看做是POJO。
代码片段5:
public class Speaker
{
public void sayHello()
{
System.out.println("Hello!");
}
}
再创建一个Greeting类。
代码片段6:
public class Greeting
{
private Speaker speaker;
public void setSpeaker(Speaker speaker)
{
this.speaker = speaker;
}
public void greet()
{
speaker.sayHello();
}
}
然后要创建一个Spring的配置文件把这两个类关联起来。
代码片段7(applicationContext.xml):
"1.0" encoding="UTF-8"?
"-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd"
bean id="Speaker" class="Speaker"
bean id="Greeting" class="Greeting"
property name="speaker"
ref bean="Speaker"/
要用Spring Framework必须把Spring的包加入到Classpath中,我用的是Eclipse+MyEclipse,这些工作是自动完成的。推荐用Spring的配置文件编辑器来编辑,纯手工编写很容易出错。我先分析一下这个xml文件的结构,然后再做测试。从节点开始,先声明了两个,第二个bean有一个speaker属性(property)要求被注入,注入的内容是另外一个bean Speaker。这里的命名是符合JavaBean规范的,也就是说如果是speaker属性,那么Spring容器就会调用setSpeaker()来注入这个属性。是reference的意思,表示引用另外一个bean。