Spring的HelloWorld示例

数据库准备

-- MySQL dump 10.13  Distrib 8.0.27, for Win64 (x86_64)
--
-- Host: 127.0.0.1    Database: spring
-- ------------------------------------------------------
-- Server version	8.0.27

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!50503 SET NAMES utf8mb4 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

--
-- Table structure for table `login_log`
--

DROP TABLE IF EXISTS `login_log`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `login_log` (
  `id` int NOT NULL AUTO_INCREMENT,
  `user_id` int DEFAULT NULL COMMENT '用户id',
  `ip` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '登录IP',
  `create_time` datetime DEFAULT NULL COMMENT '登录时间',
  `update_time` datetime DEFAULT NULL,
  `status` int DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='登录日志';
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `login_log`
--

LOCK TABLES `login_log` WRITE;
/*!40000 ALTER TABLE `login_log` DISABLE KEYS */;
/*!40000 ALTER TABLE `login_log` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `user`
--

DROP TABLE IF EXISTS `user`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `user` (
  `id` int NOT NULL AUTO_INCREMENT,
  `username` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '用户名',
  `password` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '密码',
  `last_visit` datetime DEFAULT NULL COMMENT '上次登录时间',
  `last_ip` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '上次登录IP',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `update_time` datetime DEFAULT NULL COMMENT '修改时间',
  `status` int DEFAULT NULL COMMENT '状态',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户';
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `user`
--

LOCK TABLES `user` WRITE;
/*!40000 ALTER TABLE `user` DISABLE KEYS */;
INSERT INTO `user` VALUES (1,'admin','1234',NULL,NULL,NULL,NULL,1);
/*!40000 ALTER TABLE `user` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

-- Dump completed on 2021-11-12 16:29:37

在 IDEA 中新建 maven 项目 SpringHello,pom.xml 文件配置如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.demo</groupId>
    <artifactId>SpringHello</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <spring.version>3.2.18.RELEASE</spring.version>
        <servlet.version>2.5</servlet.version>
        <jstl.version>1.2</jstl.version>
        <aspectjweaver.version>1.9.8.RC2</aspectjweaver.version>
        <dbcp.version>1.4</dbcp.version>
        <mysql.version>8.0.27</mysql.version>
        <testng.version>7.4.0</testng.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>${servlet.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>${jstl.version}</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>${aspectjweaver.version}</version>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>${dbcp.version}</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>${testng.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>SpringHello</finalName>
    </build>
</project>

建立实体类对象
User 类

package com.demo.domain;

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

public class User implements Serializable {

    private int id;

    private String username;

    private String password;

    private Date lastVisit;

    private String lastIp;

    private Date createTime;

    private Date updateTime;

    private int status;

    // getter/setter 省略
}

LoginLog 类

package com.demo.domain;

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

public class LoginLog implements Serializable {

    private int id;

    private int userId;

    private String ip;

    private Date createTime;

    private Date updateTime;

    private int status;

    // getter/setter 省略
}

数据库访问对象
UserDao

package com.demo.dao;

import com.demo.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.stereotype.Repository;

import java.sql.ResultSet;
import java.sql.SQLException;

@Repository
public class UserDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 根据用户名和密码查询匹配的用户数
     *
     * @param username 用户名
     * @param password 密码
     * @return 0/1
     */
    public int getMatchCount(String username, String password) {
        String sql = "select count(*) from user where username = ? and password = ?";
        return jdbcTemplate.queryForInt(sql, username, password);
    }

    /**
     * 根据用户名查询对应用户
     *
     * @param username 用户名
     * @return id,username
     */
    public User findUserByUsername(final String username) {
        String sql = "select id, username from user where username = ? and status = 1";
        final User user = new User();
        jdbcTemplate.query(sql, new Object[]{username}, new RowCallbackHandler() {
            @Override
            public void processRow(ResultSet rs) throws SQLException {
                user.setId(rs.getInt("id"));
                user.setUsername(rs.getString("username"));
            }
        });
        return user;
    }

    /**
     * 更新用户登录信息
     *
     * @param user lastVisit,lastIp,id
     */
    public void updateLoginInfo(User user) {
        String sql = "update user set last_visit = ?, last_ip = ? where id = ?";
        jdbcTemplate.update(sql, user.getLastVisit(), user.getLastIp(), user.getId());
    }

}

LoginLogDao

package com.demo.dao;

import com.demo.domain.LoginLog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class LoginLogDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 新增用户登录记录
     *
     * @param loginLog userId,ip
     */
    public void insertLoginLog(LoginLog loginLog) {
        String sql = "insert into login_log(user_id, ip, create_time, status) values(?, ?, now(), 1)";
        jdbcTemplate.update(sql, loginLog.getUserId(), loginLog.getIp());
    }

}

在 resource 目录新增 Spring 配置文件 applicationContext.xml,装配 Bean

<?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:p="http://www.springframework.org/schema/p"
       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">

    <!--扫描类包,将标注Spring注解的类自动转化Bean,同时完成Bean的注入-->
    <context:component-scan base-package="com.demo.dao"/>

    <!--定义一个使用DBCP实现的数据源-->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
          p:driverClassName="com.mysql.cj.jdbc.Driver"
          p:url="jdbc:mysql://localhost:3306/spring"
          p:username="root"
          p:password="1234"/>

    <!--定义JDBC模板Bean-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
          p:dataSource-ref="dataSource"/>

