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的項目
原理部分還沒有學習到感覺可以寫出來的程度
希望有朝一日可以回來寫寫
謝謝~