用一个示例来说话

本文是《轻量级 Java Web 框架架构设计》的系列博文。

前面谈到了一些框架的实现原理,现在是时候用一把这个框架了。对了,此框架现命名为 Smart Framework。我希望它和您想象得一样 Smart!

开始行动吧!

打开你心爱的代码编辑器(我用的是 IDEA)。使用 Maven 创建一个 Web 项目,初始代码目录如下:

用一个示例来说话

包名是 com.smart.sample,这个倒无所谓了。需要注意的是,我将 WEB-INF 下的 web.xml 文件给删掉了!

没有 web.xml 还是 Web 应用吗?是的!这是基于 Servlet 3.0 的规范,web.xml 可以不要了,统一采用注解的方式来编写 Servlet。现在我们还需要编写 Servlet 吗?不需要了,因为我们已经有 Smart 了。

简单看看 Maven 配置文件 pom.xml 吧:

<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>com.smart</groupId>
    <artifactId>smart-sample</artifactId>
    <version>1.0</version>
    <packaging>war</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!-- JUnit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>

        <!-- Smart -->
        <dependency>
            <groupId>com.smart</groupId>
            <artifactId>smart-framework</artifactId>
            <version>1.0</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>smart-sample</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
就依赖于两个包,JUnit 是为了做单元测试用的,另外一个就是 Smart 了。需要注意的是,由于没有 web.xml 会导致 Maven 执行 package 时报错,需要手工配置 maven-war-plugin 插件,将 failOnMissingWebXml 设置为 false。

好了,代码框架搭建完毕,下面我们不妨来做一下数据库设计吧。我用的是 MySQL 数据库,客户端是 Navicat。

先就搞一张很简单的表 product,表结构如下:

用一个示例来说话

再手工录一点数据吧,后面测试的时候也好有个效果,表数据如下图:

用一个示例来说话

一般定义数据库表结构都是有团队中水平比较高的人,比如:架构师或 DBA 来负责的,我们程序员拿到的就是一份数据库脚本,甚至是一个数据库连接,在好的情况下,我们还可以拿到一份数据字典(Excel 格式的最爽了)。

下面才是我们程序员要干的活了,根据表结构创建实体(Entity)。既然表名是 product,为了好理解,不妨将实体名定义为 Product。其实无需这样,假如表名是 abc,实体名也可以定义成 Product。不过最好在团队内部有相应的开发规范作为约束。

废话少说,先来一个 Product 实体:

public class Product extends BaseEntity {

    private long productTypeId;

    private String productName;

    private String productCode;

    private int price;

    private String description;

    public long getProductTypeId() {
        return productTypeId;
    }

    public void setProductTypeId(long productTypeId) {
        this.productTypeId = productTypeId;
    }

...
}

Product 类继承于 BaseEntity,那么它就是一个 Entity 了,无需任何注解,但字段名命名一定要按照规范,例如:字段 productTypeId 对应列名 product_type_id。下面的 getter/setter 方法太多,我就省略了。

实体有了,现在我们来做一个接口吧,就定义一个方法好了。根据 Product ID 获取 Product 对象,这类代码应该每个程序员都写过吧?

public interface ProductService {

    Product getProduct(long productId);
}

接口定义好了,直接写实现类吧:

@Bean
public class ProductServiceImpl extends BaseService implements ProductService {

    @Override
    public Product getProduct(long productId) {
        String sql = SQLHelper.getSQL("select.product.id");
        return DBHelper.queryBean(Product.class, sql, productId);
    }
}

是不是很简洁?有四件事情需要注意:

1. 在实现类上标注 @Bean 注解,这样它就交给 Bean 容器管理了(类似于 Spring 的 @Component)。

2. 扩展 BaseService 类(这个类有什么作用,以后再说)。

3. 使用 SQLHelper 获取 SQL 语句(实际上就是一个 SQL 语句模板,里面是带有“?”占位符的)。

4. 使用 DBHelper 执行数据库操作,该方法直接返回 JavaBean(将来也会返回 Map,以后会实现的)。

关于 SQL 语句,需要统一编写在 sql.properties 文件中:

select.product.id = select * from product where id = ?

好了,实现类开发完毕。下面就轮到 Action 上场了:

@Bean
public class ProductAction extends BaseAction {

    @Inject
    private ProductService productService;

    @Request("GET:/product/{id}")
    public Result getProductById(long productId) {
        if (productId == 0) {
            return new Result(ERROR_PARAM);
        }
        Product product = productService.getProduct(productId);
        if (product != null) {
            return new Result(OK, product);
        } else {
            return new Result(ERROR_DATA);
        }
    }
}

这里同样有四件事情需要注意:

1. Action 同样也使用了 @Bean 注解,也就是说,将 Action 交给依赖注入容器(或称为 Bean 容器)进行管理,由容器来为我们创建实例。

2. 这里还通过 @Inject 注解注入了一个 ProductService 接口,实现类到底是什么?Smart Framework 会为我们寻找。

3. 使用 @Request 注解,将请求 URL 与 Action 方法进行映射(是不是比 Spring MVC 的注解要来得简单呢?)。注意:URL 中占位符的顺序,一定要与方法中参数的顺序保持一致,数量上也要相等,否则无法正确匹配。

4. Action 的返回值统一使用 Result 对象,这个类封装了错误代码(int error)与返回数据(Object data)。在 Result 中使用了一些常量类,例如:ERROR_PARAM,这些常量都在 BaseAction 中定义好了。

后端到目前为止,已全部开发完毕,开启您的 Tomcat 吧。

用一个示例来说话

没有报错,那就打开您的浏览器,输入一个请求看看效果,请求:http://localhost:18080/product/1

用一个示例来说话

结果成功返回了!

为了看清整个代码目录结构,有必要贴一张图:

用一个示例来说话

总结一下,程序要做的只有四件事情:

1. 编写 Entity,例如:Product。

2. 编写接口及其实现类,例如:ProductService 与 ProductServiceImpl。

3. 编写 SQL 语句,统一写在 sql.properties 文件中。

4. 编写 Action,例如:ProductAction。

最后,还有一份配置文件 config.properties,它一般不需要频繁修改,有关 JDBC 连接属性都在里面,我就不贴出来了。

由于个人水品有限,或许会存在不少错误,期待您的留言!

你可能感兴趣的:(用一个示例来说话)