前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Web-第二十一天 Web商城实战一【悟空教程】

Web-第二十一天 Web商城实战一【悟空教程】

作者头像
Java帮帮
发布2018-07-27 15:03:50
8340
发布2018-07-27 15:03:50
举报

Web-第二十一天 Web商城实战一【悟空教程】

Web商城实战一

今日内容介绍

  • 用户管理:用户注册
  • 用户管理:用户激活
  • 用户管理:用户登录
  • 用户管理:用户退出
  • 用户管理:自动登录
  • 用户管理:记住用户名

今日内容学习目标

  • JavaWeb知识巩固

第1章 网络商城实战

1.1 数据库分析与设计

  • 参考:
  • 创建数据库:(完成整个项目时,我们采用需要时再创建对应的表。)

-- 创建数据库

drop database if exists `store_db`;

create database `store_db`;

-- 使用数据库

use store_db;

1.2 通用Servlet

1.2.1 分析

  • 方式1:一个路径对应一个servlet
  • 方式2:多个路径对应一个servlet,method请求参数与if语句进行分流

“方式2”的不足就是service()方法需要编写大量if语句。

  • 方式3:多个路径对应一个servlet,编写BaseServlet,使用反射执行当前运行类的指定方法
  • 方式4:完善BaseServlet,当前运行类的指定方法返回请求转发时jsp页面路径

1.2.2 实现

  • 步骤1:创建项目,并创建BaseServlet类
  • 步骤2:编写BaseServlet实现类

1. 获得请求参数method,确定具体需要执行的方法名

2. 获得当前运行类需要执行的方法Method

3. 执行当前运行类对应的方法

4. 通过方法返回值确定请求转发jsp位置

public class BaseServlet extends HttpServlet {

private static final long serialVersionUID = -3603954953627270784L;

@Override

public void service(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

try {

//1 获得请求参数method

String methodName = request.getParameter("method");

// * 默认方法名

if(methodName == null){

methodName = "execute";

}

//2 获得当前运行类,需要指定的方法

Method method = this.getClass().getMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);

//3 执行方法

String jspPath = (String) method.invoke(this, request,response);

//4 如果子类有返回值,将请求到指定的jsp页面

if(jspPath != null){

request.getRequestDispatcher(jspPath).forward(request, response);

}

} catch (Exception e) {

// 异常处理:根据不同的异常,进行不同的处理

throw new RuntimeException(e);

}

}

/**

* 默认方法,用于子类复写

*/

public String execute(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

//NOOP (NO OPeration,无操作)

return null;

}

}

  • 步骤3:测试
    • servlet实现类

public class UserServlet extends BaseServlet {

private static final long serialVersionUID = 1L;

public void findAll(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

System.out.println("findAll");

}

}

  • web.xml配置

<servlet>

<servlet-name>UserServlet</servlet-name>

<servlet-class>cn.com.javahelp.store.web.servlet.UserServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>UserServlet</servlet-name>

<url-pattern>/UserServlet</url-pattern>

</servlet-mapping>

  • 测试路径

http://localhost:8080/store_v1.0/UserServlet?method=findAll

第2章 环境搭建

2.1 目录结构

2.2 导入jar包

2.3 工具类

2.3.1 JdbcUtils

  • 配置c3p0连接池,

public class JdbcUtils{

//使用命名配置

private static ComboPooledDataSource dataSource = new ComboPooledDataSource("javahelp");

/**

* 获得数据源(连接池)

* @return

*/

public static DataSource getDataSource(){

return dataSource;

}

/**

* 获得连接

* @return

* @throws SQLException

*/

public static Connection getConnection() throws SQLException{

return dataSource.getConnection();

}

}

且以优雅过一生:杨绛传

作者:桑妮 著,博集天卷 出品

当当 广告

购买

  • 导入c3p0-config.xml配置文件

<c3p0-config>

<!-- 命名的配置 -->

<named-config name="javahelp">

<!-- 连接数据库的4项基本参数 -->

<property name="driverClass">com.mysql.jdbc.Driver</property>

<property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/store_db</property>

<property name="user">root</property>

<property name="password">1234</property>

<!-- 如果池中数据连接不够时一次增长多少个 -->

<property name="acquireIncrement">5</property>

<!-- 初始化连接数 -->

<property name="initialPoolSize">20</property>

<!-- 最小连接受 -->

<property name="minPoolSize">10</property>

<!-- 最大连接数 -->

<property name="maxPoolSize">40</property>

<!-- -JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量 -->

<property name="maxStatements">0</property>

<!-- 连接池内单个连接所拥有的最大缓存statements数 -->

