OK,前面的博客我们已经搭好了linkinFrame的项目结构,现在我们这里添加一个简单的web应用,在编写此web应用的过程中我们来一步一步的搭好自己的框架。
现在开始,这里举一个例子,一个客户的CRUD。
1,首先数据创建一个Customer表,主键设置自增,然后再往里面添加2条记录。建表语句如下:
CREATE TABLE `customer` ( `customer_id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `telephone` varchar(255) DEFAULT NULL, `email` varchar(255) DEFAULT NULL, `remark` varchar(255) DEFAULT NULL, PRIMARY KEY (`customer_id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
插入数据sql如下:
INSERT INTO `linkinframe`.`customer` (`name`, `telephone`, `email`) VALUES ('关羽', '15158117451', 'guanyu@qq.com'); INSERT INTO `linkinframe`.`customer` (`name`, `telephone`, `email`) VALUES ('张飞', '15158117452', 'zhangfei@qq.com');
2,编写Java代码,new一个客户的实体bean。代码如下:
package linkinframe.model; import java.io.Serializable; /** * @创建作者: LinkinPark * @创建时间: 2016年2月22日 * @功能描述: 客户类 */ public class Customer implements Serializable { private Long customerId; // 主键 private String name; // 名字 private String telephone; // 手机号 private String email; // 邮箱 private String remark; // 备注 public Long getCustomerId() { return customerId; } public Customer setCustomerId(Long customerId) { this.customerId = customerId; return this; } public String getName() { return name; } public Customer setName(String name) { this.name = name; return this; } public String getTelephone() { return telephone; } public Customer setTelephone(String telephone) { this.telephone = telephone; return this; } public String getEmail() { return email; } public Customer setEmail(String email) { this.email = email; return this; } public String getRemark() { return remark; } public Customer setRemark(String remark) { this.remark = remark; return this; } }
3,编码控制器。
控制器是一堆堆servlet,每个servlet分别实现一个业务操作。PS,好久没写这么原始的servlet,真心觉得写这么多servlet有点多余。
OK,我们写servlet吧,分别是:
CustomerCreateServlet,
CustomerDeleteServlet
,
CustomerEditServlet
,
CustomerServlet
,
CustomerShowServlet。
上面的每个servlet继承httpservlet类,然后重写里面的doGet和doPost方法。具体的里面的内容我们标记TODO,之后再一起补充代码。这里以
CustomerServlet为例,贴出代码:
package linkinframe.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class CustomerServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO } }
注意:一个servlet只有一个请求路径,但是可以处理不同的请求类型,比如get请求或者post请求。
在servlet中,请求类型有get,post,put,delete这4种,这4种请求对应doXXX(),同样这4种请求我们也是我们在框架中用到的,要处理的。
4,编写业务层。
业务层编写比较简单,先写一个接口,实现CURD的客户操作,然后写一个实现类。这里同样暂时先TODO里面的实现代码,下面贴出接口和实现类的代码:
package linkinframe.service; import java.util.List; import linkinframe.model.Customer; public interface ICustomerService { // 查询Customer列表 List<Customer> getCustomerList(); // 主键获取Customer Customer getCustomer8Id(long customerId); // 主键删除Customer boolean deleteCustomer(long customerId); // 创建Customer boolean createCustomer(Customer customer); // 修改Customer boolean updateCustomer(Customer customer); }
package linkinframe.service.impl; import java.util.List; import linkinframe.model.Customer; import linkinframe.service.ICustomerService; /** * @创建作者: LinkinPark * @创建时间: 2016年2月22日 * @功能描述: 客户业务层 */ public class CustomerService implements ICustomerService { @Override public List<Customer> getCustomerList() { return null; } @Override public Customer getCustomer8Id(long customerId) { return null; } @Override public boolean deleteCustomer(long customerId) { return false; } @Override public boolean createCustomer(Customer customer) { return false; } @Override public boolean updateCustomer(Customer customer) { return false; } }
5,编写测试
我们在实际编码中,可以使用TDD就建议尽量往测试驱动开发上靠,有测试保证对我们的代码的提示不是一点半点。具体的如果感兴趣可以去看我的TDD实战系列博客。
我们在测试结构下创建好相关的包,要和源码一样的目录结构。OK,这里我贴出对上面的业务层进行测试的测试代码:
package linkinframe.service; import java.util.List; import static org.junit.Assert.*; import org.junit.Before; import org.junit.Test; import linkinframe.model.Customer; import linkinframe.service.impl.CustomerService; /** * @创建作者: LinkinPark * @创建时间: 2016年2月22日 * @功能描述: 客户业务层测试类 */ public class CustomerServiceTest { private ICustomerService customerService; @Before public void setUp() { this.customerService = new CustomerService(); } @Test public void testGetCustomerList() { List<Customer> customerList = customerService.getCustomerList(); assertEquals(2, customerList.size()); } @Test public void testGetCustomer8Id() { Customer customer8Id = customerService.getCustomer8Id(1); assertNotNull("主键查找客户不能为空!", customer8Id); } @Test public void testDeleteCustomer() { boolean deleteCustomer = customerService.deleteCustomer(1); assertTrue("主键删除客户失败!", deleteCustomer); } @Test public void testCreateCustomer() { Customer customer = new Customer(); customer.setName("典韦").setTelephone("15158117453").setEmail("dianwei@qq.com").setRemark("测试类添加!"); boolean createCustomer = customerService.createCustomer(customer); assertTrue("添加客户失败!", createCustomer); } @Test public void testUpdateCustomer() { Customer customer8Id = customerService.getCustomer8Id(1).setName("关羽1"); boolean updateCustomer = customerService.updateCustomer(customer8Id); assertTrue("修改客户失败!", updateCustomer); } }当然现在我们的测试类一跑肯定都是异常,别慌,如果测试类执行没有问题,起码的我们的业务代码也就写的差不多了呢。这里我没有测试异常相关情况,这会在后面补充起来的。
6,最后一步,我们来写视图层。
同样的,我们也要建立多个客户CRUD的jsp。这里以customerCreate.jsp为例,贴出视图层代码。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>客户管理--> 创建客户</title> </head> <body> <h1>创建客户界面</h1> <%--TODO --%> </body> </html>注意:我们在写web项目的时候,推荐将用户登录,注册,错误页面等放入WEB-INF外面,这样子不需要经过控制器处理也可以直接访问,
但是涉及业务代码的页面,应该放到WEB-INF内部,这样子用户就无法通过浏览器地址栏来直接请求该jsp了,必须经过我们自己写的空分支器来转发或者重定向。
OK,我们根据了一个具体的业务场景,搭建了一个完整的“客户管理”模块的代码框架,这只是一个毛坯房一个,我们的代码中有好多的TODO,测试也没有通过,接下来一步我们将会一步一步实现自己的业务逻辑,将这个毛坯房装修成真正的房子。