JavaWeb 練習(xí) SMBMS

一啃沪、系統(tǒng)功能結(jié)構(gòu)圖

二码荔、項(xiàng)目搭建前期準(zhǔn)備

2.1 Maven 創(chuàng)建 web 項(xiàng)目

2.2 配置 pom.xml 并導(dǎo)入相關(guān)依賴

<?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>org.example</groupId>
    <artifactId>smbms</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>

    <dependencies>
        <!--Servlet 依賴-->
        <dependency>
            <groupId>jakarta.servlet</groupId>
            <artifactId>jakarta.servlet-api</artifactId>
            <version>5.0.0</version>
        </dependency>
        <!--JSP 依賴-->
        <dependency>
            <groupId>com.guicedee.services</groupId>
            <artifactId>jakarta.servlet.jsp-api</artifactId>
            <version>62</version>
        </dependency>
        <!--jstl 表達(dá)式依賴-->
        <dependency>
            <groupId>org.glassfish.web</groupId>
            <artifactId>jakarta.servlet.jsp.jstl</artifactId>
            <version>2.0.0</version>
        </dependency>
        <!--標(biāo)簽庫依賴-->
        <dependency>
            <groupId>org.apache.taglibs</groupId>
            <artifactId>taglibs-standard-spec</artifactId>
            <version>1.2.5</version>
        </dependency>
        <!--MySQL 依賴-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>       
        <!--單元測試-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
        </dependency>
        <!--fastjson 依賴-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.79</version>
        </dependency>
    </dependencies>
</project>

2.3 IDEA 中配置 Tomcat

<!--修改為與Tomcat 10 一致-->
<!--去掉 metadata-complete="true",開啟注解-->
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
         version="5.0">
    <!--設(shè)置首頁-->
    <welcome-file-list>
        <welcome-file>login.jsp</welcome-file>
    </welcome-file-list>
    <!--設(shè)置Session默認(rèn)過期時間30分鐘-->
    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>
</web-app>

2.4 創(chuàng)建項(xiàng)目包

  • 結(jié)構(gòu)圖:

2.5 創(chuàng)建并連接數(shù)據(jù)庫

2.6 編寫實(shí)體類

  • pojo 包下編寫對應(yīng)數(shù)據(jù)表的實(shí)體類:Bill邻寿、Provider污茵、RoleUser

  • IDEA 快捷方式創(chuàng)建實(shí)例類:

    • 連接數(shù)據(jù)庫后闪萄,在數(shù)據(jù)表上右鍵點(diǎn)擊梧却;

    • 選擇創(chuàng)建位置;

    • 修改包路徑败去;

    • 根據(jù)需求修改文件名稱放航;

  • Bill.java

public class Bill {
    private Integer id; // 主鍵ID
    private String billCode; // 賬單編碼
    private String productName; // 商品名稱
    private String productDesc; // 商品描述
    private String productUnit; // 商品單位
    private BigDecimal productCount; // 商品數(shù)量
    private BigDecimal totalPrice; // 商品總額
    private Integer isPayment; // 是否支付(1:未支付 2:已支付)
    private Integer createdBy; // 創(chuàng)建者(userId)
    private Date creationDate; // 創(chuàng)建時間
    private Integer modifyBy; // 更新者(userId)
    private Date modifyDate; // 更新時間
    private Integer providerId; // 供應(yīng)商ID
    
    private String providerName; // 供應(yīng)商名稱(聯(lián)表查詢字段)

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getBillCode() {
        return billCode;
    }

    public void setBillCode(String billCode) {
        this.billCode = billCode;
    }

    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    public String getProductDesc() {
        return productDesc;
    }

    public void setProductDesc(String productDesc) {
        this.productDesc = productDesc;
    }

    public String getProductUnit() {
        return productUnit;
    }

    public void setProductUnit(String productUnit) {
        this.productUnit = productUnit;
    }

    public BigDecimal getProductCount() {
        return productCount;
    }

    public void setProductCount(BigDecimal productCount) {
        this.productCount = productCount;
    }

    public BigDecimal getTotalPrice() {
        return totalPrice;
    }

    public void setTotalPrice(BigDecimal totalPrice) {
        this.totalPrice = totalPrice;
    }

    public Integer getIsPayment() {
        return isPayment;
    }

    public void setIsPayment(Integer isPayment) {
        this.isPayment = isPayment;
    }

    public Integer getCreatedBy() {
        return createdBy;
    }

    public void setCreatedBy(Integer createdBy) {
        this.createdBy = createdBy;
    }

    public Date getCreationDate() {
        return creationDate;
    }

    public void setCreationDate(Date creationDate) {
        this.creationDate = creationDate;
    }

    public Integer getModifyBy() {
        return modifyBy;
    }

    public void setModifyBy(Integer modifyBy) {
        this.modifyBy = modifyBy;
    }

    public Date getModifyDate() {
        return modifyDate;
    }

    public void setModifyDate(Date modifyDate) {
        this.modifyDate = modifyDate;
    }

    public Integer getProviderId() {
        return providerId;
    }

    public void setProviderId(Integer providerId) {
        this.providerId = providerId;
    }
    
     public String getProviderName() {
        return providerName;
    }

    public void setProviderName(String providerName) {
        this.providerName = providerName;
    }
}
  • Provider.java
public class Provider {
    private Integer id; // 主鍵ID
    private String proCode; // 供應(yīng)商編碼
    private String proName; // 供應(yīng)商名稱
    private String proDesc; // 供應(yīng)商詳細(xì)描述
    private String proContact; // 供應(yīng)商聯(lián)系人
    private String proPhone; // 聯(lián)系電話
    private String proAddress; // 地址
    private String proFax;  // 傳真
    private Integer createdBy; // 創(chuàng)建者(userId)
    private Date creationDate;  // 創(chuàng)建時間
    private Date modifyDate; // 更新時間
    private Integer modifyBy; // 更新者(userId)
   
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getProCode() {
        return proCode;
    }

    public void setProCode(String proCode) {
        this.proCode = proCode;
    }

    public String getProName() {
        return proName;
    }

    public void setProName(String proName) {
        this.proName = proName;
    }

    public String getProDesc() {
        return proDesc;
    }

    public void setProDesc(String proDesc) {
        this.proDesc = proDesc;
    }

    public String getProContact() {
        return proContact;
    }

    public void setProContact(String proContact) {
        this.proContact = proContact;
    }

    public String getProPhone() {
        return proPhone;
    }

    public void setProPhone(String proPhone) {
        this.proPhone = proPhone;
    }

    public String getProAddress() {
        return proAddress;
    }

    public void setProAddress(String proAddress) {
        this.proAddress = proAddress;
    }

    public String getProFax() {
        return proFax;
    }

    public void setProFax(String proFax) {
        this.proFax = proFax;
    }

    public Integer getCreatedBy() {
        return createdBy;
    }

    public void setCreatedBy(Integer createdBy) {
        this.createdBy = createdBy;
    }

    public Date getCreationDate() {
        return creationDate;
    }

    public void setCreationDate(Date creationDate) {
        this.creationDate = creationDate;
    }

    public Date getModifyDate() {
        return modifyDate;
    }

    public void setModifyDate(Date modifyDate) {
        this.modifyDate = modifyDate;
    }

    public Integer getModifyBy() {
        return modifyBy;
    }

    public void setModifyBy(Integer modifyBy) {
        this.modifyBy = modifyBy;
    }
}
  • Role.java
public class Role {
    private Integer id; // 主鍵ID
    private String roleCode; // 角色編碼
    private String roleName; // 角色名稱
    private Integer createdBy;  // 創(chuàng)建者
    private Date creationDate; // 創(chuàng)建時間
    private Integer modifyBy; // 修改者
    private Date modifyDate; // 修改時間

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getRoleCode() {
        return roleCode;
    }

    public void setRoleCode(String roleCode) {
        this.roleCode = roleCode;
    }

    public String getRoleName() {
        return roleName;
    }

    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }

    public Integer getCreatedBy() {
        return createdBy;
    }

    public void setCreatedBy(Integer createdBy) {
        this.createdBy = createdBy;
    }

    public Date getCreationDate() {
        return creationDate;
    }

    public void setCreationDate(Date creationDate) {
        this.creationDate = creationDate;
    }

    public Integer getModifyBy() {
        return modifyBy;
    }

    public void setModifyBy(Integer modifyBy) {
        this.modifyBy = modifyBy;
    }

    public Date getModifyDate() {
        return modifyDate;
    }

    public void setModifyDate(Date modifyDate) {
        this.modifyDate = modifyDate;
    }
}
  • User.java
