某马旅游网学习分享
-
- 一、介绍
- 二、注册模块
-
- 1、前端对用户名、姓名、密码、邮箱做非空和正则校验。
- 2、验证码实现
- 3、注册代码实现
- 三、登录和退出模块
-
- 四、分类栏目
-
- 五、旅游线路
-
一、介绍
- 本文主要是想在学习的过程中做一些笔记方便自己以后查询,同时对于初学者也是一个很好的练手项目,可以加深对JavaWeb相关技术的应用。
- 使用到的技术:js、html、bootstrap;Java、Servlet、JdbcTemplate、MySQL、Redis
- 项目源码地址下载:https://gitee.com/sxd123456/travel.git
二、注册模块
1、前端对用户名、姓名、密码、邮箱做非空和正则校验。
![某马旅游网学习分享_第1张图片](http://img.e-com-net.com/image/info8/0080baf0585b4cbbaa1576cc6cc9de72.jpg)
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");
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);
String checkCode = getCheckCode();
request.getSession().setAttribute("CHECKCODE_SERVER",checkCode);
g.setColor(Color.YELLOW);
g.setFont(new Font("黑体",Font.BOLD,24));
g.drawString(checkCode,15,25);
ImageIO.write(image,"PNG",response.getOutputStream());
}
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++){
int index = r.nextInt(size);
char c = base.charAt(index);
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();
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("注册失败!");
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,大家可以自行下载查看。
![邮箱激活](http://img.e-com-net.com/image/info8/68bc7719755a42c6b09ff02c63f65df8.jpg)
- 如果注册失败则会在页面提示信息,关于前端页面的调试问题在本文不做太多的阐述,我们主要关心后端的逻辑以及代码实现。
![某马旅游网学习分享_第2张图片](http://img.e-com-net.com/image/info8/d97f0d55ce904c4c97d671a846db5987.jpg)
三、登录和退出模块
1、登录
- 首先输入账户密码以及验证码,通过post请求将表单数据提交至LoginServlet,通过用户和账号查询数据中是否存在已经激活了的用户,然后将user设置入session。代码详解看注释。
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Map<String, String[]> map = request.getParameterMap();
User user =new User();
try {
BeanUtils.populate(user,map);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
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.setAttribute("user",user1);
ObjectMapper mapper=new ObjectMapper();
String json = mapper.writeValueAsString(info);
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(json);
}
- 退出登录成功后将session取出,放置欢迎页。
![某马旅游网学习分享_第3张图片](http://img.e-com-net.com/image/info8/40c66217ff25465ba8c9f9c5471e40a7.jpg)
2、退出
- 退出功能实现也简单,就是点击退出时销毁session,同时重定向跳转至登录页。
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getSession().invalidate();
response.sendRedirect(request.getContextPath()+"/login.html");
}
四、分类栏目
1、所有分类栏目查询展示实现
- 思路:页面加载时发送Ajax请求至CategoryServlet,后端接收请求后查询数据表tab_category,将数据封装后返回至前端,前端解析数据,拼装html。
- 本系统实现做了一个优化,也算是对redis的一个应用。就是在查询数据库时先判断reids中是否有值,有的话就直接取redis中数据,速度会比从数据库中查询快的多。因为分类栏目一般变动是很少的,放redis中提高用户体验。
public List<Category> findAll() {
Jedis jedis = JedisUtil.getJedis();
jedis.auth("1234");
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();
for (int i = 0; i < category.size(); i++) {
jedis.zadd("category",category.get(i).getCid(),category.get(i).getCname());
}
}else {
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://img.e-com-net.com/image/info8/6d5fd77b471c441dbecc17731b754862.jpg)
- 实现思路:点击国内游时,发送请求(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张图片](http://img.e-com-net.com/image/info8/49caad11d6934f57aeb81cf0b6be42b6.jpg)
- 思路:每个路线都有一个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 route=service.findOne(rid);
writeValue(route,response);
}
var rid = getParameter("rid");
$.get("route/findOne",{
rid:rid},function (route) {
$("#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 = '';
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();
});