簡單的SSH整合(基於註解和xml文件的配置)

SSH(SpringMVC,Spring,Hibernate)簡單整合的配置(基於註解和xml文件配置),附帶用戶登陸註冊的簡單實現

1.開發環境

Eclipse
Maven插件
JDK1.8
MySQL5.7

2.項目目錄結構

這裏寫圖片描述

3.項目依賴的jar包(pom.xml配置文件-基於Maven)

<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>com.lyx</groupId>
    <artifactId>1011house</artifactId>
    <version>1.0.0</version>
    <packaging>war</packaging>

    <dependencies>
        <!-- 單元測試 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!-- servlet的api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <!-- servlet的jsp -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.1</version>
            <scope>provided</scope>
        </dependency>
        <!-- jstl(標準標籤庫的) -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <!-- hibernate的依賴包 -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>5.2.10.Final</version>
        </dependency>
        <!-- mysql驅動依賴包 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.40</version>
        </dependency>
        <!-- DBCP2連接池 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-dbcp2</artifactId>
            <version>2.1.1</version>
        </dependency>
        <!-- 主要是生成MD5摘要的工具(數據庫庫存儲密碼時) -->
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.10</version>
        </dependency>
        <!-- 阿里巴巴的fastJSON工具 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.39</version>
        </dependency>
        <!-- SpringMVC -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.3.10.RELEASE</version>
        </dependency>
        <!-- Spring-orm框架(主要用於整合其他的ormolu框架) -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>4.3.10.RELEASE</version>
        </dependency>
        <!-- Spring的單元測試 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>4.3.10.RELEASE</version>
            <scope>test</scope>
        </dependency>
        <!-- SpringAOP的依賴包(自己寫切面時需要) -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.10</version>
        </dependency>
        <!-- SpringAOP的依賴包(自己寫切面時需要) -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.10</version>
        </dependency>
        <!-- 前臺提交的數據在服務器端進行驗證 -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.4.1.Final</version>
        </dependency>
        <!-- jackson(SpringMVC返回對象被轉換成JSON數據格式時底層依賴的對象轉JSON工具類) -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.2.0</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

4.Spring整合hibernate的配置文件(Spring.xml)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!-- <bean id="userDaoCloud" class="com.lyx.spring.persistence.imp.UserDaoCloudImpl"/>
    <bean id="userDaoDb" class="com.lyx.spring.persistence.imp.UserDaoDbImpl"/>

    <bean id="userService" class="com.lyx.spring.service.impl.UserServiceImpl">
        <property name="userDao" ref="userDaoDb"></property>
    </bean> -->

    <!-- Spring掃包(將打了@Repository,@Service註解的類納入IoC容器進行管理) -->
    <context:component-scan base-package="com.lyx.house">
        <!-- 排除掉控制層 -->
        <context:exclude-filter type="annotation" 
            expression="org.springframework.stereotype.Controller"/>
        <context:exclude-filter type="annotation" 
            expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
    </context:component-scan>
    <!-- 表示基於註解配置Spring -->
    <context:annotation-config/>

    <!-- 配置連接池 DBCP2/C3P0/Druid(該處使用的DBCP2) -->
    <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close"> 
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/house"></property>
        <property name="username" value="root"></property>
        <property name="password" value="951112"></property>
        <property name="initialSize" value="10"></property>
        <property name="maxTotal" value="100"></property>
        <property name="maxWaitMillis" value="5000"></property>
    </bean>

    <!-- 配置hibernate的一些東西(SessionFactory,Spring包裝過的) -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="packagesToScan" value="com.lyx.house.domain"></property>
        <property name="hibernateProperties">
            <value>
                hibernate.dialect=org.hibernate.dialect.MySQL57Dialect
                hibernate.show_sql=true
                hibernate.format_sql=true
                <!-- javax.persistence.validation.mode=none 讓hibernate不驗證實體類上validation的註解 -->
                <!-- hibernate.current_session_context_class=thread     聲明式事務去掉該行配置-->
            </value>
        </property>
    </bean>

    <!-- 使用spring的事務切面 -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"></property>
    </bean>

    <!-- 配置聲明式事務(打註解-@Transaction-業務層-事務腳本模式) -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

    <!-- 自己寫的切面代理(通過自動生成代理) -->
    <!-- <aop:aspectj-autoproxy></aop:aspectj-autoproxy> -->
