要求:
用户名:单词字符,8到20位长度密码:单词字符,8到20位长度email:邮件格式姓名:非空手机号:手机号格式出生日期:非空验证码:非空 <script> //校验用户名 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"); } } //校验密码 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 checkName() { //1. 获取姓名 var name = $("#name").val(); var flag; if (name == "" || name == null) { flag = false; $("#name").css("border", "1px solid red"); } else { $("#name").css("border", ""); flag = true; } return flag; } //校验手机号 function checkTelephone() { //1。 获取用户名的值 var telephone = $("#telephone").val(); //2. 定义正则 var reg_telephone = /^1\d{10}$/; //3. 判断,给出提示信息 var flag = reg_telephone.test(telephone); if (flag) { //用户名合法 $("#telephone").css("border", ""); } else { //用户名非法,加一个红色边框 $("#telephone").css("border", "1px solid red"); } } //校验出生日期 function checkBirthday() { //1. 获取姓名 var birthday = $("#birthday").val(); var flag; if (birthday == "" || birthday == null) { flag = false; $("#birthday").css("border", "1px solid red"); } else { $("#birthday").css("border", ""); flag = true; } return flag; } //校验验证码 function checkCheck() { //1. 获取姓名 var check = $("#check").val(); var flag; if (check == "" || check == null) { flag = false; $("#check").css("border", "1px solid red"); } else { $("#check").css("border", ""); flag = true; } return flag; } $(function () { //当表单提交时,调用所有校验方法 $("#registerForm").submit(function () { return checkUsername() && checkPassword() && checkEmail() && checkName() && checkBirthday() && checkCheck()&&checkTelephone(); //如果这个方法没有返回值,或者返回为true,则表单提交,如果返回为false,表单不提交 }); //当某一个组件失去焦点时调用对应的校验方法 $("#username").blur(checkUsername); $("#password").blur(checkPassword); $("#email").blur(checkEmail); $("#name").blur(checkName); $("#birthday").blur(checkBirthday); $("#check").blur(checkCheck); $("#telephone").blur(checkTelephone); }) </script>因为前台使用的是html作为视图层,不能够直接从servlet相关的域对象获取值,只能通过Ajax获取响应数据。
Ajax异步提交数据实现方式:
1. $.ajax() * 语法:$.ajax({键值对}); //使用$.ajax()发送异步请求 $.ajax({ url:"ajaxServlet1111" , // 请求路径 type:"POST" , //请求方式 //data: "username=jack&age=23",//请求参数 data:{"username":"jack","age":23}, success:function (data) { alert(data); },//响应成功后的回调函数 error:function () { alert("出错啦...") },//表示如果请求响应出现错误,会执行的回调函数 dataType:"text"//设置接受到的响应数据的格式 }); 2. $.get():发送get请求 * 语法:$.get(url, [data], [callback], [type]) * 参数: * url:请求路径 * data:请求参数 * callback:回调函数 * type:响应结果的类型 3. $.post():发送post请求 * 语法:$.post(url, [data], [callback], [type]) * 参数: * url:请求路径 * data:请求参数 * callback:回调函数 * type:响应结果的类型程序代码:
$(function () { //当表单提交时,调用所有校验方法 $("#registerForm").submit(function () { //1. 发送数据到服务器 if (checkUsername() && checkPassword() && checkEmail() && checkName() && checkBirthday() && checkCheck()&&checkTelephone()){ //校验通过,发送Ajax请求提交表单数据 序列化成这种格式的字符串形式username=zhangsan&&password=123 //this="#registerForm" //因为这个是html界面,不能使用EL表达式 $.post("registUserServlet",$(this).serialize(),function (data) { //处理服务器相应的数据 data }); } //2. 跳转页面 //如果这个方法没有返回值,或者返回为true,则表单提交,如果返回为false,表单不提交 });[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4egEBorf-1603200005353)(C:\Users\Baymax\AppData\Roaming\Typora\typora-user-images\image-20201016200717450.png)]
发送邮件的工具类:在Mailustils中设置发送邮件的qq号和密码,注意密码要在网页版qq邮箱中设置开启smtp,有一个授权码,可以当作登录密码,测试给我自己的163邮箱发送邮件,发送成功
/* 发送验证信息的邮件 */ 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; } public static void main(String[] args) throws Exception { // 做测试用 MailUtils.sendMail("ymz210594@163.com","你好,这是一封测试邮件,无需回复。","测试邮件"); System.out.println("发送成功"); }在service文件中增加激活码和状态码,并发送激活邮件:
@Override public boolean regist(User user) { //1. 根据用户名查询用户对象,存在返回false User u = userDao.findByUsername(user.getUsername()); System.out.println("查询结果" + u); if (u != null) { //用户名存在,注册失败 return false; } //2. 保存用户信息 //2.1 设置激活码,唯一字符串 user.setCode(UuidUtil.getUuid()); //2.2 设置激活状态 user.setStatus("N"); userDao.save(user); //3. 激活邮件发送,邮件正文? String content="<a href='http://localhost/travel/activeUserServlet?code="+ user.getCode()+"'>点击激活【黑马旅游网】</a>"; MailUtils.sendMail(user.getEmail(),content,"激活邮件"); return true; }修改dao中的保存方法:
@Override public void save(User user) { //1. 定义sql语句 String sql = "insert into tab_user(username,password,name,birthday,sex,telephone,email,status,code) values(?,?,?,?,?,?,?,?,?)"; //2. 执行sql语句 template.update(sql, user.getUsername(), user.getPassword(), user.getName(), user.getBirthday(), user.getSex(), user.getTelephone(), user.getEmail(),user.getStatus(),user.getCode()); }增加ActiveUserServlet
@WebServlet("/activeUserServlet") public class ActiveUserServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取激活码 String code = request.getParameter("code"); //先判断获取的参数是否为空,不为空就可以激活 if (code != null) { //调用service完成激活 UserService service = new UserServiceImpl(); boolean flag = service.active(code); //判断标记 String msg=null; if (flag){ //激活成功 msg="激活成功,请<a href='login.html'>登录</a>"; }else { //激活失败 msg="激活失败,请联系管理员"; } response.setContentType("text/html;charset=utf-8"); response.getWriter().write(msg); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }service中增加active方法:
@Override public boolean active(String code) { //通过code(唯一激活码)找到user User user=userDao.findByCode(code); //找到后判断user是否为空,如果不为空就设置它的状态码为Y if (user!=null){ userDao.updateStatus(user); return true; }else { return false; } }dao中增加findByCode和updateStatus方法
@Override public User findByCode(String code) { User user = null; try { //1. 定义sql语句 String sql = "select * from tab_user where code = ?"; //2. 执行sql user = template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), code); } catch (DataAccessException e) { e.printStackTrace(); } return user; } @Override public void updateStatus(User user) { String sql="update tab_user set status = 'Y' where uid = ?"; template.update(sql,user.getUid()); }给登录按钮绑定单击事件
<script> $(function () { //1. 给登录按钮绑定单击事件 $("#btn_sub").onclick(function () { //2. 发送ajax请求,提交表单数据 $.post("loginServlet",$("#loginForm").serialize(),function (data) { if (data.flag){ //登录成功 location.href="index.html"; }else { //登录失败 $("#errorMsg").html(data.errorMsg); } }) }) }) </script>loginServlet
@WebServlet("/loginServlet") public class LoginServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //校验验证码 String check=request.getParameter("check"); HttpSession session=request.getSession(); String checkcode =(String) session.getAttribute("CHECKCODE_SERVER"); //为了保证验证码只能用用一次,取完之就销毁 session.removeAttribute("CHECKCODE_SERVER"); //比较验证码是否正确 //如果验证码不正确,保存后退出 if (checkcode==null&&!check.equalsIgnoreCase(checkcode)){ //验证码错误,注册失败,将结果存入resultinfo里面,显示在前台 ResultInfo info=new ResultInfo(); info.setFlag(false); info.setErrorMsg("验证码错误"); //将info传到前台,序列化为json ObjectMapper mapper=new ObjectMapper(); String json=mapper.writeValueAsString(info); //设置json编码 response.setContentType("application/json;charset=utf-8"); response.getWriter().write(json); //退出 return; } //获取用户名和密码数据 Map<String, String[]> map = request.getParameterMap(); //封装user对象 User user=new User(); try { BeanUtils.populate(user,map); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } //调用service查询 UserService service=new UserServiceImpl(); User u=service.login(user); ResultInfo info=new ResultInfo(); //判断查询结果,查询出来的对象是否为null //未查询到用户 if (u==null){ //用户名或密码错误 info.setFlag(false); info.setErrorMsg("用户名或密码错误"); } //查询到用户但是未激活 if (u!=null&&!"Y".equals(u.getStatus())){ info.setFlag(false); info.setErrorMsg("您尚未激活,请激活"); } //查询到用户,且已激活,登录成功 if (u!=null&&"Y".equals(u.getStatus()){java info.setFlag(true); } //响应数据 ObjectMapper mapper=new ObjectMapper(); response.setContentType("application/json;charset=utf-8"); mapper.writeValue(response.getOutputStream(),info); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }service:
@Override public User login(User user) { return userDao.findByUsernameAndPassword(user.getUsername(),user.getPassword()); }dao:
@Override public User findByUsernameAndPassword(String username, String password) { User user = null; try { String sql = "select * from tab_user where username = ? and password = ?"; user = template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), username, password); } catch (DataAccessException e) { e.printStackTrace(); } return user; }index页面中用户姓名的提示信息功能:
此时改了代码但是一直出错,浏览器上显示改之前的代码,这时需要清除缓存和记录
<script> $(function () { $.get("findUserServlet",{},function (data) { var msg="欢迎回来"+data.name; $("#span_username").html(msg); }) }) </script>findUserServlet
@WebServlet("/findUserServlet") public class FindUserServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, 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); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }用BaseServlet完成方法的分发,从路径里面取方法名称
public class BaseServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("baseServlet的service方法被执行了..."); //完成方法分发 //获取请求路径 String uri = req.getRequestURI();// /user/add System.out.println("请求uri:"+uri); //获取方法名称 String methodName = uri.substring(uri.lastIndexOf('/') + 1); System.out.println("方法名称:"+methodName); //获取方法对象 System.out.println(this); //执行方法 } } baseServlet的service方法被执行了... 请求uri:/travel/user/add 方法名称:add cn.itcast.travel.web.servlet.UserServlet@2fc932afBaseServlet:
public class BaseServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("baseServlet的service方法被执行了..."); //完成方法分发 //获取请求路径 String uri = req.getRequestURI();// /user/add System.out.println("请求uri:"+uri); //获取方法名称 String methodName = uri.substring(uri.lastIndexOf('/') + 1); System.out.println("方法名称:"+methodName); //获取方法对象 System.out.println(this); try { Method method = this.getClass().getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class); //执行方法 //暴力反射(大可不必),改成public就行 method.invoke(this,req,resp); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } }把userservice抽取一个成员变量,就不需要重复创建,然后改写UserServlet,把所有方法加进去,别忘了还要改html页面上的名字
@WebServlet("/user/*") public class UserServlet extends BaseServlet { //声明一个userService的成员变量 private UserService service = new UserServiceImpl(); public void regist(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //校验验证码 String check=request.getParameter("check"); HttpSession session=request.getSession(); String checkcode =(String) session.getAttribute("CHECKCODE_SERVER"); //为了保证验证码只能用用一次,取完之就销毁 session.removeAttribute("CHECKCODE_SERVER"); //比较验证码是否正确 //如果验证码不正确,保存后退出 if (checkcode==null&&!check.equalsIgnoreCase(checkcode)){ //验证码错误,注册失败,将结果存入resultinfo里面,显示在前台 ResultInfo info=new ResultInfo(); info.setFlag(false); info.setErrorMsg("验证码错误"); //将info传到前台,序列化为json ObjectMapper mapper=new ObjectMapper(); String json=mapper.writeValueAsString(info); //设置json编码 response.setContentType("application/json;charset=utf-8"); response.getWriter().write(json); //退出 return; } //filter里面已经设置过编码了,不需要再设置 //1. 获取数据 Map<String, String[]> map = request.getParameterMap(); System.out.println(map); //2. 封装对象 User user = new User(); try { BeanUtils.populate(user, map); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } //3. 调用service完成注册操作 System.out.println("注册用户"+user); // UserService service = new UserServiceImpl(); boolean flag = service.regist(user); System.out.println("注册结果:"+flag); 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.getOutputStream().write(json.getBytes()); //字符流 response.getWriter().write(json); } public void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //校验验证码 String check=request.getParameter("check"); HttpSession session=request.getSession(); String checkcode =(String) session.getAttribute("CHECKCODE_SERVER"); //为了保证验证码只能用用一次,取完之就销毁 session.removeAttribute("CHECKCODE_SERVER"); //比较验证码是否正确 //如果验证码不正确,保存后退出 if (checkcode==null&&!check.equalsIgnoreCase(checkcode)){ //验证码错误,注册失败,将结果存入resultinfo里面,显示在前台 ResultInfo info=new ResultInfo(); info.setFlag(false); info.setErrorMsg("验证码错误"); //将info传到前台,序列化为json ObjectMapper mapper=new ObjectMapper(); String json=mapper.writeValueAsString(info); //设置json编码 response.setContentType("application/json;charset=utf-8"); response.getWriter().write(json); //退出 return; } //获取用户名和密码数据 Map<String, String[]> map = request.getParameterMap(); //封装user对象 User user=new User(); try { BeanUtils.populate(user,map); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } //调用service查询 // UserService service=new UserServiceImpl(); User u=service.login(user); ResultInfo info=new ResultInfo(); //判断查询结果,查询出来的对象是否为null //未查询到用户 if (u==null){ //用户名或密码错误 info.setFlag(false); info.setErrorMsg("用户名或密码错误"); } //查询到用户但是未激活 if (u!=null&&!"Y".equals(u.getStatus())){ info.setFlag(false); info.setErrorMsg("您尚未激活,请激活"); } //查询到用户,且已激活,登录成功 if (u!=null&&"Y".equals(u.getStatus())){ request.getSession().setAttribute("user",u); info.setFlag(true); } //响应数据 ObjectMapper mapper=new ObjectMapper(); response.setContentType("application/json;charset=utf-8"); mapper.writeValue(response.getOutputStream(),info); } public void active(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取激活码 String code = request.getParameter("code"); //先判断获取的参数是否为空,不为空就可以激活 if (code != null) { //调用service完成激活 // UserService service = new UserServiceImpl(); boolean flag = service.active(code); //判断标记 String msg = null; if (flag) { //激活成功 msg = "激活成功,请<a href='login.html'>登录</a>"; } else { //激活失败 msg = "激活失败,请联系管理员"; } response.setContentType("text/html;charset=utf-8"); response.getWriter().write(msg); } } public void findOne(HttpServletRequest request, HttpServletResponse response) throws ServletException, 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); } public void exit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //銷毀session request.getSession().invalidate(); //跳轉登錄界面 response.sendRedirect(request.getContextPath()+"/login.html"); } }在BaseServlet中封装了序列化json的方法,就不用每次写回数据的时候都要一遍遍敲代码
/** * 直接将传入的对象序列化为json,并且写回客户端 * @param obj */ 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); } /** * 将传入的对象序列化为json,返回 * @param obj * @return */ public String writeValueAsString(Object obj) throws JsonProcessingException, JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); return mapper.writeValueAsString(obj); }CategoryServlet中的findAll方法:
private CategoryService service=new CategoryServiceImpl(); //查询所有线路 public void findAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //调用service查询所有 List<Category> cs = service.findAll(); //序列化json返回 writeValue(cs,response); }CategoryServiceImpl中的findAll方法:
@Override public List<Category> findAll() { return categoryDao.findAll(); }CategoryDaoImpl中的findAll方法:
public List<Category> findAll() { String sql="select * from tab_category"; return template.query(sql,new BeanPropertyRowMapper<Category>(Category.class)); }hader.html加载后,发送ajax请求,请求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>'; $("#category").html(lis); });分析发现,分类的数据在每一次页面加载后都会重新请求数据库来加载,对数据库的压力比较大,而且分类的数据不会经常产生变化,所有可以使用redis来缓存这个数据。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lsFRtYEO-1603200005356)(C:\Users\Baymax\AppData\Roaming\Typora\typora-user-images\image-20201019212822146.png)]
@Override public List<Category> findAll() { //1. 从redis中查询 //1.1 获取jedis客户端 Jedis jedis = JedisUtil.getJedis(); //1.2 可使用sortedset查询 Set<String> categorys = jedis.zrange("category", 0, -1); List<Category> cs = null; //2. 判断查询的集合是否为空 if (categorys == null || categorys.size() == 0) { // System.out.println("从数据库查询。。。"); //3. 如果为空,需要从数据库查询,再将数据存入redis //3.1 从数据库查询 cs = categoryDao.findAll(); //3.2 将集合中的数据存储到redis中的category的key for (int i = 0; i < cs.size(); i++) { jedis.zadd("category", cs.get(i).getCid(), cs.get(i).getCname()); } } else { // System.out.println("从redis中查询。。。"); cs = new ArrayList<Category>(); for (String name:categorys) { Category category=new Category(); category.setCname(name); cs.add(category); } } return cs; }Redis中查询score(cid)(使用Tupl)
@Override public List<Category> findAll() { //1. 从redis中查询 //1.1 获取jedis客户端 Jedis jedis = JedisUtil.getJedis(); //1.2 可使用sortedset查询 Set<Tuple> categorys = jedis.zrangeWithScores("category", 0, -1); List<Category> cs = null; //2. 判断查询的集合是否为空 if (categorys == null || categorys.size() == 0) { // System.out.println("从数据库查询。。。"); //3. 如果为空,需要从数据库查询,再将数据存入redis //3.1 从数据库查询 cs = categoryDao.findAll(); //3.2 将集合中的数据存储到redis中的category的key for (int i = 0; i < cs.size(); i++) { jedis.zadd("category", cs.get(i).getCid(), cs.get(i).getCname()); } } else { // System.out.println("从redis中查询。。。"); cs = new ArrayList<Category>(); for (Tuple tuple:categorys) { Category category=new Category(); category.setCname(tuple.getElement()); category.setCid((int)tuple.getScore()); cs.add(category); } } return cs; }页面传递cid,header.html传递cid
$.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?cid='+data[i].cid+'">' + data[i].cname + '</a></li>'; lis += li; } lis+='<li><a href="favoriterank.html">收藏排行榜</a></li>'; $("#category").html(lis); });route_list把cid取出来:search属性,返回从?开始的url部分
<script> $(function () { var search=location.search; alert(search); }); </script>[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3G7RTE2H-1603200005358)(C:\Users\Baymax\AppData\Roaming\Typora\typora-user-images\image-20201019223509753.png)]
<script> $(function () { var search=location.search; // alert(search); // 切割字符串,拿到第二个值 var cid = search.split("=")[1]; // alert(cid); }); </script>客户端要传入的是当前的页码currentPage和路线的cid,还有每页显示的条数
创建PageBean对象
package cn.itcast.travel.domain; import java.util.List; /** * 分页对象 */ public class PageBean<T> { private int totalCount; private int totalPage; private int currentPage; private int pageSize; private List<T> list;//每页显示的数据集合 public int getTotalCount() { return totalCount; } public void setTotalCount(int totalCount) { this.totalCount = totalCount; } public int getTotalPage() { return totalPage; } public void setTotalPage(int totalPage) { this.totalPage = totalPage; } public int getCurrentPage() { return currentPage; } public void setCurrentPage(int currentPage) { this.currentPage = currentPage; } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public List<T> getList() { return list; } public void setList(List<T> list) { this.list = list; } }RouteServlet:
@WebServlet("/route/*") public class RouteServlet extends BaseServlet { private RouteService routeService = new RouteServiceImpl(); public void pageQuery(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //接受参数 String currentPageStr = request.getParameter("currentPage"); String pageSizeStr = request.getParameter("pageSize"); String cidStr = request.getParameter("cid"); //处理参数 int cid = 0; 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; } //调用service查询PageBean对象 PageBean<Route> pb = routeService.pageQuery(cid, currentPage, pageSize); //将pageBean对象序列化为json返回 writeValue(pb,response); } }RouteServiceImpl
public class RouteServiceImpl implements RouteService { private RouteDao routeDao = new RouteDaoImpl(); @Override public PageBean<Route> pageQuery(int cid, int currentPage, int pageSize) { //封装PageBean PageBean<Route> pb = new PageBean<Route>(); //设置当前页码 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; } }RouteServiceImpl
public class RouteServiceImpl implements RouteService { private RouteDao routeDao = new RouteDaoImpl(); @Override public PageBean<Route> pageQuery(int cid, int currentPage, int pageSize) { //封装PageBean PageBean<Route> pb = new PageBean<Route>(); //设置当前页码 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; } }javascript:void(0)则停留在原地,一动不动,我们称之为“死链接”
route_list.html
<script> $(function () { var search = location.search; // alert(search); // 切割字符串,拿到第二个值 var cid = search.split("=")[1]; // alert(cid); //当页码加载完成后,调用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); //1.2 展示分页页码 /* 1.一共展示10个页码,能够达到前5后4的效果 2.如果前边不够5个,后边补齐10个 3.如果后边不足4个,前边补齐10个 */ // 定义开始位置begin,结束位置 end var lis = ""; var firstPage = '<li οnclick="javascript:load(' + cid + ',1)"><a href="javascript:void(0)">首页</a></li>'; //计算上一页的页码 beforeNum = currentPage - 1; if (beforeNum <= 0) { beforeNum = 1; } var beforePage = '<li οnclick="javascript:load(' + cid + ',' + beforeNum + ')" class="threeword"><a href="javascript:void(0)">上一页</a></li>'; lis += firstPage; lis += beforePage; var begin;//开始位置 var end;//结束位置 if (pb.totalPage <= 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++) { //判断当前页码是否等于i var li; if (i == pb.currentPage) { li = '<li class="curPage" οnclick="javascript:load(' + cid + ',' + i + ')"><a href="javascript:void(0)">' + i + '</a></li>'; } else { //创建一个页码的li li = '<li οnclick="javascript:load(' + cid + ',' + i + ')"><a href="javascript:void(0)">' + i + '</a></li>'; } lis += li; } //计算下一页的页码 nextNum = currentPage + 1; if (nextNum > pb.totalPage) { nextNum = pb.totalPage; } var nextPage = '<li οnclick="javascript:load(' + cid + ',' + nextNum + ')" class="threeword"><a href="javascript:;">下一页</a></li>'; var lastPage = '<li οnclick="javascript:load(' + cid + ',' + pb.totalPage + ')" class="threeword"><a href="javascript:;">末页</a></li>'; lis += nextPage; lis += lastPage; //将lis内容设置到ul $("#pageNum").html(lis); //列表数据展示 var route_lis = ""; for (var i = 0; i < pb.list.length; i++) { /* {"rid": 1, "rname": "【旅展 半价特惠 重走丝路•漫游宁夏 双飞4天】银川西部影视城 穆民新村 中卫沙坡头【品美酒 回族学唱花儿 感悟民俗】", "price": 999.0, "routeIntroduce": "走进【宁夏沙坡头】,感受西北大漠风情、体会“大漠孤烟直,长河落日圆”的塞上风光!", "rflag": "1", "rdate": "2018-02-09 01:13:16", "isThemeTour": "0", "count": 0, "cid": 5, "rimage": "img/product/small/m304b69a4c8328f7d6b8d5dadef020fe07.jpg", "sid": 1, "sourceId": "23677", "category": null, "seller": null, "routeImgList": null} */ 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); }) } </script>header.html:增加了rname
//给搜索按钮绑定单击事件,获取搜索输入框的内容 $("#search-button").click(function () { //线路名称 var rname=$("#search_input").val(); var cid=getParameter("cid"); // 跳转路径 http://localhost/travel/route_list.html?cid=5,拼接上rname=xxx location.href="http://localhost/travel/route_list.html?cid="+cid+"&rname="+rname; });route_list.html:增加输入rname参数
$(function () { // var search = location.search; // // alert(search); // // 切割字符串,拿到第二个值 // var cid = search.split("=")[1]; // // alert(cid); // //当页码加载完成后,调用load方法,发送Ajax请求加载数据 var cid = getParameter("cid"); var rname = getParameter("rname"); //判断rname不为null或者“” if (rname) { //url解码 rname = window.decodeURIComponent(rname); } // alert(rname); load(cid, null, rname); }); function load(cid, currentPage, rname) { //发送Ajax请求,请求route/pageQuery,传递cid $.get("route/pageQuery", {cid: cid, currentPage: currentPage, rname: rname}, function (pb) { //解析pageBean数据,展示到页面上 //1. 分页工具条数据展示 //1.1 展示总页码和总记录数 $("#totalPage").html(pb.totalPage); $("#totalCount").html(pb.totalCount); //1.2 展示分页页码 /* 1.一共展示10个页码,能够达到前5后4的效果 2.如果前边不够5个,后边补齐10个 3.如果后边不足4个,前边补齐10个 */ // 定义开始位置begin,结束位置 end var lis = ""; var firstPage = '<li onclick="javascript:load(' + cid + ',1,\''+rname+'\')"><a href="javascript:void(0)">首页</a></li>'; //计算上一页的页码 beforeNum = currentPage - 1; if (beforeNum <= 0) { beforeNum = 1; } var beforePage = '<li onclick="javascript:load(' + cid + ',' + beforeNum + ',\''+rname+'\')" class="threeword"><a href="javascript:void(0)">上一页</a></li>'; lis += firstPage; lis += beforePage; var begin;//开始位置 var end;//结束位置 if (pb.totalPage <= 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++) { //判断当前页码是否等于i var li; if (i == pb.currentPage) { li = '<li class="curPage" onclick="javascript:load(' + cid + ',' + i + ',\''+rname+'\')"><a href="javascript:void(0)">' + i + '</a></li>'; } else { //创建一个页码的li li = '<li onclick="javascript:load(' + cid + ',' + i + ',\''+rname+'\')"><a href="javascript:void(0)">' + i + '</a></li>'; } lis += li; } //计算下一页的页码 nextNum = currentPage + 1; if (nextNum > pb.totalPage) { nextNum = pb.totalPage; } var nextPage = '<li onclick="javascript:load(' + cid + ',' + nextNum + ',\''+rname+'\')" class="threeword"><a href="javascript:;">下一页</a></li>'; var lastPage = '<li onclick="javascript:load(' + cid + ',' + pb.totalPage + ',\''+rname+'\')" class="threeword"><a href="javascript:;">末页</a></li>';修改servlet:
//接受rname线路名称 String rname = request.getParameter("rname"); // System.out.println(rname); rname = new String(rname.getBytes("iso-8859-1"), "utf-8"); //调用service查询PageBean对象 PageBean<Route> pb = routeService.pageQuery(cid, currentPage, pageSize, rname);修改service:
int totalCount = routeDao.findTotalCount(cid, rname); List<Route> list = routeDao.findByPage(cid, start, pageSize, rname);修改dao:
@Override public int findTotalCount(int cid, String rname) { String sql = "select count(*) from tab_route where 1 = 1 "; StringBuilder sb = new StringBuilder(sql); List params = new ArrayList();//条件们 //判断参数是否有值 if (cid != 0) { sb.append(" and cid = ? "); params.add(cid); } if (rname != null && rname.length() > 0) { sb.append(" and rname like ? "); params.add("%" + rname + "%"); } sql = sb.toString(); return template.queryForObject(sql, Integer.class, params.toArray()); } @Override public List<Route> findByPage(int cid, int start, int pageSize, String rname) { String sql = "select * from tab_route where 1 = 1 "; StringBuilder sb = new StringBuilder(sql); List params = new ArrayList();//条件们 //判断参数是否有值 if (cid != 0) { sb.append("and cid = ? "); params.add(cid); } if (rname != null && rname.length() > 0) { sb.append(" and rname like ? "); params.add("%" + rname + "%"); } sb.append(" limit ? , ? ");//分页条件 sql = sb.toString(); params.add(start); params.add(pageSize); return template.query(sql, new BeanPropertyRowMapper<Route>(Route.class), params.toArray()); }cid=null和cid="null"有区别,需要增加一个判断条件
RouteServlet/findOne
public void findOne(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1. 接受rid String rid = request.getParameter("rid"); //2. 调用service查询route对象 Route route = routeService.findOne(rid); //3. 转为json写回客户端 writeValue(route, response); }service
@Override public Route findOne(String rid) { //1.根据id去route表中查询route对象 Route route = routeDao.findOne(Integer.parseInt(rid)); //2.根据route的id 查询图片集合信息 List<RouteImg> routeImgList = routeDao.findByRid(route.getRid()); //2.2将集合设置到route对象 route.setRouteImgList(routeImgList); //3.根据route的sid(商家id)查询商家对象 Seller seller = routeDao.findBySid(route.getSid()); route.setSeller(seller); //4. 查询收藏次数 int count=routeDao.finCountByRid(route.getRid()); route.setCount(count); return route; }dao:
@Override public Route findOne(int rid) { String sql = "select * from tab_route where rid = ?"; return template.queryForObject(sql, new BeanPropertyRowMapper<Route>(Route.class), rid); } @Override 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); } @Override public Seller findBySid(int sid) { String sql = "select * from tab_seller where sid = ?"; return template.queryForObject(sql, new BeanPropertyRowMapper<Seller>(Seller.class), sid); }前台代码:
\1. 获取rid
\2. 发送ajax请求,获取route对象
\3. 解析对象的数据
function goImg() { //焦点图效果 //点击图片切换图片 $('.little_img').on('mousemove', function () { $('.little_img').removeClass('cur_img'); var big_pic = $(this).data('bigpic'); $('.big_img').attr('src', big_pic); $(this).addClass('cur_img'); }); //上下切换 var picindex = 0; var nextindex = 4; $('.down_img').on('click', function () { var num = $('.little_img').length; if ((nextindex + 1) <= num) { $('.little_img:eq(' + picindex + ')').hide(); $('.little_img:eq(' + nextindex + ')').show(); picindex = picindex + 1; nextindex = nextindex + 1; } }); $('.up_img').on('click', function () { var num = $('.little_img').length; if (picindex > 0) { $('.little_img:eq(' + (nextindex - 1) + ')').hide(); $('.little_img:eq(' + (picindex - 1) + ')').show(); picindex = picindex - 1; nextindex = nextindex - 1; } }); } $(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); $("#favoriteCount").html("已收藏"+route.count+"次"); //图片展示 var ddstr = '<a class="up_img up_img_disable"></a>'; //遍历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(); }) })把goimg抽取出来
判断当前登录用户是否收藏过该线路
当页面加载完成后,发送ajax请求,获取用户是否收藏的标记
根据标记,展示不同的按钮样式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I8yPk7l7-1603200005360)(C:\Users\Baymax\AppData\Roaming\Typora\typora-user-images\image-20201020193845127.png)]
RouteServlet:
public void isFavorite(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1. 获取线路id String rid = request.getParameter("rid"); //2. 获取当前登录用户user User user = (User) request.getSession().getAttribute("user"); int uid; if (user == null) { //用户尚未登陆 uid = 0; } else { //用户已经登录 uid = user.getUid(); } //调用FavoriteService查询是否收藏 boolean flag = routeService.isFavorite(rid, uid); //写回客户端 writeValue(flag, response); } public void addFavorite(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1. 获取线路id String rid = request.getParameter("rid"); //2. 获取当前登录用户user User user = (User) request.getSession().getAttribute("user"); int uid; if (user == null) { //用户尚未登陆 return; } else { //用户已经登录 uid = user.getUid(); } //调用service添加 routeService.addFavorite(rid,uid); }service:
@Override public boolean isFavorite(String rid, int uid) { Favorite favorite = routeDao.findByRidAndUid(Integer.parseInt(rid), uid); return favorite!=null; } @Override public void addFavorite(String rid, int uid) { routeDao.addFavorite(Integer.parseInt(rid),uid); }dao:
@Override public Favorite findByRidAndUid(int rid, int uid) { Favorite favorite = null; try { String sql = "select * from tab_favorite where rid = ? and uid = ? "; favorite = template.queryForObject(sql, new BeanPropertyRowMapper<Favorite>(Favorite.class), rid, uid); } catch (DataAccessException e) { e.printStackTrace(); } return favorite; } @Override public int finCountByRid(int rid) { String sql = "select count(*) from tab_favorite where rid = ?"; return template.queryForObject(sql, Integer.class, rid); } @Override public void addFavorite(int rid, int uid) { String sql = "insert into tab_favorite values(?,?,?)"; template.update(sql,rid,new Date(),uid); }前台代码:
$("#favoriteCount").html("已收藏"+route.count+"次"); $(function () { //发送请求,判断用户是否收藏过该线路 var rid=getParameter("rid"); $.get("route/isFavorite",{rid:rid},function (flag) { if (flag){ //用户已经收藏过 //<a class="btn already" disabled="disabled"><i class="glyphicon glyphicon-heart-empty"></i>点击收藏</a>--> $("#favorite").addClass("already"); $("#favorite").attr("disabled","disabled"); //删除按钮的点击事件 $("#favorite").removeAttr("onclick"); }else{ //用户未收藏 } }) }) //点击收藏按钮收藏 function addFavorite() { //判断用户是否登录 $.get("user/findOne",{},function (user) { var rid=getParameter("rid"); if (user){ //用户已经登录 $.get("route/addFavorite",{rid:rid},function () { //代码手动刷新页面 location.reload(); }) }else { //用户没登录 alert("您尚未登陆,请登录"); location.href="http://localhost/travel/login.html"; } }) }favorite where rid = ? and uid = ? "; favorite = template.queryForObject(sql, new BeanPropertyRowMapper(Favorite.class), rid, uid); } catch (DataAccessException e) { e.printStackTrace(); } return favorite; }
@Override public int finCountByRid(int rid) { String sql = "select count(*) from tab_favorite where rid = ?"; return template.queryForObject(sql, Integer.class, rid); } @Override public void addFavorite(int rid, int uid) { String sql = "insert into tab_favorite values(?,?,?)"; template.update(sql,rid,new Date(),uid); } 前台代码: ```html $("#favoriteCount").html("已收藏"+route.count+"次"); $(function () { //发送请求,判断用户是否收藏过该线路 var rid=getParameter("rid"); $.get("route/isFavorite",{rid:rid},function (flag) { if (flag){ //用户已经收藏过 //<a class="btn already" disabled="disabled"><i class="glyphicon glyphicon-heart-empty"></i>点击收藏</a>--> $("#favorite").addClass("already"); $("#favorite").attr("disabled","disabled"); //删除按钮的点击事件 $("#favorite").removeAttr("onclick"); }else{ //用户未收藏 } }) }) //点击收藏按钮收藏 function addFavorite() { //判断用户是否登录 $.get("user/findOne",{},function (user) { var rid=getParameter("rid"); if (user){ //用户已经登录 $.get("route/addFavorite",{rid:rid},function () { //代码手动刷新页面 location.reload(); }) }else { //用户没登录 alert("您尚未登陆,请登录"); location.href="http://localhost/travel/login.html"; } }) }