基于JSP+Servlet的旅游美食信息管理系统 - 源码深度解析

JavaScriptHTMLCSSMySQLJSP+Servlet
2026-03-114 浏览

文章摘要

本项目是一款基于JSP与Servlet技术栈构建的旅游美食信息管理系统,旨在解决旅游目的地餐饮信息分散、商家自主管理困难以及用户查询不便的核心痛点。系统通过集中式的在线管理平台,将地方特色美食、餐厅介绍、用户评价等信息进行统一整合与动态维护,为游客提供真实可靠的餐饮决策支持,同时极大降低了商家的信息...

在旅游信息化快速发展的背景下,游客对目的地餐饮信息的需求日益精细化,而传统的信息分散模式难以满足这一需求。针对这一痛点,设计并实现了一套集中式的美食信息管理平台。该系统采用经典的JSP+Servlet技术架构,通过MVC模式实现了业务逻辑、数据呈现和用户交互的有效分离。

系统架构分为三个核心层次:表现层使用JSP动态页面技术结合HTML/CSS/JavaScript构建用户界面;控制层通过Servlet组件处理所有前端请求和业务逻辑分发;数据持久层采用JDBC技术实现与MySQL数据库的交互。这种分层架构确保了系统具有良好的可维护性和扩展性。

系统首页

数据库设计包含7个核心数据表,其中美食信息表的设计体现了系统的核心业务逻辑:

CREATE TABLE food_info (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100) NOT NULL,
    description TEXT,
    price DECIMAL(10,2),
    restaurant_id INT,
    category_id INT,
    image_url VARCHAR(200),
    status TINYINT DEFAULT 1,
    create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (restaurant_id) REFERENCES restaurant(id),
    FOREIGN KEY (category_id) REFERENCES food_category(id)
);

该表通过外键关联实现数据完整性约束,price字段使用DECIMAL类型确保金额计算的精确性,status字段支持软删除逻辑,时间戳字段自动记录数据变更历史。这种设计为系统的核心功能提供了稳健的数据支撑。

用户管理模块采用角色权限分离机制,管理员和普通用户通过统一的登录入口进行身份验证:

public class UserServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String userType = request.getParameter("userType");
        
        UserDAO userDAO = new UserDAO();
        User user = userDAO.validateLogin(username, password, userType);
        
        if(user != null) {
            HttpSession session = request.getSession();
            session.setAttribute("currentUser", user);
            if("admin".equals(userType)) {
                response.sendRedirect("admin/dashboard.jsp");
            } else {
                response.sendRedirect("user/home.jsp");
            }
        } else {
            request.setAttribute("errorMsg", "用户名或密码错误");
            request.getRequestDispatcher("login.jsp").forward(request, response);
        }
    }
}

用户登录

美食信息管理功能实现了完整的CRUD操作链,通过DAO模式封装数据访问逻辑:

public class FoodDAO {
    public boolean addFood(Food food) {
        String sql = "INSERT INTO food_info(name, description, price, restaurant_id, category_id, image_url) VALUES(?,?,?,?,?,?)";
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setString(1, food.getName());
            pstmt.setString(2, food.getDescription());
            pstmt.setBigDecimal(3, food.getPrice());
            pstmt.setInt(4, food.getRestaurantId());
            pstmt.setInt(5, food.getCategoryId());
            pstmt.setString(6, food.getImageUrl());
            return pstmt.executeUpdate() > 0;
        } catch (SQLException e) {
            e.printStackTrace();
            return false;
        }
    }
    
    public List<Food> getFoodsByCategory(int categoryId) {
        List<Food> foodList = new ArrayList<>();
        String sql = "SELECT * FROM food_info WHERE category_id = ? AND status = 1";
        // 查询实现细节
        return foodList;
    }
}

美食管理

地理位置服务模块通过集成百度地图API实现附近美食搜索功能,该功能基于用户当前位置动态计算距离并排序:

function initMap() {
    var map = new BMap.Map("mapContainer");
    var geolocation = new BMap.Geolocation();
    
    geolocation.getCurrentPosition(function(r) {
        if(this.getStatus() == BMAP_STATUS_SUCCESS) {
            var pt = r.point;
            map.centerAndZoom(pt, 15);
            
            // 获取附近美食数据
            $.getJSON('NearbyFoodServlet?lat=' + pt.lat + '&lng=' + pt.lng, function(data) {
                displayNearbyFoods(data, map);
            });
        }
    });
}

function displayNearbyFoods(foods, map) {
    foods.forEach(function(food) {
        var point = new BMap.Point(food.longitude, food.latitude);
        var marker = new BMap.Marker(point);
        map.addOverlay(marker);
        
        var infoWindow = new BMap.InfoWindow(`
            <div class="food-info-window">
                <h4>${food.name}</h4>
                <p>距离:${food.distance}米</p>
                <p>价格:¥${food.price}</p>
            </div>
        `);
        
        marker.addEventListener("click", function() {
            this.openInfoWindow(infoWindow);
        });
    });
}

