一个web项目,先从原始需求开始分析,找出需求中涉及到的Use Case(案例),然后涉及表结构,画原型图,定义URL规范。
找出功能点,可以用一张UML的”用例图“来描绘以上用例,这样效果会更好,UML流程图可以用visio画图。
根据需求,找到核心的业务实体,创建对应的表。
建议:
表明与字段名均为小写,若多个单词可用“下划线”分割;
每张表都要有一个唯一ID主键字段
数据类型尽可能统一,不要出现太多数据类型
个人一般比较喜欢用powerdesigner,设计好表后可以直接生成sql语句。
可以使用Balsqmiq Mockups软件,这是一款比较Q的软件,可以快速地画出界面原型,感受一下画风。
(这个画风让我想起了饥荒这款游戏。。。。。)
设计出url与页面跳转及接口的对应关系
举个栗子
URL | 描述 |
GET:/customer | 进入列表查询界面 |
GET:/customer_create | 进入新增界面 |
POST:/customer_create | 新增 |
DELETE:/customer_delete/{id} | 删除 |
创建数据库编码方式统一为UTF-8,以免编码不一致导致中文乱码。
建立连接后,New Database输入Database Name和Character set,点击确定。
这里使用的工具为Navicat。
新建一个maven项目,具体步骤参照上一篇笔记。
这里不用框架,用servlet+jsp写一个mvc架构的项目。
数据库中添加表
CREATE TABLE `customer`( `id` BIGINT(20) NOT NULL AUTO_INCREMENT, `name` VARCHAR(255) DEFAULT NULL, `contact` VARCHAR(255) DEFAULT NULL, `telephone` VARCHAR(255) DEFAULT NULL, `email` VARCHAR(255) DEFAULT NULL, `remark` text, PRIMARY KEY(`id`) )ENGINE=INNODB DEFAULT CHARSET=utf8;
一个servlet只有一个请求路径,但可以处理多种不同的请求,请求类型有GET、POST、PUT、DELETE
这里因为是servlet3.0所以不用在web.xml中配置servlet及映射mapping,只需要用@WebServlet注解即可
package com.smart4j.chapter2.service;/** * Created by Administrator on 2018/8/13. */ import com.smart4j.chapter2.model.Customer; import java.util.List; import java.util.Map; /** * @program: chapter2->CustomerService * @description: 客户服务层 * @author: qiuyu * @create: 2018-08-13 20:15 **/ public class CustomerService { /** * @Description: 获取客户列表 * @Param: [] * @return: java.util.List<com.smart4j.chapter2.model.Customer> * @Author: qiuyu * @Date: 2018/8/13 */ public List<Customer> getCustomerList(String keyWord){ //TODO return null; } /** * @Description: 根据id获取客户 * @Param: [id] * @return: com.smart4j.chapter2.model.Customer * @Author: qiuyu * @Date: 2018/8/13 */ public Customer getCustomer(long id){ //todo return null; } /** * @Description: 创建客户 * @Param: [fieldMap] * @return: boolean * @Author: qiuyu * @Date: 2018/8/13 */ public boolean createCustomer(Map<String,Object> fieldMap){ //todo return false; } /** * @Description: 更新客户 * @Param: [] * @return: boolean * @Author: qiuyu * @Date: 2018/8/13 */ public boolean updateCustomer(long id,Map<String,Object> fieldMap){ //todo return false; } /** * @Description: 删除客户 * @Param: [] * @return: boolean * @Author: qiuyu * @Date: 2018/8/13 */ public boolean deleteCustomer(long id){ //todo return false; } }
首先要在pom.xml中添加依赖
<!--JUnit--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency>
编写单元测试
/** * Created by Administrator on 2018/8/13. */ import com.smart4j.chapter2.model.Customer; import com.smart4j.chapter2.service.CustomerService; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @program: chapter2->CustomerServiceText * @description: 客户测试类 * @author: qiuyu * @create: 2018-08-13 20:24 **/ public class CustomerServiceText { private final CustomerService customerService; public CustomerServiceText() { customerService = new CustomerService(); } @Before public void init(){ //初始化数据库 } @Test public void getCustomerListText(){ List<Customer> customerList =customerService.getCustomerList(""); Assert.assertEquals(2,customerList.size()); } @Test public void getCustomerTest(){ long id =1; Customer customer = customerService.getCustomer(id); Assert.assertNotNull(customer); } @Test public void createCustomerTest(){ Map<String,Object> fieldMap = new HashMap<String, Object>(); fieldMap.put("name","小猪佩琪"); fieldMap.put("contact","John"); fieldMap.put("telephone","18151449650"); boolean result = customerService.createCustomer(fieldMap); Assert.assertTrue(result); } @Test public void updateCustomerTest(){ long id =1; Map<String,Object> fieldMap = new HashMap<String,Object>(); fieldMap.put("contact","Aeolian"); boolean result = customerService.updateCustomer(id,fieldMap); Assert.assertTrue(result); } @Test public void deleteCustomer(){ long id =1; boolean result = customerService.deleteCustomer(id); Assert.assertTrue(result); } }
使用JSP充当视图层,在WEB-INF/view目录下存放所有的JSP文件。推荐将JSP放入到WEB-INF内部,因为用户无法通过浏览器地址栏直接请求放在WEB-INF内部的JSP文件,必须通过Servlet进行转发或者重定向。
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>客户管理-创建客户</title> </head> <body> <h1>创建客户界面</h1> <%--TODO--%> </body> </html>
在pom.xml中添加日志依赖
<!--slf4j--> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.77</version> </dependency>
在main/resource目录下新建一个名为log4j.properties的文件
log4j.rootLogger=ERROR,console,file
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%m%n
log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.File=${user.home}/logs/book.log
log4j.appender.file.DatePattern=‘_‘yyyyMMdd
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{HH:mm:ss,SSS} %p %c (%L) -%m %n
log4j.logger.org.smart4j=DEBUG
将日志级别设置为DEBUG,并提供了两种日志appender,分别是console与file。最后一句制定只有org.smart4j包下的类才能输出DEBUG级别的日志。
测试,这里user.home为C:\Users\Administrator
public class PropsUtil { private static final Logger LOGGER = LoggerFactory.getLogger(PropsUtil.class); public static void main(String[] args) throws IOException { /*测试日志*/ LOGGER.error("text"); } }
添加mysql依赖以及两个apache常用依赖
<!--mysql--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.33</version> <scope>runtime</scope> </dependency> <!--Apache Commons Lang--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.3.2</version> </dependency> <!--Apache Commons Collections--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-collections4</artifactId> <version>4.0</version> </dependency>
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://******:3306/demo2?characterEncoding=utf-8 jdbc.username=root jdbc.password=***密码**** jdbc.wait_timeout=600
详细链接Java开发常用Util工具类-StringUtil、CastUtil、CollectionUtil、PropsUtil
数据库操作类DBHelper.java,用于初始化数据库,打开连接,关闭连接。
package com.smart4j.chapter.util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; /** * @program: DBHelper * @description: 数据库操作类 **/ public class DBHelper { private static final Logger LOGGER = LoggerFactory.getLogger(DBHelper.class); private static final String DRIVER; private static final String URL; private static final String USERNAME; private static final String PASSWORD; /** * 静态代码块在类加载时运行 */ static{ Properties conf = PropsUtil.loadProps("config.properties"); DRIVER = conf.getProperty("jdbc.driver"); URL = conf.getProperty("jdbc.url"); USERNAME = conf.getProperty("jdbc.username"); PASSWORD = conf.getProperty("jdbc.password"); try { Class.forName(DRIVER); } catch (ClassNotFoundException e) { //e.printStackTrace(); LOGGER.error("can not load jdbc driver",e); } } /** * 获取数据库连接 * @return */ public static Connection getConnection(){ Connection conn = null; try { conn = DriverManager.getConnection(URL,USERNAME,PASSWORD); } catch (SQLException e) { e.printStackTrace(); //在catlina.out中打印 LOGGER.error("get connection failure",e); } return conn; } /** * 关闭数据库连接 * @param conn */ public static void closeConnection(Connection conn){ if (conn!=null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); LOGGER.error("close connection failure",e); } } } }
使用Apache Common项目中的DbUtils类库,pom.xml中插入依赖
<!-- Apache commons DbUtils --> <dependency> <groupId>commons-dbutils</groupId> <artifactId>commons-dbutils</artifactId> <version>1.6</version> </dependency>
然后在DBHelper类中增添以下方法。
private static final QueryRunner QUERY_RUNNER = new QueryRunner(); /** * 查询实体列表 * @param entityClass * @param sql * @param params * @param <T> * @return */ public static <T> List<T> queryEntityList(Class<T> entityClass,String sql,Object... params){ List<T> entityList; Connection conn = getConnection(); try { entityList = QUERY_RUNNER.query(conn,sql,new BeanListHandler<T>(entityClass),params); } catch (SQLException e) { //e.printStackTrace(); LOGGER.error("query entity list failure",e); throw new RuntimeException(e); } finally { closeConnection(conn); } return entityList; } /** * 查询实体 * @param entityClass * @param sql * @param params * @param <T> * @return */ public static <T> T queryEntity(Class<T> entityClass,String sql,Object... params){ T entity; Connection conn = getConnection(); try { entity=QUERY_RUNNER.query(conn,sql,new BeanHandler<T>(entityClass),params); } catch (SQLException e) { //e.printStackTrace(); LOGGER.error("query entity failure",e); throw new RuntimeException(e); } finally { closeConnection(conn); } return entity; } /** * 多表查询,其中的Map表示列明与列值的映射关系 * @param sql * @param params * @return */ public static List<Map<String,Object>> executeQuery(String sql,Object... params){ List<Map<String,Object>> result; Connection conn = getConnection(); try { result = QUERY_RUNNER.query(conn,sql,new MapListHandler(),params); } catch (SQLException e) { //e.printStackTrace(); LOGGER.error("execute query failure",e); throw new RuntimeException(e); } return result; } /** * 执行更新语句(包括update,insert,delete) * @param sql * @param params * @return */ public static int executeUpdate(String sql,Object... params){ int rows =0; Connection conn = getConnection(); try { rows = QUERY_RUNNER.update(conn,sql,params); } catch (SQLException e) { //e.printStackTrace(); LOGGER.error("execute update failure",e); throw new RuntimeException(e); } finally { closeConnection(conn); } return rows; } /** * 插入实体(根据executeUpdate方法) * @param entityClass * @param fieldMap * @param <T> * @return */ public static <T> boolean insertEntity(Class<T> entityClass,Map<String,Object> fieldMap){ if (CollectionUtil.isEmpty(fieldMap)){ LOGGER.error("can not insert entity: fieldMap is empty"); return false; } String sql = "insert into "+getTableName(entityClass); StringBuilder columns = new StringBuilder("("); StringBuilder values = new StringBuilder("("); for (String fieldName:fieldMap.keySet()){ columns.append(fieldName).append(", "); values.append("?, "); } columns.replace(columns.lastIndexOf(", "),columns.length(),")"); values.replace(values.lastIndexOf(", "),values.length(),")"); sql += columns+" VALUES" +values; Object[] params = fieldMap.values().toArray(); return executeUpdate(sql,params)==1; } /** * 修改 * @param entityClass * @param id * @param fieldMap * @param <T> * @return */ public static <T> boolean updateEntity(Class<T> entityClass,long id,Map<String,Object> fieldMap){ if (CollectionUtil.isEmpty(fieldMap)){ LOGGER.error("can not update entity: fieldMap is empty"); return false; } String sql = "update "+getTableName(entityClass) + " set "; StringBuilder columns = new StringBuilder(); for (String fieldName:fieldMap.keySet()){ columns.append(fieldName).append("=?, "); } sql+= columns.substring(0,columns.lastIndexOf(", "))+"where id=?"; List<Object> paramList = new ArrayList<Object>(); paramList.addAll(fieldMap.values()); paramList.add(id); Object[] params = paramList.toArray(); return executeUpdate(sql,params)==1; } /** * 删除 * @param entityClass * @param id * @param <T> * @return */ public static <T> boolean deleteEntity(Class<T> entityClass,long id){ String sql = "delete from "+getTableName(entityClass)+" where id =?"; return executeUpdate(sql,id)==1; } /** * 获取类名(不包含报名和后缀) * @param entityClass * @return */ private static String getTableName(Class<?> entityClass){ return entityClass.getSimpleName(); }
原文:https://www.cnblogs.com/aeolian/p/9457695.html