推荐淘宝秋冬男装热卖网店

追求无止境

我的程序人生
随笔 - 31, 文章 - 2, 评论 - 20, 引用 - 0
数据加载中……

2008年10月4日

有一天你会长大

什么话该说,什么话不该说,该说的话该怎么说。谁能告诉我。

posted @ 2010-01-19 13:21 追求无止境 阅读(196) | 评论 (0)编辑 收藏

2009年度盛事 - 总结2009

       2009年12月31日,站在2009年的尾巴上,不禁感到时间飞逝。2009年,匆匆而过。在过去的2009年,收获何多,失去何多。2009年,对我来说,是一个重要的转折点。渐渐的发现自己应该长大了,也发现自己确实长大了,更发现自己实际上还是需要继续长大。

      每年的这个时候,各个新闻媒体都会评出什么十大之类的,我也落一会俗(当然自己本身就很俗),来看看今年发生在我身上的几大事件:

先大体罗列一下吧:

  1. 订婚
  2. 进京
  3. 工作
  4. 毕业
  5. 读研
  6. 买笔记本

     从时间跨度上来说, 1月到2月在家过年,2月和3月在青岛某公司实习,4月和5月在北京某公司实习,6月在中国石油大学享受毕业之前的时光,7月到8月继续在北京某公司实习,9月到12月在上学+实习。2009年最幸福的事情发生在1到2月,尽快也有不快;最平常的日子在2月和3月,到了4月和5月或许是我最纠结的日子吧;6月或许是最快乐的日子的吧;7月和8月让我体会到了工作的滋味;而9月到12月,整天在公司与学校之间奔跑,知道了工作+上课两者要做到兼顾的滋味,虽然并没有做到兼顾。

     2009年大体经历如此。2009年对我最大的关键字或许就是“改变”,这一年我订婚了,在这一点上,改变了我的准非单身状态;在这一年,我实习了,而且大量的时间都在于此,改变了我仅仅是学生的状态;在这一年,我毕业了,我离开了生活学习四年的中国石油大学,离开了让我毕生难忘的日子;在这一年,我来北京了,从对北京的一无所知,到开始的彷徨,然后渐渐熟悉和适应;在这一年,我的经济渐渐独立,尽管每个月只有不到1000的收入,但能满足的我的基本需求;在这一年,我买了笔记本,虽然对其他人来说,这不是一件特别的事,对我来说,因采用了分期付款,而用接下来一年中近半个月的工资来还,但我不觉得后悔,在这个过程中,我的经济观念和理财观念开始渐渐改变;在这一年,工作成了我的核心,工作教会我很多东西,在与人交流、在工作态度、在技术上,都有一定的提高。

     回忆2009年,收获颇多,也失去不少。但日子总是向前的,有得必有失。希望在以后的2009年,自己能够渐渐提高自己的能力。无论是在生活上,在工作上,还是在心理上。

 

    2009年10大大事:

       与老婆订婚:

       2009年,

posted @ 2009-12-31 12:55 追求无止境 阅读(200) | 评论 (0)编辑 收藏

Spring web MVC 框架学习笔记 之 ViewResolver技术

上次的文章中介绍了ModelAndView对象中的view对象,可以使用字符串来让Spring框架进行解析获得适合的视图。而解析View的就是ViewResolver技术。

ViewResolver的定义如下:

public interface ViewResolver {
View resolveViewName(String viewName, Locale locale) throws Exception;
}
 
在[spring-dispatcher-name]-servlet.xml中,可以定义viewResolver:

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

来让DispacherServlet进行加载默认的viewResolver,如果没有设置viewResolver,spring使用InternalResourceViewResolver进行解析。

Spring实现ViewResolver的非抽象类且我们经常使用的viewResolver有以下四种:

InternalResourceViewResolver 将逻辑视图名字解析为一个路径
BeanNameViewResolver 将逻辑视图名字解析为bean的Name属性,从而根据name属性,找定义View的bean
ResourceBundleResolver 和BeanNameViewResolver一样,只不过定义的view-bean都在一个properties文件中,用这个类进行加载这个properties文件
XmlViewResolver 和ResourceBundleResolver一样,只不过定义的view-bean在一个xml文件中,用这个类来加载xml文件

 

使用多视图解析器:

我们不想只使用一种视图解析器的话,可以在[spring-dispatcher-name]-servlet.xml定义多个viewResolver:

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>

<bean id=”beanNameViewResolver” class=”...BeanNameViewResolver”>
<property name="order" value="1"></property>
</bean>

<bean id=”beanNameViewResolver” class=”...XmlViewResolver”>
<property name="order" value="0"></property>
</bean>

DispatcherServlet会加载所有的viewResolver到一个list中,并按照优先级进行解析。注意order中的值越小,优先级越高。而id为viewResolver

的viewResolver的优先级是最低的。

posted @ 2009-11-27 12:11 追求无止境 阅读(6869) | 评论 (1)编辑 收藏

Spring MVC框架学习笔记 之 View技术

以前,我们详细介绍了Spring的Controller技术。Spring的面向接口编程,使Controller的实现多种多样。View技术也一样。今天的分析先从在Controller中的ModelAndView开始。

public class ModelAndView {     
  private Object view; //View实例或者view的字符串    
/** Model Map */  
  private ModelMap model; //model
 /* * Convenient constructor when there is no model data to expose.     * Can also be used in conjunction with <code>addObject</code>.    
 * @param view View object to render   
  * @see #addObject     */  
 public ModelAndView(View view) {        
    this.view = view;    
}
public ModelAndView(String viewName){ 
   this.view = viewName;
}

 
可以看到view实例可以指向一个View对象或者字符串。现在先看看View接口:
public interface View { 

    /**
     * Return the content type of the view, if predetermined.
     * <p>Can be used to check the content type upfront,
     * before the actual rendering process.
     * @return the content type String (optionally including a character set),
     * or <code>null</code> if not predetermined.
     */
    String getContentType(); 

    /**
     * 绘制视图
     * 绘制视图的第一步是准备请求: 如果是JSP的视图技术
     * 首先会把model设为request的属性。
     * 第二步则是真正的绘制视图
     * @param model Map with name Strings as keys and corresponding model
     * objects as values (Map can also be <code>null</code> in case of empty model)
     * @param request current HTTP request
     * @param response HTTP response we are building
     * @throws Exception if rendering failed
     */
    void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception; 

}
在这之后,我们再来看看View的实现继承类图,可以看到Spring支持多种类型视图:

org.springframework.web.servlet.view.AbstractView (implements org.springframework.beans.factory.BeanNameAware, org.springframework.web.servlet.View)

  • org.springframework.web.servlet.view.document.AbstractExcelView
  • org.springframework.web.servlet.view.document.AbstractJExcelView
  • org.springframework.web.servlet.view.document.AbstractPdfView
  • org.springframework.web.servlet.view.AbstractUrlBasedView (implements org.springframework.beans.factory.InitializingBean)
    • org.springframework.web.servlet.view.jasperreports.AbstractJasperReportsView
      • org.springframework.web.servlet.view.jasperreports.AbstractJasperReportsSingleFormatView
        • org.springframework.web.servlet.view.jasperreports.ConfigurableJasperReportsView
        • org.springframework.web.servlet.view.jasperreports.JasperReportsCsvView
        • org.springframework.web.servlet.view.jasperreports.JasperReportsHtmlView
        • org.springframework.web.servlet.view.jasperreports.JasperReportsPdfView
        • org.springframework.web.servlet.view.jasperreports.JasperReportsXlsView
      • org.springframework.web.servlet.view.jasperreports.JasperReportsMultiFormatView
    • org.springframework.web.servlet.view.document.AbstractPdfStamperView
    • org.springframework.web.servlet.view.AbstractTemplateView
      • org.springframework.web.servlet.view.freemarker.FreeMarkerView
      • org.springframework.web.servlet.view.velocity.VelocityView
        • org.springframework.web.servlet.view.velocity.VelocityToolboxView
          • org.springframework.web.servlet.view.velocity.VelocityLayoutView
    • org.springframework.web.servlet.view.InternalResourceView
      • org.springframework.web.servlet.view.JstlView
      • org.springframework.web.servlet.view.tiles.TilesView
        • org.springframework.web.servlet.view.tiles.TilesJstlView
    • org.springframework.web.servlet.view.RedirectView
    • org.springframework.web.servlet.view.tiles2.TilesView
    • org.springframework.web.servlet.view.xslt.XsltView
  • org.springframework.web.servlet.view.xslt.AbstractXsltView
 
和Controller一样,View的第一个实现也是AbstractView。所以先让我们看看AbstractView对render函数的实现:

 

public void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {
if (logger.isTraceEnabled()) {
logger.trace("Rendering view with name '" + this.beanName + "' with model " + model +
" and static attributes " + this.staticAttributes);
}

// Consolidate static and dynamic model attributes.
Map mergedModel = new HashMap(this.staticAttributes.size() + (model != null ? model.size() : 0));
mergedModel.putAll(this.staticAttributes);
if (model != null) {
mergedModel.putAll(model);
}

// Expose RequestContext?
if (this.requestContextAttribute != null) {
mergedModel.put(this.requestContextAttribute, createRequestContext(request, mergedModel));
}

prepareResponse(request, response);
renderMergedOutputModel(mergedModel, request, response);
}

第一步,将静态属性和model的属性都添加到mergedModel里面。如果需要请求上下文,则将请求上下文添加到model中。

静态属性是继承AbstractView进行设置的属性。而请求上下文如果设置的名字就会创建一个request上下文。在requestContext中定义了一些包括本地化和主题的处理工具。

第二步,对响应进行预处理。最后调用子类需要实现的函数renderMergedOutputModel。

对PDF和EXCEL格式我们暂且不管,且Spring支持多种视图技术,这里我们主要关注JSTL技术,

接着我们来看AbstractUrlBasedView 类。在AbstractUrlBasedView 只定义了一个url属性。别的没有什么特殊处理。

接着继承AbstractUrlBasedView 的是InternalResourceView。他对renderMergedOutputModel进行实现,实现如下:

/**
* Render the internal resource given the specified model.
* This includes setting the model as request attributes.
*/
protected void renderMergedOutputModel(
Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {

// 获取要暴露的request,一般都是传入的参数request
HttpServletRequest requestToExpose = getRequestToExpose(request);

// 将model的数据添加到request属性中
        exposeModelAsRequestAttributes(model, requestToExpose);

// 设置helper,如果存在的话
exposeHelpers(requestToExpose);

// 对绘制进行预处理,从而获得到要分发的url
String dispatcherPath = prepareForRendering(requestToExpose, response);

// 获取请求分发对象
RequestDispatcher rd = requestToExpose.getRequestDispatcher(dispatcherPath);
if (rd == null) {
throw new ServletException(
"Could not get RequestDispatcher for [" + getUrl() + "]: check that this file exists within your WAR");
}

// 决定使用RequestDispatcher的include方法还是forward方法
if (useInclude(requestToExpose, response)) {
response.setContentType(getContentType());
if (logger.isDebugEnabled()) {
logger.debug("Including resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
}
rd.include(requestToExpose, response);
}

else {
// Note: The forwarded resource is supposed to determine the content type itself.
exposeForwardRequestAttributes(requestToExpose);
if (logger.isDebugEnabled()) {
logger.debug("Forwarding to resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
}
rd.forward(requestToExpose, response);
}
}
可以看到InternalResourceView对请求进行了转发。转发到url上。最后我们看看JSTLView的实现:

 
public class JstlView extends InternalResourceView {

    private MessageSource messageSource;

    public JstlView() {
    }

    
    public JstlView(String url) {
        super(url);
    }

    public JstlView(String url, MessageSource messageSource) {
        this(url);
        this.messageSource = messageSource;
    }

    protected void initServletContext(ServletContext servletContext) {
        if (this.messageSource != null) {
            this.messageSource = JstlUtils.getJstlAwareMessageSource(servletContext, this.messageSource);
        }
        super.initServletContext(servletContext);
    }

    protected void exposeHelpers(HttpServletRequest request) throws Exception {
        if (this.messageSource != null) {
            JstlUtils.exposeLocalizationContext(request, this.messageSource);
        }
        else {
            JstlUtils.exposeLocalizationContext(new RequestContext(request, getServletContext()));
        }
    }

}

 

在InternalResourceView  中,基本上所有的处理都差不多了。在JSTLView对两个方法进行了覆盖。第一个initServletContext,主要初始化了MessageResource

第二个exposeHelpers将messageSource放在了request里面。

这样view的解析就结束了。接下来容器对jsp进行解析,并进行tag等的处理。然后将生成的页面返回给客户端。

posted @ 2009-11-26 13:25 追求无止境 阅读(8199) | 评论 (2)编辑 收藏

SpringMVC web框架学习 Controller 分析

org.springframework.web.servlet.mvc.AbstractController (implements org.springframework.web.servlet.mvc.Controller)

Spring MVC框架中的Controller对请求进行处理:所有的Controller都实现接口Controller:

public interface Controller { 

    /**
     * Process the request and return a ModelAndView object which the DispatcherServlet
     * will render. A <code>null</code> return value is not an error: It indicates that
     * this object completed request processing itself, thus there is no ModelAndView
     * to render.
     * @param request current HTTP request
     * @param response current HTTP response
     * @return a ModelAndView to render, or <code>null</code> if handled directly
     * @throws Exception in case of errors
     */
    ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception; 

}
上面的doc表明Controller返回的modelandview可以使空,表明请求都是该函数中处理完成了,不需要modeland来进行渲染。
 
在继续之前先介绍一个有用的工具类:WebUtils。用这个可以简化session,request的处理。具体的内容可以参考文档。
 
Controller的第一个实现是:AbstractController。他是一个Abstract类,除了实现了Controller接口,它还继承了WebContentGenerator。
 
WebContentGenerator的作用是什么?参考文档可以发现,该类主要对Cache和Session进行管理。
 
cacheSeconds 指定内容缓存的时间,默认为1
requireSession 是否需要会话,默认支持
supportedMethods 支持的方法,默认是GET\post\Head
useCacheControlHeader 指定是否使用http1.1的cache控制头信息,默认使用
useCacheControlNoStore 指定是否设置http1.1的cache控制头信息为no-store。默认使用
useExpiresHeader 指定是否使用http1.0的expire头信息。默认使用
用户可以对这些参数进行测试,cache和expire信息涉及到了http协议信息,更多信息可以参考http协议文档。这里不再说明。
 
再看AbstractController的代码:
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
throws Exception {

// Delegate to WebContentGenerator for checking and preparing.
checkAndPrepare(request, response, this instanceof LastModified);

// Execute handleRequestInternal in synchronized block if required.
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
return handleRequestInternal(request, response);
}
}
}
return handleRequestInternal(request, response);
}
checkandPrepare的目的就是使用用于进行的配置来对request进行预处理和准备。
他会检查支持的方法,和会话,然后应用cache设置。
如果需要session同步,就进行同步处理。session同步应用于有session的情况下。如果没有session,session同步是没有用的。
AbstractController会调用handleRequestInternal方法进行处理,继承AbstractController的类需要实现该方法。
下面我们再看看AbstractUrlViewController 的代码实现和文档,先看handleRequestInternal的实现:

 
/**
* Retrieves the URL path to use for lookup and delegates to
* {@link #getViewNameForRequest}.
*/
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) {
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
String viewName = getViewNameForRequest(request);
if (logger.isDebugEnabled()) {
logger.debug("Returning view name '" + viewName + "' for lookup path [" + lookupPath + "]");
}
return new ModelAndView(viewName);
}

