前言

1、本篇仅记录本人在一学期的Java Web课程中学习所遇到一些问题及解决方法,可能不会适用于所有人。
2、代码并非本人原创,前端代码大部分为网络下载,Servlet代码为网络查找改写,如有侵权,必删。

正文

一、项目开发环境及工具

我所使用的的是JDK1.8,mysql8.0.29,tomcat8以及maven3.8.5
开发工具则使用IDEA,Navicat15,powerdesigner16.5

二、项目开发所需要做的准备

2.1 数据库

确定好数据库所需内容,也就是Java项目里的实体类,确定好类与类之间的关系,这是我在做项目时使用pd16.5软件所生成的数据库关系图。

JAVA电商在线购物商城系统设计与实现 开题报告 研究步骤_servlet


关于pd16.5的使用,可以自行查找。

2.2 C3P0

C3P0作为Java与数据库连接的一个重要配置文件,在mysql更新至8版本以后,会出现大量问题,比如时区不同步,连接超时等。这些问题同样也困扰了我许久,在网络寻觅几小时后,终于是找到了一个比较全面的配置,如下:

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
	<default-config>
		<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
		<property name="jdbcUrl">jdbc:mysql://localhost:3306/shopping?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&autoReconnect=true&failOverReadOnly=false&allowPublicKeyRetrieval=true</property>
		<property name="user">root</property>
		<property name="password">mama2929</property>
		<property name="acquireIncrement">3</property>
		<property name="initialPoolSize">3</property>
		<property name="minPoolSize">5</property>
		<property name="maxPoolSize">200</property>
		<property name="maxIdleTime">1800</property>
		<property name="idleConnectionTestPeriod">1800</property>
		<property name="maxStatements">0</property>
		<property name="checkoutTimeout">10000</property>
		<property name="acquireRetryAttempts">5</property>
		<property name="acquireRetryDelay">1000</property>
		<property name="numHelperThreads">5</property>
		<property name="testConnectionOnCheckout">true</property>
		<property name="preferredTestQuery">select 1</property>
	</default-config> 
	
</c3p0-config>

三、项目的开发

既然是要做JavaWeb,那必然少不了前端页面与后端服务器的连接,而本次课程设计使用的是JSP与Servlet为主的开发。

3.1 前端页面展示

JAVA电商在线购物商城系统设计与实现 开题报告 研究步骤_学习_02


JAVA电商在线购物商城系统设计与实现 开题报告 研究步骤_业务逻辑_03


JAVA电商在线购物商城系统设计与实现 开题报告 研究步骤_servlet_04

3.2 Servlet部分代码展示


AddressController

@WebServlet("/address")
public class AddressController extends BaseServlet {


    public String show(HttpServletRequest request, HttpServletResponse response) throws SQLException {

        HttpSession session = request.getSession();
        User user  = (User) session.getAttribute("loginUser");
        if (user == null)
        {
            session.setAttribute("msg", "需要先登录!");
            return Constants.REDIRECT + "/login.jsp";
        }

        int uid = user.getUid();

        AddressService addressService = new AddressServiceImpl();
        List<Address> addresses = addressService.findAddressByUid(uid);

        request.setAttribute("list", addresses);

        return Constants.FORWARD + "/self_info.jsp";
    }


    public String add(HttpServletRequest request,HttpServletResponse response) throws InvocationTargetException, IllegalAccessException, SQLException {

        //1.获取请求参数
        Map<String, String[]> map = request.getParameterMap();
        Address address = new Address();
        BeanUtils.populate(address,map);

        //2.调用业务逻辑进行地址添加
        AddressService addressService = new AddressServiceImpl();
        addressService.saveAddress(address);
        //3。转发到展示的方法
        return Constants.FORWARD + "/address?method=show";
    }

    public String delete(HttpServletRequest request,HttpServletResponse response) throws InvocationTargetException, IllegalAccessException, SQLException {

        //1.获取请求参数
        String aid = request.getParameter("aid");

        //2.调用业务逻辑进行地址添加
        AddressService addressService = new AddressServiceImpl();
        addressService.deleteAddressByAid(aid);
        //3。转发到展示的方法
        return Constants.FORWARD + "/address?method=show";
    }

    public String setDefault(HttpServletRequest request,HttpServletResponse response) throws InvocationTargetException, IllegalAccessException, SQLException {

        //1.获取请求参数
        String aid = request.getParameter("aid");
        HttpSession session = request.getSession();
        User user  = (User) session.getAttribute("loginUser");
        if (user == null)
        {
            session.setAttribute("msg", "需要先登录!");
            return Constants.REDIRECT + "/login.jsp";
        }

        //2.调用业务逻辑进行地址添加
        AddressService addressService = new AddressServiceImpl();
        addressService.setAddressToDefault(aid,user.getUid());
        //3。转发到展示的方法
        return Constants.FORWARD + "/address?method=show";
    }

