基于JSP+Servlet的南京地区旅游信息服务平台 - 源码深度解析

JavaScriptHTMLCSSMySQLJSP+Servlet
2026-02-114 浏览

文章摘要

本项目是一个针对南京地区旅游资源整合与服务的专业信息平台,采用经典的JSP+Servlet技术栈构建。其核心业务价值在于解决游客与本地旅游资源之间信息不对称的痛点,通过集中化、结构化的方式展示南京的景点、餐饮、住宿及文化活动信息,有效避免了游客因信息碎片化而导致的规划困难和时间浪费,为提升南京旅游体...

南京作为六朝古都,拥有丰富的历史文化遗产和现代都市魅力,每年吸引大量游客前来观光。然而,旅游信息的碎片化分布给游客规划行程带来了不小的挑战。各类景点信息、住宿推荐、交通指南分散在不同平台,缺乏统一整合。针对这一痛点,我们开发了南京智慧旅游门户平台,通过集中化信息管理和智能化服务推荐,为游客提供一站式的旅游信息服务体验。

系统架构与技术栈

平台采用经典的JSP+Servlet三层架构,严格遵循MVC设计模式。前端使用HTML+CSS+JavaScript构建用户界面,结合JSP动态页面技术实现数据展示。后端基于Servlet处理业务逻辑,通过JDBC与MySQL数据库进行数据交互。这种架构确保了系统的高内聚低耦合,便于后续维护和功能扩展。

在技术选型上,JSP负责视图渲染,使用JSTL标签库和EL表达式替代传统的Scriptlet代码,提升了代码的可读性和维护性。Servlet作为控制器层,统一处理HTTP请求,进行参数验证和业务分发。数据库连接池的使用优化了系统性能,避免了频繁创建和销毁数据库连接的开销。

数据库设计亮点

旅游景点表设计分析

CREATE TABLE `lvyoujingdian` (
  `ID` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `jingdianbianhao` varchar(50) DEFAULT '' COMMENT '景点编号',
  `jingdianmingcheng` varchar(50) DEFAULT '' COMMENT '景点名称',
  `jingdianzhutu` varchar(50) DEFAULT '' COMMENT '景点主图',
  `suoshudiqu` varchar(50) DEFAULT '' COMMENT '所属地区',
  `jingdianjieshao` mediumtext DEFAULT NULL COMMENT '景点介绍',
  `menpiaojiage` varchar(50) DEFAULT '' COMMENT '门票价格',
  `kaifangshijian` varchar(50) DEFAULT '' COMMENT '开放时间',
  `issh` varchar(2) DEFAULT '否' COMMENT '是否审核',
  `addtime` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '添加时间',
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8 COMMENT='旅游景点表'

该表设计体现了良好的规范化思想。ID字段作为自增主键,确保每条记录的唯一性。jingdianbianhao采用业务编号机制,便于管理查询。mediumtext类型的jingdianjieshao字段支持详细的景点描述,满足富文本内容存储需求。issh审核状态字段和addtime时间戳为后台管理提供了有效的数据控制手段。

用户注册表设计优化

CREATE TABLE `yonghuzhuce` (
  `ID` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `yonghuming` varchar(50) DEFAULT '' COMMENT '用户名',
  `mima` varchar(50) DEFAULT '' COMMENT '密码',
  `xingming` varchar(50) DEFAULT '' COMMENT '姓名',
  `xingbie` varchar(2) DEFAULT '' COMMENT '性别',
  `chushengnianyue` varchar(50) DEFAULT '' COMMENT '出生年月',
  `QQ` varchar(50) DEFAULT '' COMMENT 'QQ',
  `youxiang` varchar(50) DEFAULT '' COMMENT '邮箱',
  `dianhua` varchar(50) DEFAULT '' COMMENT '电话',
  `shenfenzheng` varchar(50) DEFAULT '' COMMENT '身份证',
  `touxiang` varchar(50) DEFAULT '' COMMENT '头像',
  `dizhi` varchar(300) DEFAULT '' COMMENT '地址',
  `beizhu` varchar(500) DEFAULT '' COMMENT '备注',
  `addtime` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '添加时间',
  `issh` varchar(2) DEFAULT '否' COMMENT '是否审核',
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 COMMENT='用户注册表'

用户表设计考虑了完整的用户画像需求。各字段长度设置合理,如dizhi地址字段预留300字符空间,beizhu备注字段500字符,满足不同场景下的信息存储需求。身份证、电话、邮箱等敏感信息单独存储,便于后续的数据加密处理。审核状态机制确保了用户质量可控。

用户注册界面

核心功能实现

景点信息管理模块

景点管理是平台的核心功能,实现了景点信息的增删改查完整流程。后端通过Servlet统一接收请求,调用相应的Service层处理业务逻辑。

景点查询Servlet核心代码:

@WebServlet("/jingdainQueryServlet")
public class JingdainQueryServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
        
        String jingdianmingcheng = request.getParameter("jingdianmingcheng");
        String suoshudiqu = request.getParameter("suoshudiqu");
        String currentPage = request.getParameter("currentPage");
        
        JingdainService service = new JingdainService();
        PageBean<Jingdain> pageBean = service.findByPage(jingdianmingcheng, suoshudiqu, currentPage);
        
        request.setAttribute("pageBean", pageBean);
        request.getRequestDispatcher("/admin/jingdain/list.jsp").forward(request, response);
    }
}