<property name="maxStatementsPerConnection">5</property>

</named-config>

</c3p0-config>

2.3.2 MyBeanUtils

  • 对BeanUtils进一步封装,同时处理日期转换。
  • 方式1:传递JavaBean实例,将数据封装到实例对象中。

/**

* 将数据封装给JavaBean,支持时间类型转换

* 例如:

* User user = new User();

* MyBeanUtils.populate( user , request.getParameterMap() );

* @param bean

* @param properties

*/

public static void populate(Object bean, Map<String,String[]> properties){

try {

//1 创建BeanUtils提供时间转换器

DateConverter dateConverter = new DateConverter();

//2 设置需要转换的格式

dateConverter.setPatterns(new String[]{"yyyy-MM-dd","yyyy-MM-dd HH:mm:ss"});

//3 注册转换器

ConvertUtils.register(dateConverter, java.util.Date.class);

//4 封装数据

BeanUtils.populate(bean, properties);

} catch (Exception e) {

throw new RuntimeException(e);

}

}

  • 方式2:传递JavaBean Class类型,通过反射进行实例化,然后封装数据

/**

* 高级封装,不需要new javabean

* 例如:

* User user = MyBeanUtils.populate( User.class , request.getParameterMap() );

* @param beanClass

* @param properties

* @return

*/

public static <T> T populate(Class<T> beanClass, Map<String,String[]> properties){

try {

//1 使用反射创建实例

T bean = beanClass.newInstance();

//2.1 创建BeanUtils提供时间转换器

DateConverter dateConverter = new DateConverter();

//2.2 设置需要转换的格式

dateConverter.setPatterns(new String[]{"yyyy-MM-dd","yyyy-MM-dd HH:mm:ss"});

//2.3 注册转换器

ConvertUtils.register(dateConverter, java.util.Date.class);

//3 封装数据

BeanUtils.populate(bean, properties);

return bean;

} catch (Exception e) {

throw new RuntimeException(e);

}

}

2.3.3 UUIDUtils

public class UUIDUtils {

/**

* 获得32长度的UUID字符串

* @return

*/

public static String getUUID() {

return UUID.randomUUID().toString().replace("-", "");

}

/**

* 获得64长度的UUID字符串

* @return

*/

public static String getUUID64() {

return getUUID() + getUUID();

}

}

2.4 编码过滤器

  • 步骤1:过滤器实现类

public class EncodingFilter implements Filter {

public void init(FilterConfig fConfig) throws ServletException {

}

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)

throws IOException, ServletException {

//0 强转

HttpServletRequest request = (HttpServletRequest) req;

HttpServletResponse response = (HttpServletResponse) resp;

//1 设置编码

request.setCharacterEncoding("UTF-8");

//2 创建自定义request

MyRequest myRequest = new MyRequest(request);

//3 放行,使用自定义request

chain.doFilter(myRequest, response);

}

public void destroy() {

}

}

  • 步骤2:过滤器配置

<!-- 编码 -->

<filter>

<filter-name>EncodingFilter</filter-name>

<filter-class>cn.com.javahelp.store.web.filter.EncodingFilter</filter-class>

</filter>

<filter-mapping>

<filter-name>EncodingFilter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

  • 步骤3:自定义request实现类,对获得请求参数方法进行处理

public class MyRequest extends HttpServletRequestWrapper {

//是否已经被编码,默认false,没有被编码

private boolean encoded = false;

public MyRequest(HttpServletRequest request) {

super(request);

}

/**

* 获得指定名称的第一个参数

*/

@Override

public String getParameter(String name) {

String[] all = getParameterValues(name);

if(all == null){

return null;

}

return all[0];

}

/**

* 获得指定名称的所有参数

*/

@Override

public String[] getParameterValues(String name) {

return getParameterMap().get(name);

}

/**

* 获得所有的内容,key:指定的名称;value:指定名称对象的所有值

*/

@Override

public Map<String,String[]> getParameterMap() {

try {

//1 获得原始数据

Map<String, String[]> map = super.getParameterMap();

//2 如果是get请求,存放栏目

if(!encoded){

if ("GET".equalsIgnoreCase(super.getMethod())) {

//遍历map,并遍历数组值

for (Map.Entry<String, String[]> entry : map.entrySet()) {

String[] allValue = entry.getValue();

for (int i = 0; i < allValue.length; i++) {

String encoding = super.getCharacterEncoding();

if(encoding == null){

encoding = "UTF-8";

}

allValue[i] = new String(allValue[i].getBytes("ISO-8859-1"), encoding);

}

}

//修改标记,表示已经编码

encoded = true;

}

}

return map;

} catch (Exception e) {

throw new RuntimeException(e);

}

}

}

