`
掌心童话
  • 浏览: 15175 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

Java Web Application 自架构 一 注解化配置

阅读更多

        好尴尬,发现自己写上篇技术博文,已经是一年前的事情了,好像把时间都浪费在娱乐上了?没有吧,工作还是很认真的。业余时间,是有点浪费了,不过还是有研究过一些精彩的东东来分享的。不说闲话了,这就分享出来。

       

        这段时间里还是一直对新型的几个主流的Java框架做一些研究,现在以一个 Web Application 的模型 将笔者的心得课题化并一一分享出来。今天是第一篇,分享下笔者对一个小型Web程序的架构,以及如何将原来的web.xml和spring的applicationContext.xml对应到新型注解化的配置类中。

       

       之前《究 Spring 3.1之无web.xml式 基于代码配置的servlet3.0应用》中已经将知晓了Spring是如何利用Servlet3中的ServletContainerInitializer进行Web初始化配置的,这里笔者就不再自己去写了,像利用Spring的FileCopyUtils一样,清楚它是怎么实现的就好,用时直接拿来用,方便。


架构如图所示。src包中,分层为三

1,控制层ctrl,MVC的C大家都知道,表层,与UI的数据调度,接收Http请求并做出相应响应,这里还未确定具体用什么框架,先放着。

2,业务层hub,叫biz, business, service都行,即业务逻辑层,整个web核心调度层。

3 外部层pin,通常是dao数据访问层,然后自我认为这里不单单会借助数据库做为外部辅助系统,与外部其他系统都应该放在这层里,做为与外部系统沟通的底层,所以用了个很形象的 针脚pin 一词。

 

        所谓的外部系统还有可能是邮件服务器,webService调用与被调用,等等,甚至是文件资源。比方说,文件资源有时不一定会存储在部署的服务器上,也有可能外包于其它专门的服务器,例如amazon的S3, 这时,业务层hub无需要知道文件资源的存储是何策略,直接调用底层的方法,由pin层的专门管理文件资源存储的类去具体操作。再往下面的persistence 做传统意义的dao服务。

        当然别忘了entity, 就是业务实体模型。

        Util 里放一些配置,工具等的类 。例如图中选中的高亮文件,就是对应于以往web.xml的文件,这里命名其为WebConfiguration, 当然,名字因人而异。

测试包testsrc在后面的 单元测试一节会具体说明,这里就过了。

然后用到的库,JRE不多说,Web App Lib是将所需的jar文件放到WebContent/WEB-INF/lib下后自动生成的。

        测试库SpringJunit4也是测试章节的。后面的运行时库是为了做servlet包的,随便加一个有servlet3支持的就好。

       WebContent下的内容是之后部署环境的所有内容,笔者这里放着个sysParams.properties就是系统的一些配置属性,部署人员做web部署时,只需要改这一个就行。开发过程中有可配置的选项都应该通过一个静态的Properties类对象去找到相应的名值对,通过一定方法转换为所需类型。至于怎么实现,这就来看。

首先来着,对应于原来web.xml的WebConfiguration代码如下:

 

package com.gxino.webmodel.util;

import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;

public class WebConfiguration implements WebApplicationInitializer{

	private static Properties sysParams=new Properties();
	
	public static Properties getSysParams() {
		return sysParams;
	}

	@Override
	public void onStartup(ServletContext servletContext) throws ServletException {
		try {
			String sysParamsLocation=this.getClass().getResource("/").getFile().replace("/classes/", "/sysParams.properties");
			sysParams.load(new FileReader(sysParamsLocation));
		} catch (IOException e) {
		}
		AnnotationConfigWebApplicationContext annoAppCtx 
			= new AnnotationConfigWebApplicationContext();
		annoAppCtx.register(ApplicationContext.class);
		if(servletContext!=null)servletContext.addListener(new ContextLoaderListener(annoAppCtx));
	}

}
 

 

        它实现Spring的WebApplicationInitializer后写了方法onStartup(servletContenxt), 因为支持servlet3的服务器启动后会找到WebApplicationInitializer的所有实现类并执行其onStartup方法,至于想了解它如何做到的,文章开头已经说明,请去阅读另一篇博文。 在这个方法里,笔者首先做的是load sysParams.propertyies文件到本类的一个静态Properties变量sysParams中,这样一来,任何一处代码都可以直接get到这个sysParams。 之后的两句代码是建立一个

       

       WebApplicationCotext,自然就是Spring的东西了,意思很明显,注解配置化的WebApplication环境,这个环境的配置在哪? 就是ApplicationContext.class,将它注册到上面的环境中。最后一句servletContext.addListener,就是以往配置的

 

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
 

 

      用以启动Spring。当然servletContext其实就是application, 它可以add servlet, listener, filter, servlet param, 也就是说,可以做任何 web.xml的配置。不过其实我们要写这些类时,直接去实现 WebApplicationInitializer 并在里面写了onStartup方法就行,同样会在服务器启动时就被执行,关于这点,之前的无博文也有说明。

     

       下面将关注点放在上面提到的配置类ApplicationContext.class,笔者将它命名如此,正是为了展示它就是以往的applicationContext.xml。

 

package com.gxino.webmodel.util;

import java.util.Properties;

import javax.annotation.Resource;
import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSource;
import org.hibernate.SessionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.hibernate3.HibernateInterceptor;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;

import com.gxino.webmodel.entity.AccountEntity;
import com.gxino.webmodel.entity.ActionLogEntity;

@Configuration
@ComponentScan("com.xxxx.webmodel")
public class ApplicationContext {
	private SessionFactory sessionFactory;
	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}
	@Resource
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	@Bean(destroyMethod = "close")
	public DataSource dbcpDataSource() {

		Properties parameters = WebConfiguration.getSysParams();
		BasicDataSource basicDS = new BasicDataSource();
		basicDS.setDriverClassName(parameters.getProperty("jdbc.driver",
				"oracle.jdbc.OracleDriver"));
		basicDS.setUrl(parameters.getProperty("jdbc.url",
				"jdbc:oracle:thin:@localhost:1521:xe"));
		basicDS.setUsername(parameters.getProperty("jdbc.username", "system"));
		basicDS.setPassword(parameters.getProperty("jdbc.password",
				"oraclesystem"));
		basicDS.setMaxIdle(1000);

		basicDS.setMinIdle(4);
		basicDS.setMaxActive(8);
		basicDS.setInitialSize(3);
		basicDS.setMaxWait(10000);
		return basicDS;
	}

	@Configuration
	static class SessionFactoryConfig {
		@Resource
		private DataSource ds;

		public DataSource getDs() {
			return ds;
		}

		public void setDs(DataSource ds) {
			this.ds = ds;
		}

		@Bean
		public LocalSessionFactoryBean sessionFactory() {

			LocalSessionFactoryBean asfBean = new LocalSessionFactoryBean();
			asfBean.setDataSource(this.getDs());
			Properties parameters = WebConfiguration.getSysParams();
			Properties prop = new Properties();
			prop.setProperty("hibernate.dialect", parameters.getProperty(
					"hibernate.dialect", "org.hibernate.dialect.OracleDialect"));
			prop.setProperty("hibernate.connection.autocommit", parameters
					.getProperty("hibernate.connection.autocommit", "false"));
			prop.setProperty("hibernate.show_sql",
					parameters.getProperty("hibernate.show_sql", "true"));
			prop.setProperty("hibernate.hbm2ddl.auto",
					parameters.getProperty("hibernate.hbm2ddl.auto", "update"));
			asfBean.setHibernateProperties(prop);

			@SuppressWarnings("rawtypes")
			Class[] entities = new Class[2];
			entities[0] = AccountEntity.class;
			entities[1] = ActionLogEntity.class;
			asfBean.setAnnotatedClasses(entities);
			return asfBean;
		}
	}

	@Bean
	public HibernateTransactionManager hibernateTransactionManager() {
		HibernateTransactionManager hiberTransMana = new HibernateTransactionManager();
		hiberTransMana.setSessionFactory(this.getSessionFactory());
		return hiberTransMana;
	}

	@Bean
	public HibernateInterceptor hibernateInterceptor() {
		HibernateInterceptor hiberInter = new HibernateInterceptor();
		hiberInter.setSessionFactory(this.getSessionFactory());
		return hiberInter;
	}

	@Bean
	public HibernateTemplate hibernateTemplate() {
		HibernateTemplate hiberTempl = new HibernateTemplate();
		hiberTempl.setSessionFactory(this.getSessionFactory());
		return hiberTempl;
	}

}
 

 

好,一点一点理解这个ApplicationContext的代码.

       

         首先,applicationContex.xml是<beans>包裹着的各种<bean>, 这里被@Configuration注解的一个class ApplicationContext总体就可以看作是<beans>, 其实@Configuration本身就是个bean, 去看它的代码就知道,它被@Component注解,我们可以理解它为 配置bean。然后这个ApplicationContext中有很多被@Bean注解的方法,就是在这个配置bean中配置的Bean以供程序注入使用。这些方法的返回值是bean的class类型,方法名是bean的name, 即我们xml中配置的<bean class=”” name=””>, 在方法体中,对该bean进行配置。为下文的方便理解,总结一点,配置bean的格式为: @Configuration注解的类称为 配置bean类型,其中有很多@Bean注解的方法,用这些方法中的代码配置中一个类实例以供注入准备。

         

        继续,应该看到该类里还有@Configuration注解的静态类,格式如同类ApplicationContext, 再啰嗦一遍:@Configuration注解的配置类中有一或多个@Bean注解的方法。 这是干什么用的?想象一下我们在xml中配置这个SesstionFactory, 需要用到一个ref将配置好的dataSource 注入进来,那么到了代码的方式怎么办?其实再熟悉不过了,定义一个类注册为Spring的bean类型,并用声明一个类成员变量,用@Resource将它注入进来。 OK, 到这儿有两个问题,这个内置的配置bean为什么是静态的?还有没有别的方法去配这种需要ref其它bean的bean?留给读者思考一下。

 

         总结一句话, 其实体会一下就会理解,@Configuration注解的class是一种配置bean的声明, 将会被Spring代理实例化作为特殊的bean去用,@bean注解的方法中,我们会去实例化一个类,并返回出来,很大的可能Spring会用BeanType bean ={调用@Bean注解的会返回BeanType实例的方法} 的形式来生成一个bean实例, 然后用一个诸如Map等方式储存这个bean到它的Context中,以便注入到其它bean中。

 

        别忘记看@ComponentScan("com.xxxxx.webmodel"), 它的意思是寻找类路径为com.xxx.webmodel的bean类的声明,类似于<context:component-scan base-package="com.foo.bar"/>(这个需要xml命名空间) 。即是说寻找我们自定义的bean类型,那么我们需要用@Component及其子注解类型如@Controller,@Service, @Repository注解一些com.xxxx.webmodel为类路径开头的类来让spring找到并代理生成bean实例。也就是用Spring的主旨,让它来托管我们的业务类实例。

第一篇就分享到这里。

 

分享到:
评论

相关推荐

    java和ssh注解

    Java和SSH(Struts、Spring、Hibernate)是Java Web开发中的三大框架,它们共同构建了企业级应用的基础架构。在这些技术中,注解(Annotation)的使用日益普及,极大地简化了配置工作,增强了代码的可读性和维护性。...

    Spring全注解project示例 (无web.xml配置)

    标题 "Spring全注解project示例 (无web.xml配置)" 提供了我们即将探讨的核心主题:一个使用Spring框架,完全依赖注解配置的项目,且没有传统的web.xml部署描述符。这种配置方式在现代Spring应用中非常常见,因为它...

    The Java Web Services Tutorial

    7. **服务部署**:在Java Web应用服务器如Tomcat、Jetty或GlassFish中,可以通过部署一个包含Web服务实现的WAR(Web Application Archive)文件来发布Web服务。 8. **服务测试**:开发者可以使用`cURL`命令行工具...

    零基础学Java Web开发

    Spring提供了灵活的配置方式,支持XML和注解两种配置方式,极大地简化了Java Web应用的开发和维护工作。 #### 四、Java Web开发实战 - **4.1 基于JSP的视频点播系统** 通过实例项目,深入理解如何利用JSP、...

    Java Web项目的完整案例概述和Spring boot部分代码示例.zip

    4. **Spring Boot应用结构**:一个典型的Spring Boot项目通常包含src/main/java下的主程序类,定义了@SpringBootApplication注解以启动Spring Boot应用。src/main/resources下有application.properties或application...

    基于SpringMVC+MyBatis+tomcat+mysql的java web开发环境Demo.zip

    在Java Web开发中,SpringMVC、MyBatis和MySQL是三个非常重要的组件,它们共同构建了一个高效、灵活且易于维护的开发环境。Tomcat作为轻量级的应用服务器,是运行Java Web应用的常用选择。下面我们将深入探讨这些...

    Dropwizard是一种制作快速Java web应用程序

    Dropwizard是Java开发者用于构建高性能、 RESTful web服务的一个高效工具集。它将一系列成熟的开源库集成在一起,为开发人员提供了一个简洁、高效的框架,帮助他们迅速构建出稳定且可维护的服务。Dropwizard的核心...

    IBM WebSphere Application Server V7.0 Web Services Guide

    它引入了一系列注解和配置选项,使得开发者无需编写大量的 XML 配置文件即可完成 Web 服务的创建和部署。 - **Web Services Interoperability (WS-I)**:WS-I 是一个由行业领导者组成的组织,致力于提高 Web 服务的...

    自己写的jsp web架构

    【标题】"自己写的jsp web架构"涉及到的核心技术是基于JavaServer Pages(JSP)的Web应用程序开发。JSP是一种动态网页技术,它允许开发者在HTML页面中嵌入Java代码,以便于创建交互式的Web应用。JSP的核心概念包括:...

    java web 主流框架整合开发spring例子

    - `src/main/resources`:存储配置文件,如application.properties或application.yml,以及数据库的JPA实体映射文件(如ORM的XML或注解)。 - `src/main/webapp/WEB-INF`:Web应用的配置文件,如web.xml(如果使用...

    基于java web技术的毕业设计商城项目.zip

    总的来说,这个项目提供了Java Web开发的实战案例,涵盖了SSM和SpringBoot的核心概念,对于学习和理解Web应用的架构设计、数据库操作以及前后端交互有极大的帮助。通过深入研究和实践,学生可以提升自己的编程技能,...

    spring无web.xml的jdbctemplate配置

    在Spring框架中,传统的Web应用通常会依赖于`web.xml`来配置ApplicationContext,但随着Spring的发展,特别是Spring 3.0引入的JavaConfig配置方式,我们不再需要`web.xml`来初始化Spring容器。本篇文章将深入探讨...

    基于SpringBoot的rest web基础脚手架,实现java工程快速开发.zip

    基于SpringBoot创建的RESTful Web服务是现代Web应用的常见架构模式,能够高效地构建可交互的API,为分布式系统提供数据通信。本项目提供了一个基础的脚手架,旨在帮助开发者快速启动基于SpringBoot的RESTful Web服务...

    java-ssm简单示例配置项目

    Java SSM(Spring、Spring MVC、MyBatis)是一个经典的Java web开发框架组合,用于构建高效、可维护的Web应用程序。这个"java_ssm简单示例配置项目"应该是为了演示如何将这三个组件集成并配置到一个项目中。下面,...

    Spring MVC 使用注解的示例讲解

    Spring MVC 是一款强大的Java Web开发框架,由Spring Software Foundation维护,它简化了构建基于模型-视图-控制器(MVC)架构的Web应用程序的过程。在本示例中,我们将深入探讨如何利用注解来增强Spring MVC的功能...

    java代码生成器(mysql版)

    Java代码生成器(MySQL版)是一种实用工具,主要用于自动化Java编程过程中常见的数据库操作代码的编写。这个工具专门针对MySQL数据库,能够根据数据库中的表结构自动生成对应的Java实体类、DAO接口、Service接口及其...

    基于SpringBoot的Web框架(附各种注释)

    在配置文件(`application.properties`或`application.yml`)中,你可以定义各种属性,这些属性可以通过`@Value`注解注入到类中,或者通过`@ConfigurationProperties`注解绑定到一个复杂的Java对象。 除此之外,...

    如何使用Java Spring Boot执行RAG架构GenAI项目的示例.zip

    在本示例中,我们将探讨如何使用Java Spring Boot框架来实现一个基于RAG(Red-Amber-Green)架构的GenAI项目。RAG是一种广泛应用于项目管理、风险评估和KPI跟踪的颜色编码系统,其中Red代表高风险或问题,Amber表示...

Global site tag (gtag.js) - Google Analytics