分页查询业务逻辑:

public class JingdainService {
    public PageBean<Jingdain> findByPage(String jingdianmingcheng, String suoshudiqu, String currentPageStr) {
        Connection conn = null;
        try {
            int currentPage = Integer.parseInt(currentPageStr);
            int pageSize = 10;
            PageBean<Jingdain> pageBean = new PageBean<>();
            pageBean.setCurrentPage(currentPage);
            pageBean.setPageSize(pageSize);
            
            conn = JDBCUtils.getConnection();
            JingdainDao dao = new JingdainDao();
            
            // 查询总记录数
            int totalCount = dao.findTotalCount(conn, jingdianmingcheng, suoshudiqu);
            pageBean.setTotalCount(totalCount);
            
            // 查询当前页数据
            int start = (currentPage - 1) * pageSize;
            List<Jingdain> list = dao.findByPage(conn, jingdianmingcheng, suoshudiqu, start, pageSize);
            pageBean.setList(list);
            
            return pageBean;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            JDBCUtils.closeConnection(conn);
        }
    }
}

景点管理界面

用户评论系统

评论系统采用异步提交方式,提升用户体验。前端通过AJAX技术实现无刷新提交,后端进行数据验证和存储。

评论提交Servlet:

@WebServlet("/pinglunAddServlet")
public class PinglunAddServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
        
        request.setCharacterEncoding("utf-8");
        String xinwenID = request.getParameter("xinwenID");
        String pinglunneirong = request.getParameter("pinglunneirong");
        String pinglunren = request.getParameter("pinglunren");
        String pingfen = request.getParameter("pingfen");
        String biao = request.getParameter("biao");
        String jdmc = request.getParameter("jdmc");
        
        // 数据验证
        if (pinglunneirong == null || pinglunneirong.trim().isEmpty()) {
            response.getWriter().write("error:评论内容不能为空");
            return;
        }
        
        Pinglun pinglun = new Pinglun();
        pinglun.setXinwenID(xinwenID);
        pinglun.setPinglunneirong(pinglunneirong);
        pinglun.setPinglunren(pinglunren);
        pinglun.setPingfen(pingfen);
        pinglun.setBiao(biao);
        pinglun.setJdmc(jdmc);
        
        PinglunService service = new PinglunService();
        boolean result = service.addPinglun(pinglun);
        
        response.setContentType("application/json;charset=utf-8");
        if (result) {
            response.getWriter().write("{\"status\":\"success\"}");
        } else {
            response.getWriter().write("{\"status\":\"error\"}");
        }
    }
}