2.5 导入JSP页面

  • 修改index.jsp页面,使其通过servlet访问jsp
  • 步骤1:修改index.jsp

<jsp:forward page="/IndexServlet"></jsp:forward>

相当于

<jsp:forward page="/IndexServlet?method=execute"></jsp:forward>

  • 步骤2:编写servlet实现类

public class IndexServlet extends BaseServlet {

private static final long serialVersionUID = 1L;

public String execute(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

return "/jsp/index.jsp";

}

}

  • 步骤3:web.xml indexServlet配置

<servlet>

<servlet-name>IndexServlet</servlet-name>

<servlet-class>cn.com.javahelp.store.web.servlet.IndexServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>IndexServlet</servlet-name>

<url-pattern>/IndexServlet</url-pattern>

</servlet-mapping>

第3章 前台用户模块

3.1 编写流程

  • 步骤1:创建表,并初始化数据

-- 1.1 创建用户表

CREATE TABLE `user` (

`uid` varchar(32) NOT NULL,

`username` varchar(20) DEFAULT NULL, #用户名

`password` varchar(20) 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 0, #状态:0=未激活,1=已激活

`code` varchar(64) DEFAULT NULL, #激活码

PRIMARY KEY (`uid`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- 1.2 初始化用户默认数据

INSERT INTO `user` VALUES ('373eb242933b4f5ca3bd43503c34668b','ccc','ccc','aaa','bbb@store.com','15723689921','2015-11-04','男',0,'9782f3e837ff422b9aee8b6381ccf927bdd9d2ced10d48f4ba4b9f187edf7738'),('3ca76a75e4f64db2bacd0974acc7c897','bb','bb','张三','bbb@store.com','15723689921','1990-02-01','男',0,'1258e96181a9457987928954825189000bae305094a042d6bd9d2d35674684e6'),('62145f6e66ea4f5cbe7b6f6b954917d3','cc','cc','张三','bbb@store.com','15723689921','2015-11-03','男',0,'19f100aa81184c03951c4b840a725b6a98097aa1106a4a38ba1c29f1a496c231'),('c95b15a864334adab3d5bb6604c6e1fc','bbb','bbb','老王','bbb@store.com','15712344823','2000-02-01','男',0,'71a3a933353347a4bcacff699e6baa9c950a02f6b84e4f6fb8404ca06febfd6f'),('f55b7d3a352a4f0782c910b2c70f1ea4','aaa','aaa','小王','aaa@store.com','15712344823','2000-02-01','男',1,NULL);

  • 步骤2:创建JavaBean

public class User {

private String uid;

private String username;

private String password;

private String name;

private String email;

private String telephone;

private Date birthday;

private String sex;

private int state;

private String code;

  • 步骤3:编写dao接口,及实现类

/**

* 用户模块的DAO层的接口

*/

public interface UserDao {

}

/**

* 用户模块的DAO层的实现类

*/

public class UserDaoImpl implements UserDao {

}

  • 步骤4:编写service接口,及实现类

/**

* 用户模块的Service层的接口

*/

public interface UserService {

}

/**

* 用户模块的Service层的实现类

*/

public class UserServiceImpl implements UserService {

}

  • 步骤5:编写servlet(测试BaseServlet已经编写)

public class UserServlet extends BaseServlet {

private static final long serialVersionUID = 1L;

public void findAll(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

System.out.println("findAll");

}

}

<servlet>

<servlet-name>UserServlet</servlet-name>

<servlet-class>cn.com.javahelp.store.web.servlet.UserServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>UserServlet</servlet-name>

<url-pattern>/userServlet</url-pattern>

</servlet-mapping>

3.2 功能:用户注册

3.2.1 显示注册表单

  • 步骤1:修改 /store_v1.0/WebContent/jsp/index.jsp 页面

<a href="${pageContext.request.contextPath}/UserServlet?method=registUI">注册</a>

  • 步骤2:修改UserServlet,添加registUI()方法

//注册页面

public String registUI(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

return "/jsp/register.jsp";

}

3.2.2 用户注册

3.2.2.1 分析
3.2.2.2 编写步骤

1. 完善regist.jsp表单,确定表单元素有name属性

2. 在注册页面输入信息,点击注册,提交到UserServlet的regist()方法进行处理

3. servlet调用service的 regist(user)进行用户注册操作

4. service调用dao的save(user) 将用户保存到数据库。

3.2.2.3 代码实现
  • 步骤1:完善表单,确定表单元素的name属性

<form action="${pageContext.request.contextPath}/UserServlet?method=regist" method="post" …>

<input type="text" name="username" placeholder="请输入用户名">

<input type="password"name="password" placeholder="请输入密码">

<input type="password" name="confirmpwd" placeholder="请输入确认密码">

<input type="email" name="email" placeholder="Email">

<input type="text" name="name" placeholder="请输入姓名">

<input type="radio" name="sex" value="男"> 男

<input type="radio" name="sex" value="女"> 女

<input type="date" name="birthday" >

  • 步骤2:修改UserServlet,提供regist(request,response)方法

public String regist(HttpServletRequest request, HttpServletResponse response)throws Exception {

//1 获得数据并封装

User user = MyBeanUtils.populate(User.class, request.getParameterMap());

//1.1 处理服务器自动生成

user.setUid(UUIDUtils.getUUID());

user.setCode(UUIDUtils.getUUID64());//激活码

user.setState(0);//0=未激活

//2 处理

UserService userService = new UserServiceImpl();

userService.regist(user);

//3 成功提示

request.setAttribute("msg", "注册成功,请邮件激活后请登录");

//注册成功登录

return "/jsp/login.jsp";

}

  • 步骤3:修改UserService,提供regist(user)方法进行注册

//接口

/**

* 注册

* @param user

*/

void regist(User user) throws SQLException;

//实现类

@Override

public void regist(User user) throws SQLException{

//保存用户

userDao.save(user);

//发送邮件

}

  • 步骤4:修改UserDao,提供save(user)方法进行用户信息的保存。

//接口

/**

* 保存用户

* @param user

* @throws SQLException

*/

void save(User user) throws SQLException;

//实现类

public void save(User user) throws SQLException {

QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());

String sql = "insert into user(uid,username,password, name,email,telephone, birthday,sex,state, code) values (?,?,?, ?,?,?, ?,?,?, ?)";

Object[] params = { user.getUid(), user.getUsername(), user.getPassword(),

user.getName(), user.getEmail(),user.getTelephone(),

user.getBirthday(), user.getSex(), user.getState(),

user.getCode() };

queryRunner.update(sql, params);

}

  • 步骤5:修改登录 /jsp/login.jsp页面,添加提示信息

3.2.3 发送激活邮件

3.2.3.1 邮件概述
  • 邮件协议:
    • POP3协议:接收邮件服务器(邮局协议)端口110
    • SMTP协议:发送邮件服务器(简单邮件传输协议),端口25
3.2.3.2 分析
3.2.3.3 编写步骤

1. 注册用户保存到数据库后发生激活邮箱

2. 创建会话,确定连接邮箱服务器的地址

3. 编写消息,确定需要发送的内容

4. 发送消息

3.2.3.4 代码实现
  • 步骤1:确定导入mail.jar
  • 步骤2:修改service,发送邮件

@Override

public void regist(User user) throws SQLException{

//保存用户

userDao.save(user);

//发送邮件

MailUtils.sendMail(user.getEmail(), user.getCode());

}

  • 步骤3:编写MailUtils工具类发送邮件,使用外网模拟。

/**

* 外网邮件发送

* @param to

* @param code

*/

public static void sendMail(String to,String code){

// Session对象:

Properties props = new Properties();

props.setProperty("mail.host", "smtp.163.com");

props.setProperty("mail.smtp.auth", "true");

Session session = Session.getInstance(props, new Authenticator() {

@Override

public PasswordAuthentication getPasswordAuthentication() {

return new PasswordAuthentication("******@163.com", "1qaz2wsx");

}

});

// Message对象:

Message message = new MimeMessage(session);

// 设置发件人:

try {

message.setFrom(new InternetAddress("****@163.com"));

// 设置收件人:

message.addRecipient(RecipientType.TO, new InternetAddress("***@126.com"));

// 设置主题:

message.setSubject("来自购物天堂STORE的激活邮件");

// 设置内容:

String url = "http://localhost:8080/store_v1.0/UserServlet?method=active&code="+code;

message.setContent("<h1>来自购物天堂STORE的激活邮件!激活请点击以下链接!</h1><h3><a href='"+url+"'>"+url+"</a></h3>","text/html;charset=UTF-8");

// Transport对象:

Transport.send(message);

} catch (AddressException e) {

e.printStackTrace();

} catch (MessagingException e) {

e.printStackTrace();

}

}

  • 步骤4:如果不能使用外网,可以搭建本地邮件服务器(可选)

/**

* 本地邮件发送

* @param to

* @param code

*/

public static void sendMail2(String to,String code){

// Session对象:

Properties props = new Properties();

// props.setProperty("smtp.host", "localhost");

Session session = Session.getInstance(props, new Authenticator() {

@Override

protected PasswordAuthentication getPasswordAuthentication() {

return new PasswordAuthentication("service@store.com", "111");

}

});

// Message对象:

Message message = new MimeMessage(session);

// 设置发件人:

try {

message.setFrom(new InternetAddress("service@store.com"));

// 设置收件人:

message.addRecipient(RecipientType.TO, new InternetAddress(to));

// 设置主题:

message.setSubject("来自购物天堂STORE的激活邮件");

// 设置内容:

String url = "http://localhost:8080/store_v1.0/UserServlet?method=active&code="+code;

message.setContent("<h1>来自购物天堂STORE的激活邮件!激活请点击以下链接!</h1><h3><a href='"+url+"'>"+url+"</a></h3>","text/html;charset=UTF-8");

// Transport对象:

Transport.send(message);

} catch (AddressException e) {

e.printStackTrace();

} catch (MessagingException e) {

e.printStackTrace();

}

}

3.3 功能:用户激活

3.3.1 分析

3.3.2 编写步骤

1.通过FoxMail接收邮件,点击邮件内连接

2.编写UserServlet的active方法,服务器获得用户激活码,并进行激活

3.编写UserService的activeUser方法,通过激活码,激活用户

* 激活成功,将激活码制空。

* 如果激活码不可用,抛异常

3.3.3 代码实现

  • 步骤1:通过邮箱点击激活路径
  • 步骤2:修改UserServlet,添加active方法进行用户激活

//用户激活

public String active(HttpServletRequest request, HttpServletResponse response)

throws Exception {

try {

// 1 获得激活码

String code = request.getParameter("code");

//2 用户激活

UserService userService = new UserServiceImpl();

userService.activeUser(code);

//3 成功提示

request.setAttribute("msg", "激活成功,请登录");

} catch (Exception e) {

e.printStackTrace();

request.setAttribute("msg", e.getMessage());

}

return "/jsp/login.jsp";

}

  • 步骤3:修改UserService,添加activeUser ()方法

//接口

/**

* 激活用户

* @param code

*/

void activeUser(String code) throws SQLException;

//实现类

public void activeUser(String code) throws SQLException{

//1 通过激活码查询用户

User existUser = userDao.findByCode(code);

if(existUser == null){

//自定义异常

throw new RuntimeException("用户激活码无效,请重试或重新发送激活邮件");

}

//2 更新用户信息

existUser.setState(1);

existUser.setCode(null);

userDao.update(existUser);

}

  • 步骤4:修改UserDao,添加findByCode()和update() 两个方法

//接口

/**

* 通过激活码查询用户

* @param code

* @return

*/

User findByCode(String code)throws SQLException;

/**

* 更新用户信息

* @param existUser

*/

void update(User user)throws SQLException;

//实现类

@Override

public User findByCode(String code) throws SQLException {

QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());

String sql = "select * from user where code = ?";

User existUser = queryRunner.query(sql, new BeanHandler<User>(User.class), code);

return existUser;

}

@Override

public void update(User user) throws SQLException {

QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());

String sql = "update user set username=?,password=?, name=?,email=?,telephone=?, birthday=?,sex=?,state=?, code=? where uid=?";

Object[] params = { user.getUsername(), user.getPassword(),

user.getName(), user.getEmail(),user.getTelephone(),

user.getBirthday(), user.getSex(), user.getState(),

user.getCode() ,user.getUid()};

queryRunner.update(sql, params);

}

