网上书城项目-遇到的问题-JavaWeb

缺少依赖的jar包

The import java.sql cannot be resolved

  • jre

The import javax.servlet.ServletException cannot be resolved

  • tomcat
前后端交互路径
  • jsp → servlet → service → daoImpl → db → jsp
dbutils的使用
MySQL的SQL语句编写

前台,查询本周热卖商品

  • 先用 LEFT JOIN 建立左连接,以 orderitem 订单项表为主,用 ON 去笛卡尔积。再用 GROUP BY 以商品 id 进行分类,用聚合函数计算销售量,然后用 SELECT 选择需要映射的列,LIMIT 方言限定行数,最后用 ORDER BY 进行降序排列。

  • SELECT products.id,products.name,products.imgurl,orderitem.buynum FROM orderitem LEFT JOIN products ON orderitem.product_id = products.id GROUP BY orderitem.product_id ORDER BY SUM(orderitem.buynum) DESC LIMIT 0,3

前台,根据名字查询商品

  • 模糊查询+分页查询
SELECT * FROM products WHERE name LIKE '%" + searchfield + "%' LIMIT ?,?

前台,生成订单时将商品数量减少

  • 更新操作+迭代器 foreach
UPDATE products set pnum = pnum - ? where id = ?

后台,多条件查询商品

  • sql拼接+模糊查询 (\"%\"?\"%\ ")
@Override
public List<Product> findProductByManyCondition(String id, String name, String category, String minprice,
        String maxprice) throws SQLException {
    String sql ="select * from products where 1=1";
    //存参数
    List<Object> objs = new ArrayList<Object>();
    if (id != null && id.trim().length() > 0) {
        sql += " and id like \"%\"?\"%\"";
        objs.add(id);
    }
    if (name != null && name.trim().length() > 0) {
        sql += " and name like \"%\"?\"%\"";
        objs.add(name);
    }
    if (category != null && category.trim().length() > 0) {
        sql += " and category = ?";
        objs.add(category);
    }
    if (minprice != null && minprice.trim().length() > 0) {
        sql += " and price >= ?";
        objs.add(minprice);
    }
    if (maxprice != null && maxprice.trim().length() > 0) {
        sql += " and price <= ?";
        objs.add(maxprice);
    }
    sql += " order by id";
    QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource()); 
    return (List<Product>) runner.query(sql, new BeanListHandler<Product>(Product.class), objs.toArray());
}

后台,查询所有订单

  • 对结果集的再封装
public List<Order> findAllOrder()throws SQLException{
    // 1.创建sql
    String sql = "select orders.*,user.* from orders,user where user.id=orders.user_id order by orders.user_id";
    // 2.创建QueryRunner对象
    QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
    // 3.返回QueryRunner对象query()方法的查询结果
    return runner.query(sql,new ResultSetHandler<List<Order>>(){
        public List<Order> handle(ResultSet rs)throws SQLException{
            // 创建订单集合
            List<Order> orders = new ArrayList<Order>();
            // 循环遍历订单和用户信息
            while(rs.next()){
                Order order = new Order();
                order.setId(rs.getString("orders.id"));
                order.setMoney(rs.getDouble("orders.money"));
                order.setOrdertime(rs.getDate("orders.ordertime"));
                order.setPaystate(rs.getInt("orders.paystate"));
                order.setReceiverAddress(rs.getString("orders.receiverAddress"));
                order.setReceiverName(rs.getString("orders.receiverName"));
                order.setReceiverPhone(rs.getString("orders.receiverPhone"));
                
                User user = new User();
                user.setId(rs.getInt("user.id"));
                user.setEmail(rs.getString("user.email"));
                user.setGender(rs.getString("user.gender"));
                user.setActiveCode(rs.getString("user.activecode"));
                user.setIntroduce(rs.getString("user.introduce"));
                user.setPassword(rs.getString("user.password"));
                user.setRegistTime(rs.getDate("user.registtime"));
                user.setRole(rs.getString("user.role"));
                user.setState(rs.getInt("user.state"));
                user.setTelephone(rs.getString("user.telephone"));
                user.setUsername(rs.getString("user.username"));
                
                order.setUser(user);
                orders.add(order);
            }
            return orders;
        }
    });
}
java.io.Serializable接口
  • serialVersionUID 用来表明实现序列化类的不同版本间的兼容性。
  • 为了在反序列化时,确保类版本的兼容性,最好在每个要序列化的类中加入private static final long serialVersionUID这个属性,具体数值自己定义。
