黑馬旅游網總結
一、設計想法
這次自己做了個很簡單的旅游網站,目的是為了檢驗之前學習內容。我主要是后台開發,因為沒有前台搭檔,所以前端代碼取決於該作品的源碼。
- 開發工具:
IDEA2019.2
+SQLyog
- 開發模式:前后端分離
- 開發配置:
maven
+mysql
+tomcat
+redis
二、項目環境配置和分析
這一天主要是配置好項目,關於mysql
、tomcat
、redis
、maven
在之前就配置好,也是做項目前的基礎吧,這里不在啰嗦。
1、maven管理項目
maven真的是方便了開發,因為只需要把要用的jar包在pom.xml
中配置好就行。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>Whirlwind</groupId>
<artifactId>travel</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<!--junit單元檢測-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!--servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!--mysql驅動-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.26</version>
<scope>compile</scope>
</dependency>
<!--druid連接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.9</version>
</dependency>
<!--jdbcTemplate-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.1.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<!--spring-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.1.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.1.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.1.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<!--commons-logging日志支持包-->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
<scope>compile</scope>
</dependency>
<!--beanUtils簡化javabean的操作-->
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.2</version>
<scope>compile</scope>
</dependency>
<!--jackson序列化和反序列化-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.3.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.3.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.3.3</version>
</dependency>
<!--javaMail-->
<dependency>
<groupId>javax.mail</groupId>
<artifactId>javax.mail-api</artifactId>
<version>1.5.6</version>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.5.3</version>
</dependency>
<!--jedis-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.7.0</version>
</dependency>
</dependencies>
<build>
<!--maven插件-->
<plugins>
<!--jdk編譯插件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>
<!--tomcat插件-->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<!-- tomcat7的插件, 不同tomcat版本這個也不一樣 -->
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<!-- 通過maven tomcat7:run運行項目時,訪問項目的端口號 -->
<port>80</port>
<path>/travel</path>
</configuration>
</plugin>
</plugins>
</build>
</project>
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 = "<a href='http://localhost/travel/user/active?code=\"+user.getCode()+\"'>點擊激活【任意旅游網】</a>";
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<Category> findAll() {
//從redis中查詢
//獲取jedis客戶端
Jedis jedis = JedisUtil.getJedis();
//查詢sortedset中的分數(cid)和值(cname),相當於獲取步驟
Set<Tuple> categorys = jedis.zrangeWithScores("category",0,-1);
List<Category> cs = null;
//判斷查詢的集合是否為空
if (categorys==null||categorys.size()==0) {
System.out.println("從數據庫中查詢...");
//如果為空,需要從數據庫查詢,在將數據存入redis
//從數據庫查詢
cs = categoryDao.findAll();
//將集合數據存儲到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中查詢...");
//如果不為空,將set的數據存入list
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;
}
五、旅游路線類的實現
點擊不同的旅游類別后,后面顯示的數據信息
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<RouteImg> routeImgList;//商品詳情圖片列表
//省略 get set toString 構造函數
}
PageBean
類來封裝所有的信息,不僅包含具體的景點信息還包含有多少個景點,多少頁等記錄
/**
* 分頁對象
* 存儲了各種頁面信息
*/
public class PageBean<T> {
private int totalCount;//總記錄數
private int totalPage;//總頁數
private int currentPage;//當前頁碼
private int pageSize;//每頁顯示的條數
private List<T> 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() {
}
}
恩,項目結束,開始期末復習,哭了。