3.4 功能:用户登录

3.4.1 显示登录表单

  • 步骤1:修改/store_v1.0/WebContent/jsp/index.jsp 页面

<a href="${pageContext.request.contextPath}/UserServlet?method=loginUI">登录</a>

  • 步骤2:修改servlet,添加loginUI方法

//登录页面

public String loginUI(HttpServletRequest request, HttpServletResponse response)

throws Exception {

return "/jsp/login.jsp";

}

3.4.2 登录功能

3.4.2.1 分析
3.4.2.2 编写步骤

1. 完善login.jsp表单

2. 在登录页面输入用户名和密码,点击登录,发送请求到UserServlet

3. 获得用户名和密码,通过用户名和密码查询用户

4. 如果用户存在表示登录成功,将用户信息保存到session,并重定向到首页

5. 如果用户不存在,给用户错误提示,并重新登录

3.4.2.3 代码实现
  • 步骤1:完善表单

<form action="${pageContext.request.contextPath}/UserServlet?method=login" method="post">

<input type="text" name="username" placeholder="请输入用户名">

<input type="password" name="password" placeholder="请输入密码">

  • 步骤2:修改UserServlet,添加login方法

//登录

public String login(HttpServletRequest request, HttpServletResponse response)

throws Exception {

//1 封装数据

User user= MyBeanUtils.populate(User.class, request.getParameterMap());

//2 通知service进行登录

UserService userService = new UserServiceImpl();

User loginUser = userService.login(user);

//3 成功处理

if(loginUser != null){

//3.1 session作用域记录登录状态

request.getSession().setAttribute("loginUser", loginUser);

//3.2 重定向到首页

response.sendRedirect(request.getContextPath() + "/");

//3.3 不使用baseServlet的请求转发

return null;

}

//4 错误处理

// 4.1 request作用域记录错误信息

request.setAttribute("msg", "用户名或密码不匹配或未激活");

// 4.2 请求转发到登录页

return "/jsp/login.jsp";

}

  • 步骤3:修改UserService,添加login()方法