</beans>

5.web.xml 配置文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    id="WebApp_ID" version="3.1">

    <!-- 配置前端控制器(門面模式) -->
    <servlet>
        <servlet-name>frontController</servlet-name>    <!-- 與SpringMVC配置文件的前半截名字保持一致 -->
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>    <!-- 服務器一啓動就實例化控制器 -->
        <multipart-config />    <!-- 原生的支持文件上傳 -->
    </servlet>
    <servlet-mapping>
        <servlet-name>frontController</servlet-name>
        <url-pattern>/</url-pattern>    <!-- 一定要寫斜槓(所有請求交給前端控制器) -->
    </servlet-mapping>

    <!-- 指定Spring配置文件的路徑 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>  <!-- 名字必須該名字,一字不差 -->
        <param-value>classpath:spring.xml</param-value> <!-- spring.xml-Spring配置文件的名字 -->
    </context-param>

    <!-- 配置監聽器-服務器一啓動就啓動Spring IoC容器(Spring的IoC容器) -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- 配置編碼過濾器 -->
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>   <!-- 必須是該名字 -->
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- 配置發生異常跳轉的頁面 -->
    <error-page>
        <error-code>404</error-code>
        <location>/404.html</location>
    </error-page>
    <!-- 發生錯誤跳轉的頁面 -->
    <!-- <error-page>
        <exception-type>java.lang.Throwable</exception-type>
        <location>/error.jsp</location>
    </error-page> -->

    <display-name>1011house</display-name>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

7.SpringMVC的配置文件-frontController-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 配置攔截器(攔截請求,例如沒登陸的不放行) -->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/toPublish" />
            <mvc:mapping path="/doPublish" />
            <bean class="com.lyx.house.interceptor.LoginInterceptor" />
        </mvc:interceptor>
    </mvc:interceptors>

    <!-- 掃包  在該包及子包下搜索被@Controller註解標記的控制器(納入SpringMVC的IoC容器) -->
    <context:component-scan base-package="com.lyx.house.controller" />
    <!-- <context:annotation-config/> 表示基於註解配置(這裏寫不寫無所謂) -->

    <!-- 通過註解驅動SpringMVC -->
    <mvc:annotation-driven>
        <mvc:message-converters>
            <!-- 消息轉換器(需要註解@ResponseBody),把返回的東西經過轉換放入迴應的消息體中 -->
            <!-- 將圖片輸出流經過轉換放入迴應的消息體中(需要設置MIME類型-資源的媒體類型) -->
            <bean class="org.springframework.http.converter.BufferedImageHttpMessageConverter"/>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
            <!-- 將返回的對象轉換成JSOn數據格式(底層通過Jackson工具類轉換實現) -->
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
        </mvc:message-converters>
    </mvc:annotation-driven>

    <!-- 配置使用應用服務器默認的Servlet處理靜態資源(像放入WEB-INF的jsp需要導入css,js,圖片之類的資源) -->
    <mvc:default-servlet-handler />

    <!-- 配置JSP的視圖解析器(相當於給控制器返回的視圖名字加上前綴和後綴) -->
    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"></property>
        <property name="suffix" value=".jsp"></property>
        <!-- 視圖解析器的優先級 -->
        <property name="order" value="10"></property>
        <!-- 配置jsp的標準標籤庫 -->
        <property name="viewClass"
            value="org.springframework.web.servlet.view.JstlView"></property>
    </bean>
    <!-- freemarker的視圖解析器 -->
    <bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
        <property name="contentType" value="text/html;charset=utf-8"/>
        <property name="cache" value="true" />
        <property name="prefix" value="" />
        <property name="suffix" value=".ftl" />
        <property name="order" value="5"/>
    </bean>

    <!-- 配置上傳文件的視圖解析器 -->
    <!-- Servlet 3 - StandardServletMultipartResolver -->
    <!-- Apache Commons FileUpload - CommonsMultipartResolver -->
    <!-- 如果使用Servlet 3原生的文件上傳支持那麼需要在配置DispatcherServlet時指定multipart-config -->
    <!-- 如果使用Apache的Commons-FileUpload那麼需要在依賴項中加入commons-fileupload的jar文件 -->
    <bean id="multipartResolver"
        class="org.springframework.web.multipart.support.StandardServletMultipartResolver">
    </bean>