附近美食搜索

收藏功能模块通过会话管理实现用户个性化数据持久化:

public class FavoriteServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        HttpSession session = request.getSession();
        User user = (User) session.getAttribute("currentUser");
        
        if(user == null) {
            response.getWriter().write("{\"status\":\"error\",\"message\":\"请先登录\"}");
            return;
        }
        
        int foodId = Integer.parseInt(request.getParameter("foodId"));
        String action = request.getParameter("action");
        
        FavoriteDAO favoriteDAO = new FavoriteDAO();
        boolean success = false;
        
        if("add".equals(action)) {
            success = favoriteDAO.addFavorite(user.getId(), foodId);
        } else if("remove".equals(action)) {
            success = favoriteDAO.removeFavorite(user.getId(), foodId);
        }
        
        String result = success ? "{\"status\":\"success\"}" : "{\"status\":\"error\"}";
        response.getWriter().write(result);
    }
}

系统采用过滤器技术实现统一的字符编码处理和权限验证:

@WebFilter("/*")
public class EncodingFilter implements Filter {
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
            throws IOException, ServletException {
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        chain.doFilter(request, response);
    }
}

@WebFilter("/admin/*")
public class AdminAuthFilter implements Filter {
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
            throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        HttpSession session = req.getSession();
        
        User user = (User) session.getAttribute("currentUser");
        if(user == null || !"admin".equals(user.getType())) {
            res.sendRedirect(req.getContextPath() + "/login.jsp");
            return;
        }
        chain.doFilter(request, response);
    }
}

用户收藏管理

数据统计模块为管理员提供业务洞察能力:

public class StatisticsDAO {
    public Map<String, Object> getDashboardData() {
        Map<String, Object> data = new HashMap<>();
        String sql = "SELECT " +
            "(SELECT COUNT(*) FROM user WHERE type = 'user') as userCount, " +
            "(SELECT COUNT(*) FROM restaurant) as restaurantCount, " +
            "(SELECT COUNT(*) FROM food_info WHERE status = 1) as foodCount, " +
            "(SELECT COUNT(*) FROM favorite) as favoriteCount";
        
        try (Connection conn = DBUtil.getConnection();
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(sql)) {
            if(rs.next()) {
                data.put("userCount", rs.getInt("userCount"));
                data.put("restaurantCount", rs.getInt("restaurantCount"));
                data.put("foodCount", rs.getInt("foodCount"));
                data.put("favoriteCount", rs.getInt("favoriteCount"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return data;
    }
}

数据统计视图

在实体模型设计方面,系统通过面向对象的方式封装业务数据:

public class Food {
    private int id;
    private String name;
    private String description;
    private BigDecimal price;
    private int restaurantId;
    private int categoryId;
    private String imageUrl;
    private int status;
    private Timestamp createTime;
    private Timestamp updateTime;
    
    // 构造函数、getter和setter方法
    public Food() {}
    
    public Food(String name, String description, BigDecimal price, 
                int restaurantId, int categoryId, String imageUrl) {
        this.name = name;
        this.description = description;
        this.price = price;
        this.restaurantId = restaurantId;
        this.categoryId = categoryId;
        this.imageUrl = imageUrl;
    }
    
    // 完整的getter和setter方法
    public int getId() { return id; }
    public void setId(int id) { this.id = id; }
    
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    
    // 其他属性方法...
}

数据库连接管理采用连接池技术优化性能:

public class DBUtil {
    private static DataSource dataSource;
    
    static {
        try {
            Context initContext = new InitialContext();
            Context envContext = (Context) initContext.lookup("java:/comp/env");
            dataSource = (DataSource) envContext.lookup("jdbc/travelFoodDB");
        } catch (NamingException e) {
            e.printStackTrace();
        }
    }
    
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }
}

系统在以下方面具有显著的技术优势:采用标准的MVC架构确保代码的可维护性;通过DAO模式实现数据访问层的抽象;使用过滤器技术处理跨切面关注点;集成第三方地图服务增强用户体验。

未来优化方向包括:引入Redis缓存层提升系统性能,实现Elasticsearch全文搜索提高查询效率,开发微信小程序扩展移动端访问渠道,集成支付功能支持在线预订,以及采用微服务架构提升系统可扩展性。这些优化将进一步提升系统的实用性和技术先进性。

本文关键词
JSPServlet旅游美食信息管理系统源码解析MVC架构

上下篇

上一篇
没有更多文章
下一篇
没有更多文章