//接口

/**

* 登录

* @param user

* @return

*/

User login(User user)throws SQLException;

//实现类

@Override

public User login(User user) throws SQLException{

return userDao.find(user.getUsername() ,user.getPassword());

}

  • 步骤4:修改UserDao,添加find() 方法

//接口

/**

* 通过用户名和密码查询用户

* @param username

* @param password

* @return

*/

User find(String username, String password)throws SQLException;

//实现类

public User find(String username, String password) throws SQLException {

QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());

String sql = "select * from user where username = ? and password = ?";

User existUser = queryRunner.query(sql, new BeanHandler<User>(User.class), username,password);

return existUser;

}

  • 步骤5:完善首页,根据是否登录,实现不同的程序入口。

<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<c:if test="${empty loginUser }">

<li><a href="${pageContext.request.contextPath}/UserServlet?method=loginUI">登录</a></li>

<li><a href="${pageContext.request.contextPath}/UserServlet?method=registUI">注册</a></li>

</c:if>

<li><a href="${pageContext.request.contextPath}/jsp/cart.jsp">购物车</a></li>

<c:if test="${not empty loginUser }">

欢迎:${loginUser.name} ,

<li><a href="${pageContext.request.contextPath}/jsp/order_list.jsp">我的订单</a></li>

<li><a href="${pageContext.request.contextPath}/jsp/order_list.jsp">退出</a></li>