</beans>

8.模型層(實體類)

User.java

package com.lyx.house.domain;

import java.io.Serializable;

import javax.persistence.Column;  //用官方JPA,不要耦合Hibernate
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity // 表示實體類(一個要持久化的類)
@Table(name = "tb_user") // 對應的表名稱
public class User implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id // 標誌字段(即數據庫中一張表的主鍵字段)
    @Column(name = "userid") // 對應的字段名稱
    @GeneratedValue(strategy = GenerationType.IDENTITY) // 生成策越(自動增長)
    private Integer id;
    private String username;
    private String password;
    private String realname;
    private String tel;
    @Column(name = "isadmin")
    private Boolean admin; // 是否是管理員 false 不是,true 是

    public User() {
        super();
    }

    public User(String username, String password, String realname, String tel, Boolean admin) {
        super();
        this.username = username;
        this.password = password;
        this.realname = realname;
        this.tel = tel;
        this.admin = admin;
    }

    public Integer getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getRealname() {
        return realname;
    }

    public void setRealname(String realname) {
        this.realname = realname;
    }

    public String getTel() {
        return tel;
    }

    public void setTel(String tel) {
        this.tel = tel;
    }

    public Boolean getAdmin() {
        return admin;
    }

    public void setAdmin(Boolean admin) {
        this.admin = admin;
    }
}

LoginLog.java

package com.lyx.house.domain;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = "tb_login_log")
public class LoginLog implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "loginid")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    @ManyToOne // 表示多對一關係,外鍵列(對應User實體的主鍵-即User實體的id字段)
    @JoinColumn(name = "user_id")   //外鍵列在數據庫中的名字"user_id"
    private User user;
    @Column(name = "ipaddr")
    private String ipAddress;// 登陸的ip地址
    private Date logDate;

    public LoginLog() {
        super();
    }

    public LoginLog(User user, String ipAddress, Date logDate) {
        super();
        this.user = user;
        this.ipAddress = ipAddress;
        this.logDate = logDate;
    }

    public Integer getId() {
        return id;
    }

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

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public String getIpAddress() {
        return ipAddress;
    }

    public void setIpAddress(String ipAddress) {
        this.ipAddress = ipAddress;
    }

    public Date getLogDate() {
        return logDate;
    }

    public void setLogDate(Date logDate) {
        this.logDate = logDate;
    }
}

9.DAO層(持久層)的簡單實例

這裏寫圖片描述

BaseDao.java

package com.lyx.house.persistence;

import java.io.Serializable;
import java.util.List;

/**
 * 基本的增刪改查功能
 * @author Administrator
 * @param <E> 實體類型
 * @param <K> 標識字段(主鍵類型)
 */
public interface BaseDao<E,K extends Serializable>{

    /**
     * 保存一個實體
     * @param entity 要保存的實體
     * @return 主鍵
     */
    K save(E entity);

    void delete(E entity);

    /**
     * 刪除 根據主鍵
     * @param id 主鍵
     * @return 是否刪除(真-刪除)
     */
    boolean deleteById(K id);

    /**
     * 更新一個實體
     * @param entity 要更新的實體
     * @return 更新後的實體
     */ 
    E update(E entity);

    /**
     * 查找一個實體,根據主鍵
     * @param id 主鍵
     * @return 找到的實體
     */
    E findById(K id);

