黑马旅游网项目后端总结+项目初始化文件

旅游网

一、环境配置

1.1、项目导入

黑马旅游网项目后端总结+项目初始化文件

选择travel项目的pom.xml文件,点击ok,完成项目导入。需要等待二十分钟,项目初始化完成

黑马旅游网项目后端总结+项目初始化文件

 修改数据库密码

黑马旅游网项目后端总结+项目初始化文件

修改数据库版本:Ctrl+f 查询 

黑马旅游网项目后端总结+项目初始化文件

二、启动项目

方式一

黑马旅游网项目后端总结+项目初始化文件

 方式二:配置maven快捷启动

黑马旅游网项目后端总结+项目初始化文件

 黑马旅游网项目后端总结+项目初始化文件

三、技术选型

Web层

    1. Servlet:前端控制器
    2. html:视图
    3. Filter:过滤器
    4. BeanUtils:数据封装
    5. Jackson:json序列化工具

Service层

    1. Javamail:java发送邮件工具
    2. Redis:nosql内存数据库
    3. Jedis:java的redis客户端

Dao层

    1. Mysql:数据库
    1. Druid:数据库连接池
    2. JdbcTemplate:jdbc的工具

四、功能模块

4.1、注册功能

4.1.1、页面效果  功能分析

    黑马旅游网项目后端总结+项目初始化文件

    黑马旅游网项目后端总结+项目初始化文件

4.1.2、功能分析

     黑马旅游网项目后端总结+项目初始化文件

4.1.3、代码实现

前台代码:表单校验:校验用户名、密码、Emai

//校验用户名
//单词字符,长度8到20位
function checkUsername() {
             //1.获取用户名值
   var username = $("#username").val();
   //2.定义正则
   var reg_username = /^\w{8,20}$/;
  
   //3.判断,给出提示信息
    var flag = reg_username.test(username);
    if(flag){
        //用户名合法
                 $("#username").css("border","");
   }else{
        //用户名非法,加一个红色边框
      $("#username").css("border","1px solid red");
   }
   
             return flag;
         }

         //校验密码
         function checkPassword() {
             //1.获取密码值
             var password = $("#password").val();
             //2.定义正则
             var reg_password = /^\w{8,20}$/;

             //3.判断,给出提示信息
             var flag = reg_password.test(password);
             if(flag){
                 //密码合法
                 $("#password").css("border","");
             }else{
                 //密码非法,加一个红色边框
                 $("#password").css("border","1px solid red");
             }

             return flag;
         }

         //校验邮箱
function checkEmail(){
    //1.获取邮箱
   var email = $("#email").val();
   //2.定义正则      itcast@163.com
   var reg_email = /^\w+@\w+\.\w+$/;

   //3.判断
   var flag = reg_email.test(email);
   if(flag){
                 $("#email").css("border","");
   }else{
                 $("#email").css("border","1px solid red");
   }

   return flag;
}

$(function () {
             //当表单提交时,调用所有的校验方法
   $("#registerForm").submit(function(){

                 return checkUsername() && checkPassword() && checkEmail();
                 //如果这个方法没有返回值,或者返回为true,则表单提交,如果返回为false,则表单不提交
   });

             //当某一个组件失去焦点是,调用对应的校验方法
            $("#username").blur(checkUsername);
             $("#password").blur(checkPassword);
             $("#email").blur(checkEmail);


         });

异步(ajax)提交表单

在此使用异步提交表单是为了获取服务器响应的数据。因为我们前台使用的是html作为视图层,不能够直接从servlet相关的域对象获取值,只能通过ajax获取响应数据

黑马旅游网项目后端总结+项目初始化文件

后台代码:

步骤RegisterFormServlet

  1. 设置编码:request.setCharacterEncoding("utf-8")
  2. 获取表单信息

           Map<String, String[]> map = request.getParameterMap();

    3、封装对象

             BeanUtils.populate(user,map);

    4.调用service完成注册

    5、响应结果

@WebServlet("/registUserServlet")
public class RegistUserServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {


        //验证校验
        String check = request.getParameter("check");
        //从sesion中获取验证码
        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;
        }

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

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

        //3.调用service完成注册
        UserService 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);


    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

验证码校验功能Servlet实现步骤:

         1、获取用户输入的验证码: String check = request.getParameter("check");

         2、从session中获取验证码

                  HttpSession session = request.getSession();

                 String checkcode_server = (String) session.getAttribute("CHECKCODE_SERVER");

        3、从session中获取完验证码后要立即将当前的验证码移除,避免复用

                  session.removeAttribute("CHECKCODE_SERVER");//保证验证码只能使用一次

        4、比较用户输入的验证码和session获取的是否一致  不区分大小写比较

        IF(check.equalsIgnoreCase(check);

 5、进行处理响应:注册失败:errorMsg添加提示信息

                                             注册成功:跳转到成功页面

用户激活功能:

         邮件激活:为了保证用户填写的邮箱是正确的。

1、申请邮箱

2、开启授权码

3、在MailUtils中设置自己的邮箱账号和密码(授权码) 申请邮箱

        黑马旅游网项目后端总结+项目初始化文件

发送邮件:使用工具类   红色的地方是需要替换的 
邮件工具类:MailUtils,调用其中sendMail方法可以完成邮件发

public final class MailUtils {

      private static final String USER = "1624603357@qq.com"; // 发件人称号,同邮箱地址

      private static final String PASSWORD = "sabjjbavzvpcfdaj"; // 如果是qq邮箱可以使户端授权码,或者登录密码

/**
     *
     * @param to 收件人邮箱
     * @param text 邮件正文
     * @param title 标题
     */
    /* 发送验证信息的邮件 */
    public static boolean sendMail(String to, String text, String title){
        try {
            final Properties props = new Properties();
            props.put("mail.smtp.auth", "true");
            props.put("mail.smtp.host", "smtp.qq.com");
            // 发件人的账号
            props.put("mail.user", USER);
            //发件人的密码
            props.put("mail.password", PASSWORD);
            // 构建授权信息,用于进行SMTP进行身份验证
            Authenticator authenticator = new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    // 用户名、密码
                    String userName = props.getProperty("mail.user");
                    String password = props.getProperty("mail.password");
                    return new PasswordAuthentication(userName, password);
                }
            };
            // 使用环境属性和授权信息,创建邮件会话
            Session mailSession = Session.getInstance(props, authenticator);
            // 创建邮件消息
            MimeMessage message = new MimeMessage(mailSession);
            // 设置发件人
            String username = props.getProperty("mail.user");
            InternetAddress form = new InternetAddress(username);
            message.setFrom(form);
            // 设置收件人
            InternetAddress toAddress = new InternetAddress(to);
            message.setRecipient(Message.RecipientType.TO, toAddress);
            // 设置邮件标题
            message.setSubject(title);
            // 设置邮件的内容体
            message.setContent(text, "text/html;charset=UTF-8");
            // 发送邮件
            Transport.send(message);
            return true;
        }catch (Exception e){
            e.printStackTrace();
        }
        return false;
    }

用户点击邮件激活:

保存用户的时候设置其激活状态 和 激活码code

获取激活码的工具类: public final class UuidUtil

private UuidUtil(){}
	public static String getUuid(){
		return UUID.randomUUID().toString().replace("-","");
	}
	/**
	 * 测试
	 */
	public static void main(String[] args) {
		System.out.println(UuidUtil.getUuid());
		System.out.println(UuidUtil.getUuid());
		System.out.println(UuidUtil.getUuid());
		System.out.println(UuidUtil.getUuid());
	}
}

邮件正文:连接中加上激活码  访问activeUserServlet

  String contentx="<a href='http://localhost:8088/travel/activeUserServlet?code="+

                user.getCode()+"'>点击激活【黑马旅游网】</a>";

 activeUserServlet步骤:

  1. 获取code
  2. 判断code,若不为空就调用service的active(String code)方法进行激活   传入code参数
  3. 通过service.active(code)的返回值来判断是否激活成功  通过不同结果响应到前台不同信息

Service中的的active方法:

  1. 根据激活码查询用户对象

若能够查询到user 则修改激活状态

    2.若用户存在则修改激活状态  修改为Y

4.2用户登录

4.2.1功能分析

黑马旅游网项目后端总结+项目初始化文件

4.2.1代码实现

后台代码实现步骤:

                  将表单提交到:LoginSerblet

  1. 获取用户信息
  2. 调用service查询user
  3. 判断用户是否存在
  4. 判断用户是否激活
  5. 响应错误信息
//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查询
UserService 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);
}

//响应数据
ObjectMapper mapper = new ObjectMapper();

response.setContentType("application/json;charset=utf-8");
mapper.writeValue(response.getOutputStream(),info);

前台代码实现步骤:

  1. 给登录按钮绑定单击事件
  2. 发送ajax请求,提交表单数据
  3. 处理响应结果

登录成功后index页面中有用户姓名的提示信息功能:

                  登录成功后,加载Index.html 后  异步访问findUserServlet

findUserServlet中的代码

//从session中获取登录用户
Object user = request.getSession().getAttribute("user");
//将user写回客户端

ObjectMapper mapper = new ObjectMapper();
response.setContentType("application/json;charset=utf-8");
mapper.writeValue(response.getOutputStream(),user);

4.3退出

4.3.1、实现步骤

  1. 访问servlet,将session销毁
  2. 跳转到登录页面

4.3.2、代码实现

前台代码Header.html

黑马旅游网项目后端总结+项目初始化文件

 后台代码

1/1.销毁session

request.getSession().invalidate();

//2.跳转登录页面

response.sendRedirect(request.getContextPath()+"/login.html");

控制台乱码问题解决:

         Setting->Runner

黑马旅游网项目后端总结+项目初始化文件

4.4优化Servlet

4.4.、目的

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

黑马旅游网项目后端总结+项目初始化文件

 4.4.2、BaseServlet编写

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(); //   /travel/user/add
        System.out.println("请求uri:"+uri);//  /travel/user/add
        //2.获取方法名称
        String methodName = uri.substring(uri.lastIndexOf('/') + 1);
        System.out.println("方法名称:"+methodName);
        //3.获取方法对象Method
        //谁调用我?我代表谁
        System.out.println(this);//UserServlet的对象cn.itcast.travel.web.servlet.UserServlet@4903d97e
        try {
            //获取方法
            Method method = this.getClass().getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
            //4.执行方法
            //暴力反射
            //method.setAccessible(true);
            method.invoke(this,req,resp);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

4.5、分类数据展示功能

4.5.1、功能分析

黑马旅游网项目后端总结+项目初始化文件

 黑马旅游网项目后端总结+项目初始化文件

4.5.2代码实现

后台代码:

CategoryServlet

@WebServlet("/category/*")
public class CategoryServlet extends BaseServlet {

    private CategoryService service = new CategoryServiceImpl();

    /**
     * 查询所有
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    public void findAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.调用service查询所有
        List<Category> cs = service.findAll();
        //2.序列化json返回
       /* ObjectMapper mapper = new ObjectMapper();
        response.setContentType("application/json;charset=utf-8");
        mapper.writeValue(response.getOutputStream(),cs);*/
       writeValue(cs,response);

    }

}

CategoryService

public class CategoryServiceImpl implements CategoryService {

    private CategoryDao categoryDao = new CategoryDaoImpl();

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

CategoryDao

public class CategoryDaoImpl implements CategoryDao {

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

    @Override
    public List<Category> findAll() {
        String sql = "select * from tab_category ";
        return template.query(sql,new BeanPropertyRowMapper<Category>(Category.class));
    }
}

前台代码: 小心写成了 /category/findAll

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

存在问题:每次刷新都会请求数据库加载 分类数据  分类数据不会经常产生变化,对数据库的压力大   采用缓存  减少对数据库的访问次数 查询效率高

//1、从Redis中去查询
        //获取jedis的客户端]
        Jedis jedis = JedisUtil.getJedis();
        //可以使用sortedset排序查询
        Set<String> categorys = jedis.zrange("category", 0, -1);
        //2、判断查询的集合是否为空
        List<Category> cs=null;
        if(categorys==null||categorys.size()==0)
        {
            System.out.println("从数据库查询……");
            //3、如果为空,说明是第一次访问  需要从数据库查询  将数据存入redis
            cs = categoryDao.findAll();
            //将数据存储到redis中
            for (int i = 0; i < cs.size(); i++) {
                jedis.zadd("category",cs.get(i).getCid(),cs.get(i).getCname());
            }
        }else {
            //4、如果不为空,将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.6旅游线路的分类展示功能

4.6.1、功能分析

类别id的传递:

                  Redis中查询cid  

页面传递cid      head.html传递cid

var li='<li><a href=\"route_list.html?cid='+data[i].cid+'">'+data[i].cname+'</a></li>';

获取cid

根据cid查询不同类别的旅游线路的数据

4.6.2代码实现

1、客户端代码编写

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

    //当页码加载完成后,调用load方法,发送ajax请求加载数据
    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="javascipt:load('+cid+')"><a href="javascript:void(0)">首页</a></li>';
        //计算上一页的页码
        var beforeNum =  pb.currentPage - 1;
        if(beforeNum <= 0){
            beforeNum = 1;
        }
        var beforePage = '<li  onclick="javascipt: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页

            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="javascipt:load('+cid+','+i+')"><a href="javascript:void(0)">'+i+'</a></li>';

            }else{
                //创建页码的li
                li = '<li onclick="javascipt:load('+cid+','+i+')"><a href="javascript:void(0)">'+i+'</a></li>';
            }
            //拼接字符串
            lis += li;
        }

             var lastPage = '<li class="threeword"><a href="javascript:;">末页</a></li>';
        var nextPage = '<li 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"}
            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);
    });
}

后台代码:

    1. RouteServlet
@WebServlet("/route/*")
public class RouteServlet extends BaseServlet {

    private RouteService routeService = new RouteServiceImpl();

    /**
     * 分页查询
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    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");

        int cid = 0;//类别id
        //2.处理参数
        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.7旅游线路名称查询

4.7.1、代码实现

前端代码: 在header.html中

$(function () {
            var search = location.search;
            //alert(search);//?id=5
            // 切割字符串,拿到第二个值
            var cid = getParameter("cid");
            var rname = getParameter("rname");
            //判断rnme不为空 解码
            if(rname)
            {
                 rname=window.decodeURIComponent(rname);
            }
            //当页码加载完成后,调用load方法,发送ajax请求加载数据
            load(cid);  });

后端代码:Dao层

public class RouteDaoImpl implements RouteDao {
    private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());

    @Override
    public int findTotalCount(int cid,String rname) {
        //定义sql模板
        String sql = "select count(*) from tab_route where 1=1";
        StringBuffer sb=new StringBuffer(sql);
        List parms=new ArrayList();//条件
        //判断参数是否有值
        if(cid!=0){
            sb.append(" and cid = ? ");
            parms.add(cid);//添加问号对应的值
        }
        if(rname!=null&&rname.length()>0 &&!"null".equals(rname))
        {
            sb.append(" and rname like ? ");
            parms.add("%"+rname+"%");
        }

        sql=sb.toString();
        System.out.println(sql);
        System.out.println(parms.toString());
        return template.queryForObject(sql,Integer.class,parms.toArray());
    }

    @Override
    public List<Route> findByPage(int cid, int start, int pageSize, String rname) {
        String sql = "select * from tab_route where 1=1 ";
        StringBuffer sb=new StringBuffer(sql);
        List parms=new ArrayList();//条件
        //判断参数是否有值
        if(cid!=0){
            sb.append(" and cid = ? ");
            parms.add(cid);//添加问号对应的值
        }
        if(rname!=null&&rname.length()>0 &&!"null".equals(rname))
        {
            sb.append(" and rname like ? ");
            parms.add("%"+rname+"%");
        }
        sb.append(" limit ? , ? ");
        parms.add(start);
        parms.add(pageSize);
        sql=sb.toString();
        System.out.println(sql);
        System.out.println(parms.toString());
        System.out.println("==================================");
        return template.query(sql,new BeanPropertyRowMapper<Route>(Route.class),parms.toArray());
    }
}

4.8、旅游线路详情展示

4.8.1、功能分析

黑马旅游网项目后端总结+项目初始化文件

 黑马旅游网项目后端总结+项目初始化文件

 创建旅游线路商品实体类

public class Route implements Serializable {
    private int rid;//线路id,必输
    private String rname;//线路名称,必输
    private double price;//价格,必输
    private String routeIntroduce;//线路介绍
    private String rflag;   //是否上架,必输,0代表没有上架,1代表是上架
    private String rdate;   //上架时间
    private String isThemeTour;//是否主题旅游,必输,0代表不是,1代表是
    private int count;//收藏数量
    private int cid;//所属分类,必输
    private String rimage;//缩略图
    private int sid;//所属商家
    private String sourceId;//抓取数据的来源id
    private Category category;//所属分类
    private Seller seller;//所属商家
private List<RouteImg> routeImgList;//商品详情图片列表
}

4.8.2、代码实现

后端代码:

RouteServlet中的findOne方法

public void findOne(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1、接收id
        String rid = request.getParameter("rid");
        //2、调用service查询一个route对象
        Route route=routeService.findOne(rid);
        //3、将 route对象转为json写回客户端
        writeValue(route,response);
    }

RouteImgDao:

根据rid查询返回图片集合对象,然后将图片集合设置到route对象中

public List<RouteImg> findByRid(int rid) {
        String sql="select * from tab_route_img where rid = ?";
        return template.query(sql,new BeanPropertyRowMapper<RouteImg>(RouteImg.class),rid);
    }

SellerDao

根据route的sid属性查询商家信息  然后将商家信息设置到route对象中

public Seller findById(int sid) {
        String sql="select * from tab_seller where sid = ?";
        return template.queryForObject(sql,new BeanPropertyRowMapper<Seller>(Seller.class),sid);
    }

RouteService中findOne方法

public Route findOne(String ridStr) {
        int rid = Integer.parseInt(ridStr);
        //根据rid去route表中查询route对象
        Route route = routeDao.findOne(rid);
        //根据route的id查询图片的集合信息
        List<RouteImg> routeimg = routeImgDao.findByRid(route.getRid());
        //将集合设置到route对象
        route.setRouteImgList(routeimg);
        //根据route的sid查询Serll商家对象
        Seller sell = sellerDao.findById(route.getSid());
        route.setSeller(sell);
        return route;
    }

前端代码:

Route_detall.html加载后

  1. 获取rid
  2. 发送ajax请求,获取route对象
  3. 解析对象数据
$(function () {
        //1.获取rid
        var rid = getParameter("rid");
        //2.发送请求请求 route/findOne
        $.get("route/findOne",{rid:rid},function (route) {
            //3.解析数据填充html
            $("#rname").html(route.rname);
            $("#routeIntroduce").html(route.routeIntroduce);
            $("#price").html("¥"+route.price);
            $("#sname").html(route.seller.sname);
            $("#consphone").html(route.seller.consphone);
            $("#address").html(route.seller.address);
            //图片展示
            var ddstr = '<a class="up_img up_img_disable"></a>';
            //大图为第一个小图对应的图片   至少有一张图片市
            if(route.routeImgList.length>0)
            {
                $("#bigPic").prop("src",route.routeImgList[0].bigPic);
            }

            //遍历routeImgList
            for (var i = 0; i < route.routeImgList.length; i++) {
                var astr ;
                if(i >= 4){
                    astr = '<a title="" class="little_img" data-bigpic="'+route.routeImgList[i].bigPic+'" style="display:none;">\n' +
                        '                        <img src="'+route.routeImgList[i].smallPic+'">\n' +
                        '                    </a>';
                }else{
                    astr = '<a title="" class="little_img" data-bigpic="'+route.routeImgList[i].bigPic+'">\n' +
                        '                        <img src="'+route.routeImgList[i].smallPic+'">\n' +
                        '                    </a>';
                }
                ddstr += astr;
            }
            ddstr+='<a class="down_img down_img_disable" style="margin-bottom: 0;"></a>';
            $("#dd").html(ddstr);
            //图片展示和切换代码调用
            goImg();
        });
    });

4.9、旅游线路收藏

4.9.1、功能分析

  1.  判断当前登录用户是否收藏过该线路
    1. 当页面加载完成后,发送ajax请求,获取用户是否收藏的标记
    2. 根据标记展示不同的按钮样式

黑马旅游网项目后端总结+项目初始化文件

 黑马旅游网项目后端总结+项目初始化文件

4.9.2代码编写

后台代码:

RouteServlet中的isFavorite
public void isFavorite(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1、获取线路id
        String rid = request.getParameter("rid");
        //2、获取uid
        User user = (User)request.getSession().getAttribute("user");
        int uid;
        if(user==null)
        {
            //用户尚未登录
            uid=0;
        }else {
            //用户已经登录
            uid=user.getUid();
        }
        //3、调用favoriteservice查询是否收藏
        boolean flag = favoriteService.isFavorite(rid, uid);
        //4、写回客户端
        writeValue(flag,response);
    }

 FavoriteServiceImpl

public class FavoriteServiceImpl implements FavoriteService {
    public FavoriteDao favoriteDao=new FavoriteDaoImpl();
    @Override
    public boolean isFavorite(String rid, int uid) {
        Favorite favorite = favoriteDao.findByRidAndUid(Integer.parseInt(rid), uid);
        if(favorite==null)
        {
            return false;
        }else {
            return true;
        }
    }
}

前台代码:

Route_detail.html

$(function () {
        var rid = getParameter("rid");
       //1、发送请求,判断用户是否收藏过该线路
        $.get("route/isFavorite",{rid:rid},function (flag) {
            if(flag)
            {
                //用户已经收藏过
                //设置收藏按钮样式
            $("#favorite").addClass("already");
            $("#favorite").prop("disabled",disabled);
            }else{
                //用户没有收藏
            }
        });
    });

4.9.3、收藏次数的动态展示

//设置收藏次数
$("#favoriteCount").html("已收藏"+route.count+"次");

后端代码:

RouteService

//4. 查询收藏次数
int count = favoriteDao.findCountByRid(route.getRid());
route.setCount(count);

FavoriteDao

@Override
public int findCountByRid(int rid) {
    String sql = "SELECT COUNT(*) FROM tab_favorite WHERE rid = ?";

    return template.queryForObject(sql,Integer.class,rid);
}

4.9.4、点击按钮收藏线路的功能

 功能分析:

黑马旅游网项目后端总结+项目初始化文件

代码实现:

后台代码:

RouteServlet 中的addFavorite方法

public void addFavorite(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取线路rid
        String rid = request.getParameter("rid");
        //2、获取当前登录的用户
        User user = (User)request.getSession().getAttribute("user");
        int uid;
        if(user==null)
        {
            //用户尚未登录
           return;
        }else {
            //用户已经登录
            uid=user.getUid();
        }
        favoriteService.add(rid,uid);
    }

FavoriteServiceImpl中的add方法

public void add(int rid, int uid) {
        String sql="INSERT INTO tab_favorite VALUES(?,?,?)";
        template.update(sql,rid,new Date(),uid);
    }

前台代码:

function addFavorite() {
        var rid = getParameter("rid");
        //1、判断用户是否登录
        $.get("user/findOne",{},function (user) {
            //判断用户是否登录
          if(user)
          {
              //用户登录了
              //添加功能
              $.get("route/addFavorite",{rid:rid},function () {
                  //刷新页面
                  location.reload();
              });
          }else {
              alert("您尚未登录,请登录!")
              location.href="http://localhost:8088/travel/login.html";
          }
        });
    }

上一篇:AI让边缘更智能 边缘让AI无处不在


下一篇:MySQL数据库my.cnf配置文件注释详