</c:if>

3.5 功能:用户退出

3.5.1 分析

3.5.2 编写步骤

在用户登录时,点击退出,发送请求到服务器

将session保存用户信息移除,重定向到首页

3.5.3 代码实现

  • 步骤1:确定入口

<li><a href="${pageContext.request.contextPath}/UserServlet?method=logout">退出</a></li>

  • 步骤2:修改UserServlet,添加logout()方法

//退出

public String logout(HttpServletRequest request, HttpServletResponse response)

throws Exception {

//1 将session用户状态信息移除

request.getSession().removeAttribute("loginUser");

//2 重定向到首页

response.sendRedirect(request.getContextPath() + "/UserServlet?method=loginUI");

//3.3 不使用baseServlet的请求转发

return null;

}

第4章 作业

4.1 功能:自动登录

4.1.1 分析

4.1.2 编写步骤

登录成功后,如果用户勾选自动登录,使用cookie将用户信息响应给浏览器

下次请求时,使用过滤器filter拦截器请求,获得用户信息,进行自动登录

4.1.3 代码实现

  • 步骤1:确定登录表单

<input type="checkbox" name="autoLogin" value="1"> 自动登录

  • 步骤2:修改UserServlet,修改login()方法,判断是否勾选自动登录。如果勾选,使用cookie记录用户信息;如果用登录时没有勾选复选框,将删除之前自动登录cookie。

//3 成功处理

