create database onlinemall;use onlinemall;CREATE TABLE `user` ( `uid` varchar(100) 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 NULL, `code` varchar(100) DEFAULT NULL, PRIMARY KEY (`uid`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
com.web.servlet com.web.filter com.iservice com.service.impl com.dao com.dao.impl com.bean com.utils com.constant
package com.web.servlet;import java.io.IOException;import java.lang.reflect.Method;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * 为了提高代码的复用性,我们写了这个基类, * * @author LuoJoy * */public class BaseServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 使用反射技术获取方法,并调用方法 // 获取隐藏域传过来的method String methodName = request.getParameter("method"); // 获取字节码文件对象 Class clazz = this.getClass(); try { Method method = clazz.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class); String path = (String) method.invoke(this, request, response); // 不等于null时说明都是需要执行请求转发,因为如果时请求重定向,那么就让它返回空,这样就不会执行下面的代码,而是执行原来的方法 if (path != null) { request.getRequestDispatcher(path).forward(request, response); } } catch (Exception e) { e.printStackTrace(); } } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }}
package com.web.filter;import java.io.IOException;import java.io.UnsupportedEncodingException;import java.util.Map;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletRequestWrapper;import javax.servlet.http.HttpServletResponse;/** * 统一编码 * @author Administrator * */public class EncodingFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { // TODO Auto-generated method stub } @Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { //1.强转 HttpServletRequest request=(HttpServletRequest) req; HttpServletResponse response=(HttpServletResponse) resp; //2.放行 chain.doFilter(new MyRequest(request), response); } @Override public void destroy() { // TODO Auto-generated method stub }}class MyRequest extends HttpServletRequestWrapper{ private HttpServletRequest request; private boolean flag=true; public MyRequest(HttpServletRequest request) { super(request); this.request=request; } @Override public String getParameter(String name) { if(name==null || name.trim().length()==0){ return null; } String[] values = getParameterValues(name); if(values==null || values.length==0){ return null; } return values[0]; } @Override /** * hobby=[eat,drink] */ public String[] getParameterValues(String name) { if(name==null || name.trim().length()==0){ return null; } Mapmap = getParameterMap(); if(map==null || map.size()==0){ return null; } return map.get(name); } @Override /** * map{ username=[tom],password=[123],hobby=[eat,drink]} */ public Map getParameterMap() { /** * 首先判断请求方式 * 若为post request.setchar...(utf-8) * 若为get 将map中的值遍历编码就可以了 */ String method = request.getMethod(); if("post".equalsIgnoreCase(method)){ try { request.setCharacterEncoding("utf-8"); return request.getParameterMap(); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } }else if("get".equalsIgnoreCase(method)){ Map map = request.getParameterMap(); if(flag){ for (String key:map.keySet()) { String[] arr = map.get(key); //继续遍历数组 for(int i=0;i
事务管理工具类
package com.utils;import java.beans.PropertyVetoException;import java.sql.Connection;import java.sql.SQLException;public class TransactionManager { private static ThreadLocallocal = new ThreadLocal<>(); public static Connection getConnectionFromThreadLocal() throws Exception{ Connection conn = local.get(); //判断conn是否为null if (conn == null) { conn = C3P0Util.getConnection(); //存到local中去 local.set(conn); } return conn; } /** * 开启事务 * @throws PropertyVetoException * @throws SQLException */ public static void startTransaction() throws Exception{ getConnectionFromThreadLocal().setAutoCommit(false); } /** * 提交事务 */ public static void commit() throws Exception{ getConnectionFromThreadLocal().commit(); } /** * 回滚事务 * @throws Exception */ public static void rollback() throws Exception{ getConnectionFromThreadLocal().rollback(); } /** * 关闭连接 * @throws Exception */ public static void close() throws Exception{ getConnectionFromThreadLocal().close(); //连接关闭之后,将该连接从ThreadLocal中移除掉 local.remove(); }}
生成uid的工具类
package com.utils;import java.util.UUID;public class UUIDUtils { /** * 随机生成id * @return */ public static String getId(){ return UUID.randomUUID().toString().replace("-", "").toUpperCase(); }}
邮件发送工具类
package com.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 { /** * @param email 收件人地址 * @param emailMsg 邮件内容 * @param subject 邮件主题 * @throws AddressException * @throws MessagingException */ public static void sendMail(String email, String emailMsg,String subject) throws AddressException, MessagingException { // 1.创建一个程序与邮件服务器会话对象 Session Properties props = new Properties(); //设置发送的协议 props.setProperty("mail.transport.protocol", "SMTP"); //设置发送邮件的服务器---->需要改成自己的发送邮件的服务器地址 props.setProperty("mail.host", "localhost"); props.setProperty("mail.smtp.auth", "true");// 指定验证为true // 创建验证器 Authenticator auth = new Authenticator() { public PasswordAuthentication getPasswordAuthentication() { //设置发送人的帐号和密码---->设置成本公司的邮箱账号 return new PasswordAuthentication("service@store.com", "123456"); } }; 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(subject); // message.setText("这是一封激活邮件,请点击"); //设置邮件内容 message.setContent(emailMsg, "text/html;charset=utf-8"); // 3.创建 Transport用于将邮件发送 Transport.send(message); }}
C3P0工具类
package com.utils;import java.beans.PropertyVetoException;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import javax.sql.DataSource;import com.mchange.v2.c3p0.ComboPooledDataSource;public class C3P0Util { private static ComboPooledDataSource dataSource; static{ //从C3P0连接池中获取连接对象 dataSource = new ComboPooledDataSource(); } /** * 获得连接对象 * @return * @throws SQLException * @throws PropertyVetoException */ public static Connection getConnection() throws SQLException, PropertyVetoException{ return dataSource.getConnection(); } public static void close(ResultSet resultSet,Statement statement,Connection connection) throws SQLException{ if (resultSet != null) { resultSet.close(); } if (statement != null) { statement.close(); } if (connection != null) { connection.close(); } } /** * 获得连接池对象 * @return */ public static DataSource getDataSource(){ return dataSource; } }
c3p0配置文件
30000 10 100 10 root 123 com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/onlinemall
/**
* 1 首先什么是面向接口编程? * * 面向接口编程就是先把客户的业务逻辑线提取出来,作为接口,业务具体实现通过该接口的实现类来完成。 * 当客户需求变化时,只需编写该业务逻辑的新的实现类,通过更改配置文件(例如Spring框架)中该接口 * 的实现类就可以完成需求,不需要改写现有代码,减少对系统的影响 * * 面向接口编程的优点? * 1 降低程序的耦合性。其能够最大限度的解耦,所谓解耦既是解耦合的意思,它和耦合相对。耦合就是联系 * ,耦合越强,联系越紧密。在程序中紧密的联系并不是一件好的事情,因为两种事物之间联系越紧密,你更换 * 其中之一的难度就越大,扩展功能和debug的难度也就越大。 * 2 易于程序的扩展; * 3 有利于程序的维护 * * 接口编程在设计模式中的体现:开闭原则 * 其遵循的思想是:对扩展开放,对修改关闭。其恰恰就是遵循的是使用接口来实现。在使用面向接口的编程过程 * 中,将具体逻辑与实现分开,减少了各个类之间的相互依赖,当各个类变化时,不需要对已经编写的系统进行 * 改动,添加新的实现类就可以了,不在担心新改动的类对系统的其他模块造成影响。一,案例需求
在register.jsp上填写用户的信息,点击保存,将用户信息保存到数据库中. 发送激活邮件给注册的用户.
-
修改注册的超链接,跳转到register.jsp
-
在注册页面,修改表单属性 ,提交到UserServlet里面
-
创建 UserServlet继承BaseServlet,在UserServlet里面创建regist()方法
-
在regist()方法里面
获得请求参数,封装成user对象
调用业务
分发转向
- 用于生成对象的工厂类
package com.factory;import java.io.InputStream;import org.dom4j.Attribute;import org.dom4j.Document;import org.dom4j.DocumentException;import org.dom4j.Element;import org.dom4j.io.SAXReader;/** * 工厂模式:就是传入原材料生产出相应的产品 * * @author LuoJoy * */public class ContextFactory { /** * 传入一个id返回一个实例 * * @param id * @return * @throws DocumentException * @throws ClassNotFoundException * @throws IllegalAccessException * @throws InstantiationException */ public static Object getInstance(String id) throws DocumentException, ClassNotFoundException, InstantiationException, IllegalAccessException { // 1.解析xml,获取class属性值 // 使用Dom4j XPATH工具类读取到配置文件,获取配置信息 // 创建SaxReader对象 SAXReader reader = new SAXReader(); // 将配置文件转换成流 // 使用类加载器将资源文件转换成流 InputStream stream = ContextFactory.class.getClassLoader().getResourceAsStream("context.xml"); Document document = reader.read(stream); // 获取instance id Element element = (Element) document.selectSingleNode("/contexts/instance[@id='" + id + "']"); // 获取instance 上的class Attribute attribute = element.attribute("class"); // 使用属性对象获取属性值 String className = attribute.getValue(); // 使用反射技术通过全类名创建对象 Class clazz = Class.forName(className); Object object = clazz.newInstance(); return object; }}
工厂类配置文件
-
参考jsp页面(主要目的是让大家知道我的前端参数传递及请求路径是如何处理的,这样能更好的理解服务端的代码)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
会员登录 <%--静态包含头部 --%> <%@ include file="header.jsp" %>欢迎加入我们
Copyright © 2005-2016 古代商城 版权所有 -
* 用于处理用户注册业务的方法 * * @param request * @param response */ public String regist(HttpServletRequest request, HttpServletResponse response) { // 接受请求参数 Map
map = request.getParameterMap(); // 创建user对象 User user = new User(); // 使用BeanUtil工具类把请求参数封装到user对象上 try { BeanUtils.populate(user, map); // 还有,uid,state,code 未封装 user.setUid(UUIDUtils.getId());// 封装uid user.setState(Constants.activation); user.setCode(UUIDUtils.getId());// 封装code } catch (IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } Boolean flag = false; // 调用业务层的方法完成用户注册 try { IUserService service = (IUserService) ContextFactory.getInstance("user_service"); flag = service.regist(user); } catch (Exception e) { e.printStackTrace(); } if (flag) { // 注册成功,跳转到登陆页面 request.setAttribute("msg", "恭喜您!注册成功,请前往邮箱激活账户"); } else { // 注册失败 request.setAttribute("msg", "注册失败,请重新注册!"); } return "jsp/msg.jsp"; } 5.1调用dao操作数据库
5.2 发送激活的邮件
public interface IUserService { //用户注册方法 public Boolean regist(User user); //用户激活账户 public Boolean doCode(String code); //用户登录 public User doLogin(String usename, String password);}
实现类
package com.service.impl;import org.dom4j.DocumentException;import com.bean.User;import com.dao.intf.IUserDao;import com.factory.ContextFactory;import com.service.intf.IUserService;import com.utils.MailUtils;import com.utils.TransactionManager;public class UserServiceImpl implements IUserService { @Override public Boolean regist(User user) { Boolean falg = false; try { // 开启事务 TransactionManager.startTransaction(); IUserDao dao = (IUserDao) ContextFactory.getInstance("user_dao"); dao.regist(user); // 向用户发送激活邮件 MailUtils.sendMail(user.getEmail(), "尊敬的:" + user.getName() + "欢迎注册古代商城,请点击下面的链接进行激活用户激活", "用户账户激活"); // 提交事务 TransactionManager.commit(); falg = true; } catch (Exception e) { e.printStackTrace(); // 如果出现异常回滚 try { TransactionManager.rollback(); } catch (Exception e1) { e1.printStackTrace(); } } try { TransactionManager.close(); } catch (Exception e) { e.printStackTrace(); } return falg; }}
5.创建UserDao数据库访问层,定义一个方法保存用户
-
package com.dao.intf;import java.sql.SQLException;import com.bean.User;public interface IUserDao { public void regist(User user) throws Exception; public void updateCode(String code) throws SQLException; public User doLogin(String usename, String password) throws SQLException;}
package com.dao.impl;import java.sql.SQLException;import org.apache.commons.dbutils.QueryRunner;import org.apache.commons.dbutils.handlers.BeanHandler;import com.bean.User;import com.constant.Constants;import com.dao.intf.IUserDao;import com.utils.C3P0Util;import com.utils.TransactionManager;public class UserDaoImpl implements IUserDao { /** * 用户注册的方法 */ @Override public void regist(User u) throws Exception { QueryRunner runner = new QueryRunner(); String sql = "insert into user values(?,?,?,?,?,?,?,?,?,?);"; runner.update(TransactionManager.getConnectionFromThreadLocal(), sql, u.getUid(), u.getUsername(), u.getPassword(), u.getName(), u.getEmail(), u.getTelephone(), u.getBirthday(), u.getSex(), u.getState(), u.getCode()); } }