public class User {
    private Integer id;  // 主鍵ID
    private String userCode; // 用戶編碼
    private String userName; // 用戶名稱
    private String userPassword; // 用戶密碼
    private Integer gender; // 性別(1:女、 2:男)
    private Date birthday; // 出生日期
    private String phone;  // 手機(jī)
    private String address; // 地址
    private Integer userRole; // 用戶角色(取自角色表-角色id)
    private Integer createdBy; // 創(chuàng)建者(userId)
    private Date creationDate; // 創(chuàng)建時間
    private Integer modifyBy; // 更新者(userId)
    private Date modifyDate; // 更新時間

    private Integer age;// 年齡
    private String userRoleName; // 用戶角色名稱(聯(lián)表查詢字段)

    public Integer getAge() {
        Date date = new Date();
        Integer age = date.getYear() - birthday.getYear();
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getUserRoleName() {
        return userRoleName;
    }

    public void setUserRoleName(String userRoleName) {
        this.userRoleName = userRoleName;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUserCode() {
        return userCode;
    }

    public void setUserCode(String userCode) {
        this.userCode = userCode;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserPassword() {
        return userPassword;
    }

    public void setUserPassword(String userPassword) {
        this.userPassword = userPassword;
    }

    public Integer getGender() {
        return gender;
    }

    public void setGender(Integer gender) {
        this.gender = gender;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public Integer getUserRole() {
        return userRole;
    }

    public void setUserRole(Integer userRole) {
        this.userRole = userRole;
    }

    public Integer getCreatedBy() {
        return createdBy;
    }

    public void setCreatedBy(Integer createdBy) {
        this.createdBy = createdBy;
    }

    public Date getCreationDate() {
        return creationDate;
    }

    public void setCreationDate(Date creationDate) {
        this.creationDate = creationDate;
    }

    public Integer getModifyBy() {
        return modifyBy;
    }

    public void setModifyBy(Integer modifyBy) {
        this.modifyBy = modifyBy;
    }

    public Date getModifyDate() {
        return modifyDate;
    }

    public void setModifyDate(Date modifyDate) {
        this.modifyDate = modifyDate;
    }
}

2.7 編寫基礎(chǔ)公共類

  • resources 包下圆裕,新建 db.properties 文件:
# MySQL8
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/smbms?useUnicode=true&characterEncoding=utf8&useSSL=true
username=root
password=123456
  • 編寫數(shù)據(jù)庫的公共類:dao 包下創(chuàng)建 BaseDao.java
public class BaseDao {
    private static String driver;
    private static String url;
    private static String username;
    private static String password;

    /**
     * 靜態(tài)代碼塊广鳍,類加載的同時進(jìn)行初始化
     * 從配置文件中獲取數(shù)據(jù)庫配置
     */
    static {
        // 創(chuàng)建屬性集合
        Properties params = new Properties();
        String configFile = "db.properties";
        // 通過類加載器讀取對應(yīng)資源,讀取數(shù)據(jù)庫連接信息,得到輸入流
        InputStream is = BaseDao.class.getClassLoader().getResourceAsStream(configFile);
        // 讀取流
        try {
            params.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 獲取數(shù)據(jù)庫配置屬性
        driver = params.getProperty("driver");
        url = params.getProperty("url");
        username = params.getProperty("username");
        password = params.getProperty("password");
    }

    /**
     * 獲取數(shù)據(jù)庫連接
     *
     * @return 數(shù)據(jù)庫對象
     */
    public static Connection getConnection() {
        Connection connection = null;
        try {
            // 加載驅(qū)動
            Class.forName(driver);
            // 獲取數(shù)據(jù)庫連接對象
            connection = DriverManager.getConnection(url, username, password);
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }

    /**
     * 編寫查詢公共方法
     *
     * @param connection        數(shù)據(jù)連接對象
     * @param preparedStatement SQL的執(zhí)行對象
     * @param resultSet         查詢結(jié)果集
     * @param sql               sql語句
     * @param params            占位符
     * @return 查詢結(jié)果集
     * @throws SQLException
     */
    public static ResultSet execute(Connection connection, PreparedStatement preparedStatement,
                                    ResultSet resultSet, String sql, Object[] params) throws SQLException {
        // 獲取sql語句的執(zhí)行對象 PreparedStatement(對SQL進(jìn)行預(yù)編譯)
        preparedStatement = connection.prepareStatement(sql);
        for (int i = 0; i < params.length; i++) {
            // 為占位符參數(shù)賦值葫辐,占位符:索引從1開始搜锰,數(shù)組:索引從0開始
            preparedStatement.setObject(i + 1, params[i]);
        }
        // 獲取查詢結(jié)果集
        resultSet = preparedStatement.executeQuery();
        return resultSet;
    }

    /**
     * 編寫增、刪耿战、改公共方法
     *
     * @param connection        數(shù)據(jù)連接對象
     * @param sql               sql語句
     * @param params            占位符
     * @param preparedStatement SQL的執(zhí)行對象
     * @return updateRows 記錄條數(shù)
     * @throws SQLException
     */
    public static int execute(Connection connection, PreparedStatement preparedStatement,
                              String sql, Object[] params) throws SQLException {
        // 獲取sql語句的執(zhí)行對象 PreparedStatement(對SQL進(jìn)行預(yù)編譯)
        preparedStatement = connection.prepareStatement(sql);
        for (int i = 0; i < params.length; i++) {
            // 為占位符參數(shù)賦值蛋叼,索引從1開始
            preparedStatement.setObject(i + 1, params[i]);
        }
        // 獲取增、刪剂陡、改狈涮,記錄條數(shù)
        int updateRows = preparedStatement.executeUpdate();
        return updateRows;
    }

    /**
     * 釋放資源,順序:后開先關(guān)
     *
     * @param resultSet         結(jié)果集
     * @param preparedStatement 執(zhí)行sql的對象
     * @param connection        數(shù)據(jù)庫對象
     * @return flag 是否關(guān)閉成功
     */
    public static boolean closeResource(Connection connection,
                                        PreparedStatement preparedStatement,
                                        ResultSet resultSet) {
        boolean flag = true;
        // 關(guān)閉結(jié)果集
        if (resultSet != null) {
            try {
                resultSet.close();
                // GC回收
                resultSet = null;
            } catch (SQLException e) {
                e.printStackTrace();
                // 設(shè)置異常時為false
                flag = false;
            }
        }
        // 關(guān)閉 preparedStatement
        if (preparedStatement != null) {
            try {
                preparedStatement.close();
                preparedStatement = null;
            } catch (SQLException e) {
                e.printStackTrace();
                flag = false;
            }
            System.out.println(flag);
        }
        // 關(guān)閉 connection
        if (connection != null) {
            try {
                connection.close();
                connection = null;
            } catch (SQLException e) {
                e.printStackTrace();
                flag = false;
            }
        }
        return flag;
    }
}

2.8 編寫字符編碼過濾器

  • filter 包下鸭栖,創(chuàng)建過濾器文件:
/**
 * 編碼過濾器:注意:過濾器繼續(xù)執(zhí)行的代碼8桠伞!
 * 用注解的方式晕鹊,過濾所有內(nèi)容:也可以通過配置web.xml
 */
@WebFilter("/*")
public class CharacterEncodingFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                         FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setCharacterEncoding("utf-8");
        servletResponse.setContentType("text/html;charset=utf-8");

        // 注意:過濾器繼續(xù)執(zhí)行K扇础!
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}
  • web.xml 中注冊溅话,也通過注解方式 @WebFilter("/*")晓锻;

2.9 導(dǎo)入靜態(tài)資源

  • 放在 webapp 目錄下:

三、登錄功能的實(shí)現(xiàn)

3.1 流程結(jié)構(gòu)

3.2 導(dǎo)入前端頁面

  • 導(dǎo)入登錄頁面 login.jsp 及其它 jsp 頁面飞几;
  • 將登錄頁面 login.jsp 設(shè)置為首頁:在 web.xml 中配置砚哆;
<!--設(shè)置首頁頁面-->
<welcome-file-list>
    <welcome-file>login.jsp</welcome-file>
</welcome-file-list>

3.3 編寫后端文件

  1. 編寫 dao 層:
  • 功能:操作數(shù)據(jù)庫
    • 通過 userCode 查詢,業(yè)務(wù)層傳遞的 登錄用戶 是否存在屑墨;
  • dao 中新建 user 包躁锁,創(chuàng)建 UserDao 接口類:
public interface UserDao {
    /**
     * 得到要登錄的用戶
     *
     * @param connection 數(shù)據(jù)庫連接對象
     * @param userCode   用戶名
     * @return 登錄用戶
     */
    public User getLoginUser(Connection connection, String userCode) throws SQLException;
}
  • 編寫 UserDao 接口的實(shí)現(xiàn)類 UserDaoImpl
public class UserDaoImpl implements UserDao {
    /**
     * 得到要登錄的用戶
     *
     * @param connection 數(shù)據(jù)庫連接對象
     * @param userCode   用戶名
     * @return User
     * @throws SQLException
     */
    @Override
    public User getLoginUser(Connection connection, String userCode) throws SQLException {
        PreparedStatement pstm = null;
        ResultSet rs = null;
        User user = null;

        // 判斷數(shù)據(jù)庫是否連接成功,
        if (connection != null) {
            // 創(chuàng)建SQL
            String sql = "select * from `smbms_user` where `userCode`=?";
            Object[] params = {userCode};
            // 執(zhí)行SQL
            rs = BaseDao.execute(connection, pstm, rs, sql, params);
            while (rs.next()) {
                user = new User();
                user.setId(rs.getInt("id"));
                user.setUserCode(rs.getString("userCode"));
                user.setUserName(rs.getString("userName"));
                user.setUserPassword(rs.getString("userPassword"));
                user.setGender(rs.getInt("gender"));
                user.setBirthday(rs.getDate("birthday"));
                user.setPhone(rs.getString("phone"));
                user.setAddress(rs.getString("address"));
                user.setUserRole(rs.getInt("userRole"));
                user.setCreatedBy(rs.getInt("createdBy"));
                user.setCreationDate(rs.getTimestamp("creationDate"));
                user.setModifyBy(rs.getInt("modifyBy"));
                user.setModifyDate(rs.getTimestamp("modifyDate"));
            }
            BaseDao.closeResource(null, pstm, rs);
        }
        return user;
    }
}
  1. 編寫業(yè)務(wù)層
  • 功能:調(diào)用 dao 層
    • 通過前端傳遞的用戶編碼 userCode卵史,調(diào)用 dao 層战转,查詢用戶是否存在;
  • service 下新建 user 包以躯,創(chuàng)建 UserService 接口:
public interface UserService {
    // 用戶登錄
    public User login(String userCode, String password);
}
  • 編寫業(yè)務(wù)層接口的實(shí)現(xiàn)類
    • 業(yè)務(wù)層調(diào)用 dao 層匣吊,必須先引入 dao 層;
    • 引入方式:在構(gòu)造函數(shù)中將其實(shí)例化
public class UserServiceImpl implements UserService {
    // 業(yè)務(wù)層都會調(diào)用dao層色鸳,所以需要引入dao層
    private UserDao userDao;

    // 通過構(gòu)造函數(shù)社痛,類實(shí)例化時,創(chuàng)建UserDao的實(shí)例
    public UserServiceImpl() {
        userDao = new UserDaoImpl();
    }

    /**
     * 用戶登錄
     *
     * @param userCode
     * @param password
     * @return
     */
    @Override
    public User login(String userCode, String password) {
        Connection connection = null;
        User user = null;
        try {
            connection = BaseDao.getConnection();
            // 業(yè)務(wù)層調(diào)用dao層:對應(yīng)具體的數(shù)據(jù)庫操作
            user = userDao.getLoginUser(connection, userCode);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            BaseDao.closeResource(connection, null, null);
        }
        return user;
    }
}
  1. 編寫 Servlet(控制層)
  • 功能:調(diào)用業(yè)務(wù)層
    • 獲取前端輸入的用戶名命雀、密碼和數(shù)據(jù)庫查詢的內(nèi)容做比對蒜哀;
  • util 包下,創(chuàng)建 Constants 類吏砂,存儲常量:
public class Constants {
    public final static String USER_SESSION = "userSession";
}
  • servlet 包中新建 user 包撵儿,創(chuàng)建 LoginServlet 類:
// 通過注解方式,注冊servlet狐血,也可通過web.xml配置
@WebServlet("/login.do")
public class LoginServlet extends HttpServlet {
    // Servlet:控制層淀歇,調(diào)用業(yè)務(wù)層
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("login.do=========LoginServlet start...");
        // 從前端獲取輸入的用戶名、密碼
        String userCode = req.getParameter("userCode");
        String userPassword = req.getParameter("userPassword");
        // 調(diào)用業(yè)務(wù)層:和數(shù)據(jù)庫中密碼進(jìn)行對比
        UserService userService = new UserServiceImpl();
        // 得到登錄人信息
        User user = userService.login(userCode, userPassword);

        // 如果用戶存在,且密碼正確匈织,可以登錄
        if (user != null && userPassword.equals(user.getUserPassword())) {             // 將用戶信息存儲到Session
            req.getSession().setAttribute(Constants.USER_SESSION, user);
            // 跳轉(zhuǎn)到主頁
            resp.sendRedirect(req.getContextPath() + "/jsp/frame.jsp");
        } else {
            // 用戶不存在浪默,無法登錄
            // 轉(zhuǎn)發(fā)回登錄頁面,順帶提示:用戶名或密碼錯誤
            req.setAttribute("error", "用戶名或者密碼不正確");
            req.getRequestDispatcher("login.jsp").forward(req, resp);
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
  • 注冊 servlet:可以配置 web.xml 或注解方式:@WebServlet("/login.do")缀匕;
<!--注冊登錄頁面的Servlet-->
<servlet>
    <servlet-name>login</servlet-name>
    <servlet-class>類名</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>login</servlet-name>
    <url-pattern>/login.do</url-pattern>
</servlet-mapping>
  • 測試訪問纳决,查看以上功能是否可以正常運(yùn)行;

四乡小、登錄功能的優(yōu)化

4.1 注銷功能

  • 移除 session阔加,返回登錄頁面:servlet.user 下創(chuàng)建 LogoutServlet 類:
// 注解方式,注冊servlet
@WebServlet("/jsp/logout.do")
public class LogoutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 移除用戶的Session
        req.getSession().removeAttribute(Constants.USER_SESSION);
        // 返回登頁面
        resp.sendRedirect(req.getContextPath() + "/login.jsp");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
  • 注冊 servlet:web.xml 或注解方式满钟;

4.2 登錄攔截器

  • 功能:未登錄狀態(tài)下胜榔,不能訪問 jsp 目錄下的所有頁面;
  • filter 下創(chuàng)建 SysFilter 類:
    • 注意:執(zhí)行完過濾內(nèi)容湃番,必須添加讓過濾器繼續(xù)往下執(zhí)行的代碼
      • chain.doFilter(req, resp);
// 注冊過濾器
@WebFilter("/jsp/*")
public class SysFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        // 類型轉(zhuǎn)換:獲取session夭织、重定向
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        // 從session中獲取用戶
        User user = (User) request.getSession().getAttribute(Constants.USER_SESSION);
        // 如果session為空(注銷或未登錄),跳轉(zhuǎn)到錯誤頁面
        if (user == null) {
            response.sendRedirect(request.getContextPath() + "/error.jsp");
        }
        // 過濾器繼續(xù)執(zhí)行G@薄!
        chain.doFilter(req, resp);
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}
  • 注冊過濾器:web.xml 中或注解方式:@WebFilter("/jsp/*")
<filter>
    <filter-name>Sysfilter</filter-name>
    <filter-class>類名</filter-class>
</filter>
<filter-mapping>
    <filter-name>Sysfilter</filter-name>
    <url-pattern>/jsp/*</url-pattern>
</filter-mapping>

4.3 密碼修改

思路:自頂向下設(shè)計(jì)奴饮,自底向上實(shí)現(xiàn)纬向;

  • 先寫基本邏輯戴卜,前端在測試后端時逾条,逐漸完善:

    • 需要自底向上糕篇,逐一實(shí)現(xiàn)功能墩崩,修改密碼需要更新數(shù)據(jù)庫,需要到 dao 層侯勉,進(jìn)行增鹦筹、刪、改址貌、查铐拐;

    • dao 層需要的信息,比如:用戶名芳誓、當(dāng)前的密碼余舶、要修改的密碼,需要從 Service 層獲惹绿省匿值;

    • Service 層,需要負(fù)責(zé)把從 Servlet 層傳過來的數(shù)據(jù)赂摆,進(jìn)行相應(yīng)的處理挟憔、驗(yàn)證、核算烟号,然后將最終的信息绊谭,傳遞給 dao 層磨取;

    • Servlet 直接與前端接觸程拭,返回當(dāng)前頁面上傳遞過來的,用戶輸入觸發(fā)的 參數(shù)劳吠,轉(zhuǎn)發(fā)到不同的頁面迫筑,交給不同的 Service 來處理這些請求宪赶;

  • 意味著,先從 dao 層開始寫分模塊脯燃,先寫接口搂妻,再寫接口的實(shí)現(xiàn)類,依次寫 Serviceservlet 辕棚,最后注冊 Servlet欲主,然后測試并完善前端頁面邓厕;

  1. 編寫 dao 層
  • dao.user.UserDao 的接口下增加,用戶修改密碼接口:
/**
 * 修改當(dāng)前用戶密碼
 *
 * @param connection 數(shù)據(jù)庫連接對象
 * @param id         用戶Id
 * @param password   新密碼
 * @return 更新記錄數(shù)
 * @throws SQLException
 */
public int updatePwd(Connection connection, int id, String password) throws SQLException;
  • 編寫接口實(shí)現(xiàn)類:UserDaoImpl 中增加:
/**
 * 修改當(dāng)前用戶密碼
 *
 * @param connection 數(shù)據(jù)庫連接對象
 * @param id         用戶Id
 * @param password   新密碼
 * @return updateRows
 * @throws SQLException
 */
@Override
public int updatePwd(Connection connection, int id, String password) throws SQLException {
    PreparedStatement pstm = null;
    int updateRows = 0;
    if (connection != null) {
        String sql = "update `smbms_user` set `userPassword`=? where id=?";
        Object[] params = {password, id};
        updateRows = BaseDao.execute(connection, pstm, sql, params);
        BaseDao.closeResource(null, pstm, null);
    }
    return updateRows;
}
  1. 編寫業(yè)務(wù)層 Service
  • 添加接口:在 UserService 接口類下增加:
// 根據(jù)用戶Id扁瓢,修改密碼
public boolean updatePwd(int id, String pwd);
  • 接口實(shí)現(xiàn)類:在 UserServiceImpl 下增加:
/**
 * 根據(jù)用戶Id详恼,修改密碼
 *
 * @param id  用戶Id
 * @param pwd 新密碼
 * @return boolean
 */
@Override
public boolean updatePwd(int id, String pwd) {
    boolean flag = false;
    Connection connection = null;
    try {
        connection = BaseDao.getConnection();
        if (userDao.updatePwd(connection, id, pwd) > 0) {
            flag = true;
        }
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        BaseDao.closeResource(connection, null, null);
    }
    return flag;
}
  1. 編寫 Servlet
  • servlet.user 包下,創(chuàng)建 UserServlet 類:
    • 通過前端傳遞的 method 值涤妒,做判斷单雾,去執(zhí)行操作,實(shí)現(xiàn) servlet 復(fù)用她紫;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    // 實(shí)現(xiàn)servlet復(fù)用硅堆,實(shí)現(xiàn)復(fù)用需要提取出方法,然后在doGet函數(shù)中調(diào)用即可
    String method = req.getParameter("method");
    // 修改密碼
    if (method.equals("savepwd") && method != null) {
        this.updatePwd(req, resp);   
    }
}

// 在doGet外添加復(fù)用方法
/**
 * 修改密碼
 *
 * @param req
 * @param resp
 */
private void updatePwd(HttpServletRequest req, HttpServletResponse resp) {
    // 獲取session
    Object o = req.getSession().getAttribute(Constants.USER_SESSION);
    String newpassword = req.getParameter("newpassword");
    // 設(shè)置標(biāo)志位
    boolean flag = false;
    if (o != null && newpassword != null && newpassword.length() != 0) {
        // 調(diào)用業(yè)務(wù)層
        UserService userService = new UserServiceImpl();
        // 如果修改成功贿讹,返回true
        flag = userService.updatePwd(((User) o).getId(), newpassword);
        if (flag) {
            // 設(shè)置屬性:返回前端
            req.setAttribute("message", "修改密碼成功渐逃,請退出,使用新密碼登錄");
            // 移除session
            req.getSession().removeAttribute(Constants.USER_SESSION);
        } else {
            // 密碼修改失敗
            req.setAttribute("message", "修改密碼失敗");
        }
    } else {
        // 密碼有問題
        req.setAttribute("message", "密碼有問題");
    }

    try {
        resp.sendRedirect(req.getContextPath() + "/jsp/pwdmodify.jsp");
    } catch (IOException e) {
        e.printStackTrace();
    }
}
  • 注冊 servlet:web.xml 中或注解方式 @WebServlet("/jsp/user.do")民褂;

4.4 使用 Ajax 優(yōu)化密碼修改

  • Json 轉(zhuǎn)換依賴:

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.79</version>
    </dependency>
    
  • UserServlet 中創(chuàng)建 toJson 方法:

 /**
 * 轉(zhuǎn)換為Json類型
 *
 * @param resp
 * @param object 需要轉(zhuǎn)換的對象
 */
private void toJson(HttpServletResponse resp, Object object) {
    // 返回json類型
    resp.setContentType("application/json");
    try {
        // 輸出流
        PrintWriter writer = resp.getWriter();
        // JSONArray工具類茄菊,轉(zhuǎn)換格式
        // 將結(jié)果集,以json格式返回
        writer.write(JSONArray.toJSONString(object));
        // 刷新
        writer.flush();
        // 關(guān)閉流
        writer.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
  • 編寫驗(yàn)證舊密碼的 Servlet 類(方法復(fù)用):UserServlet 中增加
// doGet 方法中添加
// 驗(yàn)證舊密碼
else if (method.equals("pwdmodify") && method != null) {
    this.pwdModify(req, resp);    
}

// 在doGet外添加復(fù)用方法
/**
 * Ajax驗(yàn)證舊密碼:與session中的密碼比對
 *
 * @param req
 * @param resp
 */
private void pwdModify(HttpServletRequest req, HttpServletResponse resp) {
    // 獲取session
    Object o = req.getSession().getAttribute(Constants.USER_SESSION);
    String oldpassword = req.getParameter("oldpassword");
    // 萬能的Map
    Map<String, String> resultMap = new HashMap<>();
    // Session過期
    if (o == null) {
        resultMap.put("result", "sessionerror");
        // 密碼為空
    } else if (StringUtils.isNullOrEmpty(oldpassword)) {
        resultMap.put("result", "error");
        // 密碼不正確
    } else {
        // session中的用戶密碼
        String userPassword = ((User) o).getUserPassword();
        if (userPassword.equals(oldpassword)) {
            resultMap.put("result", "true");
        } else {
            resultMap.put("result", "false");
        }
    }
    // 轉(zhuǎn)換為json類型
    this.toJson(resp, resultMap);
}

五赊堪、用戶管理模塊

  • 結(jié)構(gòu)流程圖:

  • 導(dǎo)入分頁的工具類:PageSupport.java

// 分頁工具類
public class PageSupport {
    //當(dāng)前頁碼-來自于用戶輸入
    private int currentPageNo = 1;

    //總數(shù)量(表)
    private int totalCount = 0;

    //頁面容量
    private int pageSize = 0;

    //總頁數(shù)-totalCount/pageSize(+1)
    private int totalPageCount = 1;

    public int getCurrentPageNo() {
        return currentPageNo;
    }

    // OOP三大特性:封裝(屬性私有面殖、get/set、在set中限定一些不安全情況)
    public void setCurrentPageNo(int currentPageNo) {
        if (currentPageNo > 0) {
            this.currentPageNo = currentPageNo;
        }
    }

    public int getTotalCount() {
        return totalCount;
    }

    /**
     * 設(shè)置總記錄數(shù)哭廉,獲取頁面總數(shù)
     *
     * @param totalCount
     */
    public void setTotalCount(int totalCount) {
        if (totalCount > 0) {
            this.totalCount = totalCount;
            //設(shè)置總頁數(shù)
            this.setTotalPageCountByRs();
        }
    }

    public int getPageSize() {
        return pageSize;
    }

    public void setPageSize(int pageSize) {
        if (pageSize > 0) {
            this.pageSize = pageSize;
        }
    }

    // 獲取頁面總數(shù)
    public int getTotalPageCount() {
        return totalPageCount;
    }

    public void setTotalPageCount(int totalPageCount) {
        this.totalPageCount = totalPageCount;
    }

    /**
     * 通過查詢記錄數(shù)脊僚,計(jì)算頁面總數(shù)
     */
    public void setTotalPageCountByRs() {
        if (this.totalCount % this.pageSize == 0) {
            this.totalPageCount = this.totalCount / this.pageSize;
        } else if (this.totalCount % this.pageSize > 0) {
            this.totalPageCount = this.totalCount / this.pageSize + 1;
        } else {
            this.totalPageCount = 0;
        }
    }
}
  • 導(dǎo)入用戶列表及相關(guān) jsp 文件:

  • 按照自底向上的流程,編寫:

    • Dao
    • DaoImpl
    • Service
    • ServiceImpl
    • Servlet

5.1 獲取用戶的數(shù)量

  • UserDao 接口遵绰,添加方法:
/**
 * 查詢用戶總數(shù)
 *
 * @param connection 數(shù)據(jù)庫連接對象
 * @param userName   用戶名
 * @param userRole   用戶角色
 * @return int
 * @throws SQLException
 */
public int getUserCount(Connection connection, String userName, int userRole) throws SQLException;
  • UserDaoImpl 中添加實(shí)現(xiàn)方法:
/**
 * 根據(jù)用戶名或角色辽幌,查詢總數(shù)
 *
 * @param connection 數(shù)據(jù)庫連接對象
 * @param userName   用戶名
 * @param userRole   用戶角色
 * @return count
 * @throws SQLException
 */
@Override
public int getUserCount(Connection connection, String userName, int userRole) throws SQLException {
    PreparedStatement pstm = null;
    ResultSet rs = null;
    int count = 0;
    if (connection != null) {
        StringBuffer sql = new StringBuffer();
        sql.append("select count(1) as count from `smbms_user` u,`smbms_role` r where u.`userRole`=r.`id`");
        // 存放參數(shù)
        ArrayList<Object> list = new ArrayList<>();
        if (!StringUtils.isNullOrEmpty(userName)) {
            sql.append(" and u.`userName` like ?");
            // index[0]
            list.add("%" + userName + "%");
        }
        if (userRole > 0) {
            sql.append(" and u.`userRole` = ?");
            // index[1]
            list.add(userRole);
        }
        // List 轉(zhuǎn)換為數(shù)組
        Object[] params = list.toArray();
        System.out.println("UserDaoImpl-->getUserCount:" + sql.toString());
        rs = BaseDao.execute(connection, pstm, rs, sql.toString(), params);
        if (rs.next()) {
            // 從結(jié)果集中獲取最終的數(shù)量
            count = rs.getInt("count");
        }
        BaseDao.closeResource(null, pstm, rs);
    }
    return count;
}
  • UserService 接口中,添加方法:
// 查詢用戶數(shù)
public int getUserCount(String userName, int userRole);
  • UserServiceImpl 實(shí)現(xiàn)方法:
/**
 * 查詢用戶數(shù)
 *
 * @param userName 用戶名
 * @param userRole 角色名
 * @return count
 */
@Override
public int getUserCount(String userName, int userRole) {
    Connection connection = null;
    int count = 0;
    try {
        connection = BaseDao.getConnection();
        count = userDao.getUserCount(connection, userName, userRole);
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        BaseDao.closeResource(connection, null, null);
    }
    return count;
}

5.2 通過條件查詢用戶列表

  • UserDao 接口椿访,添加方法:
/**
 * 通過條件查詢用戶列表
 *
 * @param connection    數(shù)據(jù)庫連接對象
 * @param userName      用戶名
 * @param userRole      用戶角色
 * @param currentPageNo 當(dāng)前頁
 * @param pageSize      頁面大小
 * @return List<User>
 * @throws SQLException
 */
public List<User> getUserList(Connection connection, String userName, int userRole, int currentPageNo, int pageSize) throws SQLException;
  • UserDaoImpl 中添加實(shí)現(xiàn)方法:
/**
 * 通過條件查詢用戶列表
 *
 * @param connection    數(shù)據(jù)庫連接對象
 * @param userName      用戶名
 * @param userRole      用戶角色
 * @param currentPageNo 當(dāng)前頁
 * @param pageSize      頁面大小
 * @return List<User>
 */
@Override
public List<User> getUserList(Connection connection, String userName, int userRole,
                              int currentPageNo, int pageSize) throws SQLException {
    PreparedStatement pstm = null;
    ResultSet rs = null;
    // 用戶列表
    List<User> userList = new ArrayList<>();
    if (connection != null) {
        StringBuffer sql = new StringBuffer();
        sql.append("SELECT u.*,r.`roleName` userRoleName FROM `smbms_user` u INNER JOIN `smbms_role` r ON u.`userRole`=r.`id`");
        ArrayList<Object> list = new ArrayList<>();
        if (!StringUtils.isNullOrEmpty(userName)) {
            sql.append(" and u.`userName` like ?");
            // index[0]
            list.add("%" + userName + "%");
        }
        if (userRole > 0) {
            sql.append(" and u.`userRole` = ?");
            // index[1]
            list.add(userRole);
        }
        // 分頁
        sql.append(" ORDER BY `creationDate` DESC LIMIT ?,?");
        // 當(dāng)前頁
        currentPageNo = (currentPageNo - 1) * pageSize;
        list.add(currentPageNo);
        list.add(pageSize);
        // List 轉(zhuǎn)換為數(shù)組
        Object[] params = list.toArray();
        System.out.println("UserDaoImpl-->getUserCount:" + sql.toString());
        rs = BaseDao.execute(connection, pstm, rs, sql.toString(), params);
        while (rs.next()) {
            User _user = new User();
            _user.setId(rs.getInt("id"));
            _user.setUserCode(rs.getString("userCode"));
            _user.setUserName(rs.getString("userName"));
            _user.setGender(rs.getInt("gender"));
            _user.setBirthday(rs.getDate("birthday"));
            _user.setPhone(rs.getString("phone"));
            _user.setUserRole(rs.getInt("userRole"));
            _user.setUserRoleName(rs.getString("userRoleName"));
            userList.add(_user);
        }
        BaseDao.closeResource(null, pstm, rs);
    }
    return userList;
}
  • UserService 接口中乌企,添加方法:
// 根據(jù)條件查詢用戶列表
public List<User> getUserList(String queryUserName, int queryUserRole, int currentPageNo, int pageSize);
  • UserServiceImpl 實(shí)現(xiàn)方法:
/**
 * 根據(jù)條件查詢用戶列表
 *
 * @param queryUserName 用戶名
 * @param queryUserRole 用戶角色
 * @param currentPageNo 當(dāng)前頁
 * @param pageSize      頁面大小
 * @return List<User>
 */
@Override
public List<User> getUserList(String queryUserName, int queryUserRole, int currentPageNo, int pageSize) {
    Connection connection = null;
    List<User> userList = null;
    
    try {
        connection = BaseDao.getConnection();
        userList = userDao.getUserList(connection, queryUserName, queryUserRole, currentPageNo, pageSize);
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        BaseDao.closeResource(connection, null, null);
    }
    return userList;
}

5.3 獲取用戶角色列表

  • dao 包下新建 role 目錄,創(chuàng)建 RoleDao 接口:
public interface RoleDao {
    // 獲取角色列表
    public List<Role> getRoleList(Connection connection) throws SQLException;
}
  • 創(chuàng)建 RoleDaoImpl 實(shí)現(xiàn)類:
public class RoleDaoImpl implements RoleDao {
    /**
     * 獲取角色列表
     *
     * @param connection 數(shù)據(jù)庫連接對象
     * @return List<Role>
     * @throws SQLException
     */
    @Override
    public List<Role> getRoleList(Connection connection) throws SQLException {
        PreparedStatement pstm = null;
        ResultSet rs = null;
        // 創(chuàng)建角色列表
        ArrayList<Role> roleList = new ArrayList<>();
        if (connection != null) {
            String sql = "select * from `smbms_role`";
            Object[] params = {};

            rs = BaseDao.execute(connection, pstm, rs, sql, params);
            while (rs.next()) {
                Role _role = new Role();
                _role.setId(rs.getInt("id"));
                _role.setRoleCode(rs.getString("roleCode"));
                _role.setRoleName(rs.getString("roleName"));
                roleList.add(_role);
            }
            BaseDao.closeResource(null, pstm, rs);
        }
        return roleList;
    }
}
  • service 包下成玫,新建 role 目錄加酵,創(chuàng)建 RoleService 接口:
public interface RoleService {
    // 獲取角色列表
    public List<Role> getRoleList();
}
  • 創(chuàng)建 RoleServiceImpl 實(shí)現(xiàn)類,實(shí)現(xiàn)方法:
    • 調(diào)用 dao 層哭当,需要先引入猪腕;
public class RoleServiceImpl implements RoleService {
    // 引入dao
    private RoleDao roleDao;

    public RoleServiceImpl() {
        roleDao = new RoleDaoImpl();
    }

    /**
     * 獲取角色列表
     *
     * @return List<Role>
     */
    @Override
    public List<Role> getRoleList() {
        Connection connection = null;
        // 創(chuàng)建角色列表
        List<Role> roleList = null;
        try {
            connection = BaseDao.getConnection();
            // 獲取角色列表
            roleList = roleDao.getRoleList(connection);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            BaseDao.closeResource(connection, null, null);
        }
        return roleList;
    }
}

5.4 查詢模塊的 Servlet

  • UserServlet 中添加:
// doGet 方法中添加
// 用戶管理
else if (method.equals("query") && method != null) {
    this.query(req, resp);            
}

/**
 * 用戶管理(重點(diǎn),難點(diǎn)):查詢
 *
 * @param req
 * @param resp
 */
private void query(HttpServletRequest req, HttpServletResponse resp) {
    // 查詢用戶列表
    // 從前端獲取數(shù)據(jù)
    String queryUserName = req.getParameter("queryname");
    String temp = req.getParameter("queryUserRole");
    String pageIndex = req.getParameter("pageIndex");
    // 設(shè)置默認(rèn)的用戶角色碼荣病,避免temp為空
    int queryUserRole = 0;

    // 獲取用戶列表
    UserService userService = new UserServiceImpl();
    List<User> userList = null;

    // 第一次請求码撰,一定是第一頁渗柿,頁面大小固定
    // 頁面大懈雠琛:可以寫配置文件脖岛,方便以后修改
    int pageSize = 5;
    // 默認(rèn)起始頁面
    int currentPageNo = 1;

    if (queryUserName == null) {
        queryUserName = "";
    }
    if (temp != null && !temp.equals("")) {
        // 給查詢賦值 0、1颊亮、2柴梆、3
        queryUserRole = Integer.parseInt(temp);
    }
    if (pageIndex != null) {
        try {
            currentPageNo = Integer.parseInt(pageIndex);
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
    }

    // 獲取用戶的總數(shù)(分頁:上一頁、下一頁)
    int totalCount = userService.getUserCount(queryUserName, queryUserRole);
    // 總頁數(shù)支持
    PageSupport pageSupport = new PageSupport();
    pageSupport.setCurrentPageNo(currentPageNo);
    pageSupport.setPageSize(pageSize);
    // 通過查詢記錄總數(shù)终惑,計(jì)算總頁面數(shù)
    pageSupport.setTotalCount(totalCount);

    // 控制首頁和尾頁
    // 總頁面數(shù)
    int totalPageCount = pageSupport.getTotalPageCount();
    // 如果當(dāng)前頁面小于1绍在,就顯示第一頁
    if (currentPageNo < 1) {
        currentPageNo = 1;
        // 如果當(dāng)前頁面大于最后一頁,就顯示最后一頁
    } else if (currentPageNo > totalPageCount) {
        currentPageNo = totalPageCount;
    }

    // 獲取用戶列表展示
    userList = userService.getUserList(queryUserName, queryUserRole, currentPageNo, pageSize);
    // 把用戶列表傳遞給前端
    req.setAttribute("userList", userList);

    // 獲取角色列表
    RoleServiceImpl roleService = new RoleServiceImpl();
    List<Role> roleList = roleService.getRoleList();
    // 把角色列表傳遞給前端
    req.setAttribute("roleList", roleList);

    // 給前端傳遞其它屬性
    req.setAttribute("totalCount", totalCount);
    req.setAttribute("currentPageNo", currentPageNo);
    req.setAttribute("totalPageCount", totalPageCount);
    req.setAttribute("queryUserName", queryUserName);
    req.setAttribute("queryUserRole", queryUserRole);

    // 返回前端頁面
    try {
        req.getRequestDispatcher("userlist.jsp").forward(req, resp);
    } catch (ServletException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

5.5 用戶管理模塊的增雹有、刪偿渡、改、查(查看)

  • UserDao 中添加:
/**
 * 添加用戶
 *
 * @param connection 數(shù)據(jù)庫連接對象
 * @param user       用戶對象
 * @return updateRows
 * @throws SQLException
 */
public int add(Connection connection, User user) throws SQLException;

// 根據(jù)id查看用戶
public User getUserById(Connection connection, int id) throws SQLException;

// 修改用戶信息
public int modify(Connection connection, User user) throws SQLException;

// 刪除用戶
public int delUser(Connection connection, int id) throws SQLException;
  • UserDaoImpl 中添加:
/**
 * 添加用戶
 *
 * @param connection 數(shù)據(jù)庫連接對象
 * @param user       用戶對象
 * @return updateRows
 * @throws SQLException
 */
@Override
public int add(Connection connection, User user) throws SQLException {
    PreparedStatement pstm = null;
    int updateRows = 0;
    if (connection != null) {
        String sql = "INSERT INTO `smbms_user` (`userCode`,`userName`,`userPassword`," +
                "`gender`,`birthday`,`phone`,`address`,`userRole`,`createdBy`," +
                "`creationDate`) VALUE (?,?,?,?,?,?,?,?,?,?)";
        Object[] params = {user.getUserCode(), user.getUserName(), user.getUserPassword(),
                user.getGender(), user.getBirthday(), user.getPhone(), user.getAddress(),
                user.getUserRole(), user.getCreatedBy(), user.getCreationDate()};
        updateRows = BaseDao.execute(connection, pstm, sql, params);
        BaseDao.closeResource(null, pstm, null);
    }
    return updateRows;
}

/**
 * 根據(jù)id查看用戶
 *
 * @param connection 數(shù)據(jù)庫連接對象
 * @param id         用戶id
 * @return User
 * @throws SQLException
 */
@Override
public User getUserById(Connection connection, int id) throws SQLException {
    PreparedStatement pstm = null;
    ResultSet rs = null;
    User _user = null;
    if (connection != null) {
        String sql = "SELECT u.*,`roleName` userRoleName FROM `smbms_user` u " +
                "INNER JOIN `smbms_role` r ON u.`userRole`= r.`id` WHERE u.`id`=?";
        Object[] params = {id};
        rs = BaseDao.execute(connection, pstm, rs, sql, params);
        while (rs.next()) {
            _user = new User();
            // id必須添加霸奕,否則修改時無法獲取id
            _user.setId(rs.getInt("id"));
            _user.setUserCode(rs.getString("userCode"));
            _user.setUserName(rs.getString("userName"));
            _user.setGender(rs.getInt("gender"));
            _user.setBirthday(rs.getDate("birthday"));
            _user.setPhone(rs.getString("phone"));
            _user.setAddress(rs.getString("address"));
            _user.setUserRole(rs.getInt("userRole"));
            _user.setUserRoleName(rs.getString("userRoleName"));
        }
        BaseDao.closeResource(null, pstm, rs);
    }
    return _user;
}

/**
 * 修改用戶信息
 *
 * @param connection 數(shù)據(jù)庫連接對象
 * @param user       用戶對象
 * @return updateRows
 * @throws SQLException
 */
@Override
public int modify(Connection connection, User user) throws SQLException {
    PreparedStatement pstm = null;
    int updateRows = 0;
    if (connection != null) {
        String sql = "UPDATE `smbms_user` SET `userName`=?,`gender`=?,`birthday`=?," +
                "`phone`=?,`address`=?,`userRole`=?,`modifyBy`=?,`modifyDate`=? WHERE `id`=?";
        Object[] params = {user.getUserName(), user.getGender(), user.getBirthday(),
                user.getPhone(), user.getAddress(), user.getUserRole(),
                user.getModifyBy(), user.getModifyDate(), user.getId()};
        updateRows = BaseDao.execute(connection, pstm, sql, params);
        BaseDao.closeResource(null, pstm, null);
    }
    return updateRows;
}

// 刪除用戶
@Override
public int delUser(Connection connection, int id) throws SQLException {
    PreparedStatement pstm = null;
    int updateRows = 0;
    if (connection != null) {
        String sql = "DELETE FROM `smbms_user` WHERE `id`=?";
        Object[] params = {id};
        updateRows = BaseDao.execute(connection, pstm, sql, params);
        BaseDao.closeResource(null, pstm, null);
    }
    return updateRows;
}
  • UserService 中添加:
// 添加用戶
public boolean add(User user);

// 查詢用戶編碼:用戶登錄login溜宽,也可以實(shí)現(xiàn)功能
public User selectUserCodeExist(String userCode) throws SQLException;

// 根據(jù)id查看用戶
public User getUserById(int id);

// 修改用戶信息
public boolean modify(User user);

// 刪除用戶
public boolean delUser(int id);
  • UserServiceImpl 里添加:
/**
 * 添加用戶
 *
 * @param user 用戶對象
 * @return boolean
 */
@Override
public boolean add(User user) {
    boolean flag = false;
    Connection connection = null;
    try {
        connection = BaseDao.getConnection();
        // 開啟事務(wù)
        connection.setAutoCommit(false);
        int updateRows = userDao.add(connection, user);
        // 提交事務(wù)
        connection.commit();
        if (updateRows > 0) {
            flag = true;
            System.out.println("用戶添加成功");
        } else {
            System.out.println("用戶添加失敗");
        }
    } catch (SQLException e) {
        e.printStackTrace();
        try {
            System.out.println("rollback==========");
            // 手動通知,事務(wù)回滾(可去掉质帅,失敗后自動回滾)
            connection.rollback();
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    } finally {
        BaseDao.closeResource(connection, null, null);
    }
    return flag;
}

/**
 * 查詢用戶編碼是否存在:與login功能相同适揉,可以通用
 *
 * @param userCode 用戶編碼
 * @return User
 */
@Override
public User selectUserCodeExist(String userCode) {
    Connection connection = null;
    User user = null;
    try {
        connection = BaseDao.getConnection();
        user = userDao.getLoginUser(connection, userCode);
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        BaseDao.closeResource(connection, null, null);
    }
    return user;
}

/**
 * 根據(jù)id查看用戶
 *
 * @param id 用戶id
 * @return 用戶對象
 */
@Override
public User getUserById(int id) {
    Connection connection = null;
    User user = null;
    try {
        connection = BaseDao.getConnection();
        user = userDao.getUserById(connection, id);
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        BaseDao.closeResource(connection, null, null);
    }
    return user;
}

/**
 * 修改用戶信息
 *
 * @param user 用戶對象
 * @return boolean
 */
@Override
public boolean modify(User user) {
    boolean flag = false;
    Connection connection = null;
    try {
        connection = BaseDao.getConnection();
        // 開啟事務(wù)
        connection.setAutoCommit(false);
        int updateRows = userDao.modify(connection, user);
        // 提交事務(wù)
        connection.commit();
        if (updateRows > 0) {
            flag = true;
        }
    } catch (SQLException e) {
        e.printStackTrace();
        try {
            // 手動通知事務(wù)回滾
            connection.rollback();
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    } finally {
        BaseDao.closeResource(connection, null, null);
    }
    return flag;
}

/**
 * 刪除用戶
 *
 * @param id 用戶id
 * @return boolean
 */
@Override
public boolean delUser(int id) {
    boolean flag = false;
    Connection connection = null;
    try {
        connection = BaseDao.getConnection();
        // 開啟事務(wù)
        connection.setAutoCommit(false);
        int updateRows = userDao.delUser(connection, id);
        // 提交事務(wù)
        connection.commit();
        if (updateRows > 0) {
            flag = true;
        }
    } catch (SQLException e) {
        e.printStackTrace();
        try {
            // 手動通知事務(wù)回滾
            connection.rollback();
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    } finally {
        BaseDao.closeResource(connection, null, null);
    }
    return flag;
}
  • UserServlet 整合文件:
// 通過注解方式,注冊servlet
@WebServlet("/jsp/user.do")
public class UserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 實(shí)現(xiàn)servlet復(fù)用
        String method = req.getParameter("method");
        // 修改密碼
        if (method.equals("savepwd") && method != null) {
            this.updatePwd(req, resp);
            // 驗(yàn)證舊密碼
        } else if (method.equals("pwdmodify") && method != null) {
            this.pwdModify(req, resp);
            // 用戶管理
        } else if (method.equals("query") && method != null) {
            this.query(req, resp);
            // 添加用戶
        } else if (method.equals("add") && method != null) {
            this.add(req, resp);
            // 角色列表:添加用戶時需獲取
        } else if (method.equals("getrolelist") && method != null) {
            this.getRoleList(req, resp);
            // 查看用戶編碼是否重復(fù)
        } else if (method.equals("ucexist") && method != null) {
            this.userCodeExist(req, resp);
            // 查看用戶
        } else if (method.equals("view") && method != null) {
            this.getUserById(req, resp, "userview.jsp");
            // 修改用戶
        } else if (method.equals("modify") && method != null) {
            this.getUserById(req, resp, "usermodify.jsp");
            // 修改確認(rèn)
        } else if (method.equals("modifyexe") && method != null) {
            this.modify(req, resp);
            // 刪除用戶
        } else if (method.equals("deluser") && method != null) {
            this.delUser(req, resp);
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }

    /**
     * 修改密碼
     *
     * @param req
     * @param resp
     */
    private void updatePwd(HttpServletRequest req, HttpServletResponse resp) {
        // 獲取session
        Object o = req.getSession().getAttribute(Constants.USER_SESSION);
        String newpassword = req.getParameter("newpassword");
        // 設(shè)置標(biāo)志位
        boolean flag = false;
        if (o != null && newpassword != null && newpassword.length() != 0) {
            // 調(diào)用業(yè)務(wù)層
            UserService userService = new UserServiceImpl();
            // 如果修改成功煤惩,返回true
            flag = userService.updatePwd(((User) o).getId(), newpassword);
            if (flag) {
                // 設(shè)置屬性:返回前端
                req.setAttribute("message", "修改密碼成功嫉嘀,請退出,使用新密碼登錄");
                // 移除session
                req.getSession().removeAttribute(Constants.USER_SESSION);
            } else {
                // 密碼修改失敗
                req.setAttribute("message", "修改密碼失敗");
            }
        } else {
            // 密碼有問題
            req.setAttribute("message", "密碼有問題");
        }

        try {
            resp.sendRedirect(req.getContextPath() + "/jsp/pwdmodify.jsp");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Ajax驗(yàn)證舊密碼:與session中的密碼比對
     *
     * @param req
     * @param resp
     */
    private void pwdModify(HttpServletRequest req, HttpServletResponse resp) {
        // 獲取session
        Object o = req.getSession().getAttribute(Constants.USER_SESSION);
        String oldpassword = req.getParameter("oldpassword");
        // 萬能的Map
        Map<String, String> resultMap = new HashMap<>();
        // Session過期
        if (o == null) {
            resultMap.put("result", "sessionerror");
            // 密碼為空
        } else if (StringUtils.isNullOrEmpty(oldpassword)) {
            resultMap.put("result", "error");
            // 密碼不正確
        } else {
            // session中的用戶密碼
            String userPassword = ((User) o).getUserPassword();
            if (userPassword.equals(oldpassword)) {
                resultMap.put("result", "true");
            } else {
                resultMap.put("result", "false");
            }
        }
        // 轉(zhuǎn)換為json類型
        this.toJson(resp, resultMap);
    }

    /**
     * 用戶管理(重點(diǎn)魄揉,難點(diǎn)):查詢
     *
     * @param req
     * @param resp
     */
    private void query(HttpServletRequest req, HttpServletResponse resp) {
        // 查詢用戶列表
        // 從前端獲取數(shù)據(jù)
        String queryUserName = req.getParameter("queryname");
        String temp = req.getParameter("queryUserRole");
        String pageIndex = req.getParameter("pageIndex");
        // 設(shè)置默認(rèn)的用戶角色碼剪侮,避免temp為空
        int queryUserRole = 0;

        // 獲取用戶列表
        UserService userService = new UserServiceImpl();
        List<User> userList = null;

        // 第一次請求,一定是第一頁什猖,頁面大小固定
        // 頁面大衅北搿:可以寫配置文件,方便以后修改
        int pageSize = 5;
        // 默認(rèn)起始頁面
        int currentPageNo = 1;

        if (queryUserName == null) {
            queryUserName = "";
        }
        if (temp != null && !temp.equals("")) {
            // 給查詢賦值 0不狮、1降铸、2、3
            queryUserRole = Integer.parseInt(temp);
        }
        if (pageIndex != null) {
            try {
                currentPageNo = Integer.parseInt(pageIndex);
            } catch (NumberFormatException e) {
                e.printStackTrace();
            }
        }

        // 獲取用戶的總數(shù)(分頁:上一頁摇零、下一頁)
        int totalCount = userService.getUserCount(queryUserName, queryUserRole);
        // 總頁數(shù)支持
        PageSupport pageSupport = new PageSupport();
        pageSupport.setCurrentPageNo(currentPageNo);
        pageSupport.setPageSize(pageSize);
        // 通過查詢記錄總數(shù)推掸,計(jì)算總頁面數(shù)
        pageSupport.setTotalCount(totalCount);

        // 控制首頁和尾頁
        // 總頁面數(shù)
        int totalPageCount = pageSupport.getTotalPageCount();
        // 如果當(dāng)前頁面小于1,就顯示第一頁
        if (currentPageNo < 1) {
            currentPageNo = 1;
            // 如果當(dāng)前頁面大于最后一頁驻仅,就顯示最后一頁
        } else if (currentPageNo > totalPageCount) {
            currentPageNo = totalPageCount;
        }

        // 獲取用戶列表展示
        userList = userService.getUserList(queryUserName, queryUserRole, currentPageNo, pageSize);
        // 把用戶列表傳遞給前端
        req.setAttribute("userList", userList);

        // 獲取角色列表
        RoleServiceImpl roleService = new RoleServiceImpl();
        List<Role> roleList = roleService.getRoleList();
        // 把角色列表傳遞給前端
        req.setAttribute("roleList", roleList);

        // 給前端傳遞其它屬性
        req.setAttribute("totalCount", totalCount);
        req.setAttribute("currentPageNo", currentPageNo);
        req.setAttribute("totalPageCount", totalPageCount);
        req.setAttribute("queryUserName", queryUserName);
        req.setAttribute("queryUserRole", queryUserRole);

        // 返回前端頁面
        try {
            req.getRequestDispatcher("userlist.jsp").forward(req, resp);
        } catch (ServletException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 添加用戶:(需先獲取角色列表)
     *
     * @param req
     * @param resp
     * @throws IOException
     * @throws ServletException
     */
    private void add(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
        // 從前端獲取屬性
        String userCode = req.getParameter("userCode");
        String userName = req.getParameter("userName");
        String userPassword = req.getParameter("userPassword");
        String gender = (req.getParameter("gender"));
        String birthday = req.getParameter("birthday");
        String phone = req.getParameter("phone");
        String address = req.getParameter("address");
        String userRole = req.getParameter("userRole");

        // 創(chuàng)建用戶對象谅畅,將前端的值存儲到對象中
        User user = new User();
        user.setUserCode(userCode);
        user.setUserName(userName);
        user.setUserPassword(userPassword);
        user.setGender(Integer.valueOf(gender));
        try {
            user.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse(birthday));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        user.setPhone(phone);
        user.setAddress(address);
        user.setUserRole(Integer.valueOf(userRole));
        user.setCreationDate(new Date());
        user.setCreatedBy(((User) req.getSession().getAttribute(Constants.USER_SESSION)).getId());

        // 調(diào)用業(yè)務(wù)層
        UserService userService = new UserServiceImpl();
        if (userService.add(user)) {
            resp.sendRedirect(req.getContextPath() + "/jsp/user.do?method=query");
        } else {
            req.getRequestDispatcher("useradd.jsp").forward(req, resp);
        }
    }

    /**
     * 獲取角色列表
     *
     * @param req
     * @param resp
     * @throws IOException
     */
    private void getRoleList(HttpServletRequest req, HttpServletResponse resp) {
        List<Role> roleList = null;
        RoleService roleService = new RoleServiceImpl();
        roleList = roleService.getRoleList();
        // 把roleList轉(zhuǎn)換成json對象輸出
        this.toJson(resp, roleList);
    }

    /**
     * 查看用戶編碼是否重復(fù)
     *
     * @param req
     * @param resp
     * @throws IOException
     */
    private void userCodeExist(HttpServletRequest req, HttpServletResponse resp) {
        String userCode = req.getParameter("userCode");
        Map<String, String> resultMap = new HashMap<>();
        if (StringUtils.isNullOrEmpty(userCode)) {
            resultMap.put("userCode", "exist");
        } else {
            UserService userService = new UserServiceImpl();
            User user = null;
            // 調(diào)用業(yè)務(wù)層
            // user = userService.selectUserCodeExist(userCode);
            // 業(yè)務(wù)層的login方法,功能相同
            user = userService.login(userCode, null);
            if (user != null) {
                resultMap.put("userCode", "exist");
            } else {
                resultMap.put("userCode", "notexist");
            }
        }
        // 轉(zhuǎn)換為Json
        this.toJson(resp, resultMap);
    }

    /**
     * 轉(zhuǎn)換為Json類型
     *
     * @param resp
     * @param object 需要轉(zhuǎn)換的對象
     */
    private void toJson(HttpServletResponse resp, Object object) {
        // 返回json類型
        resp.setContentType("application/json");
        try {
            // 輸出流
            PrintWriter writer = resp.getWriter();
            // JSONArray工具類噪服,轉(zhuǎn)換格式
            // 將結(jié)果集毡泻,以json格式返回
            writer.write(JSONArray.toJSONString(object));
            // 刷新
            writer.flush();
            // 關(guān)閉流
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 根據(jù)id查看用戶
     *
     * @param req
     * @param resp
     * @param url  跳轉(zhuǎn)網(wǎng)頁地址
     * @throws ServletException
     * @throws IOException
     */
    private void getUserById(HttpServletRequest req, HttpServletResponse resp, String url) throws ServletException, IOException {
        String id = req.getParameter("uid");
        // id不為空
        if (!StringUtils.isNullOrEmpty(id)) {
            UserService userService = new UserServiceImpl();
            User user = userService.getUserById(Integer.parseInt(id));
            req.setAttribute("user", user);
            req.getRequestDispatcher(url).forward(req, resp);
        }
    }

    /**
     * 修改用戶信息
     *
     * @param req
     * @param resp
     */
    private void modify(HttpServletRequest req, HttpServletResponse resp) {
        String id = req.getParameter("uid");
        String userName = req.getParameter("userName");
        String gender = req.getParameter("gender");
        String birthday = req.getParameter("birthday");
        String phone = req.getParameter("phone");
        String address = req.getParameter("address");
        String userRole = req.getParameter("userRole");

        User user = new User();
        user.setId(Integer.valueOf(id));
        user.setUserName(userName);
        user.setGender(Integer.valueOf(gender));
        try {
            user.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse(birthday));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        user.setPhone(phone);
        user.setAddress(address);
        user.setUserRole(Integer.valueOf(userRole));
        user.setModifyBy(((User) req.getSession().getAttribute(Constants.USER_SESSION)).getId());
        user.setModifyDate(new Date());

        UserService userService = new UserServiceImpl();
        if (userService.modify(user)) {
            try {
                resp.sendRedirect(req.getContextPath() + "/jsp/user.do?method=query");
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            try {
                req.getRequestDispatcher("usermodify.jsp").forward(req, resp);
            } catch (ServletException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    // 刪除用戶
    private void delUser(HttpServletRequest req, HttpServletResponse resp) {
        String id = req.getParameter("uid");
        Map<String, String> resultMap = new HashMap<>();
        if (StringUtils.isNullOrEmpty(id)) {
            resultMap.put("delResult", "notexist");
        } else {
            UserService userService = new UserServiceImpl();
            if (userService.delUser(Integer.parseInt(id))) {
                resultMap.put("delResult", "true");
            } else {
                resultMap.put("delResult", "false");
            }
        }
        // 轉(zhuǎn)換為Json
        this.toJson(resp, resultMap);
    }
}

六、其它模塊

  • 參照用戶模塊

  • 項(xiàng)目流程圖

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末粘优,一起剝皮案震驚了整個濱河市仇味,隨后出現(xiàn)的幾起案子呻顽,更是在濱河造成了極大的恐慌,老刑警劉巖丹墨,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件廊遍,死亡現(xiàn)場離奇詭異,居然都是意外死亡贩挣,警方通過查閱死者的電腦和手機(jī)喉前,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來王财,“玉大人卵迂,你說我怎么就攤上這事∪蘧唬” “怎么了狭握?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長疯溺。 經(jīng)常有香客問我论颅,道長,這世上最難降的妖魔是什么囱嫩? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任恃疯,我火速辦了婚禮,結(jié)果婚禮上墨闲,老公的妹妹穿的比我還像新娘今妄。我一直安慰自己,他們只是感情好鸳碧,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布盾鳞。 她就那樣靜靜地躺著,像睡著了一般瞻离。 火紅的嫁衣襯著肌膚如雪腾仅。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天套利,我揣著相機(jī)與錄音推励,去河邊找鬼。 笑死肉迫,一個胖子當(dāng)著我的面吹牛验辞,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播喊衫,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼跌造,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了族购?” 一聲冷哼從身側(cè)響起壳贪,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤财著,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后撑碴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡朝墩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年醉拓,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片收苏。...
    茶點(diǎn)故事閱讀 38,814評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡亿卤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鹿霸,到底是詐尸還是另有隱情排吴,我是刑警寧澤,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布懦鼠,位于F島的核電站钻哩,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏肛冶。R本人自食惡果不足惜街氢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望睦袖。 院中可真熱鬧珊肃,春花似錦、人聲如沸馅笙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽董习。三九已至烈和,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間皿淋,已是汗流浹背斥杜。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留沥匈,地道東北人蔗喂。 一個月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像高帖,于是被迫代替她去往敵國和親缰儿。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評論 2 351

推薦閱讀更多精彩內(nèi)容