if(loginUser != null){

//#1 自动登录start

String autoLogin = request.getParameter("autoLogin");

if("1".equals(autoLogin)){

// 如果勾选发送cookie3

Cookie autoLoginCookie = new Cookie("autoLoginCookie", user.getUsername() + "@" + user.getPassword());

autoLoginCookie.setPath("/");

autoLoginCookie.setMaxAge(60*60*24*7);

response.addCookie(autoLoginCookie);

} else {

// 删除cookie

Cookie autoLoginCookie = new Cookie("autoLoginCookie", "");

autoLoginCookie.setPath("/");

autoLoginCookie.setMaxAge(0);

response.addCookie(autoLoginCookie);

}

  • 步骤3:编写CookieUtils工具类,用于获得指定名称的cookie

public class CookieUtils {

/**

* 获得指定cookie

* @param allCookie

* @param cookieName

* @return

*/

public static Cookie getCookie(Cookie[] allCookie , String cookieName){

if(cookieName == null){

return null;

}

if(allCookie != null){

for (Cookie c : allCookie) {

if(cookieName.equals(c.getName())){

return c;

}

}

}

return null;

}

}

  • 步骤4:编写LoginFilter 过滤器

public class LoginFilter implements Filter{

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {

//0 强转

HttpServletRequest request = (HttpServletRequest) req;

HttpServletResponse response = (HttpServletResponse) resp;

// 如果是登录页直接放行

String servletPath = request.getServletPath();

if(servletPath.startsWith("/UserServlet")){

String method = request.getParameter("method");

if("loginUI".equals(method)){

chain.doFilter(request, response);

return;

}

}

//1 用户登录信息

User loginUser = (User) request.getSession().getAttribute("loginUser");

//2 如果已经登录,放行,不需要自动登录

if(loginUser != null){

chain.doFilter(request, response);

return; //程序结束

}

//3 获得 自动登录 cookie信息

Cookie userCookie = CookieUtils.findCookie(request.getCookies() , "autoLoginCookie" );

//4 判断自动登录cookie是否存在,如果没有cookie,不需要自动

if(userCookie == null){

chain.doFilter(request, response);

return;

}

//5 通过用户cookie中记录信息,查询用户

// 5.1 获得用户信息

String[] u = userCookie.getValue().split("@");

String username = u[0];

String password = u[1];

User user = new User(username, password);

try {

// 5.2 执行登录

UserService userServic = new UserServiceImpl();

loginUser = userServic.login(user);

//6 如果没有查询(修改密码

if (loginUser == null) {

chain.doFilter(request, response);

return;

}

// 7 自动登录

request.getSession().setAttribute("loginUser", loginUser);

//放行

chain.doFilter(request, response);

} catch (Exception e) {

System.out.println("自动登录异常,自动忽略");

}

}

  • 步骤5:web.xml 配置

<filter>

<filter-name>LoginFilter</filter-name>

<filter-class>cn.com.javahelp.store.web.filter.LoginFilter</filter-class>

</filter>

<filter-mapping>

<filter-name>LoginFilter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

  • 步骤6:当用户访问登录页时,不进行自动登录,但登录复选框需要勾选

<input type="checkbox" name="autoLogin" value="1" ${not empty cookie.autoLoginCookie? "checked='checked'" : ""} > 自动登录

4.2 功能:记住用户名

4.2.1 分析

4.2.2 编写步骤

登录成功后,判断是否勾选记住用户名

如果已经勾选,使用cookie记录用户名

在访问登录页面时,使用el回显用户名

4.2.3 代码实现

  • 步骤1:确定页面

<input type="checkbox" name="rememberme" value="1"> 记住用户名

  • 步骤2:修改login()方法,如果已经勾选,使用cookie 记录用户名

//#2 记住用户名 start

String rememberme = request.getParameter("rememberme");

if("1".equals(rememberme)){

Cookie remembermeCookie = new Cookie("remembermeCookie", user.getUsername());

remembermeCookie.setPath("/");

remembermeCookie.setMaxAge(60*60*24*7);

response.addCookie(remembermeCookie);

} //省略cookie的删除

//#2 记住用户名 end

  • 步骤3:修改login.jsp页面,如果有记住用户名cookie使用el表达式进行显示

<input type="text" name="username" placeholder="请输入用户名" value="${cookie.remembermeCookie.value}">

...

<input type="checkbox" name="rememberme" value="1" ${not empty cookie.remembermeCookie? "checked='checked'" : ""}> 记住用户名

4.3 功能:完善所有jsp页面,提供header

  • 步骤1:将导航条提取到header.jsp页面,摘要如下:

<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<!--

时间:2015-12-30

描述:菜单栏

-->

<c:if test="${empty loginUser }">

<li><a href="${pageContext.request.contextPath}/UserServlet?method=loginUI">登录</a></li>

<li><a href="${pageContext.request.contextPath}/UserServlet?method=registUI">注册</a></li>

</c:if>

<li><a href="${pageContext.request.contextPath}/jsp/cart.jsp">购物车</a></li>

<c:if test="${not empty loginUser }">

欢迎:${loginUser.name} ,

<li><a href="${pageContext.request.contextPath}/jsp/order_list.jsp">我的订单</a></li>

<li><a href="${pageContext.request.contextPath}/UserServlet?method=logout">退出</a></li>

</c:if>

<!--

描述:导航条

-->

<a href="${pageContext.request.contextPath}">首页</a>

  • 步骤2:其他所有的前台页面,都静态包含header.jsp页面

<%--包含导航条 --%>

<%@include file="/jsp/header.jsp" %>

4.4 功能:异步校验用户名是否存在(自己完成)

4.4.1 分析

4.4.2 编写步骤

1. 用户名文本框失去焦点触发JS函数

2. 使用AJAX发送异步请求

3. 获得服务器响应的数据,并处理,将结果显示在文本框后面的span中

4.4.3 代码实现

  • 步骤1:确定html页面

<input type="text" id="username" placeholder="请输入用户名">

<span id="s1"></span>

<input type="submit" id="regBut" value="注册" …/>

  • 步骤2:给username文本框绑定事件,blur失去焦点触发js

<script type="text/javascript">

$(function(){

$("#username").blur(function(){

// 获得文本框的值:

var val = $(this).val();

// 异步发送数据:

if(val != ""){

var url = "${ pageContext.request.contextPath }/UserServlet";

var params = {"method":"checkUsername","username":val};

$.post(url,params,function(data){

if(data == 1){

$("#s1").html("用户名可以使用").css("color","#0f0");

$("#regBut").attr("disabled",false);

}else if(data == 2){

$("#s1").html("用户名已经被注册").css("color","#f00");

$("#regBut").attr("disabled",true);

}

});

}

});

});

</script>

  • 步骤3:修改UserServlet,添加checkUsername()方法

// ajax检查用户名

public void checkUsername(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

// 接收文本框的值:

String username = request.getParameter("username");

// 调用业务层查询:

UserService userService = new UserServiceImpl();

User existUser = userService.findByUsername(username);

// 判断:

if(existUser == null){

// 用户名没有使用

response.getWriter().println(1);

}else{

// 用户名已经被使用

response.getWriter().println(2);

}

}

  • 步骤4:修改service,添加 findByUsername()方法

//接口

public interface UserService {

/**

* 通过用户名查询用户

* @param username

* @return

*/

User findByUsername(String username) throws SQLException;

}

//实现类

public class UserServiceImpl implements UserService {

private UserDao userDao = new UserDaoImpl();

@Override

public User findByUsername(String username) throws SQLException {

return userDao.findByUsername(username);

}

}

  • 步骤5:修改dao,添加findByUsername()方法

//接口

public interface UserDao {

/**

* 通过用户名查询用户

* @param username

* @return

* @throws SQLException

*/

User findByUsername(String username) throws SQLException;

}

//实现类

public class UserDaoImpl implements UserDao {

@Override

public User findByUsername(String username) throws SQLException {

QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());

String sql = "select * from user where username = ?";

User existUser = queryRunner.query(sql, new BeanHandler<User>(User.class), username);

return existUser;

}

}

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-07-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java帮帮 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Web商城实战一
  • 第1章 网络商城实战
    • 1.1 数据库分析与设计
      • 1.2 通用Servlet
        • 1.2.1 分析
        • 1.2.2 实现
    • 第2章 环境搭建
      • 2.1 目录结构
        • 2.2 导入jar包
          • 2.3 工具类
            • 2.3.1 JdbcUtils
          • 且以优雅过一生:杨绛传
            • 2.3.2 MyBeanUtils
            • 2.3.3 UUIDUtils
          • 2.4 编码过滤器
            • 2.5 导入JSP页面
            • 第3章 前台用户模块
              • 3.1 编写流程
                • 3.2 功能:用户注册
                  • 3.2.1 显示注册表单
                  • 3.2.2 用户注册
                  • 3.2.3 发送激活邮件
                • 3.3 功能:用户激活
                  • 3.3.1 分析
                  • 3.3.2 编写步骤
                  • 3.3.3 代码实现
                • 3.4 功能:用户登录
                  • 3.4.1 显示登录表单
                  • 3.4.2 登录功能
                • 3.5 功能:用户退出
                  • 3.5.1 分析
                  • 3.5.2 编写步骤
                  • 3.5.3 代码实现
              • 第4章 作业
                • 4.1 功能:自动登录
                  • 4.1.1 分析
                  • 4.1.2 编写步骤
                  • 4.1.3 代码实现
                • 4.2 功能:记住用户名
                  • 4.2.1 分析
                  • 4.2.2 编写步骤
                  • 4.2.3 代码实现
                • 4.3 功能:完善所有jsp页面,提供header
                  • 4.4 功能:异步校验用户名是否存在(自己完成)
                    • 4.4.1 分析
                    • 4.4.2 编写步骤
                    • 4.4.3 代码实现
                相关产品与服务
                数据库
                云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档