</beans>

业务层 UserService

package com.demo.service;

import com.demo.dao.LoginLogDao;
import com.demo.dao.UserDao;
import com.demo.domain.LoginLog;
import com.demo.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Autowired
    private UserDao userDao;

    @Autowired
    private LoginLogDao loginLogDao;

    public boolean hasMatchUser(String username, String password) {
        return userDao.getMatchCount(username, password) > 0;
    }

    public User findUserByUsername(String username) {
        return userDao.findUserByUsername(username);
    }

    public void loginSuccess(User user) {
        userDao.updateLoginInfo(user);

        LoginLog loginLog = new LoginLog();
        loginLog.setUserId(user.getId());
        loginLog.setIp(user.getLastIp());
        loginLogDao.insertLoginLog(loginLog);
    }

}

继续在 applicationContext.xml 文件中装配 UserService,并配置事务管理器

    <!--扫描service类包,应用Spring的注解配置-->
    <context:component-scan base-package="com.demo.service"/>

    <!--配置事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
          p:dataSource-ref="dataSource"/>

    <!--通过AOP配置提供事务增强,让service包下的所有Bean的所有方法拥有事务-->
    <aop:config proxy-target-class="true">
        <aop:pointcut id="serviceMethod" expression=" execution(* com.demo.service..*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod"/>
    </aop:config>
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>

增加业务层单元测试

package com.demo.service;

import com.demo.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.annotations.Test;

import static org.testng.Assert.*;

@ContextConfiguration(locations = {"/applicationContext.xml"})
public class UserServiceTest extends AbstractTestNGSpringContextTests {

    @Autowired
    private UserService userService;

    @Test
    public void testHasMatchUser() {
        assertTrue(userService.hasMatchUser("admin", "1234"));
        assertFalse(userService.hasMatchUser("admin", "1111"));
    }

    @Test
    public void testFindUserByUsername() {
        User user = userService.findUserByUsername("admin");
        assertEquals(user.getId(), 1);
    }

    @Test
    public void testLoginSuccess() {
    }

}

可以运行单元测试查看结果

配置 web.xml,使 Web 应用启动时自动启动 Spring 容器

<?xml version="1.0" encoding="utf-8" ?>
<web-app version="2.5"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

    <!--从类路径下加载Spring配置文件,classpath关键字特指在类路径下加载-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>

    <!--负责启动Spring容器的监听器,将引用上下文参数获得的Spring配置文件地址-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <servlet>
        <servlet-name>viewspace</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>viewspace</servlet-name>
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>

</web-app>

LoginController 控制器类

package com.demo.web;

import com.demo.domain.User;
import com.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

@Controller
@RequestMapping(value = "/admin")
public class LoginController {

    @Autowired
    private UserService userService;

    @RequestMapping(value = "/login.html")
    public String loginPage() {
        return "login";
    }

    @RequestMapping(value = "loginCheck.html")
    public ModelAndView loginCheck(HttpServletRequest request, User user) {
        boolean isValidUser = userService.hasMatchUser(user.getUsername(), user.getPassword());
        if (!isValidUser) {
            return new ModelAndView("login", "error", "用户名或密码错误。");
        } else {
            User u = userService.findUserByUsername(user.getUsername());
            u.setLastIp(request.getRemoteAddr());
            u.setLastVisit(new Date());
            userService.loginSuccess(u);
            request.getSession().setAttribute("user", u);
            return new ModelAndView("main");
        }
    }

}

在 WEB-INF 下新增 viewspace-servlet.xml,配置 Spring MVC

<?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:p="http://www.springframework.org/schema/p"
       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">

    <context:component-scan base-package="com.demo.web"/>

    <!--配置视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          p:viewClass="org.springframework.web.servlet.view.JstlView"
          p:prefix="/WEB-INF/jsp/"
          p:suffix=".jsp"/>

</beans>

在 WEB-INF 新增文件夹 jsp,增加 login.jsp 和 main.jsp 文件

<%--
  User: GeBron
  Date: 2021/11/12 13:40
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
    <title>景区网站管理员登录</title>
</head>
<body>
<c:if test="${!empty error}">
    <font color="red"><c:out value="${error}"/></font>
</c:if>
<form action="<c:url value="/admin/loginCheck.html"/>" method="post">
    用户名:<input type="text" name="username">
    <br>
    密 码:<input type="password" name="password">
    <br>
    <input type="submit" value="登录"/>
    <input type="reset" value="重置"/>
</form>
</body>
</html>
<%--
  User: GeBron
  Date: 2021/11/12 13:44
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>景区网站管理</title>
</head>
<body>
${user.username},欢迎您进入景区网站后台管理!
</body>
</html>

maven 打包,运行 Web 应用程序,访问 http://localhost:8080/SpringHello/admin/login.html 达到登录页面

登录成功页面

posted @ 2021-11-15 11:04  GeBron  阅读(63)  评论(0编辑  收藏  举报