某马旅游网学习分享

某马旅游网学习分享

    • 一、介绍
    • 二、注册模块
      • 1、前端对用户名、姓名、密码、邮箱做非空和正则校验。
      • 2、验证码实现
      • 3、注册代码实现
    • 三、登录和退出模块
      • 1、登录
      • 2、退出
    • 四、分类栏目
      • 1、所有分类栏目查询展示实现
    • 五、旅游线路
      • 1、旅游线路分页展示分页展示
      • 2、路线详情实现

一、介绍

  • 本文主要是想在学习的过程中做一些笔记方便自己以后查询,同时对于初学者也是一个很好的练手项目,可以加深对JavaWeb相关技术的应用。
  • 使用到的技术:js、html、bootstrap;Java、Servlet、JdbcTemplate、MySQL、Redis
  • 项目源码地址下载:https://gitee.com/sxd123456/travel.git

二、注册模块

1、前端对用户名、姓名、密码、邮箱做非空和正则校验。

某马旅游网学习分享_第1张图片

2、验证码实现

  • 思路:加载页面时向CheckCodeServlet发送请求,后端接收请求后生成一个随机的4位数校验码,生成一张图片,将图片返回至前端。
public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
     
		
		//服务器通知浏览器不要缓存
		response.setHeader("pragma","no-cache");
		response.setHeader("cache-control","no-cache");
		response.setHeader("expires","0");
		
		//在内存中创建一个长80,宽30的图片,默认黑色背景
		//参数一:长
		//参数二:宽
		//参数三:颜色
		int width = 80;
		int height = 30;
		BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
		
		//获取画笔
		Graphics g = image.getGraphics();
		//设置画笔颜色为灰色
		g.setColor(Color.GRAY);
		//填充图片
		g.fillRect(0,0, width,height);
		
		//产生4个随机验证码,12Ey
		String checkCode = getCheckCode();
		//将验证码放入HttpSession中
		request.getSession().setAttribute("CHECKCODE_SERVER",checkCode);
		
		//设置画笔颜色为黄色
		g.setColor(Color.YELLOW);
		//设置字体的小大
		g.setFont(new Font("黑体",Font.BOLD,24));
		//向图片上写入验证码
		g.drawString(checkCode,15,25);
		
		//将内存中的图片输出到浏览器
		//参数一:图片对象
		//参数二:图片的格式,如PNG,JPG,GIF
		//参数三:图片输出到哪里去
		ImageIO.write(image,"PNG",response.getOutputStream());
	}
	/**
	 * 产生4位随机字符串 
	 */
	private String getCheckCode() {
     
		String base = "0123456789ABCDEFGabcdefg";
		int size = base.length();
		Random r = new Random();
		StringBuffer sb = new StringBuffer();
		for(int i=1;i<=4;i++){
     
			//产生0到size-1的随机值
			int index = r.nextInt(size);
			//在base字符串中获取下标为index的字符
			char c = base.charAt(index);
			//将c放入到StringBuffer中去
			sb.append(c);
		}
		return sb.toString();
	}
  • 前端通过img标签加载图片,点击图片可以刷新校验码。
<td class="td_right check">
    								<input type="text" id="check" name="check" class="check">
    								<img src="checkCode" height="32px" alt="" onclick="changeCheckCode(this)">
									<script type="text/javascript">
										//图片点击事件
										function changeCheckCode(img) {
     
											img.src="checkCode?"+new Date().getTime();
                                        }
									</script>
    							</td>