评论数据访问层:

public class PinglunDao {
    public boolean addPinglun(Connection conn, Pinglun pinglun) throws SQLException {
        String sql = "INSERT INTO pinglun (xinwenID, pinglunneirong, pinglunren, pingfen, biao, jdmc) VALUES (?, ?, ?, ?, ?, ?)";
        PreparedStatement pstmt = null;
        
        try {
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, pinglun.getXinwenID());
            pstmt.setString(2, pinglun.getPinglunneirong());
            pstmt.setString(3, pinglun.getPinglunren());
            pstmt.setString(4, pinglun.getPingfen());
            pstmt.setString(5, pinglun.getBiao());
            pstmt.setString(6, pinglun.getJdmc());
            
            return pstmt.executeUpdate() > 0;
        } finally {
            if (pstmt != null) {
                pstmt.close();
            }
        }
    }
}

评论功能界面

权限管理系统

平台采用基于角色的访问控制机制,通过管理员表实现多级权限管理。

登录验证Servlet:

@WebServlet("/loginServlet")
public class LoginServlet 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");
        
        // 密码MD5加密验证
        String encryptedPwd = MD5Util.encrypt(password);
        
        if ("admin".equals(userType)) {
            AdminService adminService = new AdminService();
            Admin admin = adminService.login(username, encryptedPwd);
            
            if (admin != null) {
                HttpSession session = request.getSession();
                session.setAttribute("admin", admin);
                response.sendRedirect("admin/index.jsp");
            } else {
                request.setAttribute("login_error", "用户名或密码错误");
                request.getRequestDispatcher("admin/login.jsp").forward(request, response);
            }
        } else {
            UserService userService = new UserService();
            User user = userService.login(username, encryptedPwd);
            
            if (user != null) {
                if ("是".equals(user.getIssh())) {
                    HttpSession session = request.getSession();
                    session.setAttribute("user", user);
                    response.sendRedirect("index.jsp");
                } else {
                    request.setAttribute("login_error", "账号待审核,请联系管理员");
                    request.getRequestDispatcher("login.jsp").forward(request, response);
                }
            } else {
                request.setAttribute("login_error", "用户名或密码错误");
                request.getRequestDispatcher("login.jsp").forward(request, response);
            }
        }
    }
}

权限拦截过滤器:

@WebFilter("/*")
public class PermissionFilter implements Filter {
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) 
        throws IOException, ServletException {
        
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        String uri = request.getRequestURI();
        
        // 放行静态资源和登录页面
        if (uri.contains("/css/") || uri.contains("/js/") || uri.contains("/images/") || 
            uri.contains("/login.jsp") || uri.contains("/loginServlet")) {
            chain.doFilter(req, resp);
            return;
        }
        
        HttpSession session = request.getSession();
        
        // 管理员权限验证
        if (uri.contains("/admin/")) {
            Admin admin = (Admin) session.getAttribute("admin");
            if (admin == null) {
                response.sendRedirect(request.getContextPath() + "/admin/login.jsp");
                return;
            }
        }
        
        // 用户权限验证
        if (uri.contains("/user/")) {
            User user = (User) session.getAttribute("user");
            if (user == null) {
                response.sendRedirect(request.getContextPath() + "/login.jsp");
                return;
            }
        }
        
        chain.doFilter(req, resp);
    }
}

管理员登录界面

实体模型设计

平台采用面向对象的设计思想,为每个数据库表创建对应的实体类,封装业务属性和行为。

旅游景点实体类:

public class Lvyoujingdian {
    private Integer ID;
    private String jingdianbianhao;
    private String jingdianmingcheng;
    private String jingdianzhutu;
    private String suoshudiqu;
    private String jingdianjieshao;
    private String menpiaojiage;
    private String kaifangshijian;
    private String issh;
    private Timestamp addtime;
    