可以看到,它使用了getViewNameForRequest获取需要的viewName。而getViewNameForRequest是一个抽象函数,需要子类实现。lookupPath就是我们请求的URL中的一部分。如我们使用UrlFilenameViewController来进行如下的配置:
<bean name="/index.do" class="org.springframework.web.servlet.mvc.UrlFilenameViewController"></bean>、
09-11-25 11:56:06 - DEBUG [http-8200-1] - Returning view name 'index' for lookup path [/index.do]
该Controller对/index.do解析成index,然后再通过viewResolver对index进行扩展为/jsp/index.jsp。从而找到该页面。
可以看到这个类的主要是用于对url进行解析,然后转到合适的页面上,而在转到这个页面之前不需要进行特别的处理。
明白了该类的作用自然也就知道了UrlFilenameViewController的作用。这里不再进行详细分析。
 
 

posted @ 2009-11-26 09:35 追求无止境 阅读(4154) | 评论 (0)编辑 收藏

Spring MVC 框架学习之AbstractFormController以及AbstractFormControll

在看完BaseCommandController和AbstractCommandController之后,我们再看BaseCommandController的另一个实现AbstractFormController,以及AbstractFormController的具体实现SimpleFormController。

先看看AbstractFormController对handleRequestInternal的实现:

protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
throws Exception {
// Form submission or new form to show?
if (isFormSubmission(request)) {
// Fetch form object from HTTP session, bind, validate, process submission.
try {
Object command = getCommand(request);
ServletRequestDataBinder binder = bindAndValidate(request, command);
BindException errors = new BindException(binder.getBindingResult());
return processFormSubmission(request, response, command, errors);
}
catch (HttpSessionRequiredException ex) {
// Cannot submit a session form if no form object is in the session.
if (logger.isDebugEnabled()) {
logger.debug("Invalid submit detected: " + ex.getMessage());
}
return handleInvalidSubmit(request, response);
}
}
else {
// New form to show: render form view.
return showNewForm(request, response);
}
}
这个方法,首先判断是不是Form提交,判断方法是:
protected boolean isFormSubmission(HttpServletRequest request) {
return "POST".equals(request.getMethod());
}
如果是form提交的话,系统首先创建一个Command,然后对数据进行绑定和验证,之后调用processFormSubmission方法。showNewForm则调用showForm。
在AbstractFormController中里面有两个抽象方法:

protected abstract ModelAndView processFormSubmission(
HttpServletRequest request, HttpServletResponse response, Object command, BindException errors)
throws Exception;
protected abstract ModelAndView showForm(
HttpServletRequest request, HttpServletResponse response, BindException errors)
throws Exception;



 

 

好了,看完AbstractFormController之后,再看看SimpleFormController是如何实现:

protected ModelAndView processFormSubmission(
HttpServletRequest request, HttpServletResponse response, Object command, BindException errors)
throws Exception {

if (errors.hasErrors()) {
if (logger.isDebugEnabled()) {
logger.debug("Data binding errors: " + errors.getErrorCount());
}
return showForm(request, response, errors);
}
else if (isFormChangeRequest(request, command)) {
logger.debug("Detected form change request -> routing request to onFormChange");
onFormChange(request, response, command, errors);
return showForm(request, response, errors);
}
else {
logger.debug("No errors -> processing submit");
return onSubmit(request, response, command, errors);
}
}
在上面的方法中,如果有错误,调用showForm,来显示form。没有错误的话,则调用onSubmit方法。
protected final ModelAndView showForm(
HttpServletRequest request, BindException errors, String viewName, Map controlModel)
throws Exception {

// In session form mode, re-expose form object as HTTP session attribute.
// Re-binding is necessary for proper state handling in a cluster,
// to notify other nodes of changes in the form object.
if (isSessionForm()) {
String formAttrName = getFormSessionAttributeName(request);
if (logger.isDebugEnabled()) {
logger.debug("Setting form session attribute [" + formAttrName + "] to: " + errors.getTarget());
}
request.getSession().setAttribute(formAttrName, errors.getTarget());
}

// Fetch errors model as starting point, containing form object under
// "commandName", and corresponding Errors instance under internal key.
Map model = errors.getModel();

// Merge reference data into model, if any.
Map referenceData = referenceData(request, errors.getTarget(), errors);
if (referenceData != null) {
model.putAll(referenceData);
}

// Merge control attributes into model, if any.
if (controlModel != null) {
model.putAll(controlModel);
}

// Trigger rendering of the specified view, using the final model.
return new ModelAndView(viewName, model);
}
在showForm中,设置属性,放在model中,然后在viewName进行设置。
FormController就是上面的过程。具体的执行过程和详细信息会在以后的博客中具体介绍。

posted @ 2009-11-25 17:31 追求无止境 阅读(2440) | 评论 (0)编辑 收藏

Spring MVC 框架学习笔记之BaseCommandController和AbstractCommandController

 

Spring的BaseCommandController继承自AbstractController。在看BaseCommandController之前先看他的继承类AbstractCommandController是如何实现

AbstractController的handleInternalRequest方法的:

protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
throws Exception {
Object command = getCommand(request);
ServletRequestDataBinder binder = bindAndValidate(request, command);
BindException errors = new BindException(binder.getBindingResult());
return handle(request, response, command, errors);
}

getCommand就是BaseCommandController中的方法。

protected Object getCommand(HttpServletRequest request) throws Exception {
return createCommand();
}
protected final Object createCommand() throws Exception {
if (this.commandClass == null) {
throw new IllegalStateException("Cannot create command without commandClass being set - " +
"either set commandClass or (in a form controller) override formBackingObject");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating new command of class [" + this.commandClass.getName() + "]");
}
return BeanUtils.instantiateClass(this.commandClass);
}

createCommand创建了一个CommandClass的对象。

然后再看bindAndValidate方法:

protected final ServletRequestDataBinder bindAndValidate(HttpServletRequest request, Object command)
throws Exception {
ServletRequestDataBinder binder = createBinder(request, command);
BindException errors = new BindException(binder.getBindingResult());
if (!suppressBinding(request)) {
binder.bind(request);
onBind(request, command, errors);
if (this.validators != null && isValidateOnBinding() && !suppressValidation(request, command, errors)) {
for (int i = 0; i < this.validators.length; i++) {
ValidationUtils.invokeValidator(this.validators[i], command, errors);
}
}
onBindAndValidate(request, command, errors);
}
return binder;
}

这个方法首先创建了 DataBinder对象,然后,获取创建绑定对象时发生的错误。报错在errors。接下来绑定对象,调用onBind处理绑定事件;接下来应用Validator。然后调用onBindAndValidate来处理绑定和验证事件。最后返回binder。

处理完之后调用handle方法进行处理。

综上所述,AbstractCommandController具有两个功能:

1、将请求参数转换为Command对象。在该Controller中,我们设置一个object对象。然后BaseCommandController将请求的参数进行转换。如果请求参数有value值,就会调用object的的setValue对象来设置对象里的值。如果请求参数中有address.city.就会调用object中getAddress().setCity()方法来赋值。这个object可以是任意的object,唯一的要求就是这个object类没有参数。

2、对数据进行验证。在转换和验证时发生错误时,需要在handle(request, response, command, errors)中进行处理。

posted @ 2009-11-25 16:25 追求无止境 阅读(5368) | 评论 (0)编辑 收藏

Spring的MVC web框架学习笔记

1、Spring web 框架的核心:DispatcherServlet

DispatcherServlet 用于接收请求。是使用Spring框架的入口。在web.xml中,需要配置该servlet。在配置该Servlet的时候url-pattern你可以使用你自己想使用的形式,如*.aspx,*.do,*.htm,*.action,用以混淆客户端对服务器架构的认识。