    /**
     * 查找所有
     * @return 裝着所有實體的集合
     */
    List<E> findAll();
}

BaseDaoAdapter.java

package com.lyx.house.persistence.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.Collections;
import java.util.List;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.lyx.house.persistence.BaseDao;

public abstract class BaseDaoAdapter<E,K extends Serializable> implements BaseDao<E, K>{

    @Autowired  //Hibernate的自動注入
    protected SessionFactory sessionFactroy;

    private Class<E> entityType;
    private String entityName;

    @SuppressWarnings("unchecked")
    protected BaseDaoAdapter() {
        ParameterizedType pt=(ParameterizedType) this.getClass().getGenericSuperclass();
        entityType=(Class<E>) pt.getActualTypeArguments()[0];
        entityName=entityType.getSimpleName();
    }

    @SuppressWarnings("unchecked")
    @Override
    public K save(E entity) {
        return (K) sessionFactroy.getCurrentSession().save(entity);
    }

    @Override
    public void delete(E entity) {
        sessionFactroy.getCurrentSession().delete(entity);
    }

    @Override
    public boolean deleteById(K id) {
        return sessionFactroy.getCurrentSession().
            createQuery("delete from "+entityName+" as o where o.id=:id").
            setParameter("id", id).
            executeUpdate()==1;
    }

    @SuppressWarnings("unchecked")
    @Override
    public E update(E entity) {
        return (E) sessionFactroy.getCurrentSession().merge(entity);
    }

    @Override
    public E findById(K id) {
        return sessionFactroy.getCurrentSession().get(entityType, id);
    }

    @Override
    public List<E> findAll() {
        List<E> entities = sessionFactroy.getCurrentSession().
                createQuery("from "+entityName,entityType).getResultList();
        return entities.size()>0?entities:Collections.emptyList();
    }
}

UserDAO.java

package com.lyx.house.persistence;

import com.lyx.house.domain.User;

public interface UserDao extends BaseDao<User, Integer>{

    /**
     * 登陸  根據用戶名(還可以檢查用戶名是否唯一)
     * @param username
     * @return 查到的實體
     */
    User findByUsername(String username);
}

UserDaoImpl.java

package com.lyx.house.persistence.impl;

import java.util.List;

import org.springframework.stereotype.Repository;

import com.lyx.house.domain.User;
import com.lyx.house.persistence.UserDao;

@Repository //納入SpringIoC容器
public class UserDaoImpl extends BaseDaoAdapter<User, Integer> implements UserDao{

    //其中的sessionFactory繼承於抽象類(被自動注入了的)

    @Override
    public User findByUsername(String username) {
        List<User> userList= sessionFactroy.getCurrentSession()
                .createQuery("from User as u where u.username=:username",User.class).
                setParameter("username", username).
                getResultList();
        return userList.size()==1?userList.get(0):null;
    }
}

10.數據傳輸對象

UserLoginDto.java

package com.lyx.house.dto;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

//用戶登陸時,接收數據的數據傳輸實體
public class UserLoginDto {

    @Pattern(regexp = "\\w{6,20}") // 數據提交到後臺的驗證(底層依賴SpringMVC實現)
    private String username;
    @Size(min = 6) // 數據提交到後臺的驗證
    private String password;
    @NotNull // 數據提交到後臺的驗證
    private String code;
    private String ipAddress;
    private Integer id;
    private String realname;

    public UserLoginDto() {
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public void setIpAddress(String ipAddress) {
        this.ipAddress = ipAddress;
    }

    public String getIpAddress() {
        return ipAddress;
    }

    public Integer getId() {
        return id;
    }

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

    public String getRealname() {
        return realname;
    }

    public void setRealname(String realname) {
        this.realname = realname;
    }
}

11.業務層

這裏寫圖片描述

UserService.java

package com.lyx.house.service;

import com.lyx.house.dto.UserLoginDto;
import com.lyx.house.dto.UserRegisterDto;

public interface UserService {

    /**
     * 用戶登錄
     * @param userLoginDto
     * @return
     */
    boolean login(UserLoginDto userLoginDto);