    // 构造方法
    public Lvyoujingdian() {}
    
    public Lvyoujingdian(Integer ID, String jingdianbianhao, String jingdianmingcheng, 
                        String jingdianzhutu, String suoshudiqu, String jingdianjieshao,
                        String menpiaojiage, String kaifangshijian, String issh, Timestamp addtime) {
        this.ID = ID;
        this.jingdianbianhao = jingdianbianhao;
        this.jingdianmingcheng = jingdianmingcheng;
        this.jingdianzhutu = jingdianzhutu;
        this.suoshudiqu = suoshudiqu;
        this.jingdianjieshao = jingdianjieshao;
        this.menpiaojiage = menpiaojiage;
        this.kaifangshijian = kaifangshijian;
        this.issh = issh;
        this.addtime = addtime;
    }
    
    // Getter和Setter方法
    public Integer getID() { return ID; }
    public void setID(Integer ID) { this.ID = ID; }
    
    public String getJingdianbianhao() { return jingdianbianhao; }
    public void setJingdianbianhao(String jingdianbianhao) { this.jingdianbianhao = jingdianbianhao; }
    
    // 其他getter/setter方法...
    
    // 业务方法
    public boolean isAudited() {
        return "是".equals(this.issh);
    }
    
    public String getPriceDisplay() {
        if ("免费".equals(this.menpiaojiage) || this.menpiaojiage == null) {
            return "免费开放";
        } else {
            return "¥" + this.menpiaojiage;
        }
    }
}

用户注册实体类:

public class Yonghuzhuce {
    private Integer ID;
    private String yonghuming;
    private String mima;
    private String xingming;
    private String xingbie;
    private String chushengnianyue;
    private String QQ;
    private String youxiang;
    private String dianhua;
    private String shenfenzheng;
    private String touxiang;
    private String dizhi;
    private String beizhu;
    private Timestamp addtime;
    private String issh;
    
    // 构造方法和getter/setter...
    
    public boolean isAdult() {
        if (chushengnianyue != null && chushengnianyue.length() >= 4) {
            int birthYear = Integer.parseInt(chushengnianyue.substring(0, 4));
            int currentYear = Calendar.getInstance().get(Calendar.YEAR);
            return (currentYear - birthYear) >= 18;
        }
        return false;
    }
    
    public String getMaskedIdentity() {
        if (shenfenzheng != null && shenfenzheng.length() > 10) {
            return shenfenzheng.substring(0, 6) + "****" + shenfenzheng.substring(14);
        }
        return shenfenzheng;
    }
}

用户个人信息界面

功能展望与优化

智能化推荐引擎

当前平台主要提供基础的信息查询功能,未来可引入机器学习算法构建个性化推荐系统。基于用户的历史浏览记录、收藏行为和评论内容,使用协同过滤算法为用户推荐可能感兴趣的景点和旅游路线。

实现思路:

  • 收集用户行为数据,建立用户画像
  • 使用Apache Mahout或Spark MLlib实现推荐算法
  • 通过Redis缓存热门推荐结果,提升响应速度

微服务架构改造

随着业务规模扩大,可将单体应用拆分为微服务架构。将用户服务、景点服务、评论服务等独立部署,提高系统的可扩展性和容错能力。

架构规划:

// 用户服务接口示例
@FeignClient(name = "user-service")
public interface UserServiceClient {
    @GetMapping("/users/{id}")
    User getUserById(@PathVariable("id") Integer id);
    
    @PostMapping("/users")
    ResponseEntity<User> createUser(@RequestBody User user);
}

// 景点服务接口示例  
@FeignClient(name = "attraction-service")
public interface AttractionServiceClient {
    @GetMapping("/attractions")
    Page<Attraction> getAttractions(@RequestParam Map<String, String> params);
}

移动端适配优化

开发响应式前端界面,

本文关键词
JSPServlet旅游信息平台南京旅游系统架构

上下篇

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