    public String update(HttpServletRequest request,HttpServletResponse response) throws InvocationTargetException, IllegalAccessException, SQLException {

        //1.获取请求参数
        Map<String, String[]> map = request.getParameterMap();

        Address address = new Address();
        BeanUtils.populate(address,map);


        //2.调用业务逻辑进行地址添加
        AddressService addressService = new AddressServiceImpl();
        addressService.updateByAid(address);
        //3。转发到展示的方法
        return Constants.FORWARD + "/address?method=show";
    }
}

UserController

@WebServlet("/user")
public class UserController extends BaseServlet{


    public void check(HttpServletRequest request, HttpServletResponse response) throws SQLException, IOException {

        PrintWriter out = response.getWriter();


        //1.获取用户
        String username = request.getParameter("username");

        if (username == null){
            out.println(JSON.toJSON(Constants.HAS_USER));
            return;
//            return Constants.HAS_USER;//不能注册
        }
        //2.调用业务逻辑 判断用户名是否存在
        UserService userService = new UserServiceImpl();

        boolean b = userService.checkUser(username);


        //3.响应字符串  1 存在 0 不存在
        if (b) {
            //用户存在
            out.println(JSON.toJSON(Constants.HAS_USER));
            return;
//            return Constants.HAS_USER;
        }
              out.println(JSON.toJSON(Constants.NOT_HAS_USER));
//        return  Constants.NOT_HAS_USER;

    }
    public void register(HttpServletRequest request, HttpServletResponse response) throws IOException {

        PrintWriter out = response.getWriter();//加在第一行

        //1获取用户信息
        Map<String, String[]> parameterMap = request.getParameterMap();
        User user=new User();
        try {
            BeanUtils.populate(user,parameterMap);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        //2完善用户信息
        //已赋值,用户名 密码 邮箱 性别
        //没赋值,激活状态 账号类型  激活码
        user.setUstatus(Constants.USER_NOT_ACTIVE);//未激活状态0  激活 1
        user.setUrole(Constants.ROLE_CUSTOMER);//普通客户0  管理员1
        user.setCode(RandomUtils.createActive());

        //需要处理的属性,密码md5进行加密处理
        user.setUpassword(MD5Utils.md5(user.getUpassword()));



        //3调用用户的业务逻辑进行注册

        UserService userService = new UserServiceImpl();

        try {
            userService.registerUser(user);
        } catch (SQLException e) {
            e.printStackTrace();

            request.setAttribute("registerMsg","注册失败!");

            out.println(JSON.toJSON("注册失败"));
            return;
//            return Constants.FORWARD+"/register.jsp";
        }

        //4响应
        out.println(JSON.toJSON("注册成功"));
//        return Constants.FORWARD + "/registerSuccess.jsp";

    }

    public String active(HttpServletRequest request,HttpServletResponse response) throws SQLException {

        //1获取激活码
        //已经转成Base64
        String c = request.getParameter("c");
        //base64翻转
        String code= Base64Utils.decode(c);

        //2调用激活的业务逻辑
        UserService userService = new UserServiceImpl();
        int i = userService.activeUser(code);

        //3响应(激活失败(code没找到)  已经激活  激活成功)

        if(i==Constants.ACTIVE_FAIL){
            request.setAttribute("msg","未激活成功!");
        }else if (i==Constants.ACTIVE_SUCCESS){
            request.setAttribute("msg","激活成功,请登录!");
        }else {
            request.setAttribute("msg","已经激活,请登录!");
        }
        return Constants.FORWARD+ "/message.jsp";
    }

    /**
     * 1.前端提交账号密码和验证码
     * 2对比验证码 成功  --->对比账号密码
     * 3对比账号密码
     *    失败 --> 回到登录页面 进行提示
     *    成功  --> 未激活 登录页面  进行提示
     *        --> 已激活   程序首页  将用户放入session共享域
     */

    public String login(HttpServletRequest request,HttpServletResponse response) throws SQLException {

        //1获取请求参数(用户名,密码,验证码)

        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String code = request.getParameter("code");//用户输入验证码
        String auto=request.getParameter("auto");//自动登录
        //正确验证码
        HttpSession session = request.getSession();
        String codestr = (String) session.getAttribute("code");


        //2判断验证码是否正确
        if (code == null || !code.equalsIgnoreCase(codestr)){
            request.setAttribute("msg","验证码错误");
            return Constants.FORWARD + "/login.jsp";
        }

        //3调用业务逻辑判断账号密码

        UserService userService=new UserServiceImpl();
        User user = userService.login(username, password);

        //4响应
        //user等于Null 证明账号或密码错误
        //user 不为空 但是user状态未激活

        if (user==null){
            request.setAttribute("msg","账号或密码错误");
            return Constants.FORWARD+"/login.jsp";
        }

        if (user.getUstatus().equals(Constants.USER_NOT_ACTIVE)){
            request.setAttribute("msg","账号未激活");
            return Constants.FORWARD+"/login.jsp";
        }

        session.setAttribute("loginUser",user);

        //autoUser
        //1.判断是否勾选自动登录
        if (auto == null){
            //没有勾选
            //将本地浏览器的存在的cookie‘清空’
            Cookie cookie = new Cookie(Constants.AUTO_NAME,"");
            cookie.setPath("/");
            cookie.setMaxAge(0);
            response.addCookie(cookie);
        }else{
            //自动登录数据库存储 2周
            String content = username+Constants.FLAG+password;
            content = Base64Utils.encode(content);
            Cookie cookie = new Cookie(Constants.AUTO_NAME,content);
            cookie.setPath("/");
            cookie.setMaxAge(14*24*60*60);
            response.addCookie(cookie);
        }

        return  Constants.REDIRECT+"/index.jsp";
    }

    /**
     * 注销登录 清空数据 跳转登录页面
     * @param request
     * @param response
     * @return
     */
    public String logOut(HttpServletRequest request,HttpServletResponse response){
        //清空session中用户数据
        HttpSession session = request.getSession();
        session.removeAttribute("loginUser");

        //2清空和覆盖cookie存储的自动登录信息

        Cookie cookie = new Cookie(Constants.AUTO_NAME,"");
        cookie.setPath("/");
        cookie.setMaxAge(0);
        response.addCookie(cookie);
        //3转发登录页面
        request.setAttribute("msg","注销登录成功");
        return Constants.FORWARD + "/login.jsp";

    }
}

ProductDaoImpl

public class ProductDaoImpl implements ProductDao {
    @Override
    public long selectCountByTid(String tid) throws SQLException {

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

        String sql ="select count(1) from product where t_id = ?";

        Object result = queryRunner.query(sql,new ScalarHandler(),tid);

        Long total = (long) result;


        return total;
    }

