成恒 chengheng@tedu.cn
怎么开发项目
- 一次只解决一个问题
- 学会拆分项目和功能
- 不要盲目下手,但是,一定要下手
1. 用户注册
1.1 创建数据库与数据表
1.1.1 创建数据库 tedu_store
登录mysql,然后:
create database tedu_store;
1.1.2 创建/设计用户的数据表 t_user
结构分析:
id int auto_increment id
username varchar(50) unique, not null 用户名
password char(32) not null 密码
gender int - 性别(1-男,0-女)
phone varchar(20) - 电话
email varchar(50) - 邮箱
created_user varchar(50) - 创建的用户(这条数据是谁创建的)
created_time datetime - 创建的时间
modified_user 同上 - 修改的用户
modified_time 同上 - 修改的时间
先应用此前创建的数据库
use tedu_store;
创建数据表的SQL语句:
CREATE TABLE t_user (
id INT AUTO_INCREMENT,
username VARCHAR(50) UNIQUE NOT NULL,
password CHAR(32) NOT NULL,
gender INT,
phone VARCHAR(20),
email VARCHAR(50),
uuid CHAR(36),
created_user VARCHAR(50),
created_time DATETIME,
modified_user VARCHAR(50),
modified_time DATETIME,
PRIMARY KEY(id)
) DEFAULT CHARSET = UTF8;
1.2 创建项目
1.2.1 创建Maven Project:
Artifact Id: cn.tedu.store
Group Id: TeduStore
1.2.2 完成项目的基本配置
1.2.2.1 解决错误
右键项目——>javaEE tools—Generate Deploymennt Descriptor Stub
####生成WEB.XML
右击maven项目,找到ProjectFacets 取消选中 Dynamic Web Module选项,点击应用,再选中Dyanmic Web Module会出现一个选项卡----点击弹出的选项卡后—输入src/main/webapp
点击OK
1.2.2.2 添加Tomcat Runtime
1.2.2.3 添加依赖
<dependencies>
<!-- spring 的依赖jar包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.9.RELEASE</version>
</dependency>
<!-- spring-jdbc的依赖jar包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.9.RELEASE</version>
</dependency>
<!-- junit测试jar包 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!-- 数据库的连接池 -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<!-- mysql数据库 -->
<dependency>
<groupId>MySQL</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.5</version>
</dependency>
<!-- mybatis-spring整合 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>
<!-- jstl -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
1.2.2.4 配置web.xml
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-*.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<filter>
<filter-name>filter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
1.2.2.5 Spring的配置文件
复制粘贴spring-mvc.xml、spring-dao.xml、spring-service.xml,检查必要的修改位置
1.2.2.6 数据库的配置文件
复制粘贴db.properties,检查必要的修改位置
1.2.2.7 MyBatis的映射模版
创建mappers文件夹,并复制粘贴1个XML文件过来,待修改
1.3 持久层
1.3.1 检查配置
检查db.properties
中的数据库名称
检查spring-dao.xml
中配置的接口文件的包名
1.3.2 创建User类
创建cn.tedu.store.entity.User
类,属性可参考数据表。
私有化所有属性,提供所有属性的SET/GET方法,添加无参数和全参数的构造方法,自动生成toString()
方法(便于测试数据),equals()
和hashCode()
可后续再添加,实现Serializable
接口,并生成序列化ID。
1.3.3 创建包和接口
创建cn.tedu.store.mapper.UserMapper
接口,并添加抽象方法:
Integer insert(User user);
1.3.4 配置XML映射
<mapper namespace="xx.xx.xx.UserMapper">
<insert id="insert" parameterType="xx.xx.xx.User"
useGeneratedKeys="true"
keyProperty="id">
INSERT INTO t_user (
username,
password,
gender,
phone,
email,
uuid,
created_user,
created_time,
modified_user,
modified_time
) VALUES (
#{username},
#{password},
#{gender},
#{phone},
#{email},
#{uuid},
#{created_user},
#{created_time},
#{modified_user},
#{modified_time}
)
</insert>
</mapper>
1.4 业务层
1.4.1 接口
创建cn.tedu.store.service.IUserService
接口,添加抽象方法:
User reg(User user);
1.4.2 实现类
创建cn.tedu.store.service.UserServiceImpl
类,使用@Service("userService")
对类注解,声明private UserMapper userMapper
成员,并使用@Autowired
注解,实现IUserService
,实现抽象方法:
public User reg(User user) {
userMapper.insert(user);
return user;
}
在业务层,关于操作的成功与否,推荐:只要能把方法顺利执行结束,就是成功,如果中途出错,则抛出异常,后续,方法的调用者(控制器层的某个方法)通过try…catch来处理。
完成后,单元测试。
关于密码
消息摘要:对Message使用哈希算法(HASH算法/散列算法)得到另一个简短的字符串
消息摘要的特点:只要摘要不同,原数据必然不同!但是,2个不同的原始数据,是有可能得到相同的摘要的,只不过,概率非常非常低!
原始密码:原文
加密后的密码:密文,就是原始密码的摘要
密钥:同“蜜月”
常用的消息摘要算法:MDx(Message Digest,MD2、MD4、MD5)和SHAx(Secure Hash Algorithm, SHA1……)
不可逆运算:例如某原文123456经过MD5摘要后得到abcxyz,则通过abcxyz不可能得到123456。
关于MD5的破解:不存在的!一些网站是通过穷举进行暴力破解的!关于科学家的破解。
在使用了Spring后,可以调用static String DigestUtils.md5DigestAsHex(byte[] bytes)
方法,将原文的byte[]
通过MD5加密为32位长度的字符串。
使用“盐”,会使得密码更加安全,盐的使用方式可以是:
md5(md5(原文) + 盐)
md5(原文 + 盐)
其它把盐混合加密的做法
有时,为了更加增强密码的安全性,甚至用随机盐,例如使用UUID.randomUUID()
获取一个唯一的UUID
值。
小经验
数据冗余并不一定有危害
并不是所有的数据冗余都是需要归避的,应该结合数据的使用频率、项目的体量等等进行综合判断,例如各表中的create_user字段,因为使用频率极低,且认定当前项目体量不会特别大,可以使用varchar进行存储,即使这样的做法会导致数据冗余,也并没有明显的危害。
统一编码
项目中如果出现乱码,唯一的原因就是编码不统一,解决方案也就只有一个:统一编码!需要统一的编码有:数据存储编码(数据库)、数据传输编码(请求、响应、连接数据库)、数据显示编码(HTML/JSP……),所以,推荐创建每一张数据表时,都在最后添加DEFAULT CHARSET=XXX。
内存溢出(leak)
什么样的对象需要close或使用类似的方法释放资源?所有连接型资源都需要!
推荐将所有连接型资源在使用完毕后都及时释放资源!
如果没有及时释放,万一出现异常,会导致程序崩,进而可能导致程序已经不会再运行,变量也没有了,而对象仍在内存中!对于连接型资料而言,JVM可能认为这个对象仍在被使用,不会清理它,但是,由于没有变量了,这个数据实际上无法被使用,所以,就会无谓的占用内存!
其实,少量的这样的现象,对于整个项目而言,可能没有明显的危害!但是,服务器端项目是比较特殊的!一来,是因为访问量可能很大,二来,是因为项目启动到关闭之间的时间可能特别久!所以,应该尽量避免每一个可能溢出的问题。
小结:能close的对象,在使用完之后,马上close!
回顾
1. 在数据库中,char和varchar的区别
2. 数据库中的数据冗余
3. Filter和Interceptor的区别
4. 常见的响应码
5. 异常
6. @Resource与@Autowired的区别
学子商城:用户(t_user)、收获地址、商品、订单(t_order)、购物……
用户数据:增删改查 -> 注册/登录/……
public class DigestTest {
public static void main(String[] args) {
System.out.println("DigestTest");
String[] passwords = {
"123456",
"123450",
"123456" };
String salt = "java"; // 密码加盐
for (int i = 0; i < passwords.length; i++) {
String md5Str =
DigestUtils.md5DigestAsHex(
passwords[i].getBytes());
md5Str = DigestUtils.md5DigestAsHex((salt + md5Str).getBytes());
System.out.println(md5Str.toUpperCase());
}
}
}
网址:http://code.tarena.com.cn/
账号:tarenacode
密码:code_2013