一.准备工作
1.通过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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>SpringMVCPractice1</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>SpringMVCPractice1 Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- Spring MVC 依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.25</version> <!-- 可以根据需要调整版本 -->
</dependency>
<!-- Druid 依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version> <!-- 可以根据需要调整版本 -->
</dependency>
<!-- MySQL 连接器依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version> <!-- 可以根据需要调整版本 -->
</dependency>
<!-- Spring Context 依赖(通常与 Spring MVC 一起使用) -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.25</version> <!-- 可以根据需要调整版本 -->
</dependency>
<!-- Spring Core 依赖(通常与 Spring MVC 一起使用) -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.25</version> <!-- 可以根据需要调整版本 -->
</dependency>
<!-- Spring Transaction -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.3.23</version>
</dependency>
<!-- Jackson JSON Processor -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
<!-- Servlet API -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<!-- JSP (If using JSP for views) -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!--jsp坐标-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.25</version> <!-- 请根据你的项目需要调整版本 -->
</dependency>
</dependencies>
<build>
<finalName>SpringMVCPractice1</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>7</source>
<target>7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.在配置文件中添加:
<context:component-scan base-package="buka" />
<mvc:annotation-driven />
这是为了开启包扫描以使用注解
3.创建User类:
package buka;
public class User {
private int id;
private String userName;
private String passWord;
public int getId() {
return id;
}
public void setId(int 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;
}
}
4.配置中文过滤器以及DispatcherServlet
在为web.xml中添加:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!-- Filters -->
<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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Servlets -->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring-mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
二.登陆页面的实现
1.先简单写出前端页面,在webapp下创建login.jsp:
<%--
Created by IntelliJ IDEA.
User: Lenovo
Date: 2024/7/23
Time: 10:14
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<style>
body {
width: 100%;
height: 100vh;
background-color: brown;
display: flex;
align-items: center;
justify-content: center;
margin: 0;
}
div {
width: 400px;
padding: 20px;
background-color: pink;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
border-radius: 10px;
}
form {
display: flex;
flex-direction: column;
align-items: center;
}
form input[type="text"], form input[type="password"] {
margin-bottom: 15px;
padding: 10px;
width: 80%;
border: 1px solid #ccc;
border-radius: 5px;
font-size: 16px;
}
form input[type="submit"], form button {
padding: 10px 20px;
margin-top: 10px;
width: 85%;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
transition: background-color 0.3s ease;
}
form input[type="submit"] {
background-color: #4CAF50;
color: white;
}
form input[type="submit"]:hover {
background-color: #45a049;
}
form button {
background-color: #2196F3;
color: white;
}
form button:hover {
background-color: #1976D2;
}
h1 {
text-align: center;
margin-bottom: 20px;
}
</style>
<body>
<div>
<h1>登录</h1>
<form action="/login" method="post">
用户名: <input type="text" name="username"><br/>
密码: <input type="text" name="password"><br/>
<input type="submit" value="submit" id="submit">
<button id="register">register</button>
</form>
</div>
</body>
</html>
运行效果为:
2.考虑后面要发送ajax请求:
这里需要引入jquery,由于我本地有jquery的静态文件,所以这里我直接将它放进webapp下引入使用,大家如果没有可以使用CDN,即<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>也可正常运行
注意由于springMVC默认会将webapp下的文件识别为页面格式,如果这是不做任何处理直接使用的jquery的话会出现404,所以要配置资源处理器,声明该文件为静态资源:
在对应包下创建WebConfig类(这里可以在配置文件配置,但是习惯上我用注解的方式):
package buka;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "buka")
public class WebConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/js/**").addResourceLocations("/js/");
}
}
如此我们就可以正常使用jquery了
3.创建后端文件:
这里Controller是整体的控制层,Service是逻辑处理层,Dao是数据交互层
首先从Dao层开始书写,考虑登录功能要从数据库中查询对应用户信息是否存在,所以在这之前应有数据库:
(1)在Dao层添加代码:
这段代码比较简单,就是查询并根据每一行数据创建User,最后返回一个User列表
package buka.Dao;
import buka.User;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
@Repository
public class UserDao {
@Autowired
private DruidDataSource dataSource;
public List<User> getAllUsers() {
List<User> list = new ArrayList<User>();
String sql="select * from t_user";
try {
Connection conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
while(rs.next()) {
User user = new User();
user.setId(rs.getInt("id"));
user.setUserName(rs.getString("userName"));
user.setPassWord(rs.getString("passWord"));
list.add(user);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
return list;
}
}
(2)写Service层逻辑:
将传入的数据与Dao层返回的用户列表一一进行比对,如果比对成功就返回true,否则证明数据库中没有这个用户
package buka.Service;
import buka.Dao.UserDao;
import buka.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
@org.springframework.stereotype.Service
public class UserService {
@Autowired
private UserDao userDao;
public boolean validateUser(String username,String password) {
List<User> users = userDao.getAllUsers();
System.out.println(username+" "+password);
for (User user : users) {
System.out.println(user.getUserName()+"-----"+user.getPassWord());
if(user.getUserName().equals(username) && user.getPassWord().equals(password)){
return true;
}
}
return false;
}
}
(3)写Controller层:
添加地址映射,接受前端参数,如果登陆成功,将用户名存储到session域(后面会有用),进行重定向,否则重新回到该页面
package buka.Controller;
import buka.Dao.UserDao;
import buka.Service.UserService;
import buka.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@org.springframework.stereotype.Controller
public class UserController {
@Autowired
private UserService userService;
@RequestMapping(value = "/login")
public void login(HttpServletRequest request, HttpServletResponse response,
@RequestParam("username") String username,
@RequestParam("password") String password) throws IOException {
boolean flag = userService.validateUser(username, password);
if (flag) {
// 登录成功后将用户信息存储到Session中
request.getSession().setAttribute("user", username);
response.sendRedirect("success.jsp");
} else {
response.sendRedirect("login.jsp");
}
}
}
(4)进行测试:
如此证明功能没有问题,事实上现在已经实现了登录功能,但是为了体现异步编程,我们使用ajax发送请求,修改login.jsp:
<%--
Created by IntelliJ IDEA.
User: Lenovo
Date: 2024/7/23
Time: 10:14
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<style>
body {
width: 100%;
height: 100vh;
background-color: brown;
display: flex;
align-items: center;
justify-content: center;
margin: 0;
}
div {
width: 400px;
padding: 20px;
background-color: pink;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
border-radius: 10px;
}
form {
display: flex;
flex-direction: column;
align-items: center;
}
form input[type="text"], form input[type="password"] {
margin-bottom: 15px;
padding: 10px;
width: 80%;
border: 1px solid #ccc;
border-radius: 5px;
font-size: 16px;
}
form input[type="submit"], form button {
padding: 10px 20px;
margin-top: 10px;
width: 85%;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
transition: background-color 0.3s ease;
}
form input[type="submit"] {
background-color: #4CAF50;
color: white;
}
form input[type="submit"]:hover {
background-color: #45a049;
}
form button {
background-color: #2196F3;
color: white;
}
form button:hover {
background-color: #1976D2;
}
h1 {
text-align: center;
margin-bottom: 20px;
}
</style>
<body>
<div>
<h1>登录</h1>
<form action="/login" method="post">
用户名: <input type="text" name="username"><br/>
密码: <input type="text" name="password"><br/>
<input type="submit" value="submit" id="submit">
<button id="register">register</button>
</form>
</div>
</body>
<script src="js/jquery.min.js"></script>
<script>
$("#submit").click(()=>{
const username = $("input[name='username']").val();
const password = $("input[name='password']").val();
if (!username || !password) {
alert("用户名和密码不能为空");
return;
}
$.ajax({
url:"/login",
method:"POST",
success:(res)=>{
if (res.status === "success") {
alert("登陆成功!")
} else {
alert("登录失败,请重试!");
}
}
})
});
</script>
</html>
效果上应该是不变的。
三.注册功能的实现
1.前端页面:
实际上我们把登陆的页面简单修改一下就可以:
在webapp下创建register.jsp:
<%--
Created by IntelliJ IDEA.
User: Lenovo
Date: 2024/7/23
Time: 10:14
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<style>
body {
width: 100%;
height: 100vh;
background-color: lightskyblue;
display: flex;
align-items: center;
justify-content: center;
margin: 0;
}
div {
width: 400px;
padding: 20px;
background-color: brown;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
border-radius: 10px;
}
form {
display: flex;
flex-direction: column;
align-items: center;
}
form input[type="text"], form input[type="password"] {
margin-bottom: 15px;
padding: 10px;
width: 80%;
border: 1px solid #ccc;
border-radius: 5px;
font-size: 16px;
}
form input[type="submit"] {
padding: 10px 20px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
transition: background-color 0.3s ease;
}
form input[type="submit"]:hover {
background-color: #45a049;
}
h1 {
text-align: center;
margin-bottom: 20px;
}
</style>
<body>
<div>
<h1>注册</h1>
<form action="/register" method="post">
用户名: <input type="text" name="username"><br/>
密码: <input type="text" name="password"><br/>
<input type="submit" value="submit" id="submit">
</form>
</div>
</body>
<script src="js/jquery.min.js"></script>
<script>
$("#submit").click(()=>{
const username = $("input[name='username']").val();
const password = $("input[name='password']").val();
if (!username || !password) {
alert("用户名和密码不能为空");
return;
}
})
</script>
</html>
2.对登陆页面的注册按钮添加点击事件:
当点击注册按钮时跳转到register.jsp页面
注意,由于注册按钮写在了form里面,当点击按钮时,默认会发起提交,这里要阻止表单的默认行为,在login.jsp中添加:
$("#register").click((event) => {
event.preventDefault(); // 阻止表单的默认提交行为
window.location.href = "register.jsp";
});
3.创建后端文件:
(1)在Dao层添加代码:
由于注册用户相当于向数据库中添加用户,所以重要的部分就是Dao层的数据操纵
package buka.Dao;
import buka.User;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
@Repository
public class UserDao {
@Autowired
private DruidDataSource dataSource;
public List<User> getAllUsers() {
List<User> list = new ArrayList<User>();
String sql="select * from t_user";
try {
Connection conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
while(rs.next()) {
User user = new User();
user.setId(rs.getInt("id"));
user.setUserName(rs.getString("userName"));
user.setPassWord(rs.getString("passWord"));
list.add(user);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
return list;
}
public boolean addUser(User user) {
if (user.getUserName() == null || user.getUserName().isEmpty() ||
user.getPassWord() == null || user.getPassWord().isEmpty()) {
return false;
}
String sql = "insert into t_user(userName, passWord) values(?, ?)";
try {
Connection conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, user.getUserName());
ps.setString(2, user.getPassWord());
int rowsAffected = ps.executeUpdate(); // 使用 executeUpdate 方法
return rowsAffected > 0; // 判断是否有行受到影响
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
(2)写Service逻辑:
直接返回Dao层结果就行
package buka.Service;
import buka.Dao.UserDao;
import buka.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
@org.springframework.stereotype.Service
public class UserService {
@Autowired
private UserDao userDao;
public boolean validateUser(String username,String password) {
List<User> users = userDao.getAllUsers();
System.out.println(username+" "+password);
for (User user : users) {
System.out.println(user.getUserName()+"-----"+user.getPassWord());
if(user.getUserName().equals(username) && user.getPassWord().equals(password)){
return true;
}
}
return false;
}
public boolean addUser(User user) {
return userDao.addUser(user);
}
}
(3)写Controller层:
添加地址映射,判断是否添加成功以进行页面跳转
package buka.Controller;
import buka.Dao.UserDao;
import buka.Service.UserService;
import buka.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@org.springframework.stereotype.Controller
public class UserController {
@Autowired
private UserService userService;
@RequestMapping(value = "/login")
public void login(HttpServletRequest request, HttpServletResponse response,
@RequestParam("username") String username,
@RequestParam("password") String password) throws IOException {
boolean flag = userService.validateUser(username, password);
if (flag) {
// 登录成功后将用户信息存储到Session中
request.getSession().setAttribute("user", username);
response.sendRedirect("success.jsp");
} else {
response.sendRedirect("login.jsp");
}
}
@RequestMapping("/register")
public void register(HttpServletRequest request, HttpServletResponse response,
@RequestParam("username") String username,
@RequestParam("password") String password) throws IOException {
User user = new User();
user.setUserName(username);
user.setPassWord(password);
boolean flag = userService.addUser(user);
if (flag) {
response.sendRedirect("login.jsp");
}else{
response.sendRedirect("register.jsp");
}
}
}
(4)进行测试:
点击提交后跳转回登陆页面
如此注册功能书写完毕。
四.路由问题考虑
- 问题一:我们每次开启项目,都会去index.jsp页面,按理来说我应该直接来到登陆页面
- 问题二:我登陆后访问success.jsp等其他页面这没有问题,但是当我未登陆的时候,无论我想访问那个页面都应该自动跳转回登陆页面,也就是说未登录时我只能访问login.jsp和register.jsp
解决方案:在之前书写Controller层时,当用户登陆成功时,我们将用户名信息存储到了session域中,我们可以通过检测session域是否有值来进行页面控制,可是如何控制?这里我们用过滤器实现,本来我是想用拦截器写的,但是初始逻辑不好判断,这里采用过滤器给出解决办法:
1.创建AuthenticationFilter类:
package buka;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class AuthenticationFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
// 获取请求路径
String requestURI = httpRequest.getRequestURI();
System.out.println("Filter Request URI: " + requestURI);
// 检查用户是否已登录
Object user = httpRequest.getSession().getAttribute("user");
if (user != null || requestURI.endsWith("login") || requestURI.endsWith("login.jsp") || requestURI.endsWith("register.jsp") || requestURI.endsWith("register")) {
chain.doFilter(request, response);
} else {
httpResponse.sendRedirect("login.jsp");
}
}
@Override
public void destroy() {
}
}
2.在web.xml中添加过滤器:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!-- Filters -->
<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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter>
<filter-name>authenticationFilter</filter-name>
<filter-class>buka.AuthenticationFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>authenticationFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Servlets -->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring-mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
如此就大功告成了,上述两个问题都得到解决,项目的初始登录与注册就书写完毕