    @Override
    public List<Product> selectProductByPage(int page, int pageSize, String tid) throws SQLException {

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

        String sql ="select p_id as pid,t_id as tid,p_name as pname,p_time as ptime ," +
                "p_image as pimage,p_state as pstate ,p_info as pinfo ,p_price as pprice " +
                "from product where t_id = ? limit ?,?;";


        List<Product> list = queryRunner.query(sql, new BeanListHandler<Product>(Product.class),
                tid, (page - 1) * pageSize, pageSize);


        return list;
    }

    @Override
    public Product selectProductByPid(String pid) throws SQLException {

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

        String sql ="select p_id as pid,t_id as tid,p_name as pname,p_time as ptime ," +
                "p_image as pimage,p_state as pstate ,p_info as pinfo ,p_price as pprice " +
                "from product where p_id = ? ;";

        Product product = queryRunner.query(sql, new BeanHandler<Product>(Product.class), pid);

        return product;
    }
}

CartDaoImpt

public class CartDaoImpl implements CartDao {
    @Override
    public Cart hasCart(int uid, String pid) throws SQLException, InvocationTargetException, IllegalAccessException {

        //cart --> product 连接查询 多表查询
        QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());

        String sql = "select p.p_name as pname,p.p_id as pid,p.t_id as tid," +
                "p.p_time as ptime,p.p_image as pimage,p_state as pstate," +
                "p.p_info as pinfo, p.p_price as pprice,c.c_id as cid,c.u_id as uid,c.c_count as ccount," +
                "c.c_num as cnum from product p join cart c on p.p_id = c.p_id where" +
                " c.u_id = ? and c.p_id = ?;";


        Map<String, Object> query = queryRunner.query(sql, new MapHandler(), uid, pid);
        Map<String, Object> queryReplace = new HashMap<>();
        System.out.println(query);
        System.out.println(uid+" "+pid);



        if (query == null) {
            return null;
        }else{
            for(String key : query.keySet()){
                String temp = key.split("_")[0] + key.split("_")[1];
                queryReplace.put(temp,query.get(key));
            }
        }


        Cart cart = new Cart();
        Product product = new Product();

        BeanUtils.populate(cart,queryReplace);
        BeanUtils.populate(product, queryReplace);

        cart.setProduct(product);


