旅游网项目02

1. 前言

旅游网项目,今日内容主要为优化Servlet、分类数据查询和分页查询。

2. 优化Servlet

2.1 目的

为了减少Servlet的数量,现在是一个功能一个Servlet,将其优化为相同功能的Servlet为一个模块。相当于在数据库中一张表对应一个Servlet,在Servlet中提供不同的方法,完成用户的请求。

2.2 BaseServlet编写

主要进行方法的分发,利用反射机制,获取请求路径和方法名称,再获取方法对象然后执行。

package cn.itcast.travel.web.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 使用反射机制,完成方法的分发
 */
public class BaseServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("baseServlet的service方法被执行");

        // 完成方法分发
        // 1. 获取请求路径
        String uri = req.getRequestURI(); // uri = /travel/user/add
        System.out.println("请求uri:"+uri);
        // 2. 获取方法名称
        String methodName = uri.substring(uri.lastIndexOf('/') + 1);// 为何+1?
        System.out.println("方法名称"+methodName);
        // 3. 获取方法对象Method
        System.out.println(this); // this表示当前调用service的对象,谁调用我我表示谁
        try {
            // 获取方法
            Method method = this.getClass().getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
            // 4.执行方法
            method.invoke(this,req,resp);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

2.3 UserServlet改写

继承自BaseServlet,所有用户相关的方法都抽取在内。只需访问user/对应方法即可完成相应功能。

package cn.itcast.travel.web.servlet;

import cn.itcast.travel.domain.ResultInfo;
import cn.itcast.travel.domain.User;
import cn.itcast.travel.service.UserService;
import cn.itcast.travel.service.impl.UserServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.beanutils.BeanUtils;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;

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

    // 声明UserService业务对象
    private UserService service = new UserServiceImpl();


    /**
     * @Description: 用户注册功能
     * @Author: zero
     * @param request
     * @param response
     * @return void
     * @Date 2019/7/23 21:35
     */
    public void regist(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 获取用户输入的验证码
        String check = request.getParameter("check");
        // 从session中获取生成的验证码
        HttpSession session = request.getSession();
        String checkcode_server = (String)session.getAttribute("CHECKCODE_SERVER");
        session.removeAttribute("CHECKCODE_SERVER"); // 确保验证码只能使用一次
        // 如果验证码错误,直接注册失败
        if (checkcode_server == null || !checkcode_server.equalsIgnoreCase(check)){
            // 验证码错误
            ResultInfo info = new ResultInfo();
            // 注册失败
            info.setFlag(false);
            info.setErrorMsg("验证码错误");
            // 将info对象序列化为json
            ObjectMapper mapper = new ObjectMapper();
            String json = mapper.writeValueAsString(info);
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().write(json);
            return; // todo:为何return?
        }

        // 验证通过
        // 1. 获取前台表单数据
        Map<String, String[]> map = request.getParameterMap();

        // 2. 封装为user对象
        User user = new User();
        try {
            BeanUtils.populate(user,map);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        // 3. 调用service完成注册
        service = new UserServiceImpl();
        boolean flag = service.regist(user);
        ResultInfo info = new ResultInfo();
        // 4. 响应结果
        if (flag){
            // 注册成功
            info.setFlag(true);
        }else{
            // 注册失败
            info.setFlag(false);
            info.setErrorMsg("注册失败!");
        }

        // 将info对象序列化为json
        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(info);
        // 将json数据回写客户端
        // 设置content-type
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(json);
    }

    /**
     * @Description: 邮箱激活功能
     * @Author: zero
     * @param request
     * @param response
     * @return void
     * @Date 2019/7/23 21:36
     */
    public void active(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 1. 获取激活码
        String code = request.getParameter("code");
        if (code != null){
            // 2. 调用service完成激活
            service = new UserServiceImpl();
            boolean flag = service.active(code);
            // 3. 判断标记
            String msg = null;
            if (flag){
                // 激活成功
                msg = "激活成功,请<a href='login.html'>登录</a>";
            }else{
                // 激活失败
                msg = "激活失败,请联系管理员!";
            }
            // 回写数据
            response.setContentType("text/html;charset=utf-8");
            response.getWriter().write(msg);
        }
    }

    /**
     * @Description: 用户登录功能
     * @Author: zero
     * @param request
     * @param response
     * @return void
     * @Date 2019/7/23 21:37
     */
    public void login(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 1. 获取用户名和密码
        Map<String, String[]> map = request.getParameterMap();
        // 2. 封装User对象
        User user = new User();
        try {
            BeanUtils.populate(user,map);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        // 3. 调用service查询
        service = new UserServiceImpl();
        User u = service.login(user);
        ResultInfo info = new ResultInfo();

        // 4. 判断用户对象是否为null
        if (u == null){
            // 用户名或密码错误
            info.setFlag(false);
            info.setErrorMsg("用户名或密码错误");
        }
        // 5. 判断用户账户是否激活
        if (u != null && !"Y".equals(u.getStatus())){
            // 用户未激活
            info.setFlag(false);
            info.setErrorMsg("您的账户尚未激活,请激活");
        }
        // 6. 判断登录成功
        if (u != null && "Y".equals(u.getStatus())){
            // 登录成功
            info.setFlag(true);
            // 将登陆用户信息存入session中
            request.getSession().setAttribute("user",u);
        }
        // 响应数据
        ObjectMapper mapper = new ObjectMapper();
        response.setContentType("application/json;charset=utf-8");
        mapper.writeValue(response.getOutputStream(),info);
    }

    /**
     * @Description: 查询单个用户,前台显示登录用户功能
     * @Author: zero
     * @param request
     * @param response
     * @return void
     * @Date 2019/7/23 21:38
     */
    public void findOne(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 从session中获取登录用户
        Object user = request.getSession().getAttribute("user");
        // 将user回写客户端
        ObjectMapper mapper = new ObjectMapper();
        response.setContentType("application/json;charset=utf-8");
        mapper.writeValue(response.getOutputStream(),user);
    }

    /**
     * @Description: 用户退出功能
     * @Author: zero
     * @param request
     * @param response
     * @return void
     * @Date 2019/7/23 21:38
     */
    public void exit(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 1. 销毁session
        request.getSession().invalidate();
        // 2. 跳转到登录页面
        response.sendRedirect(request.getContextPath()+"/login.html");
    }
}

2.4 页面路径改写

将所有用户相关的请求路径改为user/对应方法。例登录路径:user/login

激活功能URL:String content = "<a href='http://localhost/travel/user/active?code="+user.getCode()+"'>点击激活账户</a>";

3. 分类数据展示

3.1 分析

title

3.2 后台代码实现

3.2.1 CategoryServlet代码

package cn.itcast.travel.web.servlet;

import cn.itcast.travel.domain.Category;
import cn.itcast.travel.service.CategoryService;
import cn.itcast.travel.service.impl.CategoryServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * @Author: zero
 * @Description: Date:Create: in 2019/7/23 22:51
 * Modified By:
 */
@WebServlet("/category/*")
public class CategoryServlet extends BaseServlet {
    private CategoryService service = new CategoryServiceImpl();

    /**
     * @Description:查询所有
     * @Author: zero
     * @param request
     * @param response
     * @return void
     * @Date 2019/7/23 22:52
     */
    public void findAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1. 调用servvice查询所有
        List<Category> categories = service.findAll();
        // 2. 序列化为json返回
        writeValue(categories,response);
    }
}

3.2.2 CategoryService代码

package cn.itcast.travel.service.impl;

import cn.itcast.travel.dao.CategoryDao;
import cn.itcast.travel.dao.impl.CategoryDaoImpl;
import cn.itcast.travel.domain.Category;
import cn.itcast.travel.service.CategoryService;

import java.util.List;

/**
 * @Author: zero
 * @Description: Date:Create: in 2019/7/23 22:49
 * Modified By:
 */

public class CategoryServiceImpl implements CategoryService {

    private CategoryDao categoryDao = new CategoryDaoImpl();

    @Override
    public List<Category> findAll() {
        return categoryDao.findAll();
    }
}

3.2.3 CategoryDao代码

package cn.itcast.travel.dao;

import cn.itcast.travel.domain.Category;

import java.util.List;

/**
 * @Author: zero
 * @Description: Date:Create: in 2019/7/23 22:42
 * Modified By:
 */
public interface CategoryDao {
    /**
     * @Description: 查询所有
     * @Author: zero
     * @param
     * @return List集合
     * @Date 2019/7/23 22:44
     */
    List<Category> findAll();
}

3.2.4 优化部分代码

将序列化json方法封装在BaseServlet,减少代码冗余

/**
     * @Description: 直接将传入的对象序列化为json,并且写回客户端
     * @Author: zero
     * @param obj
     * @param response
     * @return void
     * @Date 2019/7/23 23:16
     */
public void writeValue(Object obj,HttpServletResponse response) throws IOException{
    ObjectMapper mapper = new ObjectMapper();
    response.setContentType("application/json;charset=utf-8");
    mapper.writeValue(response.getOutputStream(),obj);
}
/**
     * @Description: 将传入的对象序列化为json后返回
     * @Author: zero
     * @param obj
     * @return String
     * @Date 2019/7/23 23:18
     */
public String writeValueAsString(Object obj) throws JsonProcessingException {
    return new ObjectMapper().writeValueAsString(obj);
}

3.3 前台代码实现

// 查询分类数据
$.get("category/findAll",{},function (data) {
    // [{cid:1,cname:xxx},{cid:2,cname:xxx},]
    var lis = '<li class="nav-active"><a href="index.html">首页</a></li>';
    // 遍历数组,拼接字符串(<li>)
    for (var i = 0; i < data.length; i++) {
        var li = '<li><a href="route_list.html">'+data[i].cname+'</a></li>';
        lis += li;
    }
    // 拼接收藏排行榜的li,<li><a href="favoriterank.html"> 收藏排行榜</a></li>
    lis+='<li><a href="favoriterank.html">收藏排行榜</a></li>';
    // 将lis字符串,设置到ul的html内容中
    $("#category").html(lis);
})

3.4 对分类数据进行缓存优化

分类的数据在每一次页面加载后都会重新请求数据库来加载,对数据库的压力比较大,且分类的数据不会经常产生变化,故在此可以使用redis来缓存这个数据。

3.5 优化代码实现

/**
     * @Description: 使用redis缓存,优化代码,减少对数据库的访问
     * @Author: zero
     * @param
     * @return List
     * @Date 2019/7/24 20:52
     */
@Override
public List<Category> findAll() {
    // 初始化集合对象
    List<Category> cs = null;
    // 1. 从redis中查询数据
    // 1.1 获取redis客户端连接对象
    Jedis jedis = JedisUtil.getJedis();
    // 1.2 使用sortedset排序查询
    Set<String> categorys = jedis.zrange("category", 0, -1);
    // 2. 判断集合是否为null
    if (categorys == null || categorys.size() == 0){
        // 2.1 为空,则表示第一次访问
        System.out.println("redis中无数据,查询数据库...");
        // 2.2 查询数据库,获取数据
        cs = categoryDao.findAll();
        // 2.3 将集合数据存储到redis中的category的key
        for (int i = 0; i < cs.size(); i++) {
            jedis.zadd("category",cs.get(i).getCid(),cs.get(i).getCname());
        }

    }else{
        // 3. 不为空,将查询到的set集合数据存入list再返回
        // 因返回的是list集合,故将查询到的set集合数据转换为list数据
        System.out.println("redis中有数据,查询缓存...");
        cs = new ArrayList<Category>();
        for (String name : categorys) {
            Category category = new Category();
            category.setCname(name);
            cs.add(category);
        }
    }
    return cs;
}

4. 旅游线路的分页展示

4.1 类别id的传递

  • redis中查询数据是,需要将分数也查询出来;并且在返回list集合里,将cid的值设置为对应分数

title

  • 前台页面传递对应cid,修改header.html,加上data[i].cid即可。
var li = '<li><a href="route_list.html?cid='+data[i].cid+'">'+data[i].cname+'</a></li>';
  • 获取cid
$(function(){
    var search = location.search;
    // alert(search);
    // 切割字符串,拿到第二个值
    var cid = search.split("=")[1];
});

4.2 根据id查询不同类别的旅游线路

4.2.1 分析

title

4.2.2 后台代码实现

4.2.2.1 PageBean对象

后台返回给前台的对象

public class PageBean<T> {

    private int totalCount; // 总记录数
    private int totalPage; // 总页数
    private int currentPage; // 当前页码
    private int pageSize; // 每页显示的条数

    private List<T> list; // 每页显示的数据集合

    // 省略getset方法
}
4.2.2.2 RouteServlet控制器代码

负责接收前台传递的参数并处理,调用service查询到PageBean对象后序列化为json再返回给前端。

package cn.itcast.travel.web.servlet;

import cn.itcast.travel.domain.PageBean;
import cn.itcast.travel.domain.Route;
import cn.itcast.travel.service.RouteService;
import cn.itcast.travel.service.impl.RouteServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @Author: zero
 * @Description: Date:Create: in 2019/7/24 21:52
 * Modified By:
 */
@WebServlet("/route/*")
public class RouteServlet extends BaseServlet {

    private RouteService routeService = new RouteServiceImpl();

    public void pageQuery(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1. 接受参数
        String currentPageStr = request.getParameter("currentPage");
        String pageSizeStr = request.getParameter("pageSize");
        String cidStr = request.getParameter("cid");

        // 2. 处理参数
        int cid = 0; // 类别id
        if (cidStr != null && cidStr.length() > 0){
            cid = Integer.parseInt(cidStr);
        }
        int currentPage = 0; // 当前页码,如果不传递,则默认为第一页
        if (currentPageStr != null && currentPageStr.length() > 0){
            currentPage = Integer.parseInt(currentPageStr);
        }else {
            currentPage = 1;
        }
        int pageSize = 0; // 每页显示条数,默认为5
        if (pageSizeStr != null && pageSizeStr.length() > 0){
            pageSize = Integer.parseInt(pageSizeStr);
        }else {
            pageSize = 5;
        }

        // 3. 调用service查询PageBean对象
        PageBean<Route> pb = routeService.pageQuery(cid, currentPage, pageSize);
        // 4. 将pageBean对象序列化为json,返回
        writeValue(pb,response);
    }
}
4.2.2.3 RouteServiceImpl代码

根据当前页码,类别信息等,从数据库中查询出当前类别对应数据集合,封装PageBean对象后返回

package cn.itcast.travel.service.impl;

import cn.itcast.travel.dao.RouteDao;
import cn.itcast.travel.dao.impl.RouteDaoImpl;
import cn.itcast.travel.domain.PageBean;
import cn.itcast.travel.domain.Route;
import cn.itcast.travel.service.RouteService;

import java.util.List;

/**
 * @Author: zero
 * @Description: Date:Create: in 2019/7/24 22:04
 * Modified By:
 */

public class RouteServiceImpl implements RouteService {

    private RouteDao routeDao = new RouteDaoImpl();

    /**
     * @Description: 查询当前页数据集合并封装为PageBean对象后返回
     * @Author: zero
     * @param cid
     * @param currentPage
     * @param pageSize
     * @return 封装好的PageBean对象
     * @Date 2019/7/24 22:50
     */
    @Override
    public PageBean<Route> pageQuery(int cid, int currentPage, int pageSize) {
        // 封装PageBean
        PageBean<Route> pb = new PageBean<>();
        // 设置当前页码
        pb.setCurrentPage(currentPage);
        // 设置每页显示的条数
        pb.setPageSize(pageSize);
        // 设置总记录数
        int totalCount = routeDao.findTotalCount(cid);
        pb.setTotalCount(totalCount);
        // 设置当前页显示的数据集合
        int start = (currentPage - 1) * pageSize; // 开始的记录数
        List<Route> list = routeDao.findByPage(cid, start, pageSize);
        pb.setList(list);
        // 设置总页数 = 总记录数 / 每页显示条数
        int totalPage = totalCount % pageSize == 0 ? totalCount / pageSize : (totalCount / pageSize) + 1;
        pb.setTotalPage(totalPage);

        return pb;
    }
}
4.2.2.4 RouteDaoImpl,DAO实现类

查询当前类别总记录数和类别当前页的数据集合

package cn.itcast.travel.dao.impl;

import cn.itcast.travel.dao.RouteDao;
import cn.itcast.travel.domain.Route;
import cn.itcast.travel.util.JDBCUtils;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.List;

/**
 * @Author: zero
 * @Description: Date:Create: in 2019/7/24 22:09
 * Modified By:
 */

public class RouteDaoImpl implements RouteDao {

    private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());

    /**
     * @Description: 根据cid查询总记录数
     * @Author: zero
     * @param cid
     * @return 总记录数
     * @Date 2019/7/24 22:08
     */
    @Override
    public int findTotalCount(int cid) {
        return template.queryForObject("select count(*) from tab_route where cid = ?",Integer.class,cid);
    }

    /**
     * @Description: 根据cid,start,pageSize查询当前页的数据集合
     * @Author: zero
     * @param cid
     * @param start
     * @param pageSize
     * @return 查询到的当前页数据集合
     * @Date 2019/7/24 22:08
     */
    @Override
    public List<Route> findByPage(int cid, int start, int pageSize) {
        String sql = "select * from tab_route where cid = ? limit ? , ?";
        return template.query(sql,new BeanPropertyRowMapper<Route>(Route.class),cid,start,pageSize);
    }
}

