最反主流的行动不是抵制潮流,而是在潮流中不丢弃自己的独立思考.
大家好,我是Ron,苦逼程序员一枚,最近这段时间,经过深深的思考(我的天,感觉好装逼),我突然间发现,做程序员(不知道是说程序员还是工程师好,好纠结)已经有三个年头多一点点了,回首过去,突然发现以前的很多东西都已经离我渐行渐远,很多以前了如指掌,信手拈来的东西都已经和我似曾陌路,所以,从今天开始,我决定好好学习,天天向上。
各位IT界的同仁们如果看了上面这一段忍不住想打人,那就忽略吧,因为我实在是不知道该如何开头,好了,头终于是开了,那我们进入正题吧。
接下来我将通过一个Blog系统的实战,将所忘却的以前的内容重新拾掇起来,同时增加一些最近工作中所使用到的目前市面上为大家所熟知的技术,在自己学习实践的同时和大家一起分享,这将是一个很漫长的过程,我将会从一个简单的系统慢慢开始说起,然后一步一步演进,引导大家慢慢一步步学习(当然我也是在学习)。
我们刚开始先使用Spring,Spring MVC,Mybatis,结合shiro搭建一个小型Blog系统,然后慢慢引入Redis、Zookeeper、Dubbo、Nginx、Activemq、solr, Elasticsearch等技术,让大家能够轻身体会一个系统慢慢变化和成长的过程,从中学习相关技术,那么咱们就开始吧。
Blog系统系统结构介绍
对于刚开始呢,我们的先把Blog系统分成7个模块,将系统应用层、服务层、接口、实体、数据访问层分开,方便我们后续的拓展,模块的划分方法大致如下:
1) 第一个模块时blog模块,此模块是所有其他模块的父项目,该模块主要用于配置系统所使用的相关jar包的版本以及相关参数,便于系统中统一参数的管理。
2)其余6个模块分别是blog_common模块、blog_dao模块,blog_domain模块,blog_facade模块,blog_service模块、blog_pc模块;
blog_common : 主要实现其他所有模块可共同使用的工具类;
blog_dao : 系统数据访问层;
blog_domain : 系统实体层;
blog_facade : 系统接口层;
blog_service : 系统服务层;
blog_pc : PC端网站,系统应用层;
系统研发,IDE我们使用Eclipse,使用Maven作为系统的构建工具。
接下来我们通过以上所叙述的系统结构,开始搭建基础架构;
1、新建Maven项目blog,选择quikstart.
项目中
groupId:ron.blog
artifactId : blog
新建完成之后,删除项目中所有的文件,只留下pom.xml文件
1.1 配置blog的pom.xml
打开pom.xml文件,因为我们的blog项目主要是用于配置系统所使用的相关jar包的版本以及相关参数和系统其它模块所使用的公共包,所以此项目的packaging设置为pom。pom.xml的具体配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>ron.blog</groupId>
<artifactId>blog</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>blog</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- spring 版本-->
<spring.version>4.3.5.RELEASE</spring.version>
<!-- jdk 版本-->
<jdk.version>1.8</jdk.version>
<!-- jstl 版本 在jsp中使用jstl会使用-->
<jstl.version>1.2</jstl.version>
<!-- junit 版本 单元测试使用-->
<junit.version>3.8.1</junit.version>
<slf4j.version>1.7.21</slf4j.version>
<servlet_version>3.1.0</servlet_version>
</properties>
<!-- 系统模块,这一部分可以不用配置,新建模块时可以自动产生 -->
<modules>
<module>blog_domain</module>
<module>blog_dao</module>
<module>blog_service</module>
<module>blog_pc</module>
<module>blog_facade</module>
<module>blog_common</module>
</modules>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- Spring 依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- LOGGING begin -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- common-logging 实际调用slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- java.util.logging 实际调用slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- LOGGING end -->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>jdk-1.8</id>
<activation>
<jdk>${jdk.version}</jdk>
</activation>
<properties>
<maven.compiler.source>${jdk.version}</maven.compiler.source>
<maven.compiler.target>${jdk.version}</maven.compiler.target>
<maven.compiler.compilerVersion>${jdk.version}</maven.compiler.compilerVersion>
</properties>
</profile>
</profiles>
</project>
2、新建Maven模块blog_common,选择quikstart.
Parent Project选择第一步所创建的blog项目
新建完成之后,配置pom.xml
将packaging设置成jar,删除groupId和version(因为这些继承父工程),保存即可。
3、新建Maven模块blog_domain,选择quikstart.
blog_domain模块新建同上,这里不赘述。
4、新建Maven模块blog_dao,选择quikstart.
blog_dao模块新建同2,但是需要注意的是,dao依赖blog_domain,所以在pom.xml文件中配置时,需要加入如下依赖:
<!--依赖blog-domain模块-->
<dependency>
<groupId>ron.blog</groupId>
<artifactId>blog_domain</artifactId>
<version>${project.version}</version>
</dependency>
5、新建Maven模块blog_facade,选择quikstart.
blog_facade模块新建同2,facade依赖domain和common,所以pom.xml文件配置时,需要加入如下依赖:
<!--依赖blog-domain模块-->
<dependency>
<groupId>ron.blog</groupId>
<artifactId>blog_domain</artifactId>
<version>${project.version}</version>
</dependency>
<!--依赖blog-common模块-->
<dependency>
<groupId>ron.blog</groupId>
<artifactId>blog_common</artifactId>
<version>${project.version}</version>
</dependency>
6、新建Maven模块blog_service,选择quikstart.
blog_service模块新建同2,service依赖blog_dao、blog_facade,虽然该模块也依赖blog_domain,但是由于我们blog_dao已经依赖了blog_domain,所以我们在此模块就不用再配置依赖了。
除了依赖项目的模块之外,此模块还依赖spring-context、spring-orm,spring-beans这些必要模块,所以要遭pom.xml文件中增加如下依赖:
<!--依赖blog-dao模块 -->
<dependency>
<groupId>ron.blog</groupId>
<artifactId>blog_dao</artifactId>
<version>${project.version}</version>
</dependency>
<!--依赖blog-facade模块 -->
<dependency>
<groupId>ron.blog</groupId>
<artifactId>blog_facade</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Spring 依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
7、新建Maven模块blog_pc,选择webapp
在我们的blog_pc中,对项目模块的依赖只依赖blog_service就行了,同时spring web项目,需要配置servlet、spring-context、spring-web、spring-webmvc、spring-orm、spring-beans、jstl的依赖,所以在pom.xml需要添加如下依赖:
<!-- 添加对Service的依赖 -->
<dependency>
<groupId>ron.blog</groupId>
<artifactId>blog_service</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Javax 依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet_version}</version>
</dependency>
<!-- Spring 依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- jstl依赖 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
到目前为止,我们系统模块基本已经建立完毕,相关依赖已经基本配置完成,那么接下来我们就需要配置我们的web项目并运行一个示例。
8、web.xml配置
Spring上下文加载器监听器(ContextLoaderListener)配置如下:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/spring-context*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Spring上下文加载器监听器(ContextLoaderListener)配置时必须配置contextConfigLocation,因为从ContextLoaderListener类的源码中我们可以看到,该类继承了ContextLoader,而ContextLoader类中定义了一个不可变参数CONFIG_LOCATION_PARAM:
public static final String CONFIG_LOCATION_PARAM = "contextConfigLocation";
该参数在初始化web应用程序上下文时用于指定在配置或者刷新web应用程序上下文时获取初始化配置参数。
Servlet配置如下:
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<description></description>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/spring-mvc*.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
DispatcherServlet是前端控制器设计模式的实现,提供Spring Web MVC的集中访问点,而且负责职责的分派,而且与Spring IoC容器无缝集成,从而可以获得Spring的所有好处。
init-param:前端控制器初始化参数。默认情况下,DispatcherServlet使用WebApplicationContext作为上下文,Spring默认配置文件为“/WEB-INF/[servlet名字]-servlet.xml”,但是在我们的系统中,我们将上下文的配置文件放在resources目录下,同时我们将配置文件命名为spring-mvc.xml;在我们的配置内容中,我们使用了通配符,在resources目录下,所有以spring-mvc开头的xml文件,都是我们上下文初始化参数。
load-on-startup:表示启动容器时初始化该Servlet;
默认首页和Session配置:
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
9、spring-mvc.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<mvc:annotation-driven />
<context:component-scan base-package="ron.blog"/>
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:viewClass="org.springframework.web.servlet.view.JstlView"
p:prefix="/WEB-INF/views/" p:suffix=".jsp" />
</beans>
配置说明:
mvc:annotation-driven:该配置注册了RequestMappingHandlerMapping、RequestMappingHandlerAdapter和ExceptionHandlerExceptionResolver,支持使用了类似@RequestMapping、@ExceptionHandler和其他注解的控制器方法处理请求。
同时通过该配置,同时也启动了如下的一些功能:
1、除了用于数据绑定的JavaBeans PropertyEditors之外,还可以通过ConversionService实例进行Spring的3种类型转换。
2、通过ConversionService使用@NumberFormat注解可支持格式化数字字段。
3、 使用@DateTimeFormat注解可支持格式化Date, Calendar, Long, 和Joda Time类型字段
4、如果JSR-303在classpath中被提供,那么也支持使用@Valid注解来验证@Controller的输入内容。
5、HttpMessageConverter支持@RequestBody注解的方法参数和支持使用@ResponseBody注解从被@RequestMapping或@ExceptionHandler注解的方法返回值。
项目结构如下图: