旅游网
一、环境配置
1.1、项目导入
选择travel项目的pom.xml文件,点击ok,完成项目导入。需要等待二十分钟,项目初始化完成。
修改数据库密码
修改数据库版本:Ctrl+f 查询
二、启动项目
方式一
方式二:配置maven快捷启动
三、技术选型
Web层
-
- Servlet:前端控制器
- html:视图
- Filter:过滤器
- BeanUtils:数据封装
- Jackson:json序列化工具
Service层
-
- Javamail:java发送邮件工具
- Redis:nosql内存数据库
- Jedis:java的redis客户端
Dao层
-
- Mysql:数据库
-
- Druid:数据库连接池
- 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
- 设置编码:request.setCharacterEncoding("utf-8")
- 获取表单信息
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步骤:
- 获取code
- 判断code,若不为空就调用service的active(String code)方法进行激活 传入code参数
- 通过service.active(code)的返回值来判断是否激活成功 通过不同结果响应到前台不同信息
Service中的的active方法:
- 根据激活码查询用户对象
若能够查询到user 则修改激活状态
2.若用户存在则修改激活状态 修改为Y
4.2用户登录
4.2.1功能分析
4.2.1代码实现
后台代码实现步骤:
将表单提交到:LoginSerblet
- 获取用户信息
- 调用service查询user
- 判断用户是否存在
- 判断用户是否激活
- 响应错误信息
//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);
前台代码实现步骤:
- 给登录按钮绑定单击事件
- 发送ajax请求,提交表单数据
- 处理响应结果
登录成功后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、实现步骤
- 访问servlet,将session销毁
- 跳转到登录页面
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>¥</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);
});
}
后台代码:
-
- 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加载后
- 获取rid
- 发送ajax请求,获取route对象
- 解析对象数据
$(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、功能分析
-
判断当前登录用户是否收藏过该线路
- 当页面加载完成后,发送ajax请求,获取用户是否收藏的标记
- 根据标记展示不同的按钮样式
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";
}
});
}