-
一、商城的实体
用户
订单
商品
分类
-
1-1 准备工作
-
1-1-1 数据库和表
create database store28;
use store28;
CREATE TABLE `user` (
`uid` varchar(32) NOT NULL,
`username` varchar(20) DEFAULT NULL,
`password` varchar(100) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
`email` varchar(30) DEFAULT NULL,
`telephone` varchar(20) DEFAULT NULL,
`birthday` date DEFAULT NULL,
`sex` varchar(10) DEFAULT NULL,
`state` int(11) DEFAULT NULL,
`code` varchar(64) DEFAULT NULL,
PRIMARY KEY (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
1-1-2 项目
包结构
com.itheima.web.servlet
com.itheima.web.filter
com.itheima.service ---service 的接口
com.itheima.service.impl ---service 的实现类
com.itheima.dao ---dao的接口
com.itheima.dao.impl ---dao 的实现类
com.itheima.domain
com.itheima.utils
com.itheima.constant
jar包
驱动
c3p0
dbuitls
beanutils
jstl
邮件
工具类和配置文件
datasourceutils 和 c3p0配置文件
uuidutils
uploadutils
md5uitls
mailutils
前台页面
将页面拷贝到项目中
-
二、用户模块
注册
发送邮件的方式发送激活码
激活
登录
退出
-
2-1 通用servlet设计
只定义一个Userservlet
重写doget和dopost
-
2-1-1 添加用户的时候
以前: /store/addUser
现在: /store/user?method=add
-
2-1-2 修改用户的时候
以前: /store/updateUser
现在: /store/user?method=update
-
2-1-3 在userservlet中doget方法中
Stirng m=request.getParameter("method");
if("add".equals(m)){
add(HttpServletRequest,HttpServletResponse)
}else if("update".equals(m)){
update(HttpServletRequest,HttpServletResponse)
}else if(){
}
-
2-1-4 我们可以直接重写service方法即可
在service方法中写上面的判断代码即可
但对于每个servlet都要写 重复的 判断代码——结构一样
-
2-1-5 BaseServlet extends HttpServlet{}(编写父类)
其他的servlet继承baseServlet
-
2-1-6 在baseservlet中重写service方法
1.获取请求的方法
2.找到相应的子类 父类中的this代表的是子类
Class clazz=this.getClass()
3.子类调用方法 ——所有都 if else,不能全包含,太麻烦,反射——可以获取所有方法
通过方法名称 获取一个指定的方法
Method m=clazz.getMethod(方法名,HttpServletRequest.class,HttpServletResponse.class)
方法执行
m.invoke(this,HttpServletRequest,HttpServletResponse);
-
2-1-7 完善请求转发
以前在servlet中 我们执行方法之后无非 请求转发 重定向 打印数据
请求转发 reuqest.getRequestDispatcher().forward()
继续完善我们baseservlet中service
在第3步,方法执行返回值,
现在我让所有的方法都返回一个字符串 add update
字符串代表的是请求转发的路径
若该方法不转发只需要返回一个null
String s=(String)m.invoke(this,HttpServletRequest,HttpServletResponse);
if(s!=null){
reuqest.getRequestDispatcher(s).forward(...);
}
-
2-1-8 BaseServlet实现
/**
* 通用的servlet
*/
public class BaseServlet extends HttpServlet {
@Override
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
// 1.获取子类 创建子类或者调用子类的时候 this代表的是子类对象
@SuppressWarnings("rawtypes")
Class clazz = this.getClass();
//System.out.println(this);
// 2.获取请求的方法
String m = request.getParameter("method");
if(m==null){
m="index";
}
//System.out.println(m);
// 3.获取方法对象
Method method = clazz.getMethod(m, HttpServletRequest.class, HttpServletResponse.class);
// 4.让方法执行 返回值为请求转发的路径
String s=(String) method.invoke(this, request,response);//相当于 userservlet.add(request,response)
// 5.判断s是否为空
if(s!=null){
request.getRequestDispatcher(s).forward(request, response);
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException();
}
}
public String index(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
return null;
}
}
-
三、案例1-用户注册
-
3-1 步骤实现
-
3-1-1 在index.jsp上点击 注册页面 跳转到register.jsp
<body>
<jsp:forward page="/index"></jsp:forward>
</body>
-
3-1-2 点击注册
<a href="/store/user?method=registUI"></a>
<li><a href="${pageContext.request.contextPath }/user?method=loginUI">登录</a></li> <li><a href="${pageContext.request.contextPath }/user?method=registUI">注册</a></li>
-
3-1-3 在userservlet中编写一个registUI 方法
请求转发到 register.jsp即可.
/** * 跳转到 注册页面 * @param request * @param response * @return * @throws ServletException * @throws IOException */ public String registUI(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { return "/jsp/register.jsp"; }
-
3-2 完成注册
-
3-2-1 regist
1 封装数据
设置id
设置state
设置code
2 调用service 完成注册操作
3 请求转发 /jsp/msg.jsp/** * 用户注册 * @param request * @param response * @return * @throws Exception */ public String regist(HttpServletRequest request, HttpServletResponse response) throws Exception { //1.封装数据 User user = new User(); //注册自定义转化器 ConvertUtils.register(new MyConventer(), Date.class); BeanUtils.populate(user, request.getParameterMap()); //1.1 设置用户id user.setUid(UUIDUtils.getId()); //1.2 设置激活码 user.setCode(UUIDUtils.getCode()); //1.3加密密码 user.setPassword(MD5Utils.md5(user.getPassword())); //2.调用service完成注册 UserService s=new UserServiceImpl(); s.regist(user); //3.页面请求转发 request.setAttribute("msg", "用户注册已成功,请去邮箱激活~~"); return "/jsp/msg.jsp"; }
-
3-2-2 userservice中的service
调用dao
发送激活邮件(下面补充)
-
3-2-3 userdao dao 添加一条数据
注意:封装数据的时候报了一个错误
是因为 字符串装成时间类型时出现错误
BeanUtils不支持字符串装成时间
-
3-3 解决-BeanUtils不支持字符串装成时间
自定义转化器
1.编写一个类 实现Conventer接口
2.实现方法
convert(转换成的类型,前台页面传入的字符串)
3.注册转化器 在封装数据之前注册
ConvertUtils.register(new MyConventer(), Date.class); public class MyConventer implements Converter { @Override public Object convert(Class clazz, Object value) { // class 要装成的类型 // object 页面上传入的值 //将object 转成 date SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); try { Date date = sdf.parse((String)value); return date; } catch (ParseException e) { e.printStackTrace(); } return null; } }
-
3-4 扩展-使用算法加密密码
md5加密 不对称的加密,不可逆
在数据库中可以使用 md5(字段|值)
java中api---md5utilspublic class MD5Utils { /** */ public static String md5(String plainText) { byte[] secretBytes = null; try { secretBytes = MessageDigest.getInstance("md5").digest( plainText.getBytes()); } catch (NoSuchAlgorithmException e) { throw new RuntimeException("找不到md5算法"); } String md5code = new BigInteger(1, secretBytes).toString(16); for (int i = 0; i < 32 - md5code.length(); i++) { md5code = "0" + md5code; } return md5code; } public static void main(String[] args) { System.out.println(md5("123!qwe@fs")); } }
//1.3加密密码 user.setPassword(MD5Utils.md5(user.getPassword()));
-
3-5 电子邮箱:就是在邮件服务器上开启的一块空间
服务器:提供邮件服务
协议:规定数据的格式
发送邮件的协议:smtp
接受邮件的协议:pop / pop3 imap
-
3-6 本地的服务器
-
3-6-1 邮件服务器----安装 易邮软件
设置域名 store.com
-
3-6-2 新增几个账户
普通用户
jack
tom新增一个管理员账户
service
-
3-7 收件箱安装 Foxmail 并创建用户---接受邮件的服务器为本机
-
3-8 邮件工具类
package com.itheima.utils;
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage.RecipientType;
public class MailUtils {
public static void sendMail(String email, String emailMsg)
throws AddressException, MessagingException {
// 1.创建一个程序与邮件服务器会话对象 Session
Properties props = new Properties();
//设置发送的协议
props.setProperty("mail.transport.protocol", "SMTP");
//设置发送邮件的服务器 如 smtp.126.com
props.setProperty("mail.host", "localhost");
props.setProperty("mail.smtp.auth", "true");// 指定验证为true
// 创建验证器
Authenticator auth = new Authenticator() {
public PasswordAuthentication getPasswordAuthentication() {
//设置发送人的帐号和密码
return new PasswordAuthentication("service", "123");
}
};
Session session = Session.getInstance(props, auth);
// 2.创建一个Message,它相当于是邮件内容
Message message = new MimeMessage(session);
//设置发送者
message.setFrom(new InternetAddress("service@store.com"));
//设置发送方式与接收者
message.setRecipient(RecipientType.TO, new InternetAddress(email));
//设置邮件主题
message.setSubject("用户激活");
// message.setText("这是一封激活邮件,请<a href='#'>点击</a>");
//设置邮件内容
message.setContent(emailMsg, "text/html;charset=utf-8");
// 3.创建 Transport用于将邮件发送
Transport.send(message);
}
}
-
3-9 服务器发送邮件(在 service中实现)
/**
* 用户注册
*/
@Override
public void regist(User user) throws Exception{
UserDao dao=new UserDaoImpl();
dao.add(user);
//发送邮件
//email:收件人地址
//emailMsg:邮件的内容
String emailMsg="欢迎您注册成我们的一员,<a href='http://localhost/store/user?method=active&code="+user.getCode()+"'>点此激活</a>";
MailUtils.sendMail(user.getEmail(), emailMsg);
}
-
四、案例2-用户激活
-
4-1 邮箱的连接点击
http://localhost/store/user?method=active&code=824736A172A04023A7D71A498B8F6DF1
-
4-2 需要在UserServlet编写一个active
获取激活码
调用service完成激活
页面跳转, 请求转发 jsp/msg.jsp/** * 用户激活 * @param request * @param response * @return * @throws Exception */ public String active(HttpServletRequest request, HttpServletResponse response) throws Exception { //1.获取激活码 String code = request.getParameter("code"); //2.调用service完成激活 UserService s=new UserServiceImpl(); User user=s.active(code); if(user==null){ //通过激活码没有找到用户 request.setAttribute("msg", "请重新激活"); }else{ //添加信息 request.setAttribute("msg", "激活成功"); } //3.请求转发到msg.jsp return "/jsp/msg.jsp"; }
-
4-3 userService中
active(code)
1.通过激活码获取一个用户
用户有可能为空
2.若不为空,修改用户的state 将0改成1/** * 用户激活 * @throws Exception */ @Override public User active(String code) throws Exception { UserDao dao=new UserDaoImpl(); //1.通过code获取一个用户 User user=dao.getByCode(code); //2.判断用户是否为空 if(user==null){ return null; } //3.修改用户状态 //将用户的状态设置为1 user.setState(1); dao.update(user); return user; }
/** * 通过激活码获取一个用户 */ @Override public User getByCode(String code) throws Exception { QueryRunner qr = new QueryRunner(DataSourceUtils.getDataSource()); String sql="select * from user where code = ? limit 1"; return qr.query(sql, new BeanHandler<>(User.class), code); } /** * 修改用户 */ @Override public void update(User user) throws Exception { QueryRunner qr = new QueryRunner(DataSourceUtils.getDataSource()); String sql="update user set username = ?,password = ? ,name=?,email=?,birthday = ?,state = ?,code=? where uid =? "; qr.update(sql, user.getUsername(),user.getPassword(),user.getName(),user.getEmail(),user.getBirthday(), user.getState(),null,user.getUid()); }
public interface UserDao { void add(User user) throws Exception; User getByCode(String code) throws Exception; void update(User user) throws Exception; User getByUsernameAndPwd(String username, String password) throws Exception; }
public interface UserService { void regist(User user) throws Exception; User active(String code) throws Exception; User login(String username, String password) throws Exception; }
-
五、案例3-用户登录
-
5-1 步骤分析
-
5-1-1 在index.jsp上登录连接 点击 跳转到login.jsp
可以通过userservlet进行请求转发 loginUI
<li><a href="${pageContext.request.contextPath }/user?method=registUI">注册</a></li>
/** * 跳转到登录页面 * @param request * @param response * @return * @throws ServletException * @throws IOException */ public String loginUI(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { return "/jsp/login.jsp"; }
-
5-1-2 修改页面上的form表单 action method 每个标签添加name属性
action:/store/user?method=login
<div class="col-md-5"> <div style="width:440px;border:1px solid #E7E7E7;padding:20px 0 20px 30px;border-radius:5px;margin-top:60px;background:#fff;"> <font>会员登录</font>USER LOGIN ${msg } <div> </div> <form class="form-horizontal" action="${pageContext.request.contextPath }/user?method=login" method="post"> <div class="form-group"> <label for="username" class="col-sm-2 control-label">用户名</label> <div class="col-sm-6"> <input type="text" class="form-control" id="username" placeholder="请输入用户名" name="username"> </div> </div> <div class="form-group"> <label for="inputPassword3" class="col-sm-2 control-label">密码</label> <div class="col-sm-6"> <input type="password" class="form-control" id="inputPassword3" placeholder="请输入密码" name="password"> </div> </div> <div class="form-group"> <label for="inputPassword3" class="col-sm-2 control-label">验证码</label> <div class="col-sm-3"> <input type="text" class="form-control" id="inputPassword3" placeholder="请输入验证码"> </div> <div class="col-sm-3"> <img src="${pageContext.request.contextPath}/image/captcha.jhtml"/> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <div class="checkbox"> <label> <input type="checkbox"> 自动登录 </label> <label> <input type="checkbox"> 记住用户名 </label> </div> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <input type="submit" width="100" value="登录" name="submit" border="0" style="background: url('${pageContext.request.contextPath}/images/login.gif') no-repeat scroll 0 0 rgba(0, 0, 0, 0); height:35px;width:100px;color:white;"> </div> </div> </form> </div> </div>
-
5-1-3 login操作
获取用户名和密码
调用service 获取一个user
判断用户是否为空
若为空:
若不为空
继续判断是否激活
只有激活的时候,将用户放入session中/** * 登录 * @param request * @param response * @return * @throws Exception */ public String login(HttpServletRequest request, HttpServletResponse response) throws Exception { //1.获取用户名和密码 String username=request.getParameter("username"); String password=request.getParameter("password"); password=MD5Utils.md5(password); //2.调用serive完成登录操作 返回user UserService s=new UserServiceImpl(); User user=s.login(username,password); //3.判断用户 if(user==null){ //用户名密码不匹配 request.setAttribute("msg", "用户名密码不匹配"); return "/jsp/login.jsp"; }else{ //继续判断用户的状态是否激活 if(Constant.USER_IS_ACTIVE!=user.getState()){ request.setAttribute("msg", "用户未激活"); return "/jsp/login.jsp"; } } //4.将user放入session中 重定向 request.getSession().setAttribute("user", user); response.sendRedirect(request.getContextPath()+"/");// /store return null; }
/** * 用户登录 */ @Override public User login(String username, String password) throws Exception { UserDao dao=new UserDaoImpl(); return dao.getByUsernameAndPwd(username,password); }
/** * 用户登录 */ @Override public User getByUsernameAndPwd(String username, String password) throws Exception { QueryRunner qr = new QueryRunner(DataSourceUtils.getDataSource()); String sql="select * from user where username = ? and password = ? limit 1"; return qr.query(sql, new BeanHandler<>(User.class), username,password); }
-
5-1-4 页面重定向到首页上
展示用户名 退出 我的订单
<ol class="list-inline"> <c:if test="${empty user }"> <li><a href="${pageContext.request.contextPath }/user?method=loginUI">登录</a></li> <li><a href="${pageContext.request.contextPath }/user?method=registUI">注册</a></li> </c:if> <c:if test="${not empty user }"> ${user.name }:您好 <li><a href="${pageContext.request.contextPath }/user?method=logout">退出</a></li> <li><a href="${pageContext.request.contextPath }/user?method=registUI">我的订单</a></li> </c:if> <li><a href="cart.htm">购物车</a></li> </ol>
-
六、案例4-用户退出
-
6-1 步骤分析
-
6-1-1 点击用户退出
/store/user?method=logout
<li><a href="${pageContext.request.contextPath }/user?method=logout">退出</a></li>
-
6-1-2 编写logout方法
干掉session(若有自动登录,cookie需要清空)
页面重定向public String logout(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //干掉session request.getSession().invalidate(); //重定向 response.sendRedirect(request.getContextPath()); //处理自动登录 return null; }
共有条评论 网友评论