tomcat错误

Server Tomcat v9.0 Server at localhost failed to start.

session中User对象判空
  • 前端传过来的对象时,单纯的使用 object == null 去判断是不够的,因为前端传过来的对象会是对象不为null,但是对象的所有属性均为null。(boolean类型除外,以及序列化值除外)
  • Java判断对象是否为NULL
  • 当前端没有对象时,使用该语句 user = (User) request.getSession().getAttribute(“user”); 会发生NPE异常,我这里将用户未登录所需要重定向的路径放在了catch中。
正则表达式
BeanUtils 以及 BeanUtils.populate 使用
getParameterMap()
在 js 中动态获取 session,和使用 try-catch
function user_login(){  
    try{
        var a="${user.username}";
        if(a != null && a != "" && a != ""){
            return true;
        }else{
            var flag = window.confirm("请您先登陆");
            return false;
        } 
    }catch(err){
        var flag = window.confirm("请您先登陆");
        return false;
    }
}
跳转页面产生新页签
  • 添加 target="_blank"
<a href="${pageContext.request.contextPath}/index.jsp" target="_blank"
           onclick="javascript:return confirm_logout();">返回前台</a>
sendRedirect 和 forward 的区别
  • sendRedrect()重定向:不仅可以重定向到同一web应用中的组件,可以重定向到其他站点资源,重定向后浏览器的URL会发生变化,因为重定向的实质 是 server端发送一个消息给浏览器端,使重新浏览新的URL。
  • forward() 请求转发:forward只能请求转发给同一web应用中的组件,转发后浏览器的url不会发生改变,forward实质是 站内转发,获取其他server资源,不会给浏览器端发送消息。
servlet - 添加商品
  • 这里的重点主要是对于文件的操作
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // 创建javaBean,将上传数据封装.
    Product p = new Product();
    Map<String, String> map = new HashMap<String, String>();
    // 封装商品id
    map.put("id", IdUtils.getUUID());
    DiskFileItemFactory dfif = new DiskFileItemFactory();
    // 设置临时文件存储位置
    dfif.setRepository(new File(this.getServletContext().getRealPath("/temp")));
    // 设置上传文件缓存大小为10m
    dfif.setSizeThreshold(1024 * 1024 * 10);
    // 创建上传组件
    ServletFileUpload upload = new ServletFileUpload(dfif);
    // 处理上传文件中文乱码
    upload.setHeaderEncoding("utf-8");
    try {
        // 解析request得到所有的FileItem
        List<FileItem> items = upload.parseRequest(request);
        // 遍历所有FileItem
        for (FileItem item : items) {
            // 判断当前是否是上传组件
            if (item.isFormField()) {
                // 不是上传组件
                String fieldName = item.getFieldName(); // 获取组件名称
                String value = item.getString("utf-8"); // 解决乱码问题
                map.put(fieldName, value);
            } else {
                // 是上传组件
                // 得到上传文件真实名称
                String fileName = item.getName();
                fileName = FileUploadUtils.subFileName(fileName);
                // 得到随机名称
                String randomName = FileUploadUtils.generateRandonFileName(fileName);
                // 得到随机目录
                String randomDir = FileUploadUtils.generateRandomDir(randomName);
                // 图片存储父目录
                String imgurl_parent = "/productImg" + randomDir;
                File parentDir = new File(this.getServletContext().getRealPath(imgurl_parent));
                // 验证目录是否存在,如果不存在,创建出来
                if (!parentDir.exists()) {
                    parentDir.mkdirs();
                }
                String imgurl = imgurl_parent + "/" + randomName;
                map.put("imgurl", imgurl);
                IOUtils.copy(item.getInputStream(), new FileOutputStream(new File(parentDir, randomName)));
                item.delete();
            }
        }
    } catch (FileUploadException e) {
        e.printStackTrace();
    }
    try {
        // 将数据封装到javaBean中
        BeanUtils.populate(p, map);
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
    ProductService service = new ProductService();
    try {
        // 调用service完成添加商品操作
        service.addProduct(p);
        response.sendRedirect(request.getContextPath() + "/listProduct");
        return;
    } catch (RuntimeException e) {
        e.printStackTrace();
        response.getWriter().write("添加商品失败");
        return;
    }
}
service - 删除订单