    /**
     * 用戶註冊
     * @param userRegisterDto 
     * @return
     */
    boolean register(UserRegisterDto userRegisterDto);

    /**
     * 檢查用戶名是否存在
     * @param username 用戶名
     * @return  存在返回false,不存在返回true(可以註冊)
     */
    boolean checkUsername(String username);
}

UserServiceImpl.java

package com.lyx.house.service.impl;

import java.util.Date;

import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.lyx.house.domain.LoginLog;
import com.lyx.house.domain.User;
import com.lyx.house.dto.UserLoginDto;
import com.lyx.house.dto.UserRegisterDto;
import com.lyx.house.persistence.LoginLogDao;
import com.lyx.house.persistence.UserDao;
import com.lyx.house.service.UserService;

@Service    //納入SpringIoC容器
@Transactional  //Spring的事務切面(事務腳本模式-用戶的一個操作對應一個方法-一個方法即一個事務)
public class UserServiceImpl implements UserService{

    @Autowired  //Spring自動注入
    private UserDao userDao;
    @Autowired
    private LoginLogDao loginLogDao;

    @Override
    public boolean login(UserLoginDto userLoginDto) {
        boolean flag=false;
        User temp=userDao.findByUsername(userLoginDto.getUsername());
        if (temp!=null) {
            String md5=DigestUtils.md5Hex(userLoginDto.getPassword());
            if (temp.getPassword().equals(md5)) {
                LoginLog loginLog=new LoginLog(temp, userLoginDto.getIpAddress(), new Date());
                if (loginLogDao.save(loginLog)!=null) {
                    userLoginDto.setId(temp.getId());
                    userLoginDto.setRealname(temp.getRealname());
                    flag=true;
                }
            }
        }
        return flag;
    }

    @Override
    public boolean register(UserRegisterDto userRegisterDto) {
        User temp=userDao.findByUsername(userRegisterDto.getUsername());
        if (temp==null) {
            String md5=DigestUtils.md5Hex(userRegisterDto.getPassword());
            User user=new User(userRegisterDto.getUsername(), 
                    md5,
                    userRegisterDto.getRealname(), 
                    userRegisterDto.getTel(), 
                    false);
            return userDao.save(user)!=null;
        }
        return false;
    }

    @Override
    public boolean checkUsername(String username) {
        return userDao.findByUsername(username)==null;
    }
}

11.控制層

ResourceDispatcherController.java

package com.lyx.house.controller;

import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.lyx.house.util.CommonUtil;

@Controller     //交給SpringMVC管理
// @RequestMapping("/") //類路徑映射-多級路徑
public class ResourceDispatcherController {

    private static final int CODE_LENGTH = 4;

    /*
     * 設置首頁
     */
    //Get請求
    @GetMapping({ "/toHome", "/" }) // 多個映射指向同一個資源("/"默認首頁)
    public String toIndex() {
        return "index";
    }

    /*
     * 登陸頁面
     */
    // @RequestMapping(value="/toLogin",method=RequestMethod.GET)
    @GetMapping("toLogin")
    public ModelAndView toLogin() {
        ModelAndView mav = new ModelAndView();
        mav.setViewName("login");
        mav.addObject("hint", "歡迎您的登陸!!!");
        return mav;
    }

    /*
     * 註冊頁面
     */
    @GetMapping("/toRegister")
    public String toRegister(Model model) {
        model.addAttribute("hint", "歡迎您的註冊!!!");
        return "register";
    }

    /*
     * 發佈房源的頁面
     */
    @GetMapping("/toPublish")
    public String toPublish() {
        return "pub";
    }

