2018.4.22
仅为个人理解 不足之处欢迎指正~
在上一篇文章SpringMVC学习记录(三)——Maven搭建简单SpringMVC登录项目的结尾
l
留下了没有使用的dao、pojo、service包
同时上一篇文章中所实现的登录
仅仅是进行了一个页面的跳转和把登录页面表单接收到的信息传递到新的界面上
这篇文章将实现完整的登录注册功能
最终项目结构:
先讲一下流程和思路:
1.View层(JSP页面)获取指令
2.Controller层接收到相应的指令
3.根据指令的不同 Controller层调用不同的Service
4.Service层根据要实现的功能的不同调用不同的Dao层
5.POJO层即实体层 存储各类JaveBean
各层的功能大致如下:
- View层即表现层 负责与用户产生交互
- Controller层相当于一个分配任务的管理员 将不同的任务分配给不同的Service
- Service层负责完成业务逻辑 在这一过程中通常需要与数据库产生交互
- Dao层负责与数据库之间的交互 完成增删改查或者其他操作
- POJO层存储各类JavaBean 作用于各层中
这样一来正向的关系如下(浏览器到服务端):
View——Controller——Service——Dao
而浏览器得到反馈的路径如下:
Service——Controller——View
Dao层不参与反馈的路径
POJO层参与到(几乎)所有的过程中
在思考完需要实现的功能之后 推荐按照POJO——DAO——Service——Controller——View这样的顺序进行程序编写
下面来编写这个程序:
1.对POJO类的编写
首先要明确的是我们需要进行登录与注册这两个功能
那么我们需要一个User类存储所有的用户信息用于注册
同时因为登录只需要进行用户名与密码的对比
所以我们需要一个Login类只存储用户名与密码
其实完全可以通过getter方法获取User类中的用户名与密码
但是这样的Login类比较便于理解(?)
User.java
package pojo;
public class User
{
private String username;
private String password;
private String phone;
private String email;
public User(String username,String password,String phone,String email)
{
this.username=username;
this.password=password;
this.phone=phone;
this.email=email;
}
public User()
{
//
}
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 getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
Login.java
package pojo;
public class Login
{
private String username;
private String password;
public Login(String username,String password)
{
this.username=username;
this.password=password;
}
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;
}
}
小TIPS:可以通过Myeclipse自带的方法自动添加Getter方法与Setter方法
比如说User类:
在编写完这里的时候
右键这个.java ——Source——Generate Getters and Setters
把所有的属性都勾上就行了
2.对Dao层的编写:
重要:对于Dao层与Service我们均采用“一个接口对应一个实现类”的方法编写
这样做的目的可能现在不太能够理解 但是先养成这个习惯 总的来说可以降低耦合
(1)UserDao.java
package dao;
import java.sql.Connection;
import pojo.Login;
import pojo.User;
public interface UserDao
{
User validateUser(Login login); //验证用户登录
void register(User user); //注册用户
Connection getConnection();
}
(2)对UserDao的实现——UserDaoImpl.java
package dao;
import org.springframework.stereotype.Repository;
import pojo.Login;
import pojo.User;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
@Repository("userDao")
public class UserDaoImpl implements UserDao
{
//获得连接
@Override
public Connection getConnection(){
String driver ="com.mysql.jdbc.Driver";
String url ="jdbc:mysql://localhost:3306/mvcdemo2?useUnicode=true&characterEncoding=utf-8&useSSL=false";
String user ="root";
String password ="root";
Connection connection =null;
try {
Class.forName(driver);
connection =DriverManager.getConnection(url, user, password);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
//注册用户
@Override
public void register(User user)
{
try {
Connection con = getConnection();
PreparedStatement preparedStatement = null;
String sql= "insert into user (username,password,phone,email) values(?,?,?,?)";
preparedStatement=con.prepareStatement(sql);
preparedStatement.setString(1, user.getUsername());
preparedStatement.setString(2, user.getPassword());
preparedStatement.setString(3, user.getPhone());
preparedStatement.setString(4, user.getEmail());
preparedStatement.executeUpdate();
}
catch (Exception e) {
//
}
}
//验证用户登录
@Override
public User validateUser(Login login)
{
User user=new User();
String sql="select * from user where username=?";
Connection con=getConnection();
PreparedStatement pstmt=null;
ResultSet rs=null;
try
{
pstmt=con.prepareStatement(sql);
pstmt.setString(1, login.getUsername());
rs=pstmt.executeQuery();
while(rs.next())
{
user.setUsername(rs.getString(1));
user.setPassword(rs.getString(2));
user.setPhone(rs.getString(3));
user.setEmail(rs.getString(4));
}
}
catch(SQLException e)
{
e.printStackTrace();
}
finally
{
try
{
if(pstmt!=null) pstmt.close();
if(con!=null) con.close();
}
catch(SQLException e)
{
e.printStackTrace();
}
}
return user;
}
}
以下几点需要注意:
1.本文采用了最基本的连接数据库方法 没有使用任何框架
2.
@Repository是对于Dao层Bean的注解
3.使用的数据库如下:
数据库名为mvcdemo2 表名为user 数据库帐号密码均为root
3.对Service层的编写:
仍采用“一个接口一个实现的方式”
(1)UserService.java
package service;
import pojo.User;
public interface UserService
{
void addUser(User user);
String login(User user);
}
(2)对该接口的实现——UserServiceImpl.java
package service;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import pojo.Login;
import pojo.User;
import dao.UserDao;
import dao.UserDaoImpl;
@Service
public class UserServiceImpl implements UserService
{
@Resource
UserDao userdao;
@Override
public void addUser(User user)
{
System.out.println("service:");
System.out.println(user.getUsername());
System.out.println(user.getPassword());
System.out.println(user.getPhone());
System.out.println(user.getEmail());
userdao.register(user);
}
@Override
public String login(User user)
{
Login needvalidate=new Login(user.getUsername(),user.getPassword());
User a=userdao.validateUser(needvalidate);
if(!(a.getPassword().equals(user.getPassword())))
{
return "密码错误";
}
else
{
return "登录成功";
}
}
}
@Service是对Service层的Bean的装配注解
4.对Controller层的编写:
(1)对登录相关指令的控制器——LoginController.java
package controller;
import javax.annotation.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import pojo.User;
import service.UserService;
@Controller
public class LoginController
{
@Resource
UserService userService;
@RequestMapping("/Login")
public ModelAndView login
(@RequestParam("username") String userName,
@RequestParam("password") String passWord)
{
ModelAndView mv = new ModelAndView("welcome");
User user=new User(userName,passWord,null,null);
String mes=userService.login(user);
mv.addObject("name",userName);
mv.addObject("message", mes);
return mv;
}
}
以下几点需要注意:
1.
@Controller是对Controller层的Bean的注解装配
2.
表示拦截 “/Login”url
3、
返回welcome页面 同时我们知道在login方法中返回的字符串为“登录成功”或“密码错误”
这里对welcome返回了两个动态值
一是输入的用户名
二是“登录成功”或“密码错误”
在这里用了两条addObject 在需要返回的信息比较多时需要用到addAllObject方法
(2)对注册相关指令的控制器——RegisterController.java
package controller;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
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 org.springframework.web.servlet.ModelAndView;
import pojo.User;
import service.UserService;
import service.UserServiceImpl;
@Controller
public class RegisterController
{
@Resource
UserService userService;
@RequestMapping(value="/register")
public ModelAndView showRegister(HttpServletRequest request,HttpServletResponse response)
{
ModelAndView mav=new ModelAndView("register");
mav.addObject("user",new User());
return mav;
}
@RequestMapping(value="/reg",method=RequestMethod.POST)
public ModelAndView addUser(HttpServletRequest request,HttpServletResponse response,
@RequestParam("username") String userName,
@RequestParam("password") String passWord,
@RequestParam("phone") String phone,
@RequestParam("email") String email)
{
User user=new User(userName,passWord,phone,email);
System.out.println("用户信息如下:");
System.out.println(user.getUsername());
System.out.println(user.getPassword());
System.out.println(user.getPhone());
System.out.println(user.getEmail());
userService.addUser(user);
ModelAndView mv = new ModelAndView("welcome");
String mes="注册成功";
mv.addObject("name", user.getUsername());
mv.addObject("message", mes);
return mv;
}
}
以下几点需要注意:
1.
这个Mapping对应的是显示注册界面的指令
而
对应的才是点击“注册”按钮之后实现的指令
2.
这里从浏览器传入了四个参数
这个做法比较蠢 但是自行进行封装比较方便测试与发现问题所在
可以通过User user方法配合@ModelAttribute方法直接获取一个封装好的User
这个方法以后会用到
3.
因为懒得再写页面了所以再次使用了welcome页面
为了与登录之后的页面区分开来 所以返回的值是注册的用户名与“注册成功”
5.对View层的编写
(1) index.jsp 即登录页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登录</title>
</head>
<body>
<form action="Login" method="post">
<div>
账号:<input type="text" name="username"/><br/>
密码:<input type="text" name="password"/><br/>
<input type="submit" value="Login"/>
<a href="register">注册</a>
</div>
</form>
</body>
</html>
(2)register.jsp 即注册页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登录</title>
</head>
<body>
<form action="reg" method="post">
<div>
账号:<input type="text" name="username"/><br/>
密码:<input type="text" name="password"/><br/>
电话:<input type="text" name="phone"/><br/>
邮箱:<input type="text" name="email"/><br/>
<input type="submit" value="注册"/>
</div>
</form>
</body>
</html>
(3)跳转页面 welcome.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>欢迎</title>
</head>
<body>
${name} <br>${message}
</body>
</html>
这几个页面都写的非常简洁
但是仍要注意的是action中的名字就是对应的ControllerMapping中的指令
6.运行结果:
首先进行一个注册:
看一眼数据库:
然后测试一下登录:
先输入错误的密码:
然后输入正确的密码:
7.其他配置文件:
首先就是Maven的配置文件pom.xml
在上一篇文章的基础上因为增加了与数据库的交互
所以添加了mysql-connector
<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>com.tzy</groupId>
<artifactId>MVCDemo2</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>MVCDemo1 Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<spring.version>4.3.0.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.34</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
<finalName>TestMaven2</finalName>
</build>
</project>
然后是Spring的配置文件 springContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config/>
<context:component-scan base-package="controller" />
<!-- 视图页面配置 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="UserServiceImpl" class="service.UserServiceImpl"/>
<bean id="UserDaoImpl" class="dao.UserDaoImpl"/>
</beans>
前缀与后缀问题上一章解释过了
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">
<display-name>TestMaven</display-name>
<welcome-file-list>
<welcome-file>/WEB-INF/views/index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
总结:
总的来说这是一个SpringMVC的简单登录注册项目
写起来比Servlet形式复杂很多 而且也并没有让人耳目一新的感觉
下一步打算将Dao层的Jdbc改为Mybatis
逐渐的改动和添砖加瓦成一个Spring+SpringMVC+Mybatis的项目
原理部分还没有学习到感觉可以写出来的程度
希望有朝一日可以回来写写
谢谢~