对多个表进行增加、修改或删除,需要开启事务,若有一个不成功就发生回滚。

// 普通用户删除订单
public void delOrderByIdWithClient(String id){
    try{
        // 开启事务
        DataSourceUtils.startTransaction();
        // 从订单项中查找商品购买数量
        Order order=new Order();
        order.setId(id);
        List<OrderItem> items=oidao.findOrderItemByOrder(order);
        // 修改商品数量
        pdao.updateProductNum(items);
        // 删除订单项
        oidao.delOrderItems(id);
        // 删除订单
        odao.delOrderById(id);
    }catch(SQLException e){
        e.printStackTrace();
        try{
            DataSourceUtils.rollback();
        }catch(SQLException e1){
            e1.printStackTrace();
        }
    }finally{
        try{
           DataSourceUtils.releaseAndCloseConnection();
        }catch(SQLException e){
            e.printStackTrace();
        }
    }
}
String的格式化 - time的显示

JAVA字符串格式化-String.format()的使用

public void doPost(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
    NoticeService nService = new NoticeService();
    List<Notice> notices = nService.getAllNotices();
    for (Notice notice : notices) {
        String time = notice.getN_time();
        String temp = String.format("%s-%s-%s %s:%s:%s", time.substring(0, 4),time.substring(4, 6),time.substring(6,8),
            time.substring(8, 10),time.substring(10, 12),time.substring(12, 14));
        notice.setN_time(temp);
    }
    req.setAttribute("notices", notices);
    req.getRequestDispatcher("/admin/notices/list.jsp").forward(req, resp);
}
所用到的五个工具类
filter监听器和web.xml的配置
import java.io.IOException;
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.annotation.WebFilter;
/**
 * Servlet Filter implementation class EncodingFilter
 */
@WebFilter("/EncodingFilter")
public class EncodingFilter implements Filter {
    // 定义替换后的字符集,从过滤器的配置参数中读取
    private String characterEncoding;
    /**
     * Default constructor.
     */
    public EncodingFilter() {
        // TODO Auto-generated constructor stub
    }
    /**
     * @see Filter#destroy()
     */
    public void destroy() {
        // TODO Auto-generated method stub
    }
    
    /**
     * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("web.xml中该过滤器配置的encoding值为" + characterEncoding);
        request.setCharacterEncoding(characterEncoding);
        response.setContentType("text/html;charset=" + characterEncoding);
        chain.doFilter(request, response);
    }
    
    /**
     * @see Filter#init(FilterConfig)
     */
    public void init(FilterConfig fConfig) throws ServletException {
        // 获取web.xml中filter配置的参数
        if (fConfig.getInitParameter("encoding") != null) {
            characterEncoding = fConfig.getInitParameter("encoding");
        } else {
            characterEncoding = "UTF-8";
        }
    }
}
<filter>
    <filter-name>EncodingFilter</filter-name>
    <filter-class>bookstore.web.filter.EncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>EncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
服务器端搭建web环境
  • 之前已经安装过 jdk1.8 和 tomcat9,经测试可用。这次安装的是 MySQL5.7。环境是阿里云的ecs服务器Ubuntu18无GUI。
  • 一系列的问题,我放在了另一篇博客。
  • MySQL5.7的安装、配置、远程连接-Ubuntu18
  • 项目的部署:将项目打包成war文件放在tomcat的webapps下,重启tomcat。
项目运行出现的问题

MySQL5.7与MySQL5.5的差异,导致项目直接运行失败。(我电脑上是5.5,服务器上是5.7)

问题出现的原因:
MySQL 5.7.5及以上功能依赖检测功能。如果启用了ONLY_FULL_GROUP_BY SQL模式(默认情况下),MySQL将拒绝选择列表,HAVING条件或ORDER BY列表的查询引用在GROUP BY子句中既未命名的非集合列,也不在功能上依赖于它们。(5.7.5之前,MySQL没有检测到功能依赖关系,默认情况下不启用ONLY_FULL_GROUP_BY。有关5.7.5之前的行为的说明,请参见“MySQL 5.6参考手册”。)

将eclipse项目导入到idea
使用 Alibaba Cloud Toolkit 中间件 部署项目

猜你喜欢

转载自blog.csdn.net/weixin_43845524/article/details/106296510