3、注册代码实现

  • 输入完相关校验后点击注册通过post请求将表单数据提交至UserServlet, UserServlet首先判断校验码是否正确
 		//判断验证码是否正确
        String checkcode_server = request.getParameter("check");
        HttpSession session = request.getSession();
        //从session中获取验证码
        String checkcodeServer = (String) session.getAttribute("CHECKCODE_SERVER");
        //获取后移除改验证码
        session.removeAttribute("CHECKCODE_SERVER");
        if(checkcode_server==null || !checkcode_server.equalsIgnoreCase(checkcodeServer)){
     
            ResultInfo info=new ResultInfo();
            info.setFlag(false);
            info.setErrorMsg("注册失败!");
            //将info序列化为json发送至前端
            ObjectMapper mapper=new ObjectMapper();
            String info_json = mapper.writeValueAsString(info);
            response.setContentType("application/json;charzset=utf-8");
            response.getWriter().write(info_json);
            return;
        }
  • 然后根据用户名查询数据库中是否存在相同用户名称的用户,存在则注册失败
 //根据用户名查找用户
 public User findByName(String username) {
     
        String sql="select * from tab_user where username=?";
        User user=null;
        try {
     
             user = template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), username);
        }catch (Exception e){
     
            e.printStackTrace();
        }
        return user;
    }
  • 全部校验通过后将用户信息存入数据库,同时根据用户注册时填写的邮箱发送一份邮件,用户需要通过邮件激活账户。具体邮箱如何发送邮件已经封装为工具类MailUtils,大家可以自行下载查看。
    邮箱激活
  • 如果注册失败则会在页面提示信息,关于前端页面的调试问题在本文不做太多的阐述,我们主要关心后端的逻辑以及代码实现。
    某马旅游网学习分享_第2张图片

三、登录和退出模块

1、登录

  • 首先输入账户密码以及验证码,通过post请求将表单数据提交至LoginServlet,通过用户和账号查询数据中是否存在已经激活了的用户,然后将user设置入session。代码详解看注释。
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     
        //获取登录信息
        Map<String, String[]> map = request.getParameterMap();
        //用User对象封装
        User user =new User();
        try {
     
            //如果user中属性和map中key相匹配,则将map中的value赋值给user相关属性
            BeanUtils.populate(user,map);
        } catch (IllegalAccessException e) {
     
            e.printStackTrace();
        } catch (InvocationTargetException e) {
     
            e.printStackTrace();
        }
        //调用service根据用户名以及密码查询是否注册和激活
        RegistService service=new RegistServiceImpl();
       User user1= service.findByNameAndPassword(user.getUsername(),user.getPassword());
        HttpSession session = request.getSession();
        //封装提交给前端的数据
        ResultInfo info=new ResultInfo();
       if(user1==null){
     
           //数据库不存在该用户
           info.setFlag(false);
           info.setErrorMsg("用户名或密码错误");
       }
       if(user1!=null && "N".equalsIgnoreCase(user1.getStatus())){
     
            //未激活
           info.setFlag(false);
           info.setErrorMsg("尚未激活,请激活");
       }
       if(user1!=null && "Y".equalsIgnoreCase(user1.getStatus())){
     
           //登录成功
           info.setFlag(true);
       }
        //将用户设置入session
        session.setAttribute("user",user1);
       //序列化为json
        ObjectMapper mapper=new ObjectMapper();
        String json = mapper.writeValueAsString(info);
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(json);
    }
  • 退出登录成功后将session取出,放置欢迎页。
    某马旅游网学习分享_第3张图片

2、退出

  • 退出功能实现也简单,就是点击退出时销毁session,同时重定向跳转至登录页。
 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     
        //销毁session
        request.getSession().invalidate();
        //重定向
        response.sendRedirect(request.getContextPath()+"/login.html");
    }

四、分类栏目

  • 效果图

1、所有分类栏目查询展示实现

  • 思路:页面加载时发送Ajax请求至CategoryServlet,后端接收请求后查询数据表tab_category,将数据封装后返回至前端,前端解析数据,拼装html。
  • 本系统实现做了一个优化,也算是对redis的一个应用。就是在查询数据库时先判断reids中是否有值,有的话就直接取redis中数据,速度会比从数据库中查询快的多。因为分类栏目一般变动是很少的,放redis中提高用户体验。
 public List<Category> findAll() {
     
        //查找redis缓存是否有数据
        Jedis jedis = JedisUtil.getJedis();
        jedis.auth("1234");
        //Set categorys = jedis.zrange("category", 0, -1);
        Set<Tuple> categorys = jedis.zrangeWithScores("category", 0, -1);
        List<Category> category=new ArrayList<>();
        if(categorys.size()==0 || categorys==null){
     
            //说明缓存中没有数据,则查询数据库
            System.out.println("查询数据库。。。。");
            category = dao.findAll();
            //将查询的数据存入redis
            for (int i = 0; i < category.size(); i++) {
     
                jedis.zadd("category",category.get(i).getCid(),category.get(i).getCname());
            }
        }else {
     
            //缓存中有数据,把set集合转化为list集合
            System.out.println("查询缓存。。。。");
            for (Tuple tuple : categorys) {
     
                Category category1=new Category();
                category1.setCname(tuple.getElement());
                category1.setCid((int) tuple.getScore());
                category.add(category1);
            }
        }
        return category;
    }