另外,该Servlet在容器中还会加载一个APPlicationContext的xml文件。默认加载的是[servlet-name]-servlet.xml。例如,你在web.xml中配置的servlet如下:

<web-app>
<servlet>
<servlet-name>example</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>example</servlet-name>
<url-pattern>*.form</url-pattern>
</servlet-mapping>
</web-app>
该Servlet就会在服务器启动时,加载example-servlet.xml。当然,你也可以自己来指定加载文件。
要看看DispatcherServlet真面目,打开源文件,发现定义了很多BeanName的常量,如本地化解析器beanname,主题解析器beanname,视图解析器beanname,上传文件解析的multipart解析器beanname。
等:
public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver";
public static final String LOCALE_RESOLVER_BEAN_NAME = "localeResolver";
public static final String THEME_RESOLVER_BEAN_NAME = "themeResolver";
public static final String HANDLER_MAPPING_BEAN_NAME = "handlerMapping";
public static final String HANDLER_ADAPTER_BEAN_NAME = "handlerAdapter";
public static final String HANDLER_EXCEPTION_RESOLVER_BEAN_NAME = "handlerExceptionResolver";
public static final String REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME = "viewNameTranslator";
public static final String VIEW_RESOLVER_BEAN_NAME = "viewResolver";
这个类怎么使用这些bean呢?以上面的exexample-servlet.xml为例,我们定义的名字为example的DispatcherServlet使用example-servlet.xml的配置。在example-servlet.xml里,我们可以配置名字上面的beanName的bean,来让servlet加载这些bean。
这下明白了,servlet.xml该怎么配置,该配置什么了。
好了,看完了最重要的servlet的配置问题,我们再看下一个重要的接口:Controller。至于上面servlet要使用的什么什么解析器啦,我们稍后在分析。
 
2、Controller
我们的请求提交到DispacherServlet后,会转给Controller。怎么找Controller?通过使用handlerMapping。如果没有设置handlerMapping,spring使用默认的BeanNameUrlHandlerMapping来找Controller。
BeanNameUrlHandlerMapping?顾名思义,就是通过bean的name属性来映射controller。bean的name请求是一个url,如果请求的是logout.do,在example-servlet.xml中定义一个名字(name)为login.do的Controller.

<bean name="/logout.do" class="com.jy.bookshop.web.spring.LogoutController">
    </bean>

再插一句话,在handlerMapping中,我们可以使用请求拦截器来对请求进行拦截处理。该拦截器怎么使用这里暂且不表,有机会再讨论。

ok,现在我们创建一个LogoutController来让他处理请求,让他实现Controller吧:

public class LogOutController implements Controller {
    public ModelAndView handleRequest(HttpServletRequest req,
            HttpServletResponse res) throws Exception {
          …
        return new ModelAndView(new RedirectView("login.do"));
    }
}
看看这个Controller接口的定义,发现这个接口只定义了一个handleRequest方法。在这个方法中,返回一个ModelAndView。
先说ModelAndView。我们知道MVC,那么ModelAndView就是 MV了。Controller就是C。这样MVC全了。呵呵。
继续说ModelAndView,要了解他的结构,那自然要看看他的源代码了:
/** View instance or view name String */
private Object view; 

/** Model Map */
private ModelMap model;

   

    只关注我们关注的,里面包含了一个View对象和model对象。model对象是一个Map,这里不再说了。关键看看view,奇怪,怎么是一个Object,太抽象了。再继续看源代码的话,会更加明白:

 

public ModelAndView(String viewName, String modelName, Object modelObject) {
        this.view = viewName;
        addObject(modelName, modelObject);
    }
public void setViewName(String viewName) {
        this.view = viewName;
    }

原来这个view可以指向一个View对象,也可以指向String对象啊。View一个接口,如果看doc的话,他的实现类有AbstractExcelView, AbstractJasperReportsSingleFormatView, AbstractJasperReportsView, AbstractJExcelView, AbstractPdfStamperView, AbstractPdfView,AbstractTemplateView, AbstractUrlBasedView, AbstractView, AbstractXsltView, ConfigurableJasperReportsView, FreeMarkerView, InternalResourceView,JasperReportsCsvView, JasperReportsHtmlView, JasperReportsMultiFormatView, JasperReportsPdfView, JasperReportsXlsView, JstlView, RedirectView,TilesJstlView, TilesView, TilesView, VelocityLayoutView, VelocityToolboxView, VelocityView, XsltView(诚实的说,这些View是拷doc的)。

现在可以知道,我们的Controller返回一个View和Model,来让Spring框架来创建一个回应。

现在奇怪的还有一点,我吧view设置为字符串,Spring框架怎么处理?在ModelAndView中,如果view是一个字符串,则会将这个值交给DispatcherServlet的viewResovler来处理。记得上面提到的viewResovler了吗?呵呵,派上用场了。

view的问题解决了,然后再说model吧。在ModelAndView添加了一些对象,Spring是怎么处理的呢?总应该把这些对象给弄到request对象里,让jsp页面来使用吧。让View使用?那么看看View接口吧:

public interface View {

    String getContentType();

    void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception;

}
render函数需要带一个model变量。再找找view的实现类,看看是怎么工作的。不过view有那么多,对于一些像什么pdf啦,excel了他们都不需要在request中添加这个model。
最终呢,我们在jstlView的父类InternalResourceView中的renderMergedOutputModel函数发现他把model放在了request里面了。
 
OK,现在我们明白了,controller返回的modelandview交给Servlet进行处理,来生成一个页面。
最简单的Controller介绍完毕。现在看看Spring提供的一些controller的实现,Spring提供了很多controller的实现,继承的结构如下:

 

