任意旅游网总结
一、设计想法
这次自己做了个很简单的旅游网站,目的是为了检验之前学习内容。我主要是后台开发,因为没有前台搭档,所以前端代码取决于该作品的源码。
- 开发工具:
IDEA2019.2
+SQLyog
- 开发模式:前后端分离
- 开发配置:
maven
+mysql
+tomcat
+redis
+SpringMVC
二、项目环境配置和分析
这一天主要是配置好项目,关于mysql
、tomcat
、redis
、maven
在之前就配置好,也是做项目前的基础吧,这里不在啰嗦。
1、maven管理项目
maven真的是方便了开发,因为只需要把要用的jar包在pom.xml
中配置好就行。
4.0.0
Whirlwind
travel
1.0-SNAPSHOT
war
junit
junit
3.8.1
test
javax.servlet
javax.servlet-api
3.1.0
provided
mysql
mysql-connector-java
5.1.26
compile
com.alibaba
druid
1.0.9
org.springframework
spring-core
4.1.2.RELEASE
compile
org.springframework
spring-jdbc
4.1.2.RELEASE
compile
org.springframework
spring-tx
4.1.2.RELEASE
compile
org.springframework
spring-beans
4.1.2.RELEASE
compile
commons-logging
commons-logging
1.1.1
compile
commons-beanutils
commons-beanutils
1.9.2
compile
com.fasterxml.jackson.core
jackson-databind
2.3.3
com.fasterxml.jackson.core
jackson-core
2.3.3
com.fasterxml.jackson.core
jackson-annotations
2.3.3
javax.mail
javax.mail-api
1.5.6
com.sun.mail
javax.mail
1.5.3
redis.clients
jedis
2.7.0
org.apache.maven.plugins
maven-compiler-plugin
1.8
utf-8
org.apache.tomcat.maven
tomcat7-maven-plugin
2.1
80
/travel
2、项目结构分析
先上图
(1)、java目录下主要放后端逻辑代码
这里利用了经典的三层构架,一层一层来分析。
dao
目录:
dao
包主要放数据层接口规范和对应的实现类
domain
目录:
domain
包主要放实体类
service
目录:
service
包主要放服务层接口规范和对应的实现类
util
目录:
util
包主要放工具类
web
目录:
web
包主要放过滤器和servlet
(2)、resources目录下主要放加载文件
druid
主要是来提供高效率的数据查询,阿里爸爸做的,网上可以下载,因为是旅游网站,数据量还是可观,所以用到了。jedis
是是Redis
官方推荐的Java连接开发工具,因为用到了NOSQL
,所以也用到了。数据库没有自己写,根据源码提供而来,看一下所有表的关系吧,
(3)、webapp目录下主要放前端代码
不是自己写的,大致看的懂就想,个人认为不咋好看,贴出来瞅瞅,
前后端分离的模式使得逻辑更清晰,同时java
目录下的包各有功能,在以后需要添加功能时也更加便捷。
三、用户类的实现
1、用户类分析
这里主要完成了User
相关的内容,在真正的项目中,需要考虑的内容还是很丰富,贴一下用户实体类
/**
* 用户实体类
*/
public class User implements Serializable {
private int uid;//用户id
private String username;//用户名,账号
private String password;//密码
private String name;//真实姓名
private String birthday;//出生日期
private String sex;//男或女
private String telephone;//手机号
private String email;//邮箱
private String status;//激活状态,Y代表激活,N代表未激活
private String code;//激活码(要求唯一)
//省略 get set toString 构造函数等方法
在我们的实际生活中,比如我要玩LOL,首先我要有个微信或者qq号吧,这里用户就要注册、激活(类似邮箱认证和电话号码验证)、登录,在玩完之后退出,这一完整过程才称得上用户功能实现。当然腾讯爸爸作为服务端,他要记录你的信息啊,如果有账号了,你就直接来玩就行,但没有账号,就需要你来注册,然后我为你保存信息,记录下你的账号和密码,以后你就不用在这么麻烦了。同理,几乎所有网站对User
对象都要实现这些方法吧。
这里展示出写的内容
dao
包:
UserDao.java UserDaoImpl.java
domain
包:
User.java
service
包:
UserService.java UserServiceImpl.java
servlet
包:
RegistServlet.java ActiveServlet.java LoginServlet.java ExitServlet.java
2、用户类学习
(1)、激活状态记录
这一点设计的很巧妙,你没有注册过,在数据库user
表中的字段status
中显示N就可,如果注册了,用update更新一下即可。
public void updateStatus(User user) {
//修改指定用户激活状态
String sql = "update tab_user set status = 'Y' where uid=?";
template.update(sql,user.getUid());
(2)、激活发送邮件
这里用了一个MailUtils
的工具类,在git上随便找吧,但目前只支持qq邮箱
//激活邮件
String content = "点击激活【任意旅游网】";
MailUtils.sendMail(user.getEmail(),content,"激活邮件");
(3)、Servlet性能优化
通常,写一个项目可能会出现N多个Servlet
,而且一般一个Servlet
只有一个方法(doGet
或doPost
),如果项目大一些,那么Servlet
的数量就会很惊人。为了避免Servlet
的“膨胀”,我们写一个BaseServlet
。它的作用是让一个Servlet
可以处理多种不同的请求。不同的请求调用Servlet
的不同方法。同时,我们可以将用户的这些servlet
写成一整个模块UserServlet
。?通俗讲,以前一个功能一个Servlet,现在一个模块一个Servlet。 BaseServlet可以帮我们解决代码冗余,解决创建过多的Servlet,可以让我们开发的过程只需要注重业务实现,提高工作效率。
四、旅游分类的实现
就是实现这一框框
1、旅游分类分析
这一功能,就类似博客的标签分类吧,只需要做好分类id即可。
/**
* 分类实体类
*/
public class Category implements Serializable {
private int cid;//分类id
private String cname;//分类名称
//省略 get set toString 构造函数
}
这里展示出写的内容
dao
包:
CategoryDao.java CategoryDaoImpl.java
domain
包:
Category.java
service
包:
CategoryService.java CategoryServiceImpl.java
servlet
包:
CategoryServlet.java
2、旅游分类学习
(1)、redis的运用
这里涉及到缓存的问题,我在之前有写过。https://www.cnblogs.com/wangzheming35/p/11990614.html
首先分析一下,分类数据在每一次页面加载后都会出现重新请求数据库来加载,对数据库压力很大且数据不常变化,没必要每次都要去访问,所以用到了redis
来做缓存。
场景:分类信息不常变化却每一次都要去访问
redis
查询- 判断集合是否为null?
- Y-第一次访问-查数据库存入
redis
,N-非第一次访问,直接在缓存中取出 - 返回集合
//查询旅游分类的所有方法
public List findAll() {
//从redis中查询
//获取jedis客户端
Jedis jedis = JedisUtil.getJedis();
//查询sortedset中的分数(cid)和值(cname),相当于获取步骤
Set categorys = jedis.zrangeWithScores("category",0,-1);
List cs = null;
//判断查询的集合是否为空
if (categorys==null||categorys.size()==0) {
System.out.println("从数据库中查询...");
//如果为空,需要从数据库查询,在将数据存入redis
//从数据库查询
cs = categoryDao.findAll();
//将集合数据存储到redis中的 category的key,相当于存储步骤
for (int i=0;i();
for (Tuple tuple: categorys
) {
Category category = new Category();
category.setCname(tuple.getElement());
category.setCid((int)tuple.getScore());
cs.add(category);
}
}
return cs;
}
五、旅游路线类的实现
点击不同的旅游类别后,后面显示的数据信息
1、旅游路线类分析
这一功能主要是展示一个大页面,每个分类对应不同的旅游路线。在这里还写了一个分页功能。
每个旅游景点的详细信息我们封装在Route
类
/**
* 旅游线路商品实体类
* 每一个项目的具体信息
*/
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 routeImgList;//商品详情图片列表
//省略 get set toString 构造函数
}
PageBean
类来封装所有的信息,不仅包含具体的景点信息还包含有多少个景点,多少页等记录
/**
* 分页对象
* 存储了各种页面信息
*/
public class PageBean {
private int totalCount;//总记录数
private int totalPage;//总页数
private int currentPage;//当前页码
private int pageSize;//每页显示的条数
private List list;//每页显示的数据集合
//省略 get set toString 构造函数
}
这里展示出写的内容
dao
包:
RouteDao.java RouteDaoImpl.java
domain
包:
Route.java PageBean.java
service
包:
RouteService.java RouteServiceImpl.java
servlet
包:
RouteServlet.java
2、旅游路线分类学习
(1)、逻辑关系
其实在这个模块,最多要弄清楚的是逻辑模块,因为要实现很多功能。比如:从旅游分类点击后,要显示具体的旅游路线分类,这些线路分类为了美观,我们要分页展示,其次路线这一模块对应的是每一个不同的商家还有用户们是否收藏的问题。这里用的SQLyog的可视化关系
可见Route
这一模块和四个表存在关系,在设计时必须弄清关系,才能更好的书写代码。
六、详情设计的类的实现
可见上表,有哪些详情呢?商品图片、商家信息、收藏信息,这些都是设计到的详情。
1、其他详情类分析
商品图片展示类,用来展示旅游路线图片的
/**
* 旅游线路图片实体类
*/
public class RouteImg implements Serializable {
private int rgid;//商品图片id
private int rid;//旅游商品id
private String bigPic;//详情商品大图
private String smallPic;//详情商品小图
//...
}
商家信息类,展示商家的信息的
/**
* 商家实体类
*/
public class Seller implements Serializable {
private int sid;//商家id
private String sname;//商家名称
private String consphone;//商家电话
private String address;//商家地址
//...
}
收藏信息类,判断用户是否收藏该宝贝
/**
* 收藏实体类
*/
public class Favorite implements Serializable {
private Route route;//旅游线路对象
private String date;//收藏时间
private User user;//所属用户
//...
}
这里展示出写的内容
dao
包:
FavoriteDao.java FavoriteDaoImpl.java
SellerDao.java SellerDaoImpl.java
RouteImgDao.java RouteImgDaoImpl.java
domain
包:
Favorite.java Seller.java RouteImg.java
service
包:
FavoriteService.java FavoriteServiceImpl.java
这里没有Servlet
,因为这些功能都是在RouteServlet
中实现。
七、其他一些问题
1、网站乱码问题
在打开网站的时候,结果缩成了一团,而且都是乱码,在掘金上看到片文章,可以用过滤器处理。
过滤器可以做:过滤一些敏感的字符串【规定不能出现敏感字符串】、避免中文乱码【规定Web资源都使用UTF-8编码】、权限验证【规定只有带Session或Cookie的浏览器,才能访问web资源】等等等,过滤器的作用非常大,只要发挥想象就可以有意想不到的效果 https://juejin.im/post/5a7be1fbf265da4e8263377f
这里做了一个字符个过滤器,避免中文乱码
package Whirlwind.travel.web.filter;
import javax.servlet.*;
import java.io.IOException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author wzm
*/
public class CharchaterFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest req, ServletResponse rep, FilterChain chain) throws IOException, ServletException {
//将父接口转为子接口
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) rep;
//获取请求方法
String method = request.getMethod();
//解决post请求中文数据乱码问题
if(method.equalsIgnoreCase("post")){
request.setCharacterEncoding("utf-8");
}
//处理响应乱码
response.setContentType("text/html;charset=utf-8");
chain.doFilter(request,response);
}
@Override
public void destroy() {
}
}
恩,项目结束,开始期末复习,哭了。