五、旅游线路

1、旅游线路分页展示分页展示

效果图
某马旅游网学习分享_第4张图片

  • 实现思路:点击国内游时,发送请求(http://localhost:8086/route/pageQuery?cid=5¤tPage=&rname=)至RouteServlet,请求的参数有类别编号cid,当前页码currentPage,路线查询名称rname。根据传入的参数查询数据表tab_route,查出数据封装返回至前端解析。
  • 分页查询思路:MySQL分页查询的语句(select * from 表 limt 起始页 每页显示条数),因此我们根据页面传入的条件便可以查询出相关数据。
  • 条数、页码以及上一页下一页实现思路:总条数(select count (*) from tab_route where cid=?)
    总页数=total%pageSize==0 ? total/pageSize:total/pageSize+1;
    下一页则拿取当前页码加一,Ajax请求一次数据,上一页实现也是类似,同时需要考虑边界值,如在第一页点击上一页和在最后一页点击下一页的情况。部分代码实现如下:
@WebServlet( "/route/*")
public class RouteServlet extends BaseServlet {
     
    private RouteService service=new RouteServiceImpl();
    public void pageQuery(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     
        String cidStr = request.getParameter("cid");//类别编号
        String currentPageStr = request.getParameter("currentPage");//当前页码
        String pageSizeStr = request.getParameter("pageSize");//每页显示条数
        //接受rname 线路名称
        String rname = request.getParameter("rname");
        rname = new String(rname.getBytes("iso-8859-1"),"utf-8");
        int cid=0;
        if(cidStr!=null && cidStr.length()>0 && !"null".equals(cidStr)){
     
            cid=Integer.parseInt(cidStr);
        }
        int currentPage=1;
        if(currentPageStr!=null && currentPageStr.length()>0){
     
            currentPage=Integer.parseInt(currentPageStr);
        }

        int pageSize=5;
        if(pageSizeStr!=null && pageSizeStr.length()>0){
     
            pageSize=Integer.parseInt(pageSizeStr);
        }
        //获取参数
        //调用service获取pageBean
        PageBean<Route> pageBean=service.findPageQuery(cid,currentPage,pageSize,rname);
        writeValue(pageBean,response);
    }
    public void findOne(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     
        String rid = request.getParameter("rid");//获取route的id
        Route route=service.findOne(rid);
        writeValue(route,response);
    }
}

2、路线详情实现

效果图:
某马旅游网学习分享_第5张图片

  • 思路:每个路线都有一个rid,点击详情时将rid传后台就可以查出该条数据,然后将相关信息拼装到html(http://localhost:8086/route/findOne?rid=1)。这块后端实现很简单,主要是前端html的拼接繁琐了一点。
  • 后端代码
public void findOne(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     
        String rid = request.getParameter("rid");//获取route的id
        Route route=service.findOne(rid);
        writeValue(route,response);
    }
  • 前端代码
//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 = '';

            //遍历routeImgList
            for (var i = 0; i < route.routeImgList.length; i++) {
     
                var astr ;
                if(i >= 4){
     
                    astr = '+route.routeImgList[i].bigPic+'" style="display:none;">\n' +
                        '                        +route.routeImgList[i].smallPic+'">\n' +
                        '                    ';
                }else{
     
                    astr = '+route.routeImgList[i].bigPic+'">\n' +
                        '                        +route.routeImgList[i].smallPic+'">\n' +
                        '                    ';
                }
                ddstr += astr;
            }
            ddstr+='';

            $("#dd").html(ddstr);
            //图片展示和切换代码调用
            goImg();
        });

你可能感兴趣的:(学习项目,java,servlet,redis,mysql)