• 【Javaweb项目实战】黑马旅游网


    本次项目主要有以下几个重点导入项目、优化servlet、前后台勾连等。

    如图片所示,这是一个常见的网站首页,包括登录、注册、查看相关信息的功能。

    但要怎么实现呢?

    除了准备好相应的图片文字信息,我们要怎么做才能让它拥有以上功能并展示在页面上呢?

    抱着这样的疑惑,我们慢慢来一探究竟吧?

    首先是基本准备(也可以使用maven直接导入半成品项目):

    后端:

     还有要提前建立存放图片和文字资源的数据库。

    这里我使用的是Navicat软件。

    这是一款可视化建库软件,使用起来非常方便。

    前端及资源文件:

    看到pom.xml文件了吗?这表示 我是从maven导入的半成品项目,接下来我们来了解一下如何使用maven导入项目。

    maven导入项目:

    maven:Maven是一个跨平台的项目管理工具,是Apache组织中的一个颇为成功的开源项目。Maven主要服务基于java的项目构建,项目信息管理和依赖管理。

    作用:
    1.Maven可以创建项目。
    2.Maven可以引入依赖的jar包。
    在Maven中有一个核心的概念--仓库,分为本地仓库和远程仓库。远程仓库又分为中央仓库,私服和其他仓库。

    首先是确保自己下载了maven的资源文件,并且IDE安装并启动了maven插件:

    打开设置:

     以上准备操作没有问题就会在右侧导航栏出现以下内容:

     点击maven,出现以下内容:

     点击“+”号,导入项目。

     选择pom.xml文件,点击OK完成项目导入,初始化微微等待一会即可。

    以下是pom.xml文件的内容,我们可以看到里面包含了诸多插件的信息,这是依赖管理:对jar包统一管理的过程

    1. "1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    4. <modelVersion>4.0.0modelVersion>
    5. <groupId>cn.itcastgroupId>
    6. <artifactId>travelartifactId>
    7. <version>1.0-SNAPSHOTversion>
    8. <packaging>warpackaging>
    9. <dependencies>
    10. <dependency>
    11. <groupId>junitgroupId>
    12. <artifactId>junitartifactId>
    13. <version>3.8.1version>
    14. <scope>testscope>
    15. dependency>
    16. <dependency>
    17. <groupId>javax.servletgroupId>
    18. <artifactId>javax.servlet-apiartifactId>
    19. <version>3.1.0version>
    20. <scope>providedscope>
    21. dependency>
    22. <dependency>
    23. <groupId>mysqlgroupId>
    24. <artifactId>mysql-connector-javaartifactId>
    25. <version>5.1.26version>
    26. <scope>compilescope>
    27. dependency>
    28. <dependency>
    29. <groupId>com.alibabagroupId>
    30. <artifactId>druidartifactId>
    31. <version>1.0.9version>
    32. dependency>
    33. <dependency>
    34. <groupId>org.springframeworkgroupId>
    35. <artifactId>spring-coreartifactId>
    36. <version>4.1.2.RELEASEversion>
    37. <scope>compilescope>
    38. dependency>
    39. <dependency>
    40. <groupId>org.springframeworkgroupId>
    41. <artifactId>spring-jdbcartifactId>
    42. <version>4.1.2.RELEASEversion>
    43. <scope>compilescope>
    44. dependency>
    45. <dependency>
    46. <groupId>org.springframeworkgroupId>
    47. <artifactId>spring-txartifactId>
    48. <version>4.1.2.RELEASEversion>
    49. <scope>compilescope>
    50. dependency>
    51. <dependency>
    52. <groupId>org.springframeworkgroupId>
    53. <artifactId>spring-beansartifactId>
    54. <version>4.1.2.RELEASEversion>
    55. <scope>compilescope>
    56. dependency>
    57. <dependency>
    58. <groupId>commons-logginggroupId>
    59. <artifactId>commons-loggingartifactId>
    60. <version>1.1.1version>
    61. <scope>compilescope>
    62. dependency>
    63. <dependency>
    64. <groupId>commons-beanutilsgroupId>
    65. <artifactId>commons-beanutilsartifactId>
    66. <version>1.9.2version>
    67. <scope>compilescope>
    68. dependency>
    69. <dependency>
    70. <groupId>com.fasterxml.jackson.coregroupId>
    71. <artifactId>jackson-databindartifactId>
    72. <version>2.3.3version>
    73. dependency>
    74. <dependency>
    75. <groupId>com.fasterxml.jackson.coregroupId>
    76. <artifactId>jackson-coreartifactId>
    77. <version>2.3.3version>
    78. dependency>
    79. <dependency>
    80. <groupId>com.fasterxml.jackson.coregroupId>
    81. <artifactId>jackson-annotationsartifactId>
    82. <version>2.3.3version>
    83. dependency>
    84. <dependency>
    85. <groupId>javax.mailgroupId>
    86. <artifactId>javax.mail-apiartifactId>
    87. <version>1.5.6version>
    88. dependency>
    89. <dependency>
    90. <groupId>com.sun.mailgroupId>
    91. <artifactId>javax.mailartifactId>
    92. <version>1.5.3version>
    93. dependency>
    94. <dependency>
    95. <groupId>redis.clientsgroupId>
    96. <artifactId>jedisartifactId>
    97. <version>2.7.0version>
    98. dependency>
    99. dependencies>
    100. <build>
    101. <plugins>
    102. <plugin>
    103. <groupId>org.apache.maven.pluginsgroupId>
    104. <artifactId>maven-compiler-pluginartifactId>
    105. <configuration>
    106. <source>1.8source>
    107. <target>1.8target>
    108. <encoding>utf-8encoding>
    109. configuration>
    110. plugin>
    111. <plugin>
    112. <groupId>org.apache.tomcat.mavengroupId>
    113. <artifactId>tomcat7-maven-pluginartifactId>
    114. <version>2.1version>
    115. <configuration>
    116. <port>80port>
    117. <path>/path>
    118. configuration>
    119. plugin>
    120. plugins>
    121. build>
    122. project>

    项目导入成功之后我们便要启动项目:

    项目启动:

    方式一:

     启动Tomcat7:run;的命令

    方式二:配置maven快捷启动

     

     启动项目之后来分析一下每一层我们要做的事情:

    技术选型:

      1. Web层
      1. Servlet:前端控制器
      2. html:视图
      3. Filter:过滤器
      4. BeanUtils:数据封装
      5. Jackson:json序列化工具
      1. Service层
      1. Javamail:java发送邮件工具
      2. Redis:nosql内存数据库
      3. Jedis:java的redis客户端
      1. Dao层
      1. Mysql:数据库
      2. Druid:数据库连接池
      3. JdbcTemplate:jdbc的工具

    现在我们手里已经有了一个前端页面后端实体类已经写好的网页,接下来要让它具备登录注册的功能。

    注册功能:

    页面效果:

     

    前台代码设计:

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="utf-8">
    5. <title>注册title>
    6. <link rel="stylesheet" type="text/css" href="css/common.css">
    7. <link rel="stylesheet" href="css/register.css">
    8. <script src="js/jquery-3.3.1.js">script>
    9. <script>
    10. /*
    11. 表单校验:
    12. 1.用户名:单词字符,长度8到20位
    13. 2.密码:单词字符,长度8到20位
    14. 3.email:邮件格式
    15. 4.姓名:非空
    16. 5.手机号:手机号格式
    17. 6.出生日期:非空
    18. 7.验证码:非空
    19. */
    20. //校验用户名
    21. //单词字符,长度4到20位
    22. function checkUsername() {
    23. //1.获取用户名值
    24. var username = $("#username").val();
    25. //2.定义正则
    26. var reg_username = /^\w{4,20}$/;
    27. //3.判断,给出提示信息
    28. var flag = reg_username.test(username);
    29. if(flag){
    30. //用户名合法
    31. $("#username").css("border","");
    32. }else{
    33. //用户名非法,加一个红色边框
    34. $("#username").css("border","1px solid red");
    35. }
    36. return flag;
    37. }
    38. //校验密码
    39. function checkPassword() {
    40. //1.获取密码值
    41. var password = $("#password").val();
    42. //2.定义正则
    43. var reg_password = /^\w{6,20}$/;
    44. //3.判断,给出提示信息
    45. var flag = reg_password.test(password);
    46. if(flag){
    47. //密码合法
    48. $("#password").css("border","");
    49. }else{
    50. //密码非法,加一个红色边框
    51. $("#password").css("border","1px solid red");
    52. }
    53. return flag;
    54. }
    55. //校验邮箱
    56. function checkEmail(){
    57. //1.获取邮箱
    58. var email = $("#email").val();
    59. //2.定义正则 itcast@163.com
    60. var reg_email = /^\w+@\w+\.\w+$/;
    61. //3.判断
    62. var flag = reg_email.test(email);
    63. if(flag){
    64. $("#email").css("border","");
    65. }else{
    66. $("#email").css("border","1px solid red");
    67. }
    68. return flag;
    69. }
    70. //校验姓名
    71. //非空单词字符,长度1到10位
    72. function checkName() {
    73. //1.获取姓名
    74. var name = $("#name").val();
    75. //2.定义姓名正则
    76. var reg_name = /^\w{1,10}$/;
    77. //3.判断,给出提示信息
    78. var flag = reg_name.test(name);
    79. if (name!=null){
    80. if(flag){
    81. //姓名合法
    82. $("#name").css("border","");
    83. }
    84. }else{
    85. //姓名非法,加一个红色边框
    86. $("#name").css("border","1px solid red");
    87. }
    88. return flag;
    89. }
    90. //校验手机号
    91. //非空单词字符,长度11位
    92. function checkPhoneNumber() {
    93. //1.获取用号码
    94. var number = $("#number").val();
    95. //2.定义11位手机号码正则
    96. var reg_number = /^[1][3,4,5,7,8][0-9]{9}$/;
    97. //3.判断,给出提示信息
    98. var flag = reg_number.test(number);
    99. if(flag){
    100. //号码合法
    101. $("#number").css("border","");
    102. }else{
    103. //号码非法,加一个红色边框
    104. $("#number").css("border","1px solid red");
    105. }
    106. return flag;
    107. }
    108. //校验生日
    109. function checkBirthday() {
    110. //1.获取生日
    111. var birthday = $("#birthday").val();
    112. //2.定义日期正则
    113. var reg_birthday =/^((?:19[2-9]\d{1})|(?:20(?:(?:0[0-9])|(?:1[0-8]))))\-((?:0?[1-9])|(?:1[0-2]))\-((?:0?[1-9])|(?:[1-2][0-9])|30|31)$/;
    114. //3.判断,给出提示信息
    115. var flag = reg_birthday.test(birthday);
    116. if(flag){
    117. //生日合法
    118. $("#birthday").css("border","");
    119. }else{
    120. //生日非法,加一个红色边框
    121. $("#birthday").css("border","1px solid red");
    122. }
    123. return flag;
    124. }
    125. //校验4位验证码authCode
    126. function checkAuthCode() {
    127. //1.获取密码值
    128. var authCode = $("#authCode").val();
    129. //2.定义正则
    130. var reg_authCode = /^\w{4}$/;
    131. //3.判断,给出提示信息
    132. var flag = reg_authCode.test(authCode);
    133. if(flag){
    134. //密码合法
    135. $("#authCode").css("border","");
    136. }else{
    137. //密码非法,加一个红色边框
    138. $("#authCode").css("border","1px solid red");
    139. }
    140. return flag;
    141. }
    142. $(function () {
    143. //当表单提交时,调用所有的校验方法
    144. $("#registerForm").submit(function(){
    145. //1.发送数据到服务器
    146. if(checkUsername() && checkPassword() && checkEmail()){
    147. //校验通过,发送ajax请求,提交表单的数据 username=zhangsan&password=123
    148. $.post("user/regist",$(this).serialize(),function(data){
    149. //处理服务器响应的数据 data {flag:true,errorMsg:"注册失败"}
    150. if(data.flag){
    151. //注册成功,跳转成功页面
    152. location.href="register_ok.html";
    153. }else{
    154. //注册失败,给errorMsg添加提示信息
    155. $("#errorMsg").html(data.errorMsg);
    156. }
    157. });
    158. }
    159. //2.不让页面跳转
    160. return false;
    161. //如果这个方法没有返回值,或者返回为true,则表单提交,如果返回为false,则表单不提交
    162. });
    163. //当某一个组件失去焦点是,调用对应的校验方法
    164. $("#username").blur(checkUsername);
    165. $("#password").blur(checkPassword);
    166. $("#email").blur(checkEmail);
    167. $("#name").blur(checkName);
    168. $("#number").blur(checkPhoneNumber);
    169. $("#birthday").blur(checkBirthday);
    170. $("#authCode").blur(changeCheckCode);
    171. });
    172. script>
    173. head>
    174. <body>
    175. <div id="header">div>
    176. <div class="rg_layout">
    177. <div class="rg_form clearfix">
    178. <div class="rg_form_left">
    179. <p>新用户注册p>
    180. <p>USER REGISTERp>
    181. div>
    182. <div class="rg_form_center">
    183. <div id="errorMsg" style="color:red;text-align: center">div>
    184. <form id="registerForm" action="user">
    185. <input type="hidden" name="action" value="register">
    186. <table style="margin-top: 25px;">
    187. <tr>
    188. <td class="td_left">
    189. <label for="username">用户名label>
    190. td>
    191. <td class="td_right">
    192. <input type="text" id="username" name="username" placeholder="请输入4-20位账号">
    193. td>
    194. tr>
    195. <tr>
    196. <td class="td_left">
    197. <label for="password">密码label>
    198. td>
    199. <td class="td_right">
    200. <input type="text" id="password" name="password" placeholder="请输入6-10位密码">
    201. td>
    202. tr>
    203. <tr>
    204. <td class="td_left">
    205. <label for="email">Emaillabel>
    206. td>
    207. <td class="td_right">
    208. <input type="text" id="email" name="email" placeholder="请输入Email">
    209. td>
    210. tr>
    211. <tr>
    212. <td class="td_left">
    213. <label for="name">姓名label>
    214. td>
    215. <td class="td_right">
    216. <input type="text" id="name" name="name" placeholder="请输入真实姓名">
    217. td>
    218. tr>
    219. <tr>
    220. <td class="td_left">
    221. <label for="telephone">手机号label>
    222. td>
    223. <td class="td_right">
    224. <input type="text" id="telephone" name="telephone" placeholder="请输入您的11位手机号">
    225. td>
    226. tr>
    227. <tr>
    228. <td class="td_left">
    229. <label for="sex">性别label>
    230. td>
    231. <td class="td_right gender">
    232. <input type="radio" id="sex" name="sex" value="男" checked>
    233. <input type="radio" name="sex" value="女">
    234. td>
    235. tr>
    236. <tr>
    237. <td class="td_left">
    238. <label for="birthday">出生日期label>
    239. td>
    240. <td class="td_right">
    241. <input type="date" id="birthday" name="birthday" placeholder="年/月/日">
    242. td>
    243. tr>
    244. <tr>
    245. <td class="td_left">
    246. <label for="check">验证码label>
    247. td>
    248. <td class="td_right check">
    249. <input type="text" id="check" name="check" class="check">
    250. <img src="checkCode" height="32px" alt="" onclick="changeCheckCode(this)">
    251. <script type="text/javascript">
    252. //图片点击事件
    253. function changeCheckCode(img) {
    254. img.src="checkCode?"+new Date().getTime();
    255. }
    256. script>
    257. td>
    258. tr>
    259. <tr>
    260. <td class="td_left">
    261. td>
    262. <td class="td_right check">
    263. <input type="submit" class="submit" value="注册">
    264. <span id="msg" style="color: red;">span>
    265. td>
    266. tr>
    267. table>
    268. form>
    269. div>
    270. <div class="rg_form_right">
    271. <p>
    272. 已有账号?
    273. <a href="#">立即登录a>
    274. p>
    275. div>
    276. div>
    277. div>
    278. <div id="footer">div>
    279. <script type="text/javascript" src="js/include.js">script>
    280. body>
    281. html>

     

    异步(ajax)提交表单:

     后台代码实现:

    RegistUserServlet

    1. package cn.itcast.travel.web.servlet;
    2. import cn.itcast.travel.domain.ResultInfo;
    3. import cn.itcast.travel.domain.User;
    4. import cn.itcast.travel.service.UserService;
    5. import cn.itcast.travel.service.impl.UserServiceImpl;
    6. import cn.itcast.travel.service.impl.routeServiceImpl;
    7. import cn.itcast.travel.service.routeService;
    8. import com.fasterxml.jackson.databind.ObjectMapper;
    9. import org.apache.commons.beanutils.BeanUtils;
    10. import javax.servlet.ServletException;
    11. import javax.servlet.annotation.WebServlet;
    12. import javax.servlet.http.HttpServlet;
    13. import javax.servlet.http.HttpServletRequest;
    14. import javax.servlet.http.HttpServletResponse;
    15. import javax.servlet.http.HttpSession;
    16. import java.io.IOException;
    17. import java.lang.reflect.InvocationTargetException;
    18. import java.util.Map;
    19. @WebServlet("/registUserServlet")
    20. public class RegistUserServlet extends HttpServlet {
    21. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    22. //验证校验
    23. String check = request.getParameter("check");
    24. //从sesion中获取验证码
    25. HttpSession session = request.getSession();
    26. String checkcode_server = (String) session.getAttribute("CHECKCODE_SERVER");
    27. session.removeAttribute("CHECKCODE_SERVER");//为了保证验证码只能使用一次
    28. //比较
    29. if(checkcode_server == null || !checkcode_server.equalsIgnoreCase(check)){
    30. //验证码错误
    31. ResultInfo info = new ResultInfo();
    32. //注册失败
    33. info.setFlag(false);
    34. info.setErrorMsg("验证码错误");
    35. //将info对象序列化为json
    36. ObjectMapper mapper = new ObjectMapper();
    37. String json = mapper.writeValueAsString(info);
    38. response.setContentType("application/json;charset=utf-8");
    39. response.getWriter().write(json);
    40. return;
    41. }
    42. //1.获取数据
    43. Map map = request.getParameterMap();
    44. //2.封装对象
    45. User user = new User();
    46. try {
    47. BeanUtils.populate(user,map);
    48. } catch (IllegalAccessException e) {
    49. e.printStackTrace();
    50. } catch (InvocationTargetException e) {
    51. e.printStackTrace();
    52. }
    53. System.out.println(user);
    54. //3.调用service完成注册
    55. UserService service = new UserServiceImpl();
    56. boolean flag = service.regist(user);
    57. ResultInfo info = new ResultInfo();
    58. //4.响应结果
    59. if(flag){
    60. //注册成功
    61. info.setFlag(true);
    62. }else{
    63. //注册失败
    64. info.setFlag(false);
    65. info.setErrorMsg("注册失败!");
    66. }
    67. //将info对象序列化为json
    68. ObjectMapper mapper = new ObjectMapper();
    69. String json = mapper.writeValueAsString(info);
    70. //将json数据写回客户端
    71. //设置content-type
    72. response.setContentType("application/json;charset=utf-8");
    73. response.getWriter().write(json);
    74. }
    75. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    76. this.doPost(request, response);
    77. }
    78. }

     有了请求信息,我们现在要做的就是做可注册用户的校验和存入注册信息到数据库。

    编写UserService以及UserServiceImpl:

     

    1. public class UserServiceImpl implements UserService {
    2. private UserDao userDao = new UserDaoImpl();
    3. /**
    4. * 注册用户
    5. * @param user
    6. * @return
    7. */
    8. @Override
    9. public boolean regist(User user) {
    10. //1.根据用户名查询用户对象
    11. User u = userDao.findByUsername(user.getUsername());
    12. //判断u是否为null
    13. if(u != null){
    14. //用户名存在,注册失败
    15. return false;
    16. }
    17. //2.保存用户信息
    18. userDao.save(user);
    19. return true;
    20. }

    Dao部分:

    userDao:

     UserDaoImpl:

    1. public class UserDaoImpl implements UserDao {
    2. private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
    3. @Override
    4. public User findByUsername(String username) {
    5. User user = null;
    6. try {
    7. //1.定义sql
    8. String sql = "select * from tab_user where username = ?";
    9. //2.执行sql
    10. user = template.queryForObject(sql, new BeanPropertyRowMapper(User.class), username);
    11. } catch (Exception e) {
    12. }
    13. return user;
    14. }
    15. @Override
    16. public void save(User user) {
    17. //1.定义sql
    18. String sql = "insert into tab_user(username,password,name,birthday,sex,telephone,email,status,code) values(?,?,?,?,?,?,?,?,?)";
    19. //2.执行sql
    20. template.update(sql,user.getUsername(),
    21. user.getPassword(),
    22. user.getName(),
    23. user.getBirthday(),
    24. user.getSex(),
    25. user.getTelephone(),
    26. user.getEmail(),
    27. user.getStatus(),
    28. user.getCode()
    29. );
    30. }
    31. }

    完成这个功能之后我们需要激活账户。

    现在常用的方法是通过邮件验证激活。

    具体操作如下:

    邮件激活功能:

    1. 申请邮箱
    2. 开启授权码
    3. 在MailUtils中设置自己的邮箱账号和密码(授权码)

     

    邮件工具类:MailUtils,调用其中sendMail方法可以完成邮件发送:

    MailUtils:

    1. package cn.itcast.travel.util;
    2. import javax.mail.*;
    3. import javax.mail.internet.InternetAddress;
    4. import javax.mail.internet.MimeMessage;
    5. import java.util.Properties;
    6. /**
    7. * 发邮件工具类
    8. */
    9. public final class MailUtils {
    10. private static final String USER = "********@qq.com"; // 发件人称号,同邮箱地址
    11. private static final String PASSWORD = "**********"; // 如果是qq邮箱可填写户端授权码,或者登录密码
    12. /**
    13. *
    14. * @param to 收件人邮箱
    15. * @param text 邮件正文
    16. * @param title 标题
    17. */
    18. /* 发送验证信息的邮件 */
    19. public static boolean sendMail(String to, String text, String title){
    20. try {
    21. final Properties props = new Properties();
    22. props.put("mail.smtp.auth", "true");
    23. props.put("mail.smtp.host", "smtp.qq.com");
    24. // 发件人的账号
    25. props.put("mail.user", USER);
    26. //发件人的密码
    27. props.put("mail.password", PASSWORD);
    28. // 构建授权信息,用于进行SMTP进行身份验证
    29. Authenticator authenticator = new Authenticator() {
    30. @Override
    31. protected PasswordAuthentication getPasswordAuthentication() {
    32. // 用户名、密码
    33. String userName = props.getProperty("mail.user");
    34. String password = props.getProperty("mail.password");
    35. return new PasswordAuthentication(userName, password);
    36. }
    37. };
    38. // 使用环境属性和授权信息,创建邮件会话
    39. Session mailSession = Session.getInstance(props, authenticator);
    40. // 创建邮件消息
    41. MimeMessage message = new MimeMessage(mailSession);
    42. // 设置发件人
    43. String username = props.getProperty("mail.user");
    44. InternetAddress form = new InternetAddress(username);
    45. message.setFrom(form);
    46. // 设置收件人
    47. InternetAddress toAddress = new InternetAddress(to);
    48. message.setRecipient(Message.RecipientType.TO, toAddress);
    49. // 设置邮件标题
    50. message.setSubject(title);
    51. // 设置邮件的内容体
    52. message.setContent(text, "text/html;charset=UTF-8");
    53. // 发送邮件
    54. Transport.send(message);
    55. return true;
    56. }catch (Exception e){
    57. e.printStackTrace();
    58. }
    59. return false;
    60. }
    61. public static void main(String[] args) { // 做测试用
    62. MailUtils.sendMail("2621247177@qq.com","你好,这是一封测试邮件,无需回复。","测试邮件");
    63. System.out.println("发送成功");
    64. }
    65. }

    用户点击邮件激活:用户激活其实就是修改用户表中的status为‘Y’

     修改保存Dao代码,加上存储status和code 的代码逻辑:

     

    激活代码实现:

    ActiveUserServlet:

    1. package cn.itcast.travel.web.servlet;
    2. import cn.itcast.travel.service.UserService;
    3. import cn.itcast.travel.service.impl.UserServiceImpl;
    4. import javax.servlet.ServletException;
    5. import javax.servlet.annotation.WebServlet;
    6. import javax.servlet.http.HttpServlet;
    7. import javax.servlet.http.HttpServletRequest;
    8. import javax.servlet.http.HttpServletResponse;
    9. import java.io.IOException;
    10. @WebServlet("/activeUserServlet")
    11. public class ActiveUserServlet extends HttpServlet {
    12. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    13. //1.获取激活码
    14. String code = request.getParameter("code");
    15. if(code != null){
    16. //2.调用service完成激活
    17. UserService service = new UserServiceImpl();
    18. boolean flag = service.active(code);
    19. //3.判断标记
    20. String msg = null;
    21. if(flag){
    22. //激活成功
    23. msg = "激活成功,请登录";
    24. }else{
    25. //激活失败
    26. msg = "激活失败,请联系管理员!";
    27. }
    28. response.setContentType("text/html;charset=utf-8");
    29. response.getWriter().write(msg);
    30. }
    31. }
    32. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    33. this.doPost(request, response);
    34. }
    35. }

    UserService:active:

    1. /**
    2. * 激活用户
    3. * @param code
    4. * @return
    5. */
    6. @Override
    7. public boolean active(String code) {
    8. //1.根据激活码查询用户对象
    9. User user = userDao.findByCode(code);
    10. if(user != null){
    11. //2.调用dao的修改激活状态的方法
    12. userDao.updateStatus(user);
    13. return true;
    14. }else{
    15. return false;
    16. }
    17. }

     userDao:之后会有相同的流程,为了便捷,接口部分将省略不写,对三层架构有了解的小伙伴应该对这个流程轻车熟路了。

     

      userDaoImpl:

    1. /**
    2. * 根据激活码查询用户对象
    3. * @param code
    4. * @return
    5. */
    6. @Override
    7. public User findByCode(String code) {
    8. User user = null;
    9. try {
    10. String sql = "select * from tab_user where code = ?";
    11. user = template.queryForObject(sql,new BeanPropertyRowMapper(User.class),code);
    12. } catch (DataAccessException e) {
    13. e.printStackTrace();
    14. }
    15. return user;
    16. }
    17. /**
    18. * 修改指定用户激活状态
    19. * @param user
    20. */
    21. @Override
    22. public void updateStatus(User user) {
    23. String sql = " update tab_user set status = 'Y' where uid=?";
    24. template.update(sql,user.getUid());
    25. }

    登录功能的实现:

    前台代码:

    login.html

     

    1. "utf-8">
    2. "X-UA-Compatible" content="IE=edge">
    3. "viewport" content="width=device-width, initial-scale=1">
    4. 黑马旅游网-登录
    5. "stylesheet" type="text/css" href="css/common.css">
    6. "stylesheet" type="text/css" href="css/login.css">
  • 欢迎登录黑马旅游账户
  • 自动登录
  • 没有账户?立即注册
  • 后台代码:

    LoginServlet

    //1.获取用户名和密码数据
    
    Map map = request.getParameterMap();
    
    //2.封装User对象
    
    User user = new User();
    
    try {
    
        BeanUtils.populate(user,map);
    
    } catch (IllegalAccessException e) {
    
        e.printStackTrace();
    
    } catch (InvocationTargetException e) {
    
        e.printStackTrace();
    
    }
    
    
    
    //3.调用Service查询
    
    UserService service = new UserServiceImpl();
    
    User u  = service.login(user);
    
    
    
    ResultInfo info = new ResultInfo();
    
    
    
    //4.判断用户对象是否为null
    
    if(u == null){
    
        //用户名密码或错误
    
        info.setFlag(false);
    
        info.setErrorMsg("用户名密码或错误");
    
    }
    
    //5.判断用户是否激活
    
    if(u != null && !"Y".equals(u.getStatus())){
    
        //用户尚未激活
    
        info.setFlag(false);
    
        info.setErrorMsg("您尚未激活,请激活");
    
    }
    
    //6.判断登录成功
    
    if(u != null && "Y".equals(u.getStatus())){
    
        //登录成功
    
        info.setFlag(true);
    
    }
    
    
    
    //响应数据
    
    ObjectMapper mapper = new ObjectMapper();
    
    
    
    response.setContentType("application/json;charset=utf-8");
    
    mapper.writeValue(response.getOutputStream(),info);

    UserService

    public User login(User user) {
    
        return userDao.findByUsernameAndPassword(user.getUsername(),user.getPassword());
    
    }

    UserDao

    public User findByUsernameAndPassword(String username, String password) {
    
        User user = null;
    
        try {
    
            //1.定义sql
    
            String sql = "select * from tab_user where username = ? and password = ?";
    
            //2.执行sql
    
            user = template.queryForObject(sql, new BeanPropertyRowMapper(User.class), username,password);
    
        } catch (Exception e) {
    
    
    
        }
    
    
    
        return user;
    
    }

    细节优化提示交给小伙伴自己完成。

    接下来是一个重点(但非常简单)优化servlet——

    减少Servlet的数量,现在是一个功能一个Servlet,将其优化为一个模块一个Servlet,相当于在数据库中一张表对应一个Servlet,在Servlet中提供不同的方法,完成用户的请求。

     通过继承实现:

    BaseServlet编写:

    1. //9.2 BaseServlet编写:
    2. public class BaseServlet extends HttpServlet {
    3. @Override
    4. protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    5. //System.out.println("baseServlet的service方法被执行了...");
    6. //完成方法分发
    7. //1.获取请求路径
    8. String uri = req.getRequestURI(); // /travel/user/add
    9. System.out.println("请求uri:"+uri);// /travel/user/add
    10. //2.获取方法名称
    11. String methodName = uri.substring(uri.lastIndexOf('/') + 1);
    12. System.out.println("方法名称:"+methodName);
    13. //3.获取方法对象Method
    14. //谁调用我?我代表谁
    15. System.out.println(this);//UserServlet的对象cn.itcast.travel.web.servlet.UserServlet@4903d97e
    16. try {
    17. //获取方法
    18. Method method = this.getClass().getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
    19. //4.执行方法
    20. //暴力反射
    21. //method.setAccessible(true);
    22. method.invoke(this,req,resp);
    23. } catch (NoSuchMethodException e) {
    24. e.printStackTrace();
    25. } catch (IllegalAccessException e) {
    26. e.printStackTrace();
    27. } catch (InvocationTargetException e) {
    28. e.printStackTrace();
    29. }
    30. }
    31. }

    UserServlet改写:

    将之前的Servlet实现的功能,抽取到UserServlet中的不同方法中实现,并且将UserService创建抽取到成员变量位置

    1. @WebServlet("/user/*") // /user/add /user/find
    2. public class UserServlet extends BaseServlet {
    3. //声明UserService业务对象
    4. private UserService service = new UserServiceImpl();
    5. /**
    6. * 注册功能
    7. * @param request
    8. * @param response
    9. * @throws ServletException
    10. * @throws IOException
    11. */
    12. public void regist(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    13. //验证校验
    14. String check = request.getParameter("check");
    15. //从sesion中获取验证码
    16. HttpSession session = request.getSession();
    17. String checkcode_server = (String) session.getAttribute("CHECKCODE_SERVER");
    18. session.removeAttribute("CHECKCODE_SERVER");//为了保证验证码只能使用一次
    19. //比较
    20. if(checkcode_server == null || !checkcode_server.equalsIgnoreCase(check)){
    21. //验证码错误
    22. ResultInfo info = new ResultInfo();
    23. //注册失败
    24. info.setFlag(false);
    25. info.setErrorMsg("验证码错误");
    26. //将info对象序列化为json
    27. ObjectMapper mapper = new ObjectMapper();
    28. String json = mapper.writeValueAsString(info);
    29. response.setContentType("application/json;charset=utf-8");
    30. response.getWriter().write(json);
    31. return;
    32. }
    33. //1.获取数据
    34. Map map = request.getParameterMap();
    35. //2.封装对象
    36. User user = new User();
    37. try {
    38. BeanUtils.populate(user,map);
    39. } catch (IllegalAccessException e) {
    40. e.printStackTrace();
    41. } catch (InvocationTargetException e) {
    42. e.printStackTrace();
    43. }
    44. //3.调用service完成注册
    45. //UserService service = new UserServiceImpl();
    46. boolean flag = service.regist(user);
    47. ResultInfo info = new ResultInfo();
    48. //4.响应结果
    49. if(flag){
    50. //注册成功
    51. info.setFlag(true);
    52. }else{
    53. //注册失败
    54. info.setFlag(false);
    55. info.setErrorMsg("注册失败!");
    56. }
    57. //将info对象序列化为json
    58. ObjectMapper mapper = new ObjectMapper();
    59. String json = mapper.writeValueAsString(info);
    60. //将json数据写回客户端
    61. //设置content-type
    62. response.setContentType("application/json;charset=utf-8");
    63. response.getWriter().write(json);
    64. }
    65. /**
    66. * 登录功能
    67. * @param request
    68. * @param response
    69. * @throws ServletException
    70. * @throws IOException
    71. */
    72. public void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    73. //1.获取用户名和密码数据
    74. Map map = request.getParameterMap();
    75. //2.封装User对象
    76. User user = new User();
    77. try {
    78. BeanUtils.populate(user,map);
    79. } catch (IllegalAccessException e) {
    80. e.printStackTrace();
    81. } catch (InvocationTargetException e) {
    82. e.printStackTrace();
    83. }
    84. //3.调用Service查询
    85. // UserService service = new UserServiceImpl();
    86. User u = service.login(user);
    87. ResultInfo info = new ResultInfo();
    88. //4.判断用户对象是否为null
    89. if(u == null){
    90. //用户名密码或错误
    91. info.setFlag(false);
    92. info.setErrorMsg("用户名密码或错误");
    93. }
    94. //5.判断用户是否激活
    95. if(u != null && !"Y".equals(u.getStatus())){
    96. //用户尚未激活
    97. info.setFlag(false);
    98. info.setErrorMsg("您尚未激活,请激活");
    99. }
    100. //6.判断登录成功
    101. if(u != null && "Y".equals(u.getStatus())){
    102. request.getSession().setAttribute("user",u);//登录成功标记
    103. //登录成功
    104. info.setFlag(true);
    105. }
    106. //响应数据
    107. ObjectMapper mapper = new ObjectMapper();
    108. response.setContentType("application/json;charset=utf-8");
    109. mapper.writeValue(response.getOutputStream(),info);
    110. }
    111. /**
    112. * 查询单个对象
    113. * @param request
    114. * @param response
    115. * @throws ServletException
    116. * @throws IOException
    117. */
    118. public void findOne(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    119. //从session中获取登录用户
    120. Object user = request.getSession().getAttribute("user");
    121. //将user写回客户端
    122. ObjectMapper mapper = new ObjectMapper();
    123. response.setContentType("application/json;charset=utf-8");
    124. mapper.writeValue(response.getOutputStream(),user);
    125. }
    126. /**
    127. * 退出功能
    128. * @param request
    129. * @param response
    130. * @throws ServletException
    131. * @throws IOException
    132. */
    133. public void exit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    134. //1.销毁session
    135. request.getSession().invalidate();
    136. //2.跳转登录页面
    137. response.sendRedirect(request.getContextPath()+"/login.html");
    138. }
    139. /**
    140. * 激活功能
    141. * @param request
    142. * @param response
    143. * @throws ServletException
    144. * @throws IOException
    145. */
    146. public void active(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    147. //1.获取激活码
    148. String code = request.getParameter("code");
    149. if(code != null){
    150. //2.调用service完成激活
    151. //UserService service = new UserServiceImpl();
    152. boolean flag = service.active(code);
    153. //3.判断标记
    154. String msg = null;
    155. if(flag){
    156. //激活成功
    157. msg = "激活成功,请登录";
    158. }else{
    159. //激活失败
    160. msg = "激活失败,请联系管理员!";
    161. }
    162. response.setContentType("text/html;charset=utf-8");
    163. response.getWriter().write(msg);
    164. }
    165. }
    166. }

    分类数据展示(难点):

    后端代码完成这个功能十分简单,麻烦的是前端代码的分页显示设置。

    以下代码是优化缓存之后的版本,启动redis服务,第一次从数据库中获取数据,并保存在缓存中,之后每次访问都从缓存中查询,提高效率节约资源。

    CategoryServiceImpl:

    1. public class CategoryServiceImpl implements CategoryService {
    2. private categoryDao categoryDao=new categoryDaoImpl();
    3. @Override
    4. public List findAll() {
    5. //1.从redis中查询
    6. Jedis jedis = JedisUtil.getJedis();
    7. //1.1使查询的结果有顺序使用sortedset
    8. Listcs=null;
    9. // Set categorys = jedis.zrange("category", 0, -1);
    10. Set categorys = jedis.zrangeWithScores("category", 0, -1);
    11. //2.获取jedis客户端
    12. //3.如果为空从数据库查询,不为空在redis中查询
    13. if (categorys==null||categorys.size()==0){
    14. System.out.println("从数据库中查询。。。");
    15. cs=categoryDao.findAll();
    16. //将集合数据存储到redis;
    17. for (int i = 0; i
    18. jedis.zadd("category",cs.get(i).getCid(),cs.get(i).getCname());
    19. }
    20. }else {
    21. System.out.println("从缓存中查询。。。");
    22. //如果不为空,将set集合数据存入list
    23. cs=new ArrayList();
    24. for (Tuple tuple : categorys) {
    25. Category category=new Category();
    26. category.setCname(tuple.getElement());
    27. category.setCid((int)tuple.getScore());
    28. cs.add(category);
    29. }
    30. }
    31. return cs;
    32. }
    33. }

    CategoryServlet:

    1. package cn.itcast.travel.web.servlet;
    2. import cn.itcast.travel.domain.Category;
    3. import cn.itcast.travel.service.CategoryService;
    4. import cn.itcast.travel.service.impl.CategoryServiceImpl;
    5. import com.fasterxml.jackson.databind.ObjectMapper;
    6. import javax.servlet.ServletException;
    7. import javax.servlet.annotation.WebServlet;
    8. import javax.servlet.http.HttpServlet;
    9. import javax.servlet.http.HttpServletRequest;
    10. import javax.servlet.http.HttpServletResponse;
    11. import java.io.IOException;
    12. import java.util.List;
    13. @WebServlet("/category/*")
    14. public class CategoryServlet extends BaseServlet {
    15. private CategoryService service=new CategoryServiceImpl();
    16. /**
    17. * 查询所有
    18. * @param request
    19. * @param response
    20. * @throws ServletException
    21. * @throws IOException
    22. */
    23. public void findAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    24. //1.查询所有
    25. Listcs=service.findAll();
    26. // //2.序列化返回
    27. // ObjectMapper mapper=new ObjectMapper();
    28. // response.setContentType("application/json;charset=utf-8");
    29. // mapper.writeValue(response.getOutputStream(),cs);
    30. writeValue(cs,response);
    31. }
    32. public void find(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    33. }
    34. }

    CategoryDao:

    1. public class CategoryDaoImpl implements CategoryDao {
    2. private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
    3. @Override
    4. public List findAll() {
    5. String sql = "select * from tab_category ";
    6. return template.query(sql,new BeanPropertyRowMapper(Category.class));
    7. }
    8. }

    在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 {
    
        ObjectMapper mapper = new ObjectMapper();
    
        return mapper.writeValueAsString(obj);
    
    }

    之后根据需要调用即可。

    之后是最麻烦的前台代码:麻烦的点在于分页处理,需要设置分页信息展示:

    后端别忘记了创建分页展示使用到的实体类:

    pageBean内容:

    1. package cn.itcast.travel.domain;
    2. import java.util.List;
    3. public class PageBean {
    4. private int totalCount;//总记录数
    5. private int totalPage;//总页数
    6. private int currentPage;//当前页码
    7. private int pageSize;//每页显示的条数
    8. private Listlist;//每页显示的数据集合
    9. public int getTotalCount() {
    10. return totalCount;
    11. }
    12. public void setTotalCount(int totalCount) {
    13. this.totalCount = totalCount;
    14. }
    15. public int getTotalPage() {
    16. return totalPage;
    17. }
    18. public void setTotalPage(int totalPage) {
    19. this.totalPage = totalPage;
    20. }
    21. public int getCurrentPage() {
    22. return currentPage;
    23. }
    24. public void setCurrentPage(int currentPage) {
    25. this.currentPage = currentPage;
    26. }
    27. public int getPageSize() {
    28. return pageSize;
    29. }
    30. public void setPageSize(int pageSize) {
    31. this.pageSize = pageSize;
    32. }
    33. public List getList() {
    34. return list;
    35. }
    36. public void setList(List list) {
    37. this.list = list;
    38. }
    39. }

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
    7. <title>黑马旅游-搜索title>
    8. <link rel="stylesheet" type="text/css" href="css/common.css">
    9. <link rel="stylesheet" href="css/search.css">
    10. <script src="js/jquery-3.3.1.js">script>
    11. <script src="js/getParameter.js">
    12. script>
    13. <script>
    14. $(function () {
    15. var search = location.search;
    16. // alert(search);
    17. //获取切割字符串,拿到第二个值
    18. // var cid = search.split("=")[1];
    19. var cid = getParameter("cid");
    20. var rname = getParameter("rname");
    21. if (rname){
    22. rname=window.decodeURIComponent(rname);
    23. }
    24. //当页面加载完成后,调用load1方法发送ajax请求加载数据
    25. load1(cid,null,rname);
    26. });
    27. function load1(cid,currentPage,rname) {
    28. //发送ajax请求,请求route/pageQuery,传递cid
    29. $.get("/route/pageQuery",{cid:cid,currentPage:currentPage,rname:rname},function (pb) {
    30. $("#totalPage").html(pb.totalPage);
    31. $("#totalCount").html(pb.totalCount);
    32. /**
    33. * <li><a href="">首页a>li>
    34. <li class="threeword"><a href="#">上一页a>li>
    35. <li><a href="#">1a>li>
    36. <li><a href="#">2a>li>
    37. <li><a href="#">3a>li>
    38. <li><a href="#">4a>li>
    39. <li><a href="#">5a>li>
    40. <li><a href="#">6a>li>
    41. <li><a href="#">7a>li>
    42. <li><a href="#">8a>li>
    43. <li><a href="#">9a>li>
    44. <li><a href="#">10a>li>
    45. <li class="threeword"><a href="JavaScript:;">下一页a>li>
    46. <li class="threeword"><a href="JavaScript:;">末页a>li>
    47. */
    48. var beforePage=pb.currentPage-1;
    49. if (beforePage<=0){
    50. beforePage=1;
    51. }
    52. var fistPage='<li onclick="JavaScript:load1('+cid+',1,'+rname+')"><a href="JavaScript:void(0)">首页a>li>';
    53. var prePage='<li onclick="JavaScript:load1('+cid+','+beforePage+','+rname+')" class="threeword"><a href="#">上一页a>li>';
    54. var lis="";
    55. lis+=fistPage;
    56. lis+=prePage;
    57. //展示分页页码
    58. var begin;
    59. var end;
    60. if (pb.totalPage<10){
    61. begin=1;
    62. end=pb.totalPage;
    63. }else {
    64. begin=pb.currentPage-5;
    65. end=pb.currentPage+4;
    66. if (begin<1){
    67. begin=1;
    68. end=10;
    69. }
    70. if (end>pb.totalPage){
    71. end=pb.totalPage;
    72. begin=end-9;
    73. }
    74. }
    75. for (var i = begin; i <=end ; i++) {
    76. var li;
    77. if (pb.currentPage==i){
    78. var li='<li class="curPage" onclick="JavaScript:load1('+cid+','+i+','+rname+')"><a href="JavaScript:void(0)">'+i+'a>li>';
    79. }else {
    80. var li='<li onclick="JavaScript:load1('+cid+','+i+','+rname+')"><a href="JavaScript:void(0)">'+i+'a>li>';
    81. }
    82. //创建页码的li
    83. //拼接字符串
    84. lis+=li;
    85. }
    86. var nextPage=pb.currentPage+1;
    87. if (nextPage>=pb.totalPage){
    88. nextPage=pb.totalPage;
    89. }
    90. nextPage='<li li onclick="JavaScript:load1('+cid+','+nextPage+','+rname+')" class="threeword"><a href="#">下一页a>li>';
    91. var finalPage=' <li onclick="JavaScript:load1('+cid+','+pb.totalPage+','+rname+')" class="threeword"><a href="#">末页a>li>';
    92. lis+=nextPage;
    93. lis+=finalPage;
    94. //将lis内容设置到url
    95. var route_lis="";
    96. $("#pageNum").html(lis);
    97. for (var i = 0; i
    98. var route=pb.list[i];
    99. var li=' <li>\n' +
    100. '<div class="img"><img src="'+route.rimage+'" style="width: 299px">div>\n' +
    101. '<div class="text1">\n' +
    102. ' <p>'+route.rname+'p>\n' +
    103. '<br/>\n' +
    104. '<p>'+route.routeIntroduce+'p>\n' +
    105. 'div>\n' +
    106. '<div class="price">\n' +
    107. '<p class="price_num">\n' +
    108. '<span>¥span>\n' +
    109. '<span>'+route.price+'span>\n' +
    110. '<span>span>\n' +
    111. 'p>\n' +
    112. '<p><a href="route_detail.html">查看详情a>p>' +
    113. 'div>\n' +
    114. 'li>';
    115. route_lis+=li;
    116. }
    117. $("#route").html(route_lis);
    118. //跳转到页面顶部
    119. window.scrollTo(0,0);
    120. });
    121. //分页工具条展示
    122. //解析数据,展示到页面上
    123. }
    124. script>
    125. head>
    126. <body>
    127. <div id="header">div>
    128. <div class="page_one">
    129. <div class="contant">
    130. <div class="crumbs">
    131. <img src="images/search.png" alt="">
    132. <p>黑马旅行><span>搜索结果span>p>
    133. div>
    134. <div class="xinxi clearfix">
    135. <div class="left">
    136. <div class="header">
    137. <span>商品信息span>
    138. <span class="jg">价格span>
    139. div>
    140. <ul id="route">
    141. <li>
    142. <div class="img"><img src="images/04-search_03.jpg" alt="">div>
    143. <div class="text1">
    144. <p>【减100元 含除夕/春节出发】广州增城三英温泉度假酒店/自由行套票p>
    145. <br/>
    146. <p>1-2月出发,网付立享¥1099/2人起!爆款位置有限,抢完即止!p>
    147. div>
    148. <div class="price">
    149. <p class="price_num">
    150. <span>¥span>
    151. <span>299span>
    152. <span>span>
    153. p>
    154. <p><a href="route_detail.html">查看详情a>p>
    155. div>
    156. li>
    157. <li>
    158. <div class="img"><img src="images/04-search_03.jpg" alt="">div>
    159. <div class="text1">
    160. <p>浪花朵朵旅行普吉岛丛林飞跃空中飞人探险游中文服务泰国旅游p>
    161. <br/>
    162. <p>1-2月出发,网付立享¥1099/2人起!爆款位置有限,抢完即止!p>
    163. div>
    164. <div class="price">
    165. <p class="price_num">
    166. <span>¥span>
    167. <span>899span>
    168. <span>span>
    169. p>
    170. <p><a href="route_detail.html">查看详情a>p>
    171. div>
    172. li>
    173. <li>
    174. <div class="img"><img src="images/04-search_03.jpg" alt="">div>
    175. <div class="text1">
    176. <p>黑妞皇家旅行普吉岛攀牙湾大船星光之旅皮划艇日落休闲特色体验p>
    177. <br/>
    178. <p>1-2月出发,网付立享¥1099/2人起!爆款位置有限,抢完即止!p>
    179. div>
    180. <div class="price">
    181. <p class="price_num">
    182. <span>¥span>
    183. <span>999span>
    184. <span>span>
    185. p>
    186. <p><a href="route_detail.html">查看详情a>p>
    187. div>
    188. li>
    189. <li>
    190. <div class="img"><img src="images/04-search_03.jpg" alt="">div>
    191. <div class="text1">
    192. <p>浪花朵朵旅行普吉岛皇帝岛珊瑚岛香蕉船拖拽伞水上项目p>
    193. <br/>
    194. <p>1-2月出发,网付立享¥1099/2人起!爆款位置有限,抢完即止!p>
    195. div>
    196. <div class="price">
    197. <p class="price_num">
    198. <span>¥span>
    199. <span>99span>
    200. <span>span>
    201. p>
    202. <p><a href="route_detail.html">查看详情a>p>
    203. div>
    204. li>
    205. <li>
    206. <div class="img"><img src="images/04-search_03.jpg" alt="">div>
    207. <div class="text1">
    208. <p>环游记 泰国清迈Lila massage女子监狱spa 丽菈泰式按摩马杀鸡p>
    209. <br/>
    210. <p>1-2月出发,网付立享¥1099/2人起!爆款位置有限,抢完即止!p>
    211. div>
    212. <div class="price">
    213. <p class="price_num">
    214. <span>¥span>
    215. <span>199span>
    216. <span>span>
    217. p>
    218. <p><a href="route_detail.html">查看详情a>p>
    219. div>
    220. li>
    221. <li>
    222. <div class="img"><img src="images/04-search_03.jpg" alt="">div>
    223. <div class="text1">
    224. <p>【减100元 含除夕/春节出发】广州增城三英温泉度假酒店/自由行套票p>
    225. <br/>
    226. <p>1-2月出发,网付立享¥1099/2人起!爆款位置有限,抢完即止!p>
    227. div>
    228. <div class="price">
    229. <p class="price_num">
    230. <span>¥span>
    231. <span>899span>
    232. <span>span>
    233. p>
    234. <p><a href="route_detail.html">查看详情a>p>
    235. div>
    236. li>
    237. <li>
    238. <div class="img"><img src="images/04-search_03.jpg" alt="">div>
    239. <div class="text1">
    240. <p>【减100元 含除夕/春节出发】广州增城三英温泉度假酒店/自由行套票p>
    241. <br/>
    242. <p>1-2月出发,网付立享¥1099/2人起!爆款位置有限,抢完即止!p>
    243. div>
    244. <div class="price">
    245. <p class="price_num">
    246. <span>¥span>
    247. <span>1199span>
    248. <span>span>
    249. p>
    250. <p><a href="route_detail.html">查看详情a>p>
    251. div>
    252. li>
    253. <li>
    254. <div class="img"><img src="images/04-search_03.jpg" alt="">div>
    255. <div class="text1">
    256. <p>泰国芭提雅三合一日游芭提雅蒂芬妮人妖秀成人门票bigeye含接送p>
    257. <br/>
    258. <p>1-2月出发,网付立享¥1099/2人起!爆款位置有限,抢完即止!p>
    259. div>
    260. <div class="price">
    261. <p class="price_num">
    262. <span>¥span>
    263. <span>1589span>
    264. <span>span>
    265. p>
    266. <p><a href="route_detail.html">查看详情a>p>
    267. div>
    268. li>
    269. ul>
    270. <div class="page_num_inf">
    271. <i>i> 共
    272. <span id="totalPage">12span>页<span id="totalCount">132span>条
    273. div>
    274. <div class="pageNum">
    275. <ul id="pageNum">
    276. <li><a href="">首页a>li>
    277. <li class="threeword"><a href="#">上一页a>li>
    278. <li><a href="#">1a>li>
    279. <li><a href="#">2a>li>
    280. <li><a href="#">3a>li>
    281. <li><a href="#">4a>li>
    282. <li><a href="#">5a>li>
    283. <li><a href="#">6a>li>
    284. <li><a href="#">7a>li>
    285. <li><a href="#">8a>li>
    286. <li><a href="#">9a>li>
    287. <li><a href="#">10a>li>
    288. <li class="threeword"><a href="JavaScript:;">下一页a>li>
    289. <li class="threeword"><a href="JavaScript:;">末页a>li>
    290. ul>
    291. div>
    292. div>
    293. <div class="right">
    294. <div class="top">
    295. <div class="hot">HOTdiv>
    296. <span>热门推荐span>
    297. div>
    298. <ul>
    299. <li>
    300. <div class="left"><img src="images/04-search_09.jpg" alt="">div>
    301. <div class="right">
    302. <p>清远新银盏温泉度假村酒店/自由行套...p>
    303. <p>网付价<span>¥<span>899span>起span>
    304. p>
    305. div>
    306. li>
    307. <li>
    308. <div class="left"><img src="images/04-search_09.jpg" alt="">div>
    309. <div class="right">
    310. <p>清远新银盏温泉度假村酒店/自由行套...p>
    311. <p>网付价<span>¥<span>899span>起span>
    312. p>
    313. div>
    314. li>
    315. <li>
    316. <div class="left"><img src="images/04-search_09.jpg" alt="">div>
    317. <div class="right">
    318. <p>清远新银盏温泉度假村酒店/自由行套...p>
    319. <p>网付价<span>¥<span>899span>起span>
    320. p>
    321. div>
    322. li>
    323. <li>
    324. <div class="left"><img src="images/04-search_09.jpg" alt="">div>
    325. <div class="right">
    326. <p>清远新银盏温泉度假村酒店/自由行套...p>
    327. <p>网付价<span>¥<span>899span>起span>
    328. p>
    329. div>
    330. li>
    331. <li>
    332. <div class="left"><img src="images/04-search_09.jpg" alt="">div>
    333. <div class="right">
    334. <p>清远新银盏温泉度假村酒店/自由行套...p>
    335. <p>网付价<span>¥<span>899span>起span>
    336. p>
    337. div>
    338. li>
    339. ul>
    340. div>
    341. div>
    342. div>
    343. div>
    344. <div id="footer">div>
    345. <script type="text/JavaScript" src="js/include.js">script>
    346. body>
    347. html>

    实现我的收藏查看功能实质上也是同一个道理,只不过加一个用户登录验证的判断,但麻烦的依旧是标签设置和拼接问题。前台代码不如后台代码逻辑清晰。

    后台代码:

    1. //RouteServlet
    2. @WebServlet("/route/*")
    3. public class RouteServlet extends BaseServlet {
    4. private RouteService routeService = new RouteServiceImpl();
    5. /**
    6. * 分页查询
    7. * @param request
    8. * @param response
    9. * @throws ServletException
    10. * @throws IOException
    11. */
    12. public void pageQuery(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    13. //1.接受参数
    14. String currentPageStr = request.getParameter("currentPage");
    15. String pageSizeStr = request.getParameter("pageSize");
    16. String cidStr = request.getParameter("cid");
    17. int cid = 0;//类别id
    18. //2.处理参数
    19. if(cidStr != null && cidStr.length() > 0){
    20. cid = Integer.parseInt(cidStr);
    21. }
    22. int currentPage = 0;//当前页码,如果不传递,则默认为第一页
    23. if(currentPageStr != null && currentPageStr.length() > 0){
    24. currentPage = Integer.parseInt(currentPageStr);
    25. }else{
    26. currentPage = 1;
    27. }
    28. int pageSize = 0;//每页显示条数,如果不传递,默认每页显示5条记录
    29. if(pageSizeStr != null && pageSizeStr.length() > 0){
    30. pageSize = Integer.parseInt(pageSizeStr);
    31. }else{
    32. pageSize = 5;
    33. }
    34. //3. 调用service查询PageBean对象
    35. PageBean pb = routeService.pageQuery(cid, currentPage, pageSize);
    36. //4. 将pageBean对象序列化为json,返回
    37. writeValue(pb,response);
    38. }
    39. }
    40. // RouteService
    41. public class RouteServiceImpl implements RouteService {
    42. private RouteDao routeDao = new RouteDaoImpl();
    43. @Override
    44. public PageBean pageQuery(int cid, int currentPage, int pageSize) {
    45. //封装PageBean
    46. PageBean pb = new PageBean();
    47. //设置当前页码
    48. pb.setCurrentPage(currentPage);
    49. //设置每页显示条数
    50. pb.setPageSize(pageSize);
    51. //设置总记录数
    52. int totalCount = routeDao.findTotalCount(cid);
    53. pb.setTotalCount(totalCount);
    54. //设置当前页显示的数据集合
    55. int start = (currentPage - 1) * pageSize;//开始的记录数
    56. List list = routeDao.findByPage(cid,start,pageSize);
    57. pb.setList(list);
    58. //设置总页数 = 总记录数/每页显示条数
    59. int totalPage = totalCount % pageSize == 0 ? totalCount / pageSize :(totalCount / pageSize) + 1 ;
    60. pb.setTotalPage(totalPage);
    61. return pb;
    62. }
    63. }
    64. //RouteDao
    65. public class RouteDaoImpl implements RouteDao {
    66. private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
    67. @Override
    68. public int findTotalCount(int cid) {
    69. String sql = "select count(*) from tab_route where cid = ?";
    70. return template.queryForObject(sql,Integer.class,cid);
    71. }
    72. @Override
    73. public List findByPage(int cid, int start, int pageSize) {
    74. String sql = "select * from tab_route where cid = ? limit ? , ?";
    75. return template.query(sql,new BeanPropertyRowMapper(Route.class),cid,start,pageSize);
    76. }
    77. }

    完成收藏功能:

    1. 旅游线路收藏功能
      1. 分析
        1.  判断当前登录用户是否收藏过该线路

    当页面加载完成后,发送ajax请求,获取用户是否收藏的标记

    根据标记,展示不同的按钮样式

    后台代码:

    1. //后台代码
    2. //RouteServlet:
    3. public void isFavorite(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    4. //1. 获取线路id
    5. String rid = request.getParameter("rid");
    6. //2. 获取当前登录的用户 user
    7. User user = (User) request.getSession().getAttribute("user");
    8. int uid;//用户id
    9. if(user == null){
    10. //用户尚未登录
    11. uid = 0;
    12. }else{
    13. //用户已经登录
    14. uid = user.getUid();
    15. }
    16. //3. 调用FavoriteService查询是否收藏
    17. boolean flag = favoriteService.isFavorite(rid, uid);
    18. //4. 写回客户端
    19. writeValue(flag,response);
    20. }
    21. FavoriteService
    22. @Override
    23. public boolean isFavorite(String rid, int uid) {
    24. Favorite favorite = favoriteDao.findByRidAndUid(Integer.parseInt(rid), uid);
    25. return favorite != null;//如果对象有值,则为true,反之,则为false
    26. }
    27. //FavoriteDao
    28. @Override
    29. public Favorite findByRidAndUid(int rid, int uid) {
    30. Favorite favorite = null;
    31. try {
    32. String sql = " select * from tab_favorite where rid = ? and uid = ?";
    33. favorite = template.queryForObject(sql, new BeanPropertyRowMapper(Favorite.class), rid, uid);
    34. } catch (DataAccessException e) {
    35. e.printStackTrace();
    36. }
    37. return favorite;
    38. }

     前台代码:

    1. //前台代码
    2. //route_detail.html
    3. $(function () {
    4. // 发送请求,判断用户是否收藏过该线路
    5. var rid = getParameter("rid");
    6. $.get("route/isFavorite",{rid:rid},function (flag) {
    7. if(flag){
    8. // 用户已经收藏过
    9. //<a class="btn already" disabled="disabled">
    10. //设置收藏按钮的样式
    11. $("#favorite").addClass("already");
    12. $("#favorite").prop("disabled",disabled);
    13. }else{
    14. // 用户没有收藏
    15. }
    16. });

     收藏次数的动态展示:

    前台:

    //设置收藏次数
    
    $("#favoriteCount").html("已收藏"+route.count+"");

    后台:

             //RouteService

    //4. 查询收藏次数
    
    int count = favoriteDao.findCountByRid(route.getRid());
    
    route.setCount(count);

    //FavoriteDao

    @Override
    
    public int findCountByRid(int rid) {
    
        String sql = "SELECT COUNT(*) FROM tab_favorite WHERE rid = ?";
    
    
    
        return template.queryForObject(sql,Integer.class,rid);
    
    }


    1. 点击按钮收藏线路

    2.  分析:

              

    1.  编码

    前台代码

    1. $(function () {
    2. // 发送请求,判断用户是否收藏过该线路
    3. var rid = getParameter("rid");
    4. $.get("route/isFavorite",{rid:rid},function (flag) {
    5. if(flag){
    6. // 用户已经收藏过
    7. //<a class="btn already" disabled="disabled">
    8. //设置收藏按钮的样式
    9. $("#favorite").addClass("already");
    10. $("#favorite").attr("disabled","disabled");
    11. //删除按钮的点击事件
    12. $("#favorite").removeAttr("onclick");
    13. }else{
    14. // 用户没有收藏
    15. }
    16. });
    17. });
    18. //点击收藏按钮触发的方法
    19. function addFavorite(){
    20. var rid = getParameter("rid");
    21. //1. 判断用户是否登录
    22. $.get("user/findOne",{},function (user) {
    23. if(user){
    24. //用户登录了
    25. //添加功能
    26. $.get("route/addFavorite",{rid:rid},function () {
    27. //代码刷新页面
    28. location.reload();
    29. });
    30. }else{
    31. //用户没有登录
    32. alert("您尚未登录,请登录");
    33. location.href="http://localhost/travel/login.html";
    34. }
    35. })
    36. }

    记得在标签内绑定单击事件:

    
    <a οnclick="addFavorite();" class="btn" id="favorite">点击收藏
    
    
    <a οnclick="removeFavorite();" class="btn already" disabled="disabled" id="cancel_favorite">取消收藏
    
    

    后台代码:

    RouteServlet

    1. public void addFavorite(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    2. //1. 获取线路rid
    3. String rid = request.getParameter("rid");
    4. //2. 获取当前登录的用户
    5. User user = (User) request.getSession().getAttribute("user");
    6. int uid;//用户id
    7. if(user == null){
    8. //用户尚未登录
    9. return ;
    10. }else{
    11. //用户已经登录
    12. uid = user.getUid();
    13. }
    14. //3. 调用service添加
    15. favoriteService.add(rid,uid);
    16. }

    FavoriteService

    1. @Override
    2. public void add(String rid, int uid) {
    3. favoriteDao.add(Integer.parseInt(rid),uid);
    4. }

    FavoriteDao

    1. @Override
    2. public void add(int rid, int uid) {
    3. String sql = "insert into tab_favorite values(?,?,?)";
    4. template.update(sql,rid,new Date(),uid);
    5. }

     

  • 相关阅读:
    前端使用 Konva 实现可视化设计器(3)- 单选、多选、选择框
    数据结构(二叉树)——Java实现
    【算法】三层嵌套循环的时间复杂度
    结合电压与电流定律进行总体分析
    Python之PyMySQL操作详解
    【Java设计模式 经典设计原则】七 LOD迪米特法则
    LLVM学习笔记(57)
    C++ Builder XE关于AdvStringGrid对EXCEL母表快速分表,并批量插入sheet子表简单操作
    EulerDAO 上线:社区可提案和投票决定治理
    Bigder:45/100 测试日报怎么报风险
  • 原文地址:https://blog.csdn.net/akisi/article/details/126662168