org.springframework.web.servlet.mvc.AbstractController (implements org.springframework.web.servlet.mvc.Controller)

  • org.springframework.web.servlet.mvc.AbstractUrlViewController
    • org.springframework.web.servlet.mvc.UrlFilenameViewController
  • org.springframework.web.servlet.mvc.BaseCommandController
    • org.springframework.web.servlet.mvc.AbstractCommandController
    • org.springframework.web.servlet.mvc.AbstractFormController
      • org.springframework.web.servlet.mvc.AbstractWizardFormController
      • org.springframework.web.servlet.mvc.SimpleFormController
        • org.springframework.web.servlet.mvc.CancellableFormController
  • org.springframework.web.servlet.mvc.ParameterizableViewController
  • org.springframework.web.servlet.mvc.ServletForwardingController (implements org.springframework.beans.factory.BeanNameAware)
  • org.springframework.web.servlet.mvc.ServletWrappingController (implements org.springframework.beans.factory.BeanNameAware, org.springframework.beans.factory.DisposableBean, org.springframework.beans.factory.InitializingBean)
    AbstractController是Controller的第一个实现。其他的Controller都是继承这个Controller的。我们先看比较重要的Controller。
    先说UrlFilenameViewController。不如我们自己来部署一个吧。
    在example-servlet.xml中增加如下的配置:

    <bean name="/error.do"  class="org.springframework.web.servlet.mvc.UrlFilenameViewController">
        </bean>

    OK,当/error.do的请求上来后,urlFileNameViewController将他变成/error。然后返回个View,这个view的name就是/error,然后使用viewresolver来进行解析,可以解析成/jsp/error.jsp。
    另外还有比较重要的controller是baseCommandController,将请求参数转换为一个对象,并对对象参数合法性进行验证。另外,SimpleFormController可以对表单进行处理。
    关于各个controller的分析。未完待续。。

     

     

     

    posted @ 2009-11-25 11:09 追求无止境 阅读(3707) | 评论 (2)编辑 收藏

    [转] java.beans.PropertyEditor(属性编辑器)简单应用

    原文:http://www.blogjava.net/orangewhy/archive/2007/06/26/126371.html

    java.beans.PropertyEditor的从字义来看是一个属性编辑器,但总觉得它的作用更像一个转换器--从字符串转换为类对象的属性。

    java.beans.PropertyEditor接口定义的方法有好几个,但是最重要为下面两个:

     void setValue(Object value)

     void setAsText(String text) throws java.lang.IllegalArgumentException;

    一般地,我们要使用PropertyEditor时,并不直接实现此接口,而是通过继承实现此接口的java.beans.PropertyEditorSupport来简化我们的工作,在子类覆盖setAsText方法就可以了,setValue方法一般不直接使用,在setAsText方法中将字符串进行转换并产生目标对象以后,由调setAsText调用setValue来把目标对象注入到编辑器中。当然,你可用覆盖更多的方法来满足你的特殊要求。JavaBean的类和接口,被大部分spring包使用,可以从spring中学习更成熟的JavaBean使用方法。

    简单的例子:

    实体类Person:

    public class Person
    {
        
    private String name;
        
    private String sex;
        
    private int age;
        
        
    public Person(String name, String sex, int age)
        
    {
            
    this.name = name;
            
    this.sex = sex;
            
    this.age = age;
        }

        
        
    public int getAge()
        
    {
            
    return age;
        }

        
    public void setAge(int age)
        
    {
            
    this.age = age;
        }

        
    public String getName()
        
    {
            
    return name;
        }

        
    public void setName(String name)
        
    {
            
    this.name = name;
        }

        
    public String getSex()
        
    {
            
    return sex;
        }

        
    public void setSex(String sex)
        
    {
            
    this.sex = sex;
        }

        
        @Override
        
    public String toString()
        
    {
            
    return "Person["+name+""+sex+""+age+"]";
        }

    }

     

    Person的属性编辑器:

    public class PersonPropertyEditor extends PropertyEditorSupport
    {
        
    public void setAsText(String text)
        
    {
            setValue(parseString(text));
        }


        
    private Object parseString(String text)
        
    {
            String[] parts 
    = tokenizeToStringArray(text, ""falsefalse);
            String name 
    = (parts.length > 0 ? parts[0] : "undefine");
            String sex 
    = (parts.length > 1 ? parts[1] : "undefine");
            
    int age = (parts.length > 2 ? Integer.valueOf(parts[2]) : 0);
            
    return (text.length() > 0 ? new Person(name, sex, age) : null);
        }


        
    private  String[] tokenizeToStringArray(String str, String delimiters, boolean trimTokens,
                                                        
    boolean ignoreEmptyTokens)
        
    {
            StringTokenizer st 
    = new StringTokenizer(str, delimiters);
            List tokens 
    = new ArrayList();
            
    while(st.hasMoreTokens())
            
    {
                String token 
    = st.nextToken();
                
    if(trimTokens)
                
    {
                    token 
    = token.trim();
                }

                
    if(!ignoreEmptyTokens || token.length() > 0)
                
    {
                    tokens.add(token);
                }

            }

            
    return toStringArray(tokens);
        }


        
    private  String[] toStringArray(Collection collection)
        
    {
            
    if(collection == null)
            
    {
                
    return null;
            }

            
    return (String[])collection.toArray(new String[collection.size()]);
        }

    }

     

    测试代码:

        public static void main(String[] args)
        
    {
            PersonPropertyEditor editor 
    = new PersonPropertyEditor();
            editor.setAsText(
    "aSam,man,22");
            System.out.println(editor.getValue());
        }

     

    结果输出:

    Person[aSam, man, 22]

    posted @ 2009-11-20 22:07 追求无止境 阅读(287) | 评论 (0)编辑 收藏

    提高开发技术的Tip

     

      以下Tip和学习路线从自己身上出发进行总结,仅代表个人观点。你可以留言进行讨论。

    1.有计划的学习

           学习是一个循序渐进的过程。如果没有一个计划,学习将变得没有规律,我们也无法提高自己的能力。想起上学的时候,学校每个学期都会制定一个教学大纲来指导老师的教学和我们的学习。是的,如果没有计划,今天突然想学这个,明天突然想学那个,朝三暮四,我们永远也无法学到自己想学的东西。所以我们需要制定一个学习计划。有计划的学习才能提高自己的能力。Java web项目的开发是需要很多知识的积累的,包括Java SE,数据库,JDBC,Linux,Log4j,Html/CSS/Javascript,持久层框架,JUNIT及其他测试框架,IOC框架,web MVC框架等等,如果我们没有一个良好的计划,今天学习Log4j,明天学习Junit,这些东西都不会掌握好并学习好。

          如果给自己做计划。计划可以按照时间段来进行。例如本年度的工作,本季度要达到的水平,本月要学习的东西,本周学习的计划安排,以及每一天的安排。每天晚上睡觉前,想想今天的计划安排是否完成,明天该学习什么;每周到结束的时候,总结一下本周完成了什么,下周要学习什么。根据自己对计划的实行情况可以改变自己的计划。总之要有计划的学习。可以使用google 日历和 qq mail 邮箱等来管理自己的计划。

    2. 同一段时间只学习一种技术  

           我是一个什么都想学的人。我不想把自己的时间都用在学习Java上,我还想学习C++,还想学习 web 设计,还想学好windows编程,想学Linux编程,想学习计算机网络编程,想学习路由器、网络的配置……。于是,今天看了VC++深入详解,明天学习Linux shell编程。计算机技术包含了太多技术。我们无法一一将他们都掌握。所以不要想什么都学会。至少在一段时间内学习一种技术。我给自己制定了这样的计划,今年要把所有的精力都致力为 java EE 开发技术上。一年后,努力学习C/C++编程。

          是的。我们学习的东西可以广一点,但一定要有自己专的方面。学专了一个方面,你就可以接着学习其他的技术。一个什么都会的人,很可能什么都不会;所以,精于一,而博于广。

    3.学会休息

         我们都很忙,上学的时候学好各科,至少不能挂科,然后在课外学习自己喜欢的java 编程;工作的时候,需要做好工作,然后在工作之余多学一些东西;时间长了,我们就可能倦了,累了。所以我们需要学会休息来改变自己的精神状态。

         整天在电脑前进行软件开发的我们,要学会放松自己和休息。作为程序员整天在电脑前,极容易养成工作和休息都离不开电脑的习惯。休息的时候,也是在电脑前看电影,玩游戏。我想,在我们工作累了之后,应该离开电脑,走向户外来放松和休息。或到大街上转转,或到商场里购物,或去游泳馆游泳,或去健身房健身,或和朋友一起打台球。等等等等。总之要学会放松自己,走出户外,不要整天在电脑前。

         以上3点是自己对自己工作学习的总结和提醒,特别写出来和大家一起分享。


      感谢HiMagic!分享自己的观点。值得学习。

    提高开发技术->如何学习,这个转换并不完全对等。对于学习来说,最重要的不是计划和过程,而是结果,没有成果的学习等于白费时间。对于提高技术来说,必须要有笑傲江湖唯我独尊的气势,以及持之以恒的定力。
    2009-11-17 08:54 | HiMagic!


    感谢CoderCream分享自己的观点,没错,执行和结果更加重要!

    posted @ 2009-11-16 15:11 追求无止境 阅读(1768) | 评论 (6)编辑 收藏

    Java DOC学习笔记

    1、Interface Comparable<T>

    只有实现该接口的对象的列表或数组才能调用Collections.sort()方法。

    在实现 int compareTo(T o)时,需要注意:

    1、如果两个对象相等,返回为0;

    2、如果同一个null对象进行比较,应抛出NullPointerException。

    3、实现必须保证sgn(x.compareTo(y)) == -sgn(y.compareTo(x))、(x.compareTo(y)==0) == (x.equals(y)) 、(x.compareTo(y)>0 && y.compareTo(z)>0) impliesx.compareTo(z)>0 。如果 x.compareTo(y)抛出异常,y.compareTo(x)也必须抛出异常。

    2、Interface Iterable<T>

    Iterator<T> iterator()

    对于链表等对象应实现该接口来允许一个对象可以使用foreach语句。

    上面的方法返回java.util.Interface Iterator<E>,该接口的主要方法有:

    hasNext();next();remove();

    3、Interface Readable

    java.lang.Interface Readable

          一个Readable 是一个字符串的来源。实现这个接口需要实现的方法是:

    int read(CharBuffer cb)

    4、java.lang  Interface Runnable

    不用说,这个谁都知道。如果想在一个单独的线程中执行,就需要实现这个接口。

    5、java.lang Interface Thread.UncaughtExceptionHandler

           从名字就可以判断出来,当线程抛出未捕获的异常时,实现这个接口的类的对象可以对一场进行处理。

          官方文档:当线程被一个未捕获的异常打断时,这个接口被调用。

          当线程要被为捕获异常打断是,JVM使用Thread.getUncaughtExceptionHandler(),查询异常处理器,如果线程没有这个接口的设置,则查询该线程的ThreadGroup的UncaughtExceptionHandler,如果县城没有处理异常,他就会抛出这个异常。

    void uncaughtException(Thread t, Throwable e)
              Method invoked when the given thread terminates due to the given uncaught exception.

    6、包装型对象:Boolean Byte Character Double Float Long Short Integer

        这些类就不用了说了,主要会使用里面的静态方法和一些常量就可以了。

    7、Class Character.Subset

       这个类的实例代表了Unicode字符集的特殊的子集。定义在Character中的唯一子集族类是UnicodeBlock.其他的Java API或许因为自己的用户定义了其他的子集。

    static Character.UnicodeBlock
    AEGEAN_NUMBERS
              Constant for the "Aegean Numbers" Unicode character block.

    static Character.UnicodeBlock
    ALPHABETIC_PRESENTATION_FORMS
              Constant for the "Alphabetic Presentation Forms" Unicode character block.

    static Character.UnicodeBlock
    ARABIC
              Constant for the "Arabic" Unicode character block.

    static Character.UnicodeBlock
    ARABIC_PRESENTATION_FORMS_A
              Constant for the "Arabic Presentation Forms-A" Unicode character block.

    static Character.UnicodeBlock
    ARABIC_PRESENTATION_FORMS_B
              Constant for the "Arabic Presentation Forms-B" Unicode character block.

    static Character.UnicodeBlock
    ARMENIAN
              Constant for the "Armenian" Unicode character block.

    static Character.UnicodeBlock
    ARROWS
              Constant for the "Arrows" Unicode character block.

    static Character.UnicodeBlock
    BASIC_LATIN
              Constant for the "Basic Latin" Unicode character block.

    static Character.UnicodeBlock
    BENGALI
              Constant for the "Bengali" Unicode character block.

    static Character.UnicodeBlock
    BLOCK_ELEMENTS
              Constant for the "Block Elements" Unicode character block.

    static Character.UnicodeBlock
    BOPOMOFO
              Constant for the "Bopomofo" Unicode character block.

    static Character.UnicodeBlock
    BOPOMOFO_EXTENDED
              Constant for the "Bopomofo Extended" Unicode character block.

    static Character.UnicodeBlock
    BOX_DRAWING
              Constant for the "Box Drawing" Unicode character block.

    …………

    具体参见java.lang
    Class Character.UnicodeBlock里面的定义。

    8 、java.langClass Class<T>

    这个类的实力代表了Java运行程序中的类和接口。Enum是类,而Annotation是一个接口。Every array also belongs to a class that is reflected as a Class object that is shared by all arrays with the same element type and number of dimensions.

    Class的对象在程序中可以获取类的详细信息。

    9、Java.lang.Class ClassLoader

    ClassLoader是个不错的东西,下面是官方文档的简单翻译和注解:

    1、ClassLoader用于加载类对象。ClassLoader是一个抽象类。给出类的二进制名字(如“

      "java.lang.String"
       "javax.swing.JSpinner$DefaultEditor"
       "java.security.KeyStore$Builder$FileBuilder$1"
       "java.net.URLClassLoader$3$1"

    ”),ClassLoader会使用定位和生成类。一个典型的策略就是将二进制名字转化为文件名,然后从文件系统中读取这个类文件。

    每一个Class对象都包含了一个创建它的引用。

    数组的Class对象不能由ClassLoader创建,但是可以由Java运行时动态创建。一个数组类的ClassLoader,和他的元素的ClassLoader是一样的;如果元素是基本类型,则数组类没有ClassLoader。

    应用程序可以实现ClassLoader的子类,来扩展行为。这样可以在JVM动态的创建类。

    ClassLoader主要由安全管理器来使用,用于保证安全区域。

    ClassLoader 使用一个delegation(委托)模型来搜索类和资源。每一个ClassLoader有一个相关的父类ClassLoader。当请求来查找一个资源或者类的时候,ClassLoader 实例会委托搜索类和资源。

    内建的ClassLoader,叫做bootstrap class loader,没有父类。

    正常的,ClassLoader从本地文件系统中加载数据。通过CLassPath。

    当然,也可以通过NetWork从服务器上下载字节码。来加载类:

    ClassLoader loader = new NetworkClassLoader(host, port);
    Object main = loader.loadClass("Main", true).newInstance();
    Network ClassLoader 子类必须定义方法FindClass 和loadClassData来加载来自互联网上的类。一旦或得到字节码,它使用defineClass方法来创建类实例。
    class NetworkClassLoader extends ClassLoader {
             String host;
             int port;
    
             public Class findClass(String name) {
                 byte[] b = loadClassData(name);
                 return defineClass(name, b, 0, b.length);
             }
    
             private byte[] loadClassData(String name) {
                 // load the class data from the connection  . . .
             }
         }

    个人理解:

    ClassLoader是一个类加载器,除了可以从ClassPath加载类之外,还可以从ClassPath中加载资源:

    InputStream
    getResourceAsStream(String name)
              Returns an input stream for reading the specified resource.

    Enumeration<URL>
    getResources(String name)
              Finds all the resources with the given name.

    static URL
    getSystemResource(String name)
              Find a resource of the specified name from the search path used to load classes.

    static InputStream
    getSystemResourceAsStream(String name)
              Open for reading, a resource of the specified name from the search path used to load classes.

    static Enumeration<URL>
    getSystemResources(String name)
              Finds all resources of the specified name from the search path used to load classes.

    protected  Class<?>
    findClass(String name)
              Finds the class with the specified binary name.

    10、Compiler类3

    编译类是提供给支持Java到本地代码编译器和相关服务。根据设计,编译器类什么都不做;它作为一个占位符来为运行时编译执行的技术。

    当JVM第一次启动时,他判断java.compiler是否存在。如果存在,他3

    posted @ 2009-11-16 13:11 追求无止境 阅读(142) | 评论 (0)编辑 收藏

    CSS学习笔记


    1、background相关:

    属性
    描述

    background
    简写属性,作用是将背景属性设置在一个声明中。

    background-attachment
    背景图像是否固定或者随着页面的其余部分滚动。

    background-color
    设置元素的背景颜色。

    background-image
    把图像设置为背景。

    background-position
    设置背景图像的起始位置。

    background-repeat
    设置背景图像是否及如何重复。

    (1)background

    background-color:


    描述

    color_name
    规定颜色值为颜色名称的背景颜色(比如 red)。

    hex_number
    规定颜色值为十六进制值的背景颜色(比如 #ff0000)。

    rgb_number
    规定颜色值为 rgb 代码的背景颜色(比如 rgb(255,0,0))。

    transparent
    默认。背景颜色为透明。

    inherit
    规定应该从父元素继承 background-color 属性的设置。

    background-image :


    描述

    url('URL')
    指向图像的路径。

    none
    默认值。不显示背景图像。

    inherit
    规定应该从父元素继承 background-image 属性的设置。

    background-repeat :

    repeat

    默认。背景图像将在垂直方向和水平方向重复。

    repeat-x

    背景图像将在水平方向重复。

    repeat-y

    背景图像将在垂直方向重复。

    no-repeat

    背景图像将仅显示一次。

    background-position :center top buttom right left XX% XX%


    描述

    • top left
    • top center
    • top right
    • center left
    • center center
    • center right
    • bottom left
    • bottom center
    • bottom right

    如果您仅规定了一个关键词,那么第二个值将是"center"。

    默认值:0% 0%。

    x% y%

    第一个值是水平位置,第二个值是垂直位置。

    左上角是 0% 0%。右下角是 100% 100%。

    如果您仅规定了一个值,另一个值将是 50%。

    xpos ypos

    第一个值是水平位置,第二个值是垂直位置。

    左上角是 0 0。单位是像素 (0px 0px) 或任何其他的 CSS 单位。

    如果您仅规定了一个值,另一个值将是50%。

    您可以混合使用 % 和 position 值。

    background-attachment: fixed

     


    2、文本相关

    text-indent :缩进元素中的首行文本。


    描述

    length
    定义固定的缩进。默认值:0。

    %
    定义基于父元素宽度的百分比的缩进。

    text-align: 文本对应方式

    您可能会认为 text-align:center 与 <CENTER> 元素的作用一样,但实际上二者大不相同。

    <CENTER> 不仅影响文本,还会把整个元素居中。text-align 不会控制元素的对齐,而只影响内部内容。元素本身不会从一段移到另一端,只是其中的文本受影响。


    描述

    left
    把文本排列到左边。默认值:由浏览器决定。

    right
    把文本排列到右边。

    center
    把文本排列到中间。

    justify
    实现两端对齐文本效果。

    word-spacing :以改变字(单词)之间的标准间隔


    描述

    normal
    默认。定义单词间的标准空间。

    length
    定义单词间的固定空间。

    letter-spacing:改变字母之间的距离


    描述

    normal
    默认。定义字符间的标准空间。

    length
    定义字符间的固定空间。

    text-transform:处理文本的大小写


    描述

    none
    默认。定义带有小写字母和大写字母的标准的文本。

    capitalize
    文本中的每个单词以大写字母开头。

    uppercase
    定义仅有大写字母。

    lowercase
    定义无大写字母,仅有小写字母。

    text-decoration


    描述

    none
    默认。定义标准的文本。

    underline
    定义文本下的一条线。

    overline
    定义文本上的一条线。

    line-through
    定义穿过文本下的一条线。

    blink
    定义闪烁的文本(无法运行在 IE 和 Opera 中)。

    white-space


    描述

    normal
    默认。空白会被浏览器忽略。

    pre
    空白会被浏览器保留。其行为方式类似 HTML 中的 <pre> 标签。

    nowrap
    文本不会换行,文本会在在同一行上继续,直到遇到 <br> 标签为止。

    pre-wrap
    保留空白符序列,但是正常地进行换行。

    pre-line
    合并空白符序列,但是保留换行符。

     

    空白 换行 自动换行
    pre-line 合并 保留 允许
    normal 合并 忽略 允许
    nowrap 合并 忽略 不允许
    pre 保留 保留 不允许

    pre-wrap

    保留

    保留

    允许

    direction :文本的方向属性

    ltr
    默认。文本方向从左到右。

    rtl
    文本方向从右到左。

    属性
    描述

    color
    设置文本颜色

    direction
    设置文本方向。

    line-height
    设置行高。

    letter-spacing
    设置字符间距。

    text-align
    对齐元素中的文本。

    text-decoration
    向文本添加修饰。

    text-indent
    缩进元素中文本的首行。

    text-shadow
    设置文本阴影。CSS2 包含该属性,但是 CSS2.1 没有保留该属性。

    text-transform
    控制元素中的字母。

    unicode-bidi
    设置文本方向。

    white-space
    设置元素中空白的处理方式。

    word-spacing
    设置字间距。


    3、CSS字体相关

    font
    简写属性。作用是把所有针对字体的属性设置在一个声明中。

    font-family
    设置字体系列。

    font-size
    设置字体的尺寸。

    font-size-adjust
    当首选字体不可用时,对替换字体进行智能缩放。(CSS2.1 已删除该属性。)

    font-stretch
    对字体进行水平拉伸。(CSS2.1 已删除该属性。)

    font-style
    设置字体风格。

    font-variant
    以小型大写字体或者正常字体显示文本。

    font-weight
    设置字体的粗细。


    CSS 列表属性(list)

    属性
    描述

    list-style
    简写属性。用于把所有用于列表的属性设置于一个声明中。

    list-style-image
    将图象设置为列表项标志。

      1. url
        图像的路径。
      2. none
        默认。无图形被显示。

    list-style-position
    设置列表中列表项标志的位置。

      1. inside
        列表项目标记放置在文本以内,且环绕文本根据标记对齐。
      2. outside
        默认。保持标记位于文本的左侧。列表项目标记放置在文本以外,且环绕文本不根据标记对齐。

    list-style-type
    设置列表项标志的类型。

      1. none
        无标记。
      2. disc
        默认。标记是实心圆。
      3. circle
        标记是空心圆。
      4. square
        标记是实心方块。
      5. decimal
        标记是数字。
      6. decimal-leading-zero
        0开头的数字标记。(01, 02, 03, 等。)
      7. lower-roman
        小写罗马数字(i, ii, iii, iv, v, 等。)
      8. upper-roman
        大写罗马数字(I, II, III, IV, V, 等。)
      9. lower-alpha
        小写英文字母The marker is lower-alpha (a, b, c, d, e, 等。)
      10. upper-alpha
        大写英文字母The marker is upper-alpha (A, B, C, D, E, 等。)
      11. lower-greek
        小写希腊字母(alpha, beta, gamma, 等。)
      12. lower-latin
        小写拉丁字母(a, b, c, d, e, 等。)
      13. upper-latin
        大写拉丁字母(A, B, C, D, E, 等。)
      14. hebrew
        传统的希伯来编号方式
      15. armenian
        传统的亚美尼亚编号方式
      16. georgian
        传统的乔治亚编号方式(an, ban, gan, 等。)
      17. cjk-ideographic
        简单的表意数字
      18. hiragana
        标记是:a, i, u, e, o, ka, ki, 等。(日文片假名)
      19. katakana
        标记是:A, I, U, E, O, KA, KI, 等。(日文片假名)
      20. hiragana-iroha
        标记是:i, ro, ha, ni, ho, he, to, 等。(日文片假名)
      21. katakana-iroha
        标记是:I, RO, HA, NI, HO, HE, TO, 等。(日文片假名)

    marker-offset


    CSS Table 属性

    CSS 表格属性允许你设置表格的布局。(请注意,本节介绍的不是如何使用表来建立布局,而是要介绍 CSS 中表本身如何布局。)

    属性
    描述

    border-collapse
    设置是否把表格边框合并为单一的边框。

    border-spacing
    设置分隔单元格边框的距离。(仅用于 "separated borders" 模型)

    caption-side
    设置表格标题的位置。

    empty-cells
    设置是否显示表格中的空单元格。(仅用于 "separated borders" 模型)

    table-layout
    设置显示单元、行和列的算法。


    CSS 边框属性

    "CSS" 列中的数字指示哪个 CSS 版本定义了该属性。

    轮廓(outline)是绘制于元素周围的一条线,位于边框边缘的外围,可起到突出元素的作用。

    CSS outline 属性规定元素轮廓的样式、颜色和宽度。

    outline
    在一个声明中设置所有的轮廓属性。
    2

    outline-color
    设置轮廓的颜色。
    2

    outline-style
    设置轮廓的样式。
    2

    outline-width
    设置轮廓的宽度。
    2


    CSS 框模型概述

     

    CSS 框模型 (Box Model) 规定了元素框处理元素内容、内边距边框外边距 的方式。

    ct_boxmodel

     

    • element : 元素。
    • padding : 内边距,也有资料将其翻译为填充。
    • border : 边框。
    • margin : 外边距,也有资料将其翻译为空白或空白边。

    CSS 内边距属性

    属性
    描述

    padding
    简写属性。作用是在一个声明中设置元素的所内边距属性。

    padding-bottom
    设置元素的下内边距。

    padding-left
    设置元素的左内边距。

    padding-right
    设置元素的右内边距。

    padding-top
    设置元素的上内边距。


    CSS 边框属性

    属性
    描述

    border
    简写属性,用于把针对四个边的属性设置在一个声明。

    border-style
    用于设置元素所有边框的样式,或者单独地为各边设置边框样式。

    1. none
      定义无边框。
    2. hidden
      与 "none" 相同。不过应用于表时除外,对于表,hidden 用于解决边框冲突。
    3. dotted
      定义点状边框。在大多数浏览器中呈现为实线。
    4. dashed
      定义虚线。在大多数浏览器中呈现为实线。
    5. solid
      定义实线。
    6. double
      定义双线。双线的宽度等于 border-width 的值。
    7. groove
      定义 3D 凹槽边框。其效果取决于 border-color 的值。
    8. ridge
      定义 3D 垄状边框。其效果取决于 border-color 的值。
    9. inset
      定义 3D inset 边框。其效果取决于 border-color 的值。
    10. outset
      定义 3D outset 边框。其效果取决于 border-color 的值。

    border-width
    简写属性,用于为元素的所有边框设置宽度,或者单独地为各边边框设置宽度。

    1. thin
      定义细的边框。
    2. medium
      默认。定义中等的边框。
    3. thick
      定义粗的边框。
    4. length
      允许您自定义边框的宽度。

    border-color
    简写属性,设置元素的所有边框中可见部分的颜色,或为 4 个边分别设置颜色。

     

    border-bottom
    简写属性,用于把下边框的所有属性设置到一个声明中。

    border-bottom-color
    设置元素的下边框的颜色。

    border-bottom-style
    设置元素的下边框的样式。

    border-bottom-width
    设置元素的下边框的宽度。

    border-left
    简写属性,用于把左边框的所有属性设置到一个声明中。

    border-left-color
    设置元素的左边框的颜色。

    border-left-style
    设置元素的左边框的样式。

    border-left-width
    设置元素的左边框的宽度。

    border-right
    简写属性,用于把右边框的所有属性设置到一个声明中。

    border-right-color
    设置元素的右边框的颜色。

    border-right-style
    设置元素的右边框的样式。

    border-right-width
    设置元素的右边框的宽度。

    border-top
    简写属性,用于把上边框的所有属性设置到一个声明中。

    border-top-color
    设置元素的上边框的颜色。

    border-top-style
    设置元素的上边框的样式。

    border-top-width
    设置元素的上边框的宽度。


    CSS 外边距属性

    属性
    描述

    margin
    简写属性。在一个声明中设置所有外边距属性。

    margin-bottom
    设置元素的下外边距。

    margin-left
    设置元素的左外边距。

    margin-right
    设置元素的右外边距。

    margin-top
    设置元素的上外边距。


    CSS 定位属性

    CSS 定位属性允许你对元素进行定位。

    详细参见http://www.w3school.com.cn/css/css_positioning.asp

    CSS 定位和浮动

    CSS 为定位和浮动提供了一些属性,利用这些属性,可以建立列式布局,将布局的一部分与另一部分重叠,还可以完成多年来通常需要使用多个表格才能完成的任务。

    定位的基本思想很简单,它允许你定义元素框相对于其正常位置应该出现的位置,或者相对于父元素、另一个元素甚至浏览器窗口本身的位置。显然,这个功能非常强大,也很让人吃惊。要知道,用户代理对 CSS2 中定位的支持远胜于对其它方面的支持,对此不应感到奇怪。

    另一方面,CSS1 中首次提出了浮动,它以 Netscape 在 Web 发展初期增加的一个功能为基础。浮动不完全是定位,不过,它当然也不是正常流布局。我们会在后面的章节中明确浮动的含义。

    一切皆为框

    div、h1 或 p 元素常常被称为块级元素。这意味着这些元素显示为一块内容,即“块框”。与之相反,span 和 strong 等元素称为“行内元素”,这是因为它们的内容显示在行中,即“行内框”。

    您可以使用 display 属性改变生成的框的类型。这意味着,通过将 display 属性设置为 block,可以让行内元素(比如 <a> 元素)表现得像块级元素一样。还可以通过把 display 设置为 none,让生成的元素根本没有框。这样的话,该框及其所有内容就不再显示,不占用文档中的空间。

    但是在一种情况下,即使没有进行显式定义,也会创建块级元素。这种情况发生在把一些文本添加到一个块级元素(比如 div)的开头。即使没有把这些文本定义为段落,它也会被当作段落对待:

    <div>
    some text
    <p>Some more text.</p>
    </div>
    

    在这种情况下,这个框称为无名块框,因为它不与专门定义的元素相关联。

    块级元素的文本行也会发生类似的情况。假设有一个包含三行文本的段落。每行文本形成一个无名框。无法直接对无名块或行框应用样式,因为没有可以应用样式的地方(注意,行框和行内框是两个概念)。但是,这有助于理解在屏幕上看到的所有东西都形成某种框。

    CSS 定位机制

    CSS 有三种基本的定位机制:普通流、浮动和绝对定位。

    除非专门指定,否则所有框都在普通流中定位。也就是说,普通流中的元素的位置由元素在 X(HTML) 中的位置决定。

    块级框从上到下一个接一个地排列,框之间的垂直距离是由框的垂直外边距计算出来。

    行内框在一行中水平布置。可以使用水平内边距、边框和外边距调整它们的间距。但是,垂直内边距、边框和外边距不影响行内框的高度。由一行形成的水平框称为行框(Line Box),行框的高度总是足以容纳它包含的所有行内框。不过,设置行高可以增加这个框的高度。

    在下面的章节,我们会为您详细讲解相对定位、绝对定位和浮动。

    CSS position 属性

    通过使用 position 属性,我们可以选择 4 中不同类型的定位,这会影响元素框生成的方式。

    position 属性值的含义:

    static
    元素框正常生成。块级元素生成一个矩形框,作为文档流的一部分,行内元素则会创建一个或多个行框,置于其父元素中。
    relative
    元素框偏移某个距离。元素仍保持其未定位前的形状,它原本所占的空间仍保留。
    absolute
    元素框从文档流完全删除,并相对于其包含块定位。包含块可能是文档中的另一个元素或者是初始包含块。元素原先在正常文档流中所占的空间会关闭,就好像元素原来不存在一样。元素定位后生成一个块级框,而不论原来它在正常流中生成何种类型的框。
    fixed
    元素框的表现类似于将 position 设置为 absolute,不过其包含块是视窗本身。

    提示:相对定位实际上被看作普通流定位模型的一部分,因为元素的位置相对于它在普通流中的位置。

    属性
    描述

    position
    把元素放置到一个静态的、相对的、绝对的、或固定的位置中。

    1. static
      默认。位置设置为 static 的元素,它始终会处于页面流给予的位置(static 元素会忽略任何 top、bottom、left 或 right 声明)。
    2. relative
      位置被设置为 relative 的元素,可将其移至相对于其正常位置的地方,因此 "left:20" 将向元素的 LEFT 位置添加 20 个像素。
    3. absolute
      位置设置为 absolute 的元素,可定位于相对于包含它的元素的指定坐标。此元素的位置可通过 "left"、"top"、"right" 以及"bottom" 属性来规定。
    4. fixed
      位置被设置为 fixed 的元素,可定位于相对于浏览器窗口的指定坐标。此元素的位置可通过 "left"、"top"、"right" 以及"bottom" 属性来规定。不论窗口滚动与否,元素都会留在那个位置。工作于 IE7(strict 模式)。

    top
    定义了一个定位元素的上外边距边界与其包含块上边界之间的偏移。

    1. auto
      默认。通过浏览器来计算顶部的位置。
    2. %
      设置元素的顶部到最近一个具有定位设置父元素的上边缘的百分比位置。
    3. length
      使用 px、cm 等单位设置元素的顶部到最近一个具有定位设置上边缘的顶部的位置。可使用负值。

    right
    定义了定位元素右外边距边界与其包含块右边界之间的偏移。

    bottom
    定义了定位元素下外边距边界与其包含块下边界之间的偏移。

    left
    定义了定位元素左外边距边界与其包含块左边界之间的偏移。

    overflow
    设置当元素的内容溢出其区域时发生的事情。

    1. visible
      默认。内容不会被修剪,会呈现在元素之外。
    2. hidden
      内容会被修剪,但是浏览器不会显示供查看内容的滚动条。
    3. scroll
      内容会被修剪,但是浏览器会显示滚动条以便查看其余的内容。
    4. auto
      如果内容被修剪,则浏览器会显示滚动条以便查看其余的内容。

    clip
    设置元素的形状。元素被剪入这个形状之中,然后显示出来。

    1. shape
      设置元素的形状。合法的形状值是:rect (top, right, bottom, left)
    2. auto
      默认。浏览器可设置元素的形状。

    vertical-align
    设置元素的垂直对齐方式。

    1. baseline
      默认。元素放置在父元素的基线上。
    2. sub
      垂直对齐文本的下标。
    3. super
      垂直对齐文本的上标
    4. top
      把元素的顶端与行中最高元素的顶端对齐
    5. text-top
      把元素的顶端与父元素字体的顶端对齐
    6. middle
      把此元素放置在父元素的中部。
    7. bottom
      把元素的顶端与行中最低的元素的顶端对齐。
    8. text-bottom
      把元素的底端与父元素字体的底端对齐。
    9. length
    10. %
      使用 "line-height" 属性的百分比值来排列此元素。允许使用负值。

    z-index
    设置元素的堆叠顺序。

    1. auto
      默认。堆叠顺序与父元素相等。
    2. number
      设置元素的堆叠顺序。

     


    CSS 尺寸属性

    CSS 尺寸属性允许你控制元素的高度和宽度。同样,还允许你增加行间距。

    属性
    描述

    height
    设置元素的高度。

    line-height
    设置行高。

    max-height
    设置元素的最大高度。

    max-width
    设置元素的最大宽度。

    min-height
    设置元素的最小高度。

    min-width
    设置元素的最小宽度。

    width
    设置元素的宽度。


    CSS 分类属性 (Classification)

    CSS 分类属性允许你控制如何显示元素,设置图像显示于另一元素中的何处,相对于其正常位置来定位元素,使用绝对值来定位元素,以及元素的可见度。

    属性
    描述

    clear
    设置一个元素的侧面是否允许其他的浮动元素。

    cursor
    规定当指向某元素之上时显示的指针类型。

    display
    设置是否及如何显示元素。

    float
    定义元素在哪个方向浮动。

    position
    把元素放置到一个静态的、相对的、绝对的、或固定的位置中。

    visibility
    设置元素是否可见或不可见。

     

    伪类

    浏览器支持IE Internet Explorer, F: Firefox, N: Netscape。

    W3C:“W3C” 列的数字显示出伪类属性由哪个 CSS 标准定义(CSS1 还是 CSS2)。

    伪类
    作用
    IE
    F
    N
    W3C

    :active
    将样式添加到被激活的元素
    4
    1
    8
    1

    :focus
    将样式添加到被选中的元素
    -
    -
    -
    2

    :hover
    当鼠标悬浮在元素上方时,向元素添加样式
    4
    1
    7
    1

    :link
    将特殊的样式添加到未被访问过的链接
    3
    1
    4
    1

    :visited
    将特殊的样式添加到被访问过的链接
    3
    1
    4
    1

    :first-child
    将特殊的样式添加到元素的第一个子元素
    1
    7
    2

    :lang
    允许创作者来定义指定的元素中使用的语言
    1
    8
    2

    伪元素
    作用
    IE
    F
    N
    W3C

    :first-letter
    将特殊的样式添加到文本的首字母
    5
    1
    8
    1

    :first-line
    将特殊的样式添加到文本的首行
    5
    1
    8
    1

    :before
    在某元素之前插入某些内容
    1.5
    8
    2

    :after
    在某元素之后插入某些内容
    1.5
    8
    2

     

    不同的媒介类型

    注释:媒介类型名称对大小写不敏感。

    浏览器支持IE: Internet Explorer, F: Firefox, N: Netscape。

    W3C:“W3C” 列的数字显示出属性背景由哪个 CSS 标准定义(CSS1 还是 CSS2)。

    媒介类型
    描述

    all
    用于所有的媒介设备。

    aural
    用于语音和音频合成器。

    braille
    用于盲人用点字法触觉回馈设备。

    embossed
    用于分页的盲人用点字法打印机。

    handheld
    用于小的手持的设备。

    print
    用于打印机。

    projection
    用于方案展示,比如幻灯片。

    screen
    用于电脑显示器。

    tty
    用于使用固定密度字母栅格的媒介,比如电传打字机和终端。

    tv
    用于电视机类型的设备。

    posted @ 2009-11-16 13:08 追求无止境 阅读(285) | 评论 (0)编辑 收藏

    JDBC高级特性

    1、可滚动的结果集(Scrollable Result Sets)

    (1)创建可滚动的结果集:

      Statement stmt = con.createStatement(
                           ResultSet.TYPE_SCROLL_INSENSITIVE, 
                           ResultSet.CONCUR_READ_ONLY);
    ResultSet.TYPE_FORWARD_ONLY:结果集是不能滚动的;他的游标只能向前移动;
    ResultSet.TYPE_SCROLL_INSENSITIVE:结果是可滚动的;游标可以向前也可以后退。也可以移动到一个绝对位置。
    ResultSet.TYPE_SCROLL_SENSITIVE:结果是可滚动的;游标可以向前也可以后退。也可以移动到一个绝对位置。
    ResultSet.CONCUR_READ_ONLY:结果集是只读的。
    ResultSet.ResultSet.CONCUR_UPDATABLE:结果集是可以更新的。
    
      ResultSet srs = stmt.executeQuery("SELECT COF_NAME, 
                           PRICE FROM COFFEES");
    尽管我们可以在这里设置创建的是可滚动结果集,但是如果厂商的JDBC实现不支持,我们获取到的结果将不具有可滚动属性。
    可以使用ResultSet.getType()方法来获取是否支持滚动:
     int type = rs.getType();
    

    The variable type will be one of the following:

    1003 to indicate ResultSet.TYPE_FORWARD_ONLY

    1004 to indicate ResultSet.TYPE_SCROLL_INSENSITIVE

    1005 to indicate ResultSet.TYPE_SCROLL_SENSITIVE

    TYPE_SCROLL_INSENSITIVE和TYPE_SCROLL_SENSITIVE的主要区别是在如果发生改变他们的敏感度。前一个将不会很敏感后一个则会。

    (2)移动游标,使用以下方法可以移动游标:

    rs.next();

    rs.previous();

    rs.absolute();

    rs.relative();

    rs.first();

    rs.last();

    rs.beforeFirst();

    rs.afterLast();

    使用rs.getRow()获取游标当前行。

    rs.isAfterLast();
    rs.isBeforeFirst();
    rs.isLast();
    rs.isFirst();
    rs.hasNext();
    等等方法。
    2、更新结果集
    (1)创建可以更新的结果集
    Statement stmt = con.createStatement(
                   ResultSet.TYPE_SCROLL_SENSITIVE, 
                   ResultSet.CONCUR_UPDATABLE);
      ResultSet uprs = stmt.executeQuery(
                   "SELECT COF_NAME, 
                   PRICE FROM COFFEES");

    在JDBC 2.0中,我们可以向可以更新的结果集中插入行或删除行,或者修改其中的行。

    下面的方法用于判断结果集是否可以更新:

      int concurrency = uprs.getConcurrency();
    

    The variable concurrency will be one of the following:

    1007 to indicate ResultSet.CONCUR_READ_ONLY

    1008 to indicate ResultSet.CONCUR_UPDATABLE

    (2)更新结果集

    JDBC 1.0中可以这样更新: 
     stmt.executeUpdate(
        "UPDATE COFFEES SET PRICE = 10.99 " +
        "WHERE COF_NAME = 'French_Roast_Decaf'");
    在JDBC2.0中。则可以:
     uprs.last();
      uprs.updateFloat("PRICE", 10.99f);
    uprs.updateRow();
    在移动游标前,必须先调用updateRow方法。否则更新信息会丢失。调用cancelRowUpdates可以取消对行的更新。
    (3)向结果集中插入或者删除行
      Connection con = DriverManager.getConnection(
                          "jdbc:mySubprotocol:mySubName");
      Statement stmt = con.createStatement(
                           ResultSet.TYPE_SCROLL_SENSITIVE, 
                           ResultSet.CONCUR_UPDATABLE);
      ResultSet uprs = stmt.executeQuery(
                          "SELECT * FROM COFFEES");
      uprs.moveToInsertRow();
    
      uprs.updateString("COF_NAME", "Kona");
      uprs.updateInt("SUP_ID", 150);
      uprs.updateFloat("PRICE", 10.99f);
      uprs.updateInt("SALES", 0);
      uprs.updateInt("TOTAL", 0);
      
      uprs.insertRow();
    在移动游标前,必须要先调用insertRow否则插入的信息将丢失。
    uprs.absolute(4);
    uprs.deleteRow();
    删除行。
    (4)查看结果集中的变化(其实就是说了一个意思,用TYPE_SCROLL_SENSITIVE对数据很敏感,一旦数据变化就会反映在ResultSet中)

    Result sets vary greatly in their ability to reflect changes made in their underlying data. If you modify data in a ResultSet object, the change will always be visible if you close it and then reopen it during a transaction. In other words, if you re-execute the same query after changes have been made, you will produce a new result set based on the new data in the target table. This new result set will naturally reflect changes you made earlier. You will also see changes made by others when you reopen a result set if your transaction isolation level makes them visible.

    So when can you see visible changes you or others made while the ResultSet object is still open? (Generally, you will be most interested in the changes made by others because you know what changes you made yourself.) The answer depends on the type of ResultSet object you have.

    With a ResultSet object that is TYPE_SCROLL_SENSITIVE, you can always see visible updates made to existing column values. You may see inserted and deleted rows, but the only way to be sure is to use DatabaseMetaData methods that return this information. ("New JDBC 2.0 Core API Features" on page 371 explains how to ascertain the visibility of changes.)

    You can, to some extent, regulate what changes are visible by raising or lowering the transaction isolation level for your connection with the database. For example, the following line of code, wherecon is an active Connection object, sets the connection's isolation level to TRANSACTION_READ_COMMITTED:

      con.setTransactionIsolation(
                  Connection.TRANSACTION_READ_COMMITTED);
    

    With this isolation level, a TYPE_SCROLL_SENSITIVE result set will not show any changes before they are committed, but it can show changes that may have other consistency problems. To allow fewer data inconsistencies, you could raise the transaction isolation level to TRANSACTION_REPEATABLE_READ. The problem is that, in most cases, the higher the isolation level, the poorer the performance is likely to be. And, as is always true of JDBC drivers, you are limited to the levels your driver actually provides. Many programmers find that the best choice is generally to use their database's default transaction isolation level. You can get the default with the following line of code, where con is a newly-created connection:

      int level = con.getTransactionIsolation();
    

    The explanation of Connection fields, beginning on page 347, gives the transaction isolation levels and their meanings.

    If you want more information about the visibility of changes and transaction isolation levels, see "What Is Visible to Transactions" on page 597.

    In a ResultSet object that is TYPE_SCROLL_INSENSITIVE, you cannot see changes made to it by others while it is still open, but you may be able to see your own changes with some implementations. This is the type of ResultSet object to use if you want a consistent view of data and do not want to see changes made by others.

    posted @ 2009-11-16 13:05 追求无止境 阅读(276) | 评论 (0)编辑 收藏

    视频感想

    昨天晚上看了关于“都市信息网”项目开发视频,给人总体感觉差强人意,学到了一些知识,记录如下:

    1、页面结构:

    在页面结构的定义上,将页面分成多部分,例如页头,页尾,左侧栏和右主栏。在每个栏中导入需要的JSP文件。

    2、关于controller:

    要让controller实现RequestAware和ResponseAware。然后使用继承。

    3、关于DAO层的设计

    遗憾的是都市信息在DAO层的设计上,是一个败笔。在controller里面使用sql语句。不利于各个层次的独立。

    4、关于TreeMap

    在该项目中,使用map多使用TreeMap,查一下TreeMap是什么东西吧:

    A Red-Black tree based NavigableMap implementation. The map is sorted according to the natural ordering of its keys, or by aComparator provided at map creation time, depending on which constructor is used.

    哦,是一个基于红黑树的Map。

    什么是红黑树。

    红黑树(Red-Black Tree)是二叉搜索树(Binary Search Tree)的一种改进。我们知道二叉搜索树在最坏的情况下可能会变成一个链表(当所有节点按从小到大的顺序依次插入后)。而红黑树在每一次插入或删除节点之后都会花O(log N)的时间来对树的结构作修改,以保持树的平衡。也就是说,红黑树的查找方法与二叉搜索树完全一样;插入和删除节点的的方法前半部分节与二叉搜索树完全一样,而后半部分添加了一些修改树的结构的操作。
    红黑树的每个节点上的属性除了有一个key、3个指针:parent、lchild、rchild以外,还多了一个属性:color。它只能是两种颜色:红或黑。而红黑树除了具有二叉搜索树的所有性质之外,还具有以下4点性质:
    1. 根节点是黑色的。
    2. 空节点是黑色的(红黑树中,根节点的parent以及所有叶节点lchild、rchild都不指向NULL,而是指向一个定义好的空节点)。
    3. 红色节点的父、左子、右子节点都是黑色。
    4. 在任何一棵子树中,每一条从根节点向下走到空节点的路径上包含的黑色节点数量都相同。

    有了这几条规则,就可以保证整棵树的平衡,也就等于保证了搜索的时间为O(log N)。

    但是在插入、删除节点后,就有可能破坏了红黑树的性质。所以我们要做一些操作来把整棵树修补好。下面我就来介绍一下。

    posted @ 2009-11-16 13:03 追求无止境 阅读(96) | 评论 (0)编辑 收藏

    一个简单的小测验,考查一下对Java基础的掌握情况

    今天看Java Language Specification的时候看到了下面的一段代码:
    package testPackage;
    class Test {
    public static void main(String[] args) {
    String hello 
    = "Hello", lo = "lo";
    System.out.print((hello 
    == "Hello"+ " ");
    System.out.print((Other.hello 
    == hello) + " ");
    System.out.print((other.Other.hello 
    == hello) + " ");
    System.out.print((hello 
    == ("Hel"+"lo")) + " ");
    System.out.print((hello 
    == ("Hel"+lo)) + " ");
    System.out.println(hello 
    == ("Hel"+lo).intern());
    }

    }

    class Other static String hello = "Hello"; }


    package other;
    public class Other static String hello = "Hello"; }



    输出的结果出人预料。不运行它,大家自己想想答案吧,然后把答案和你的想法贴出来分享给大家吧。
    正确答案的话,运行一下运行一下就知道了。。

    posted @ 2009-08-11 09:39 追求无止境 阅读(1530) | 评论 (8)编辑 收藏

    JSP优化(转)

    你时常被客户抱怨JSP页面响应速度很慢吗?你想过当客户访问次数剧增时,你的WEB应用能承受日益增加的访问量吗?本文讲述了调整JSP和servlet的一些非常实用的方法,它可使你的servlet和JSP页面响应更快,扩展性更强。而且在用户数增加的情况下,系统负载会呈现出平滑上长的趋势。在本文中,我将通过一些实际例子和配置方法使得你的应用程序的性能有出人意料的提升。其中,某些调优技术是在你的编程工作中实现的。而另一些技术是与应用服务器的配置相关的。在本文中,我们将详细地描述怎样通过调整servlet和JSP页面,来提高你的应用程序的总体性能。在阅读本文之前,假设你有基本的servlet和JSP的知识。
    方法一:在servlet的init()方法中缓存数据
    当应用服务器初始化servlet实例之后,为客户端请求提供服务之前,它会调用这个servlet的init()方法。在一个servlet的生命周期中,init()方法只会被调用一次。通过在init()方法中缓存一些静态的数据或完成一些只需要执行一次的、耗时的操作,就可大大地提高系统性能。
    例如,通过在init()方法中建立一个JDBC连接池是一个最佳例子,假设我们是用jdbc2.0的DataSource接口来取得数据库连接,在通常的情况下,我们需要通过JNDI来取得具体的数据源。我们可以想象在一个具体的应用中,如果每次SQL请求都要执行一次JNDI查询的话,那系统性能将会急剧下降。解决方法是如下代码,它通过缓存DataSource,使得下一次SQL调用时仍然可以继续利用它:
    <table borderColor=#ffcc66 width="90%" align=center bgColor=#e6e4dd border=1> 
    <tr> 
    <td>public class ControllerServlet extends HttpServlet
    {
    private javax.sql.DataSource testDS = null; 
    public void init(ServletConfig config) throws ServletException
    {
    super.init(config); 
    Context ctx = null;
    try
    ctx = new InitialContext();
    testDS = (javax.sql.DataSource)ctx.lookup("jdbc/testDS");
    }
    catch(NamingException ne)
    {
    ne.printStackTrace(); 
    }
    catch(Exception e)
    {
    e.printStackTrace();
    }
    }
    public javax.sql.DataSource getTestDS()
    {
    return testDS;
    }
    ...
    ... 
    }</td></tr></table>
    方法 2:禁止servlet和JSP 自动重载(auto-reloading)
    Servlet/JSP提供了一个实用的技术,即自动重载技术,它为开发人员提供了一个好的开发环境,当你改变servlet和JSP页面后而不必重启应用服务器。然而,这种技术在产品运行阶段对系统的资源是一个极大的损耗,因为它会给JSP引擎的类装载器(classloader)带来极大的负担。因此关闭自动重载功能对系统性能的提升是一个极大的帮助。
    方法 3: 不要滥用HttpSession 
    在很多应用中,我们的程序需要保持客户端的状态,以便页面之间可以相互联系。但不幸的是由于HTTP具有天生无状态性,从而无法保存客户端的状态。因此一般的应用服务器都提供了session来保存客户的状态。在JSP应用服务器中,是通过HttpSession对像来实现session的功能的,但在方便的同时,它也给系统带来了不小的负担。因为每当你获得或更新session时,系统者要对它进行费时的序列化操作。你可以通过对HttpSession的以下几种处理方式来提升系统的性能:
    · 如果没有必要,就应该关闭JSP页面中对HttpSession的缺省设置: 如果你没有明确指定的话,每个JSP页面都会缺省地创建一个HttpSession。如果你的JSP中不需要使用session的话,那可以通过如下的JSP页面指示符来禁止它:
    <table borderColor=#ffcc66 width="90%" align=center bgColor=#e6e4dd border=1> 
    <tr> 
    <td><%@ page session="false"%> </td></tr></table>
    · 不要在HttpSession中存放大的数据对像:如果你在HttpSession中存放大的数据对像的话,每当对它进行读写时,应用服务器都将对其进行序列化,从而增加了系统的额外负担。你在HttpSession中存放的数据对像越大,那系统的性能就下降得越快。
    · 当你不需要HttpSession时,尽快地释放它:当你不再需要session时,你可以通过调用HttpSession.invalidate()方法来释放它。
    · 尽量将session的超时时间设得短一点:在JSP应用服务器中,有一个缺省的session的超时时间。当客户在这个时间之后没有进行任何操作的话,系统会将相关的session自动从内存中释放。超时时间设得越大,系统的性能就会越低,因此最好的方法就是尽量使得它的值保持在一个较低的水平。
    方法 4: 将页面输出进行压缩
    压缩是解决数据冗余的一个好的方法,特别是在网络带宽不够发达的今天。有的浏览器支持gzip(GNU zip)进行来对HTML文件进行压缩,这种方法可以戏剧性地减少HTML文件的下载时间。因此,如果你将servlet或JSP页面生成的HTML页面进行压缩的话,那用户就会觉得页面浏览速度会非常快。但不幸的是,不是所有的浏览器都支持gzip压缩,但你可以通过在你的程序中检查客户的浏览器是否支持它。下面就是关于这种方法实现的一个代码片段:
    <table borderColor=#ffcc66 width="90%" align=center bgColor=#e6e4dd border=1> 
    <tr> 
    <td>public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws IOException, ServletException 
    {
    OutputStream out = null
    String encoding = request.getHeader("Accept-Encoding"); 
    if (encoding != null && encoding.indexOf("gzip") != -1)
    {
    request.setHeader("Content-Encoding" , "gzip");
    out = new GZIPOutputStream(request.getOutputStream());
    }
    else if (encoding != null && encoding.indexOf("compress") != -1)
    {
    request.setHeader("Content-Encoding" , "compress");
    out = new ZIPOutputStream(request.getOutputStream());
    else
    {
    out = request.getOutputStream();
    }
    ...
    ... 
    } </td></tr></table>
    方法 5: 使用线程池
    应用服务器缺省地为每个不同的客户端请求创建一个线程进行处理,并为它们分派service()方法,当service()方法调用完成后,与之相应的线程也随之撤消。由于创建和撤消线程会耗费一定的系统资源,这种缺省模式降低了系统的性能。但所幸的是我们可以通过创建一个线程池来改变这种状况。另外,我们还要为这个线程池设置一个最小线程数和一个最大线程数。在应用服务器启动时,它会创建数量等于最小线程数的一个线程池,当客户有请求时,相应地从池从取出一个线程来进行处理,当处理完成后,再将线程重新放入到池中。如果池中的线程不够地话,系统会自动地增加池中线程的数量,但总量不能超过最大线程数。通过使用线程池,当客户端请求急剧增加时,系统的负载就会呈现的平滑的上升曲线,从而提高的系统的可伸缩性。
    方法 6: 选择正确的页面包含机制
    在JSP中有两种方法可以用来包含另一个页面:1、使用include指示符(<%@ includee file=”test.jsp” %>)。2、使用jsp指示符(<jsp:includee page=”test.jsp” flush=”true”/>)。在实际中我发现,如果使用第一种方法的话,可以使得系统性能更高。
    方法 7:正确地确定javabean的生命周期
    JSP的一个强大的地方就是对javabean的支持。通过在JSP页面中使用<jsp:useBean>标签,可以将javabean直接插入到一个JSP页面中。它的使用方法如下:
    <table borderColor=#ffcc66 width="90%" align=center bgColor=#e6e4dd border=1> 
    <tr> 
    <td><jsp:useBean id="name" scope="page|request|session|application" class=
    "package.className" type="typeName">
    </jsp:useBean></td></tr></table>
    其中scope属性指出了这个bean的生命周期。缺省的生命周期为page。如果你没有正确地选择bean的生命周期的话,它将影响系统的性能。
    举例来说,如果你只想在一次请求中使用某个bean,但你却将这个bean的生命周期设置成了session,那当这次请求结束后,这个bean将仍然保留在内存中,除非session超时或用户关闭浏览器。这样会耗费一定的内存,并无谓的增加了JVM垃圾收集器的工作量。因此为bean设置正确的生命周期,并在bean的使命结束后尽快地清理它们,会使用系统性能有一个提高。
    其它一些有用的方法 
    · 在字符串连接操作中尽量不使用“+”操作符:在java编程中,我们常常使用“+”操作符来将几个字符串连接起来,但你或许从来没有想到过它居然会对系统性能造成影响吧?由于字符串是常量,因此JVM会产生一些临时的对像。你使用的“+”越多,生成的临时对像就越多,这样也会给系统性能带来一些影响。解决的方法是用StringBuffer对像来代替“+”操作符。
    · 避免使用System.out.println()方法:由于System.out.println()是一种同步调用,即在调用它时,磁盘I/O操作必须等待它的完成,因此我们要尽量避免对它的调用。但我们在调试程序时它又是一个必不可少的方便工具,为了解决这个矛盾,我建议你最好使用Log4j工具(http://jakarta.apache.org ),它既可以方便调试,而不会产生System.out.println()这样的方法。
    · ServletOutputStream 与 PrintWriter的权衡:使用PrintWriter可能会带来一些小的开销,因为它将所有的原始输出都转换为字符流来输出,因此如果使用它来作为页面输出的话,系统要负担一个转换过程。而使用ServletOutputStream作为页面输出的话就不存在一个问题,但它是以二进制进行输出的。因此在实际应用中要权衡两者的利弊。
    总结
    本文的目的是通过对servlet和JSP的一些调优技术来极大地提高你的应用程序的性能,并因此提升整个J2EE应用的性能。通过这些调优技术,你可以发现其实并不是某种技术平台(比如J2EE和.NET之争)决定了你的应用程序的性能,重要是你要对这种平台有一个较为深入的了解,这样你才能从根本上对自己的应用程序做一个优化!

    posted @ 2009-07-23 09:55 追求无止境 阅读(177) | 评论 (0)编辑 收藏

    转帖--每个人都该学会的50件事情

       要过得健康充实,还得靠自立。要学会自立,必须得掌握一些技巧。可能和你在学校里学到的不同,但全才远远要比专门只会一样的人更能够适应生活。

    这里是每个人都该学会的50件事情。(不完全统计)

     
    1.   生火——火能产生光和热。这两件是生存的必需品。也许在某个时候,这项技能可以救你的命。

    2.   操作电脑——基本的电脑常识是现代生活之必需。必要的时候,请帮助他人。

    3。有效使用Google——Google无所不知。如果你用Google找不到你想找的东西,那就是你的问题了。

    4。人工呼吸和处理喉咙被塞住的急救措施——有一天你的妻子、丈夫、儿子或女儿,可能正是需要你帮助的那个人。

    5。开手排档的车——也许有时候你会需要这项技能,要是不会就糟了。

    6。简单地做饭——如果你连鸡蛋或牛排都不会煎,那就麻烦了。

    7。讲一个能吸引人们注意力的故事——如果你不能吸引别人的注意力,那还是别废话了。

    8。不与人打架,除非你能赢——两种情况下,你都赢了。

    9。告诉别人坏消息——总得有人去做这件事。不幸的是,有一天这个重任也会落到你肩上。

    10。换轮胎——轮胎里面有气体,只要有气体的东西总有一天会爆掉。

    11。从容应对面试——要是紧张得浑身是汗,你肯定得不到那份工作。

    12。管理好自己的时间——否则你就是在浪费时间。偶尔浪费时间也没关系,但不能一直这样。

    13。快速阅读——很多时候你只要读要点就可以了。(看到这里就觉得没早点学会这条了吧)

    14。记住名字——你会喜欢别人管你叫“喂,那个谁。。。”吗?

    15。整理房间——真正做起来总比想象的要难一点。

    16。轻装上阵——旅行时只带最必需的东西。这样更便宜、更简单、更灵活。

    17。和警察打交道——蹲监狱可不是好玩的,监狱里面的大汉就更不用说了。

    18。给别人指路——没人喜欢迷路,所以最好第一次就指对。

    19。进行基本的急救——会正确处理伤口,不是只有医生或天才才能做到的。

    20。游泳——地球表面71%的地方都是水,所以学会游泳绝对是个好主意。

    21。路边停车——大多数标准驾照考试都要求考路边停车,然而大多数人还是不知道该怎么做。很奇怪啊。

    22。了解自己的酒量——不然你一不小心就会很难看。

    23。选择好的产品——腐坏的水果和蔬菜只能成为恶作剧的道具用来吓人。

    24。会用锤子、斧子和手锯——不是只有木匠才用得着这些工具的。每个人都得有点使用这些工具的基本常识。

    25。进行简单的财务规划——负债累累可不好,一个简单地预算计划可以帮你解决这些问题。

    26.至少会说两种通用的语言——世界上只有25%的人说英语。如果能跟剩下75%的人沟通也挺好的。

    27.正确地做俯卧撑和仰卧起坐——姿势不正确的话只会伤害身体,也是浪费时间。

    28.多赞美别人——赞美是世上最好的礼物之一,更何况是免费的。

    29.谈判——再多问一两个问题就会得到更好的价钱。

    30.仔细听别人说话——多听少讲,学到的多,失去的少。

    31.复习基本的地理知识——如果你不知道你生活圈以外的环境,大部分的人只会认为你什么都不知道(而且通常他们是对的)。

    32.粉刷房间——粉刷房间的价格百分之九十是人工费用,简单的油漆活自己做比付给别人9倍的工资要来得划算。

    33.简单明了又内容丰富的演说——如果下次公司开会时你的上司要你解释你上个月做了什么活,这样的演讲能让你过关。“嗯。。。不知道”的话就惨了。

    34.照相的时候微笑——硬是不笑的人最糟了!

    35.不出丑的搭讪——搭讪成功跟失败只是一念之间。如果太刻意的话会失败,不够用心的话也会失败。

    36.做有用的笔记——因为没用的笔记和不做笔记一样都是没用的。

    37.礼待住在自己家里的客人——要不然的话哪天你需要借住他们家的时候就只能睡旅馆了。

    38.给人好的第一次印象——亚里士多德曾经说过,“好的开始是成功的一半。”

    39.会看地图和使用指南针——如果你的卫星导航器在一个鸟不生蛋的地方坏了,你要怎么办?

    40.缝钮扣——比买新衣便宜。

    41.自己装家里的视听系统——又不是多难,付钱给别人装只是因为偷懒。

    42.打字——打字打得好的话会节省很多时间,一生受用。

    43.保护私人资料——除非你是那个小偷,不然个人资料被偷可不是好玩的。

    44.设定基本的电脑系统防护措施——设定密码跟防火墙并不需要计算机本科毕业,但可以预防将来倒大霉。

    45。识别谎言——人们会对你说谎,此乃人生之一大不幸。

    46。有礼貌地结束约会,而不承诺下一次——千万别给别人一个你不愿给的承诺。你也不用急着决定和一个刚认识没多久的人有什么未来。

    47。除去污渍——总比再买一件便宜。

    48。保持房间整洁——整洁的房间是健康、规律生活的开始。

    49。正确地抱婴儿——你可不想无意弄伤一个小宝宝。

    50。启动汽车电瓶——这总比走路或叫拖车好得多。

    风雨雷电---MP3MP4专卖;

    posted @ 2008-10-04 14:16 追求无止境 阅读(100) | 评论 (0)编辑 收藏