??xml version="1.0" encoding="utf-8" standalone="yes"?> Author: 江南白衣 1.所以业务异常类z于BusinessException基类?/p>
2.原则上,要进行相同处理的异常分ؓ一c,用ERROR_CODE标识不同?/p>
3.出错信息l一写在errors.propertiesQ以ERROR_CODEZ键,支持i18NQ由基类提供默认的getMessage()函数?/p>
参考BussinessException.java和OrderException.java?/p>
spring-mvc可在xxx-serverlet.xml里定义default?按Excepitoncd影射的错误页? 和Servlet规范?主要作了Spring特色的JSP路径转向和日志记?参见bookstore-servlet.xml error.jsp会同时处理jsp,servlet,和spring抛过来的异常 其中jsp的异常在exception 变量? servlet的异常在(Exception)request.getAttribute("javax.servlet.error.exception") spring的异常在(Exception) request.getAttribute("exception") 使用 (String) request.getAttribute("javax.servlet.error.request_uri")获得 request_uri Delegates 通过一pd的由spring托管的beans Q代理过滤请求?br />FilterChainProxy 通过在web.xml中定义的FilterToBeanProxy 被加载,FilterChainProxy 会通过 It is particularly noted the If a filter name of Author: cac 差沙 Acegi是Spring Framework 下最成熟的安全系l,它提供了强大灉|的企业安全服务Q如完善的认证和授权机制QHttp资源讉K控制QMethod 调用讉K控制QAccess Control List (ACL) Z对象实例的访问控ӞYale Central Authentication Service (CAS) 耉单点登陆QX509 认证Q当前所有流行容器的认证适配器,Channel Security频道安全理{功能?/p>
官方|站 http://acegisecurity.sourceforge.net Acegi只是安全框架之一Q其实还存在其它优秀的安全框架可供选择Q?/p>
<bean id="c3p0DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass">
<value>${jdbc.driverClassName}</value>
</property>
<property name="jdbcUrl">
<value>${jdbc.url}</value>
</property>
<property name="user">
<value>${jdbc.username}</value>
</property>
<property name="password">
<value>${jdbc.password}</value>
</property>
<property name="initialPoolSize"><value>10</value></property>
<property name="minPoolSize"><value>5</value></property>
<property name="maxPoolSize"><value>30</value></property>
<property name="acquireIncrement"><value>5</value></property>
<property name="maxIdleTime"><value>10</value></property>
<property name="maxStatements"><value>0</value></property>
</bean>
以下几个参数是用的基本配置参数Q?br />initialPoolSizeQ?
Number of Connections a pool will try to acquire upon startup. Should be between minPoolSize and maxPoolSize
q接池初始化时获取的链接敎ͼ介于minPoolSize和maxPoolSize之间
minPoolSizeQ?br />Minimum number of Connections a pool will maintain at any given time.
最链接数
maxPoolSizeQ?br />Maximum number of Connections a pool will maintain at any given time.
最大连接数
acquireIncrementQ?br />Determines how many connections at a time c3p0 will try to acquire when the pool is exhausted.
在当前连接数耗尽的时候,一ơ获取的新的q接?br />
maxIdleTimeQ?br />Seconds a Connection can remain pooled but unused before being discarded. Zero means idle connections never expire.
最大空闲的旉Q单位是U,无用的链接再q时后会被回?br />
]]>
]]>1.业务异常c?/h2>
2.Servlet规范里的异常控制
2.1按error-codel一定义错误面
<error-page>
<error-code>404</error-code>
<location>/404.jsp</location>
</error-page><error-page>
<error-code>500</error-code>
<location>/error.jsp</location>
</error-page>2.2按异常类型定义单独错误页?/h3>
<error-page>
<exception-type>org.sprngside.bookstore.UserNotFound</exception-type>
<location>/userNotFound.jsp</location>
</error-page>2.3 在JSP里单独定义错误页?/h3>
<@ errorPage="error.jsp">
3.Spring MVC里的异常控制
<bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="defaultErrorView" value="/error.jsp"/>
<property name="exceptionMappings">
<props>
<prop key="org.springside.framework.base.BusinessException">/businessError.jsp</prop>
</props>
</property>
</bean>4. error.jsp的处?/h2>
使用 logger.error(exception.getMessage(), exception); 记录整个异常?/p>
java.lang.Object
org.acegisecurity.util.FilterChainProxy
public class FilterChainProxy
Filter
requests to a list of Spring-managed beans. init(FilterConfig)
, destroy()
and doFilter(ServletRequest, ServletResponse, FilterChain)
调用Q调用每一个在其中定义的过滤器?br />
The FilterChainProxy
is loaded via a standard FilterToBeanProxy
declaration in web.xml
. FilterChainProxy
will then pass init(FilterConfig)
, destroy()
and doFilter(ServletRequest, ServletResponse, FilterChain)
invocations through to each Filter
defined against FilterChainProxy
.
is configured using a standard
FilterChainProxy 是通过一个标准的FilterInvocationDefinitionSource 来实现配|的Q每个可能的FilterChainProxy应该服务的URI模式都必进?br /> W一个搭配的URI模式会被用来定义处理请求的所有的qo器,是说只适配W一l过滤器Q后面的其他qo器将无效?br />FilterChainProxyFilterInvocationDefinitionSource
. Each possible URI pattern that FilterChainProxy
should service must be entered. The first matching URI pattern located by FilterInvocationDefinitionSource
for a given request will be used to define all of the Filter
s that apply to that request. NB: This means you must put most specific URI patterns at the top of the list, and ensure all Filter
s that should apply for a given URI pattern are entered against the respective entry. The FilterChainProxy
will not iterate the remainder of the URI patterns to locate additional Filter
s. The FilterInvocationDefinitionSource
described the applicable URI pattern to fire the filter chain, followed by a list of configuration attributes. Each configuration attribute's ConfigAttribute.getAttribute()
corresponds to a bean name that is available from the application context.FilterChainProxy
respects normal handling of Filter
s that elect not to call Filter.doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
, in that the remainder of the origial or FilterChainProxy
-declared filter chain will not be called.Filter
lifecycle mismatch between the servlet container and IoC container. As per FilterToBeanProxy
JavaDocs, we recommend you allow the IoC container to manage lifecycle instead of the servlet container. By default the FilterToBeanProxy
will never call this class' init(FilterConfig)
and destroy()
methods, meaning each of the filters defined against FilterInvocationDefinitionSource
will not be called. If you do need your filters to be initialized and destroyed, please set the lifecycle
initialization parameter against the FilterToBeanProxy
to specify servlet container lifecycle management.TOKEN_NONE
is used, this allows specification of a filter pattern which should never cause any filters to fire.
]]>1.1 |站资源
论坛 http://forum.springframework.org/forumdisplay.php?f=33
Jira http://opensource.atlassian.com/projects/spring/browse/SEC1.2 多方面的安全控制_度
http://apps:8080/index.htm -> for public
http://apps:8080/user.htm -> for authorized user
public void getData() -> all user
public void modifyData() -> supervisor only
order.getValue() < $100 -> all user
order.getValue() > $100 -> supervisor only1.3 非入侵式安全架构
1.4 其它安全架构
]]>
http://www.springside.org.cn/docs/reference/Acegi2.htm
http://www.springside.org.cn/docs/reference/Acegi3.htm
http://www.springside.org.cn/docs/reference/Acegi4.htm
http://www.springside.org.cn/docs/reference/Acegi5.htm
http://www.springside.org.cn/docs/reference/Acegi6.htm
]]>
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.generic.GenericBeanFactoryAccessor;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.ColumnMapRowMapper;
import org.springframework.jdbc.core.ConnectionCallback;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCallback;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.jdbc.core.RowCountCallbackHandler;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.StatementCallback;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.samples.petclinic.Person;
/**
*
* @author worldheart
*
*/
public class MainTestForJdbcTemplate {
private static final Log log = LogFactory.getLog(MainTestForJdbcTemplate.class);
public static void main(String[] args) {
ListableBeanFactory cbf = new ClassPathXmlApplicationContext("ac1.xml");
GenericBeanFactoryAccessor gbfa = new GenericBeanFactoryAccessor(cbf);
JdbcTemplate jt = gbfa.getBean("jdbcTemplate");
jt.execute(new ConnectionCallback(){
public Object doInConnection(Connection con) throws SQLException, DataAccessException {
System.out.println(con.getMetaData().getDriverName());
return null;
}
});
List nameList = (List)jt.execute(new StatementCallback(){
public Object doInStatement(Statement stmt) throws SQLException, DataAccessException {
System.out.println(stmt.getConnection().getMetaData().getDatabaseProductVersion());
List<String> nameList = new ArrayList<String>();
ResultSet rs = null;
try{
rs = stmt.executeQuery("select name from types");
while(rs.next()){
nameList.add(rs.getString("name"));
}
}finally{
JdbcUtils.closeResultSet(rs);
}
return nameList;
}
});
System.out.println(nameList);
List perList = (List)jt.query("select * from vets",
new ResultSetExtractor(){
public Object extractData(ResultSet rs) throws SQLException, DataAccessException {
List<Person> personList = new ArrayList<Person>();
while(rs.next()){
Person per = new Person();
per.setId(rs.getInt("id"));
per.setFirstName(rs.getString("first_name"));
per.setLastName(rs.getString("last_name"));
personList.add(per);
}
return personList;
}
});
for(Iterator iterator = perList.iterator(); iterator.hasNext();){
Person person = (Person)iterator.next();
System.out.println(person.getId() + "," + person.getFirstName() + "," + person.getLastName());
}
final List<Person> pSonList = new ArrayList<Person>();
jt.query("select * from vets", new RowCallbackHandler(){
public void processRow(ResultSet rs) throws SQLException {
Person per = new Person();
per.setId(rs.getInt("id"));
per.setFirstName(rs.getString("first_name"));
per.setLastName(rs.getString("last_name"));
pSonList.add(per);
}
});
for(Person pSon: pSonList){
System.out.println(pSon.getId() + "," + pSon.getFirstName() + "," + pSon.getLastName());
}
RowCountCallbackHandler rcch = new RowCountCallbackHandler();
jt.query("select * from vets", rcch);
for(String colName: rcch.getColumnNames())
System.out.println(colName);
for(int colType: rcch.getColumnTypes())
System.out.println(colType);
System.out.println(rcch.getColumnCount());
System.out.println(rcch.getRowCount());
List vetsList = (List)jt.query("select * from vets",
new RowMapper(){
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
Person pers = new Person();
pers.setId(rs.getInt("id"));
pers.setFirstName(rs.getString("first_name"));
pers.setLastName(rs.getString("last_name"));
return pers;
}
});
System.out.println(vetsList);
ColumnMapRowMapper cmrw = new ColumnMapRowMapper();
List vList = (List)jt.query("select * from vets", cmrw);
System.out.println(vList);
System.out.println(jt.queryForInt("select count(*) from vets where id = ?",
new Object[]{3}));
jt.execute("update owners set address = 'GuangZhou' where telephone = ?",
new PreparedStatementCallback(){
public Object doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException {
ps.setString(1, "16068008");
ps.addBatch();
ps.setString(1, "6085555487");
ps.addBatch();
return ps.executeBatch();
}
});
System.out.println(jt.query("select address from owners where first_name = ? and last_name = ?",
new PreparedStatementSetter(){
public void setValues(PreparedStatement ps) throws SQLException {
ps.setString(1, "Jeff");
ps.setString(2, "Black");
}
},
new RowMapper(){
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
return rs.getString("address");
}
}));
System.out.println(jt.execute(
new PreparedStatementCreator(){
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
return con.prepareStatement("select address from owners");
}
},
new PreparedStatementCallback(){
public Object doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException {
List<String> list = new ArrayList<String>();
ResultSet rs = null;
try{
rs = ps.executeQuery();
while(rs.next()){
list.add(rs.getString("address"));
}
}finally{
JdbcUtils.closeResultSet(rs);
}
return list;
}
}));
}
}
public class BindStatus
Simple adapter to expose the bind status of a field or object. Set as a variable both by the JSP bind tag and Velocity/FreeMarker macros.
单的适配器获取域或者是对象l定状态, 同样适用于模ѝ?br />Obviously, object status representations (i.e. errors at the object level rather than the field level) do not have an expression and a value but only error codes and messages. For simplicity's sake and to be able to use the same tags and macros, the same status class is used for both scenarios.
昄Q对象的状态表C(例如错误是对象的而不是域U别的)没有表达式或者|而是只有错误码和消息
Method Summary | |
---|---|
int
|
doEndTag
()
|
void
|
doFinally
()
|
protected int
|
doStartTagInternal
()
Called by doStartTag to perform the actual work. |
PropertyEditor
|
getEditor
()
Retrieve the PropertyEditor for the property that this tag is currently bound to. |
Errors
|
getErrors
()
Retrieve the Errors instance that this tag is currently bound to. |
String
|
getPath
()
Return the path that this tag applies to. |
String
|
getProperty
()
Retrieve the property that this tag is currently bound to, or null if bound to an object rather than a specific property. |
boolean
|
isIgnoreNestedPath
()
Return whether to ignore a nested path, if any. |
void
|
setIgnoreNestedPath
(boolean ignoreNestedPath)
Set whether to ignore a nested path, if any. |
void
|
setPath
(String path)
Set the path that this tag should apply. |
/**
List perList = (List)jt.query("select * from vets",
new ResultSetExtractor(){
public Object extractData(ResultSet rs) throws SQLException, DataAccessException {
List<Person> personList = new ArrayList<Person>();
while(rs.next()){
Person per = new Person();
per.setId(rs.getInt("id"));
per.setFirstName(rs.getString("first_name"));
per.setLastName(rs.getString("last_name"));
personList.add(per);
}
return personList;
}
});
public interface Mappable {
/**
/**
控制器的概念是MVC设计模式的一部分(切地说Q是MVC中的CQ。应用程序的行ؓ通常被定义ؓ服务接口Q而控制器使得用户可以讉K应用所提供的服务。控制器解析用户输入Qƈ其转换成合理的模型数据Q从而可以进一步由视图展示l用戗Spring以一U抽象的方式实现了控制器概念Q这样得不同类型的控制器可以被创徏。Spring本n包含表单控制器、命令控制器、向导型控制器等多种多样的控制器?/p>
Spring控制器架构的基础?code class="interfacename">org.springframework.mvc.Controller接口Q其代码如下Q?/p>
public interface Controller { /** * Process the request and return a ModelAndView object which the DispatcherServlet * will render. */ ModelAndView handleRequest( HttpServletRequest request, HttpServletResponse response) throws Exception; }
你可以发?code class="interfacename">Controller接口仅仅声明了一个方法,它负责处理请求ƈq回合适的模型和视图。Spring MVC实现的基是q三个概念:Mdel、ViewQ?code class="classname">ModelAndViewQ以?Controller
。虽?code class="interfacename">Controller接口是完全抽象的Q但Spring也提供了许多你可能会用到的控制器。Controller接口仅仅定义了每个控制器都必L供的基本功能Q处理请求ƈq回一个模型和一个视图?/p>
Z提供一套基设施Q所有的Spring控制器都l承?AbstractController
Q?code class="classname">AbstractController 提供了诸如缓存支持和mimetype讄q样的功能?/p>
表?3.3. AbstractController
提供的功?/b>
功能 | 描述 |
---|---|
supportedMethods
|
指定q个控制器应该接受什么样的请求方法。通常它被讄成同时支持GET和POSTQ但是你可以选择你想支持的方法。如果控制器不支持请求发送的ҎQ客L会得到通知Q通常是抛Z?code class="classname">ServletExceptionQ? |
requiresSession
|
指定q个控制器是否需要HTTP session才能正常工作。如果控制器在没有session的情况下接收到请求,客户端会因ؓ抛出ServletException 而得到通知? |
synchronizeSession
|
指定controller是否同步用户的HTTP session? |
cacheSeconds
|
指定controller通知客户端对数据内容~存的秒敎ͼ一般ؓ大于零的整数。默认gؓ-1Q即不缓存? |
useExpiresHeader
|
指定Controller在响应请求时是否兼容HTTP 1.0 Expires header。缺省gؓtrue ? |
useCacheHeader
|
指定Controller在相应请求时是否兼容HTTP 1.1 Cache-Control header。默认gؓtrue ? |
当从AbstractController
l承Ӟ需要实?code class="literal">handleRequestInternal(HttpServletRequest, HttpServletResponse)抽象ҎQ该Ҏ用来实现自q逻辑Qƈq回一?code class="classname">ModelAndView对象。下面这个简单的例子演示了如何从AbstractController
l承以及如何在applicationContext.xml中进行配|?/p>
package samples; public class SampleController extends AbstractController { public ModelAndView handleRequestInternal( HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView mav = new ModelAndView("hello"); mav.addObject("message", "Hello World!"); return mav; } }
<bean id="sampleController" class="samples.SampleController"> <property name="cacheSeconds" value="120"/> </bean>
该controllerq回的ModelAndView使用了硬~码的视囑Q尽这样做不好Q,q知客户端将响应数据~存2分钟。除了通过以上方式创徏和配|controller之外Q还需要配|handler mapping(请参?a title="13.4. 处理器映(handler mappingQ? href="mk:@MSITStore:C:\Documents%20and%20Settings\ljl\桌面\spring2.0-reference_final_zh_cn.chm::/ch13s04.html">W?3.4 ?“处理器映射Qhandler mappingQ?/a>)Q这栯controller可以工作了?/p>
管可以l承AbstractController
来实现自q控制器,不过Spring提供的众多控制器减轻了我们开发简单MVC应用时的负担?code class="classname">ParameterizableViewController基本上和上面例子中的一P不同的是Q你可以在applicationContext.xml配置中指定返回视囑从而避免了在Java代码中的编码?/p>
UrlFilenameViewController
会检查URLQ获取文件请求的文g名,q把它作囑加以使用。。例如,http://www.springframework.org/index.html
对应的视图文件名?code class="literal">index?/p>
MultiActionController
多个行?action)合ƈ在一个控制器里,q样可以把相兛_能组合在一赗?code class="classname">MultiActionController位于org.springframework.web.mvc.multiaction
包中Q它通过请求映到正确的方法名来调用方法。当在一个控制器存在大量公共的行为,但是有多个调用入口时Q?code class="classname">MultiActionControllerq别方ѝ?/p>
表?3.4. MultiActionController
提供的功?/b>
功能 | 描述 |
---|---|
delegate
|
MultiActionController 有两U用方式。第一U是你?code class="classname">MultiActionControllerQƈ在子cM指定?code class="interfacename">MethodNameResolver解析的方法(q种情况下不需要这个delegate参数Q。第二种是你定义一个代理对象,由它提供MethodNameResolver 解析出来的方法(q种情况下,你必M用这个配|参数定义代理对象)? |
methodNameResolver
|
MultiActionController 需要一U策略,使其可以通过解析h信息来获得要调用的方法。这个解析策略由MethodNameResolver q个接口定义的。这个参数允怽实现MethodNameResolver 接口Q然后在控制器中使用你的{略? |
MultiActionController
所支持的方法需要符合下列格式:
// anyMeaningfulName can be replaced by any methodname
public [ModelAndView | Map | void] anyMeaningfulName(HttpServletRequest, HttpServletResponse [, Exception | AnyObject]);
注意Q在?span class="emphasis">不允?/em>Ҏ重蝲Q因?code class="classname">MultiActionController无法分L出重载(overloadingQ了的方法。此外,你可以定?span class="emphasis">exception handler来处理方法中抛出的异常?
Exception
参数是可选的Q它可以?span class="emphasis">M异常Q只要它?code class="classname">java.lang.Exception?code class="classname">java.lang.RuntimeException的子cR?code class="classname">AnyObject参数也是可选的Q它可以?span class="emphasis">M对象。HTTP Request中的参数会存在这个对象中Q以便用?/p>
下面几个例子C?code class="classname">MultiActionController正确的方法定义?/p>
标准格式(?code class="interfacename">Controller接口定义的一??/p>
public ModelAndView doRequest(HttpServletRequest, HttpServletResponse)
下面q个Ҏ支持Login
参数Q?q个参数中包含从h中抽取出来的信息?/p>
public ModelAndView doLogin(HttpServletRequest, HttpServletResponse, Login)
下面q个Ҏ可以处理Exception
?/p>
public ModelAndView processException(HttpServletRequest, HttpServletResponse, IllegalArgumentException)
下面q个Ҏ不返回Q何数倹{?(请参考后面的章节 W?3.11 ?“惯例优先原?convention over configuration)?/a>)
public void goHome(HttpServletRequest, HttpServletResponse)
This signature has a Map
return type (see the section entitled W?3.11 ?“惯例优先原?convention over configuration)?/a> below).
下面q个Ҏq回一?code class="interfacename">Map?(请参考后面的章节W?3.11 ?“惯例优先原?convention over configuration)?/a>)
public Map doRequest(HttpServletRequest, HttpServletResponse)
MethodNameResolver
负责从请求中解析出需要调用的Ҏ名称。下面是Spring中内|的三个MethodNameResolver
实现?/p>
ParameterMethodNameResolver
- 解析h参数Qƈ它作ؓҎ名?对应http://www.sf.net/index.view?testParam=testIt
的请求,会调?testIt(HttpServletRequest,HttpServletResponse)
Ҏ)。?code class="literal">paramName配置参数Q可以设定要查的参数?/p>
InternalPathMethodNameResolver
-从\径中获取文g名作为方法名 (http://www.sf.net/testing.view
的请求会调用testing(HttpServletRequest,HttpServletResponse)
Ҏ?/p>
PropertiesMethodNameResolver
- 使用用户自定义的属性对象,请求的URL映射到方法名。当属性中包含/index/welcome.html=doIt
Ӟ发到/index/welcome.html
的请求会调用doIt(HttpServletRequest, HttpServletResponse)
q个Ҏ?q个Ҏ名解析器可以?code class="literal">PathMatcher一起工作,比如上边那个URL写成/**/welcom?.html
也是可以的?/p>
我们来看一l例子。首先是一个?code class="classname">ParameterMethodNameResolver和代理(delegateQ属性的例子Q它接受包含参数?method"的请求,调用ҎretrieveIndex
Q?
<bean id="paramResolver" class="org....mvc.multiaction.ParameterMethodNameResolver">
<property name="paramName" value="method"/>
</bean>
<bean id="paramMultiController" class="org....mvc.multiaction.MultiActionController">
<property name="methodNameResolver" ref="paramResolver"/>
<property name="delegate" ref="sampleDelegate"/>
</bean>
<bean id="sampleDelegate" class="samples.SampleDelegate"/>
## together with
public class SampleDelegate {
public ModelAndView retrieveIndex(HttpServletRequest req, HttpServletResponse resp) {
return new ModelAndView("index", "date", new Long(System.currentTimeMillis()));
}
}
当用上面的代理对象Ӟ我们也可以?code class="classname">PropertiesMethodNameRseolver来匹配一lURLQ将它们映射到我们定义的Ҏ上:
<bean id="propsResolver" class="org....mvc.multiaction.PropertiesMethodNameResolver"> <property name="mappings"> <value> /index/welcome.html=retrieveIndex /**/notwelcome.html=retrieveIndex /*/user?.html=retrieveIndex </value> </property> </bean> <bean id="paramMultiController" class="org....mvc.multiaction.MultiActionController"> <property name="methodNameResolver" ref="propsResolver"/> <property name="delegate" ref="sampleDelegate"/> </bean>
Spring?span class="emphasis">CommandController是Spring MVC的重要部分。命令控制器提供了一U和数据对象交互的方式,q动态地来?code class="interfacename">HttpServletRequest的参数绑定到你指定的数据对象上。它的功能和Struts中的ActionForm
有点像,不过在Spring中,你不需要实CQ何接口来实现数据l定。首先,让我们看一下有哪些可以使用的命令控制器Q?/p>
AbstractCommandController
Q-你可以用该抽象命o控制器来创徏自己的命令控制器Q它能够请求参数绑定到你指定的命o对象。这个类q不提供M表单功能Q但是它提供验证功能Qƈ且让你在子类中去实现如何处理p求参C生的命o对象?
AbstractFormController
Q-一个支持表单提交的抽象控制器类。用这个控制器Q你可以定义表单Qƈ使用从控制器获取的数据对象构单。当用户输入表单内容Q?code class="classname">AbstractFormController用戯入的内容l定到命令对象,验证表单内容Qƈ该对象交给控制器,完成相应的操作。它支持的功能有防止重复提交、表单验证以及一般的表单处理程。子c需要实现自qҎ来指定采用哪个视图来昄输入表单Q哪个视图显C单正提交后的结果。如果你需要表单,但不惛_应用上下文中指定昄l用L视图Q就使用q个控制器?
SimpleFormController
Q-q是一个form cotnrollerQ当需要根据命令对象来创徏相应的form的时候,该类可以提供更多的支持。你可以为其指定一个命令对象,昄表单的视囑Q当表单提交成功后显C给用户的视囑{等?
AbstractWizardFormController
Q-q是一个抽象类Q承这个类需要实?code class="literal">validatePage()?code class="literal">processFinish() ?code class="literal">processCancel() Ҏ?/p>
你有可能也需要写一个构造器Q它臛_需要调?code class="literal">setPages()?code class="literal">setCommandName()Ҏ。setPages()的参数是一个String数组Q这个数l包含了l成向导的视囑。setCommandName()的参数是一个StringQ该参数用来在视图中调用你的命令对象?/p>
?code class="classname">AbstractFormController的实C? 你需要用命令对象(其实是一个JavaBeanQ?q个bean中包含了表单的信息)。你有两个选择Q在构造函C调用setCommandClass()
ҎQ参数是命o对象的类名)Q或者实?code class="literal">formBackingObject()Ҏ?/p>
AbstractWizardFormController
有几个你可以复写QoverrideQ的Ҏ。最有用的一个是referenceData(..)
。这个方法允怽把模型数据以Map
的格式传递给视图Q?code class="literal">getTargetPage() 允许你动态地更改向导的页面顺序,或者直接蟩q某些页面;onBindAndValidate()
允许你复写内|的l定和验证流E?/p>
最后,我们有必要提一?code class="literal">setAllowDirtyBack() ?code class="literal">setAllowDirtyForward()两个Ҏ?你可以在getTargetPage()
中调用这两个ҎQ这两个Ҏ决定在当前面验证p|Ӟ是否允许向导前移或后退?/p>
AbstractWizardFormController
的更详细内容请参考JavaDoc。在Spring附带的例子jPetStore中,有一个关于向导实现的例子Q?org.springframework.samples.jpetstore.web.spring.OrderFormController
?/p>
p和Spring集成的其他表现层技术一P对于JSP面你需要一个视图解析器来解析。最常用的JSP视图解析器是InternalResourceViewResolver?tt class="literal">ResourceBundleViewResolver。它们被定义在WebApplicationContext里:
# The ResourceBundleViewResolver: <bean id="viewResolver" class="org.springframework.web.servlet.view.ResourceBundleViewResolver"> <property name="basename"><value>views</value></property> </bean> # And a sample properties file is uses (views.properties in WEB-INF/classes): welcome.class=org.springframework.web.servlet.view.JstlView welcome.url=/WEB-INF/jsp/welcome.jsp productList.class=org.springframework.web.servlet.view.JstlView productList.url=/WEB-INF/jsp/productlist.jsp
你可以看到ResourceBundleViewResolver需要一个属性文件来把视囑U映到 1)cd 2) URL?通过ResolverBundleViewResolverQ你可以用一个解析器来解析两U类型的视图?/p>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass"><value>org.springframework.web.servlet.view.JstlView</value></property> <property name="prefix"><value>/WEB-INF/jsp/</value></property> <property name="suffix"><value>.jsp</value></property> </bean>
InternalResourceBundleViewResolver可以配置成用JSP面。作为好的实现方式,强烈推荐你将JSP文g攑֜WEB-INF下的一个目录中Q这样客L׃会直接访问到它们?/p>
Spring 2.0版本支持扩展XML配置Q着实兴奋了一下,在我看来QSpring作ؓ目前最行的框Ӟ不能扩展用户自定义的配置Q实在是Spring的一个很不爽的地方,<bean />的方式用h比较通用Qv码到目前为止W合大部分h的用习惯,q且能完成Spring所有的配置操作,但是对于W三方的提供商或则会l常扩展Spring功能的开发者来?使用<bean />q样的配|方式或怸是他们最惌的,他们需要ɾlg的配|更加直观、易阅读、易扩展……试想用下面的配置方式 代码
上面的代码中配置了两个组Ӟdatasource和cachelgQ相比普通的bean&propertiy方式,很显Ӟq种配置方式更直观,更易读,更重要的是,如果作ؓlg发布Q用者也可以很方便快L开始用,而不需要关心组件的M实现l节? 扩展XML配置大致需要一下几个步? 提供一个简单的例子Q来说明如何L展一个Spring配置Q需求如下:使用自定义标{֮义一个简单的beanQ这个bean有一个或多个属性,标签定义完成后,可以在其他项目中用自定义标签来定义该bean?/p> 首先Q创Z个需要扩展的lgQ在q里只是一个简单的beanQ而且q个bean只有一个属性age. 代码
然后Q徏立一个xsd文gQ来描述q个bean 代码
在上面的xsd文g描述了一个新的targetNamespaceQƈ在这个空间中定义了一个name为one的element,one有一个age属性,cd为stringQ默认gؓ99999.xsd文g是xml DTD的替代者,使用XML Schema语言q行~写Q这里对xsd schema不做太多解释Q有兴趣可以参考相关的资料? 创徏一个Java文gQ该文g实现了BeanDefinitionParser接口Q用来解析xsd文g中的定义q注册到lg中? 代码
上面的代码仅仅实C一个方法public BeanDefinition parse(Element arg0, ParserContext arg1)Q设|相关的Bean ClassQ解析了对应的xsd文gQƈ解析的内容注册C下文中,同时q回一个BeanDefinition对象QBeanDefinition是Spring的bean定义Q提供了bean部分的操作方法,如isSingleton()、isLazyInit(){?? 注意Qid属性是一个默认的属性,可以不在xsd文g中描qͼ但是需要注册它Q否则将无法通过getBeanҎ获取标签定义的beanQ也无法被其他bean引用? 代码
然后为组件编写一个Handler文gQ扩展自NamespaceHandlerSupportQ它的作用是组件注册到Spring容器 代码
实际执行的过E只有一句代码,注册了一个名字ؓone的扩展配|,包含了MyBeanDefinitionParser所parser相关xsd的内宏V? Cq里Q一个Spring扩展标签已经完成Q但是我们目前还没办法用它QSpring没那么聪明,它无法知道我们在什么地方定义了哪些扩展标签Q这些标{ְ被谁解析Q这个过E要我们通过一些文件来告知Spring知道Q它们就是spring.handlers和spring.schemasQ它们放在META-INF目录中,Spring.jar的META-INF目录中也有同名的文gQ它们的文g内容基本上是怼的,而Spring在执行过E中Q如果发现其他jar文g的META-INF文g夹中包含有这两个文gQSpring会合ƈ它们? 代码
spring.handlers 代码
spring.schemas告诉Spring配置文g知道Q如果在配置中引用http://www.mysite.org/schema/mytag.xsdQ它应该M么地Ҏ相应的xsd文g? 现在为止Q一个完整的xml扩展标签全部完成Q做一个小应用试一下? 代码
在xml文g引用上可以看?配置了一个名字ؓtag的名U空?目标为http://www.mysite.org/schema/mytag命名I间,q个目标名称I间必须是存在于目的引用中?mytag.xsd中所定义?. 代码
上面定义了一个id为oneBean的组Ӟ使用了“one”扩展标{,也就是我们在handler中所注册的,lgage属性的gؓ99? Main.java 代码
q行试E序Q结果如? 代码
Spring的xml扩展是一个非常有用的Ҏ,在Spring2.0的版本中也提供了一些新的标{用,?lt;aop>,<tx>{?但就目前来讲受大家关注程度ƈ不高Q我惛_部分使用Spring的开发h员都在用Spring开发企业应用,而Spring所提供?lt;bean />定义的方式对于开发h员来说已l能够满需要,但是如果看的更远一些,在Spring以后的发展过E中Qxml扩展应该会成为spring的核心特性之一Q或许到时大家会习惯q样的方式来~写Spring配置文g? 代码
|
评论 ?2 ? | 发表评论 |
代码
对于单的应用可以用p标签好了? |
h的分?/p> h首先到达DispatcherServletQ应用服务器会根据Web应用中web.xml文g定义的url映射相应的h分发到DispatcherServlet?/p> h的处?/p> DispatcherServlet会查扄应的HandlerMapping接口的实现类Q调用其中的ҎQHandlerExecutionChain getHandler(HttpServletRequest request) throws ExceptionQ该Ҏ会返回一个HandlerExecutionChain。返回的HandlerExecutionChain中包含了零个或者是多个Interceptor和一个处理请求的Handler。DispatcherServlet会调用Interceptor中的preHandle() Ҏ。然后处理HandlerQ这个Handler相当于Struts中ActionQ在SpringMVC中默认的实现是Controller接口Q是具体处理h的代码所ȝ的地斏V事实上HandlerExecutionChain中的getHandler()q回的是一个Objectcd。DispatcherServlet不会直接调用getHandlerQ)q回对象中的ҎQDispatcherServlet会查扄应的HandlerAdapterQ然后具体通过HandlerAdapter来调用getHandler()q回的handler对象中的Ҏ。就是说我们可以实现自己的HandlerAdapter然后通过IoC注入到DispatcherServlet中,从而可以实C套自定义的控制器。随后DispatcherServlet会调用Interceptor中的postHandle()Ҏ? 视图的处?/p> DispatcherServlet会期望Handerq回一个ModelAndViewQDispatcherServlet会根据所q回的ModelAndView对象所包含的信息进行视囄渲染。v具体出来程如下Q?/p> 首先DispatcherServlet会根据LocaleResolver来识别请求中的LocaleQ开发h员可以自己实现LocaleResolver接口Q然后通过IoC注入到DispatcherServlet中,然后DispatcherServlet会判断ModelAndView中是否已l包含了接口View的具体实玎ͼ如果包含了,则直接调用View中的Ҏrender(Map model, HttpServletRequest request, HttpServletResponse response)。如果不包含Q则说明该ModelAndView只是包含了View的名U引用,DispatcherServlet会调用ViewResolver中的resolveViewName(String viewName, Locale locale)来解析其真正的视图。该Ҏ会返回一个View的具体实现?/p> 视图的渲?/p> Spring支持多种视图技术,其中比较常用的包括有Jstl视图QVeloctiy视图QFreeMarker视图{。对Jstl视图的渲染Spring是通过JstlViewq个cd体实现的。事实上其最l的渲染是交l容器来做的QSpring只是通过RequestDispatcher实现了服务器内部h的Forward。而对于模板视图,如Veloctiy和FreeMarker{,Spring会初始化其相应的模板引擎Q由模板引擎生成最l的Html面然后在合q到Response的输出流中?/p> 异常的处?/p> 如果在Hander中处理请求是抛出异常QDispatcherServlet会查找HandlerExceptionResolver接口的具体实玎ͼ该接口定义了一个方法: ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)Q实现类需要实现该Ҏ以便对异常进行处理,最后该Ҏ需要返回一个ModelAndView?/p> SpringMVC的一些ȝ |
public abstract class HttpServletBean
Simple extension of HttpServlet
which treats its config parameters (init-param
entries within the servlet
tag in web.xml
) as bean properties.
HttpServlet的简单扩展用来处?Qinit-paramQin the web.xml
A handy superclass for any type of servlet. Type conversion of config parameters is automatic, with the corresponding setter method getting invoked with the converted value. It is also possible for subclasses to specify required properties. Parameters without matching bean property setter will simply be ignored.
This servlet leaves request handling to subclasses, inheriting the default behavior of HttpServlet (doGet
, doPost
, etc).
This generic servlet base class has no dependency on the Spring ApplicationContext
concept. Simple servlets usually don't load their own context but rather access service beans from the Spring root application context, accessible via the filter's ServletContext
(see WebApplicationContextUtils
).
The FrameworkServlet
class is a more specific servlet base class which loads its own application context. FrameworkServlet serves as direct base class of Spring's full-fledged DispatcherServlet
.
public abstract class FrameworkServlet
Base servlet for Spring's web framework. Provides integration with a Spring application context, in a JavaBean-based overall solution.
spring web Framework的基 servlet Q提供在以javabean为基的整体解x案已完成与spring应用上下文的集成
This class offers the following functionality:
1.理一个servlet一个网l应用上下文实例Q这个servlet的配|由servlet命名I间里的bean来决?br />2.Ҏh处理发布事gQ是否请求成功的被处理了
WebApplicationContext
instance per servlet. The servlet's configuration is determined by beans in the servlet's namespace.
Subclasses must implement doService(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
to handle requests. Because this extends HttpServletBean
rather than HttpServlet directly, bean properties are automatically mapped onto it. Subclasses can override initFrameworkServlet()
for custom initialization.
因ؓ它承自httpservletBean 所以bean的属性已l被自动的装配了Q子cd以通过覆盖initFrameworkServlet来定制初始化bean
Detects a "contextClass" parameter at the servlet init-param level, falling back to the default context class, XmlWebApplicationContext
, if not found. Note that, with the default FrameworkServlet, a custom context class needs to implement the ConfigurableWebApplicationContext
SPI.
Passes a "contextConfigLocation" servlet init-param to the context instance, parsing it into potentially multiple file paths which can be separated by any number of commas and spaces, like "test-servlet.xml, myServlet.xml". If not explicitly specified, the context implementation is supposed to build a default location from the namespace of the servlet.
Note: In case of multiple config locations, later bean definitions will override ones defined in earlier loaded files, at least when using Spring's default ApplicationContext implementation. This can be leveraged to deliberately override certain bean definitions via an extra XML file.
The default namespace is "'servlet-name'-servlet", e.g. "test-servlet" for a servlet-name "test" (leading to a "/WEB-INF/test-servlet.xml" default location with XmlWebApplicationContext). The namespace can also be set explicitly via the "namespace" servlet init-param.
<bean id="exampleInitBean" class="examples.ExampleBean" init-method="cleanup"/>
setBeanName
setBeanClassLoader
setBeanFactory
setResourceLoader
(only applicable when running in an application context)setApplicationEventPublisher
(only applicable when running in an application context)setMessageSource
(only applicable when running in an application context)setApplicationContext
(only applicable when running in an application context)setServletContext
(only applicable when running in a web application context)postProcessBeforeInitialization
methods of BeanPostProcessorsafterPropertiesSet
postProcessAfterInitialization
methods of BeanPostProcessors destroy
Method Summary | |
---|---|
boolean | containsBean(String name) Does this bean factory contain a bean with the given name? |
String[] | getAliases(String name) Return the aliases for the given bean name, if any. |
Object | getBean(String name) Return an instance, which may be shared or independent, of the specified bean. |
Object | getBean(String name, Class requiredType) Return an instance, which may be shared or independent, of the specified bean. |
Class | getType(String name) Determine the type of the bean with the given name. |
boolean | isPrototype(String name) Is this bean a prototype? |
boolean | isSingleton(String name) Is this bean a shared singleton? |
boolean | isTypeMatch(String name, Class targetType) Check whether the bean with the given name matches the specified type. |
public interface Lifecycle
Interface defining methods for start/stop lifecycle control. The typical use case for this is to control asynchronous processing.
Can be implemented by both components (typically a Spring bean defined in a Spring BeanFactory
) and containers (typically a Spring ApplicationContext
). Containers will propagate start/stop signals to all components that apply.
Can be used for direct invocations or for management operations via JMX. In the latter case, the MBeanExporter
will typically be defined with an InterfaceBasedMBeanInfoAssembler
, restricting the visibility of activity-controlled components to the Lifecycle interface.
ConfigurableApplicationContext
, AbstractMessageListenerContainer
, SchedulerFactoryBean
Method Summary | |
---|---|
boolean
|
isRunning
()
Check whether this component is currently running. |
void
|
start
()
Start this component. |
void
|
stop
()
Stop this component. |
|