        return cart;
    }

    @Override
    public void updateCart(Cart cart) throws SQLException {

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

        String sql = "update cart set c_num = ? , c_count = ? where c_id = ?";

        queryRunner.update(sql, cart.getCnum(),cart.getCcount(),cart.getCid());

    }

    @Override
    public void insertCart(Cart cart) throws SQLException {
        QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());

        String sql = "insert into cart (u_id,p_id,c_num,c_count) value(?,?,?,?)";

        queryRunner.update(sql, cart.getUid(),cart.getProduct().getPid(),cart.getCnum(),cart.getCcount());
    }

    @Override
    public List<Cart> selectCartsByUid(int uid) throws InvocationTargetException, IllegalAccessException, SQLException {


        //注意 查询cart需要关联到商品表
        //cart --> product 连接查询 多表查询
        QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());

        String sql = "select p.p_name as pname,p.p_id as pid,p.t_id as tid," +
                "p.p_time as ptime,p.p_image as pimage,p_state as pstate," +
                "p.p_info as pinfo, p.p_price as pprice,c.c_id as cid,c.u_id as uid,c.c_count as ccount," +
                "c.c_num as cnum from product p join cart c on p.p_id = c.p_id where" +
                " c.u_id = ?;";



        List<Map<String, Object>> list = queryRunner.query(sql, new MapListHandler(), uid);


        if (list == null){
            return null;
        }

        List<Cart> carts = new ArrayList<>();

        for (Map<String, Object> map : list) {
            //cart + product
            Cart cart = new Cart();
            Product product = new Product();
            Map<String, Object> queryReplace = new HashMap<>();
            for(String key : map.keySet()){
                String temp = key.split("_")[0] + key.split("_")[1];
                queryReplace.put(temp,map.get(key));
            }

            BeanUtils.populate(cart, queryReplace);
            BeanUtils.populate(product,queryReplace);

            cart.setProduct(product);
            carts.add(cart);
        }

        return carts;
    }

    @Override
    public void deleteCartByCid(String cid) throws SQLException {

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

        String sql = "delete from cart where c_id = ?;";

        queryRunner.update(sql, cid);
    }

    @Override
    public void updateByCid(BigDecimal count, BigDecimal cnumbig, String cid) throws SQLException {
        QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
        String sql = "update cart set c_count = ? , c_num = ? where c_id = ?;";
        queryRunner.update(sql, count,cnumbig,cid);
    }

    @Override
    public void deleteCartByUid(String uid) throws SQLException {
        QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
        String sql = "delete from cart where u_id = ?;";
        queryRunner.update(sql, uid);
    }
}

四、总结

写这个代码时,遇到了许许多多的问题,就比如:关于BeanUtils工具类的使用,.popular的使用,是要求Bean值与Key值完全相同,而在代码中,数据库的命名为 B_id,在Java实体类中的命名则为Bid,这样就导致查找不到,从而无法实现赋值,关于这个问题的解决方法,只需分割“_”即可解决

for (Map<String, Object> map : list) {
    //cart + product
    Cart cart = new Cart();
    Product product = new Product();
    Map<String, Object> queryReplace = new HashMap<>();
    for(String key : map.keySet()){
        String temp = key.split("_")[0] + key.split("_")[1];
        queryReplace.put(temp,map.get(key));
    }

    BeanUtils.populate(cart, queryReplace);
    BeanUtils.populate(product,queryReplace);

    cart.setProduct(product);
    carts.add(cart);
}

如果在数据库中有Datetime数据,在Java中定义实体类为Date型时,可能会导致无法从String型转为Date型,这是因为BeanUtils工具只支持转换 java.sql.Date。所以一定检查自己的实体类使用的是什么包。 当然,仅仅是使用sql包并不能真正解决这个问题,还需在DaoImpt中做一些代码的修改,将存储的数据类型进行转化

ConvertUtils.register(new Converter() {
            @Override
            public Object convert(Class clazz, Object value) {
                //将String转化为date
                Date parse=null;
                try {
                    //parse()返回的是一个Date类型数据,format返回的是一个StringBuffer类型的数据
                    // parse = (Date) format.parse(value.toString());

                    LocalDateTime localDateTime = (LocalDateTime) value;
                    ZoneId zoneId = ZoneId.systemDefault();
                    ZonedDateTime zonedDateTime = localDateTime.atZone(zoneId);
                    Instant instant = zonedDateTime.toInstant();
                    java.util.Date date= Date.from(instant);
                    parse=new java.sql.Date(date.getTime());
                } catch (Exception e) {

                    e.printStackTrace();
                }
                return parse;
            }
        }, Date.class);