    @GetMapping(value="/getCodeImage",produces="image/png") //produces配置MIME類型(資源的媒體類型)
    @ResponseBody
    public BufferedImage getCode(HttpSession session) throws IOException {
        String code = CommonUtil.generateCode(CODE_LENGTH);
        session.setAttribute("code", code);
        return CommonUtil.generateCodeImage(code, 80, 30);
//      response.setContentType("image/png");
//      BufferedImage bi = CommonUtil.generateCodeImage(code, 80, 30);
//      ImageIO.write(bi, "PNG", response.getOutputStream());
    }
}

UserController.java

package com.lyx.house.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.lyx.house.dto.CheckResult;
import com.lyx.house.dto.UserLoginDto;
import com.lyx.house.dto.UserRegisterDto;
import com.lyx.house.service.UserService;

@Controller
public class UserController {

    @Autowired  //自動注入
    private UserService userService;

    /*
     * 用戶登錄
     */
    @PostMapping("/doLogin")
    public String doLogin(@Valid UserLoginDto userLoginDto,Errors errors,HttpServletRequest request) {
        String viewName="login";
        if (request.getSession().getAttribute("code").toString().equalsIgnoreCase(userLoginDto.getCode())) {
            request.getSession().removeAttribute("code");
            if (!errors.hasErrors()) {
                userLoginDto.setIpAddress(request.getRemoteAddr());
                if (userService.login(userLoginDto)) {
                    request.getSession().setAttribute("userId", userLoginDto.getId());
                    request.getSession().setAttribute("userRealname", userLoginDto.getRealname());
                    viewName="redirect:toHome";
                } else {
                    request.setAttribute("hint", "用戶名或密碼錯誤,請重新登陸!!!");
                }
            }else {
                request.setAttribute("hint", "MMP,能不能好好填寫登陸信息!!!");
            }
        } else {
            request.setAttribute("hint", "驗證碼錯誤!!!");
            request.setAttribute("codeHint", "X");
        }
        return viewName;
    }

    /*
     * 用戶註冊
     */
    @PostMapping("/doRegister")
    public String doRegister(@Valid UserRegisterDto userRegisterDto,Errors errors,HttpServletRequest request) {
        String viewName="register";
        if (request.getSession().getAttribute("code").toString().equalsIgnoreCase(userRegisterDto.getCode())) {
            request.getSession().removeAttribute("code");
            if (!errors.hasErrors()) {
                if (userService.register(userRegisterDto)) {
                    viewName="redirect:toLogin";
                } else {
                    request.setAttribute("hint", "註冊失敗!!!請重新註冊!!!");
                }
            }else if(userRegisterDto.getPassword().equals(userRegisterDto.getRepassword())){
                request.setAttribute("hint", "MMP,能不能好好填寫註冊信息");
            }else{
                request.setAttribute("hint", "MMP,能不能填好好寫註冊信息");
            }
        } else {
            request.setAttribute("hint", "驗證碼錯誤!!!");
            request.setAttribute("codeHint", "X");
        }
        return viewName;
    }


    /*
     * 檢查用戶名的唯一性(Ajax操作)
     */
    @GetMapping("doCheck")
    @ResponseBody
    public CheckResult doCheckUsername(String username) {
        boolean valid=userService.checkUsername(username);
        return new CheckResult(username,valid, valid?"可以註冊":"已被佔用", valid?"ok.png":"no.png");
    }

    /*
     * 註銷登錄
     */
    @GetMapping("/doLogout")
    public String doLogout(HttpSession session) {
        session.removeAttribute("userId");
        session.removeAttribute("userRealname");
        return "redirect:toHome";
    }
}

MyExceptionAdive.java

package com.lyx.house.controller;

import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice   //配置服務器控制層拋出異常或錯誤時的處理(跳轉到指定頁面-用戶最小驚訝原則-不要抱異常或錯誤拋到頁面給用戶看)
public class MyExceptionAdvice {

    @ExceptionHandler({Exception.class})    //發生哪些異常
    public String toException(Model model) {
        return "error/hint";
    }
}

12.用到的工具類

CommonUtil.java

package com.lyx.house.util;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

import javax.imageio.ImageIO;

public final class CommonUtil {
    private static final String ALL_CHAR = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

    private CommonUtil() {
        throw new AssertionError();
    }