4.2.3 前台代码实现

<script>
    $(function () {
    var search = location.search;
    // alert(search);
    // 切割字符串,拿到第二个值
    var cid = search.split("=")[1];

    // 当页码加载完毕后,调用load方法,
    load(cid);
})


function load(cid, currentPage) {
    // 发送ajax请求,请求route/pageQuery,传递cid
    $.get("route/pageQuery",{cid:cid,currentPage:currentPage},function (pb) {
        // 解析PageBean数据,展示到页面上
        // 1. 分页工具条数据展示
        // 1.1 展示总页码和总记录数
        $("#totalPage").html(pb.totalPage);
        $("#totalCount").html(pb.totalCount);

        var lis = "";
        var fristPage = '<li onclick="javascript:load('+cid+')"><a href="javascript:void(0)">首页</a></li>';

        // 计算上一页的页码
        var beforeNum = pb.currentPage - 1;
        if (beforeNum <= 0){
            beforeNum = 1;
        }

        var beforePage = '<li onclick="javascript:load('+cid+','+beforeNum+')" class="threeword"><a href="javascript:void(0)">上一页</a></li>';

        lis += fristPage;
        lis += beforePage;
        // 1.2 展示分页页码
        /*
                    仿百度分页样式:前五后四
                    1. 一共展示10个页码,能够达到前5后4的效果
                    2. 如果前边不足5个,后边补齐10个
                    3. 如果后边不足4个,前边补齐10个
                 */

        // 定义开始位置begin和结束位置end
        var begin; // 开始位置
        var end; // 结束位置

        // 1. 显示10个页码
        if(pb.totalPage < 10){
            // 总页码不足10页
            begin = 1;
            end = pb.totalPage;
        }else{
            // 总页码超过10页
            // 实现前5后4效果
            begin = pb.currentPage - 5;
            end = pb.currentPage + 4;

            // 进行数据修正
            // 2. 如果前边不够5个,后边补齐10个
            if (begin < 1){
                begin = 1;
                end = begin + 9;
            }
            // 3. 如果后边不足4个,前边补齐10个
            if (end > pb.totalPage){
                end = pb.totalPage;
                begin = end - 9;
            }
        }

        for (var i = begin; i <= end; i++) {
            var li;
            // 判断当前页码是否等于i
            if (pb.currentPage == i){
                li = '<li class="curPage" onclick="javascript:load('+cid+','+i+')"><a href="javascript:void(0)">'+i+'</a></li>';
            }else{
                // 创建页码的li
                li = '<li onclick="javascript:load('+cid+','+i+')"><a href="javascript:void(0)">'+i+'</a></li>';
            }
            // 拼接进字符串
            lis += li;
        }





        // for (var i = 1; i <= pb.totalPage ; i++) {
        //     var li;
        //     // 判断当前页码是否等于i
        //     if (pb.currentPage == i){
        //         li = '<li class="curPage" onclick="javascript:load('+cid+','+i+')"><a href="javascript:void(0)">'+i+'</a></li>';
        //     }else{
        //         // 创建页码的li
        //         li = '<li onclick="javascript:load('+cid+','+i+')"><a href="javascript:void(0)">'+i+'</a></li>';
        //     }
        //     // 拼接进字符串
        //     lis += li;
        // }

        // 计算下一页页码
        var nextNum = pb.currentPage + 1;
        if(nextNum >= pb.totalPage){
            nextNum = pb.totalPage;
        }

        var nextPage = '<li onclick="javascript:load('+cid+','+nextNum+')" class="threeword"><a href="javascript:void(0);">下一页</a></li>';
        var lastPage = '<li onclick="javascript:load('+cid+','+pb.totalPage+')" class="threeword"><a href="javascript:;">末页</a></li>';

        lis += nextPage;
        lis += lastPage;

        // 将lis内容设置到ul中
        $("#pageNum").html(lis);


        // 2. 列表数据展示
        var route_lis = "";

        for (var i = 0; i < pb.list.length; i++) {
            // 获取数据 {rid": 1,"rname": "xxx","price": 999.0,xxxx}
            var route = pb.list[i];
            var li = '<li>\n' +
                '                <div class="img"><img src="'+route.rimage+'" style="width: 299px"></div>\n' +
                '                    <div class="text1">\n' +
                '                    <p>'+route.rname+'</p>\n' +
                '                    <br/>\n' +
                '                    <p>'+route.routeIntroduce+'</p>\n' +
                '                </div>\n' +
                '                <div class="price">\n' +
                '                    <p class="price_num">\n' +
                '                    <span>&yen;</span>\n' +
                '                <span>'+route.price+'</span>\n' +
                '                <span>起</span>\n' +
                '                </p>\n' +
                '                <p><a href="route_detail.html">查看详情</a></p>\n' +
                '                </div>\n' +
                '             </li>';

            route_lis += li;
        }

        $("#route").html(route_lis);

        // 每次点击翻页后,定位到页面顶部
        window.scrollTo(0,0);
    });
}
</script>

  转载请注明: Zero的博客 旅游网项目02

 上一篇
旅游网项目03 旅游网项目03
前言今日内容为旅游网项目的旅游线路名称查询,详情页展示,线路收藏功能。 1. 旅游线路名称查询功能1.1 查询参数的传递在header.html中添加如下js // 给搜索按钮绑定单击事件,获取搜索输入框的内容 $("#sear
2019-07-27
下一篇 
旅游网项目01 旅游网项目01
1. 前言为了巩固web基础知识,提升综合运用能力,故编写此项目,以做练习。 今日内容为登录注册内容。 2. 技术选型2.1 Web层 Servlet:前端控制器 html:视图 Filter:过滤器 BeanUtils:数据封装 Jac
2019-07-21
  目录