    /**
     * 生成[min, max)範圍的隨機整數
     * @param min 下限值(閉區間)
     * @param max 上限值(開區間)
     * @return 隨機整數
     */
    public static int getRandomInt(int min, int max) {
        return (int) (Math.random() * (max - min) + min);
    }

    /**
     * 生成隨機碼
     * @param length 隨機碼的長度
     * @return
     */
    public static String generateCode(int length) {
        String code = ALL_CHAR;
        StringBuilder targetCode = new StringBuilder();
        for (int i = 0; i < length; i++) {
            int index = getRandomInt(0, 62);
            targetCode.append(code.charAt(index));
        }
        return targetCode.toString();
    }

    /**
     * 根據隨機碼生成模糊圖片
     * @param code 隨機碼
     * @param width
     * @param height
     * @return
     */
    public static BufferedImage generateCodeImage(String code, int width, int height) {
        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
        Graphics g = bi.getGraphics();
        g.setColor(new Color(getRandomInt(0, 256), getRandomInt(0, 256), getRandomInt(0, 256)));
        g.fillRect(0, 0, width, height);
        int size = (width - 10) / code.length();
        g.setFont(new Font("Arial", Font.BOLD, size));
        for (int i = 0; i < code.length(); i++) {
            g.setColor(new Color(getRandomInt(0, 256), getRandomInt(0, 256), getRandomInt(0, 256)));
            String currentChar = code.substring(i, i + 1);
            g.drawString(currentChar, 5 + size * i, height / 2);
        }
        // 干擾線
        for (int i = 0; i < 12; i++) {
            g.setColor(new Color(getRandomInt(0, 256), getRandomInt(0, 256), getRandomInt(0, 256)));
            g.drawLine(getRandomInt(0, 60), getRandomInt(0, 30), getRandomInt(0, 60), getRandomInt(0, 30));
        }
        g.dispose();// 圖片生成
        return bi;
    }

    /**
     * 字符串日期轉換成Date對象
     * @param 指定的日期格式
     * @param 字符串日期
     * @return Date對象
     */
    public static Date stringToDate(String pattern, String str) {
        SimpleDateFormat myFormat = new SimpleDateFormat(pattern);
        try {
            return myFormat.parse(str);
        } catch (ParseException e) {
            throw new RuntimeException("字符串轉日期格式出錯!!!", e);
        }
    }

    /**
     * 日期轉換成指定的字符串形式
     * @param 日期格式
     * @param 具體日期
     * @return 日期的字符串形式
     */
    public static String dateToString(String pattern, Date date) {
        SimpleDateFormat myFormat = new SimpleDateFormat(pattern);
        return myFormat.format(date);
    }

    /**
     * 取得文件後綴名
     * @param 文件名
     * @return 文件後綴名
     */
    public static String getFilenameSuffix(String fileName) {
        int index = fileName.lastIndexOf(".");
        return index > 0 && index < fileName.length() - 1 ? fileName.substring(index) : "";
    }

    /**
     * 隨機生成文件名(全局唯一)
     * @return 隨機文件名
     */
    public static String getRadomFilename() {
        return UUID.randomUUID().toString();
    }

    /**
     * 上傳圖片並壓縮(全部轉換成PNG格式)
     * 
     * @param inputStream 圖片二進制流
     * @param filePath 文件要存儲的路徑
     * @param width 寬度(高度自適應)
     * @throws IOException
     */
    public static void imgUploadCompress(InputStream inputStream, String filePath, int width) throws IOException {
        File file = new File(filePath);
        BufferedImage oldImage = ImageIO.read(inputStream);
        int oldWidth = oldImage.getWidth();
        double ratio = (double) width / (double) oldWidth;
        int newHeight = (int) (oldImage.getHeight() * ratio);
        // System.out.println("比例="+ratio+"--高="+newHeight);
        BufferedImage newImage = new BufferedImage(width, newHeight, BufferedImage.TYPE_INT_RGB);
        newImage.getGraphics().drawImage(oldImage, 0, 0, width, newHeight, null);
        ImageIO.write(newImage, "PNG", file);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章