经过这段时间的努力,我们对Spring框架已经有了基本认识。是时候按下暂停键,学以致用,写个简单的小项目巩固一下我们至今所学的知识了。
这个小项目名为come-in,是个Web应用程序,实现了登录注册的功能。因此,整个网站总共包含三个页面:一个登录页面;一个注册页面;一个欢迎页面。如下:
登录页面:
注册页面:
欢迎页面:
实现这个网站用到的知识都是前文介绍过的。我们不会在这里讨论实现这个小项目所用的知识,而是把重心放在项目的实现上。为此,请打开IntelliJ IDEA,新建项目come-in,开始我们的网站实现之旅。
01.编写SQL脚本,运行SQL脚本,创建数据库。
1 CREATE DATABASE come_in DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
2
3 USE come_in;
4
5 CREATE TABLE person (
6 person_id INT NOT NULL AUTO_INCREMENT, # 数据库表ID
7 person_phone CHAR(11) NOT NULL, # 手机号码
8 person_password CHAR(68) NOT NULL, # 密码
9 person_name VARCHAR(12) NOT NULL, # 名字
10 person_time TIMESTAMP NOT NULL, # 注册时间
11 PRIMARY KEY (person_id) # 添加主键
12 ) ENGINE = INNODB;
02.在com.dream包下定义ErrorCode枚举。
1 package com.dream;
2
3 public enum ErrorCode {
4 SUCCESS(0),
5 ERROR_FATAL(1),
6 ERROR_DUPLICATE(2),
7 ERROR_CREDENTIAL(3);
8
9 private final int value;
10
11 ErrorCode(int value) {
12 this.value = value;
13 }
14
15 public int value() {
16 return value;
17 }
18 }
03.在com.dream包下定义Converter类。
1 package com.dream;
2
3 import java.util.*;
4 import java.text.*;
5
6 public final class Converter {
7 private Converter() {}
8
9 public static Integer toInteger(String value) {
10 try {
11 return value != null && value.length() > 0 ? Integer.parseInt(value) : null;
12 } catch (NumberFormatException e) {
13 return null;
14 }
15 }
16
17 public static Date toDate(String value) {
18 try {
19 return value != null ? new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(value) : null;
20 } catch (ParseException e) {
21 return null;
22 }
23 }
24 }
04.在com.dream包下定义Validator类。
1 package com.dream; 2 3 import java.util.regex.*; 4 5 public final class Validator { 6 private static final String PATTERN_PHONE = "^1[0-9]{10}$"; 7 8 private Validator() {} 9 10 public static boolean validatePersonName(String value) { 11 if (value == null) { 12 return false; 13 } 14 if (value.length() > 12) { 15 return false; 16 } 17 return true; 18 } 19 20 public static boolean validatePersonPhone(String value) { 21 if (value == null) { 22 return false; 23 } 24 if (!Pattern.compile(PATTERN_PHONE).matcher(value).matches()) { 25 return false; 26 } 27 return true; 28 } 29 30 public static boolean validatePersonPassword(String value) { 31 if (value == null) { 32 return false; 33 } 34 if (value.length() < 6) { 35 return false; 36 } 37 if (value.length() > 48) { 38 return false; 39 } 40 return true; 41 } 42 }
05.在com.dream.repository包下定义AddPerson接口。
1 package com.dream.repository;
2
3 public interface AddPerson {
4 void access(String name, String phone, String password);
5 }
06.在com.dream.repository包下定义实现了AddPerson接口的AddPersonImpl类。
1 package com.dream.repository;
2
3 import javax.sql.*;
4 import org.springframework.jdbc.core.*;
5 import org.springframework.stereotype.*;
6 import org.springframework.beans.factory.annotation.*;
7
8 @Repository
9 public class AddPersonImpl implements AddPerson {
10 private static final String STATEMENT;
11 private JdbcTemplate jdbcTemplate = null;
12
13 @Autowired
14 public void setJdbcTemplate(DataSource dataSource) {
15 this.jdbcTemplate = new JdbcTemplate(dataSource);
16 }
17
18 @Override
19 public void access(String name, String phone, String password) {
20 this.jdbcTemplate.update(STATEMENT, preparedStatement -> {
21 preparedStatement.setString(1, phone);
22 preparedStatement.setString(2, password);
23 preparedStatement.setString(3, name);
24 });
25 }
26
27 static {
28 STATEMENT = ""
29 + " INSERT INTO person"
30 + " (person_phone, person_password, person_name, person_time)"
31 + " VALUES"
32 + " (?, ?, ?, NOW())";
33 }
34 }
07.在com.dream.repository包下定义CountPersonByPhone接口。
1 package com.dream.repository;
2
3 public interface CountPersonByPhone {
4 int access(String phone);
5 }
08.在com.dream.repository包下定义实现了CountPersonByPhone接口的CountPersonByPhoneImpl类。
1 package com.dream.repository;
2
3 import javax.sql.DataSource;
4 import org.springframework.jdbc.core.*;
5 import org.springframework.stereotype.*;
6 import org.springframework.beans.factory.annotation.*;
7
8 @Repository
9 public class CountPersonByPhoneImpl implements CountPersonByPhone {
10 private static final String STATEMENT;
11 private JdbcTemplate jdbcTemplate = null;
12
13 @Autowired
14 public void setJdbcTemplate(DataSource dataSource) {
15 this.jdbcTemplate = new JdbcTemplate(dataSource);
16 }
17
18 @Override
19 public int access(String phone) {
20 return this.jdbcTemplate.query(STATEMENT, preparedStatement -> {
21 preparedStatement.setString(1, phone);
22 }, resultSet -> resultSet.next() ? resultSet.getInt(1) : 0);
23 }
24
25 static {
26 STATEMENT = "SELECT COUNT(*) FROM person WHERE person_phone=?";
27 }
28 }
09.在com.dream.repository包下定义QueryPersonByIdOut数据模型。
1 package com.dream.repository;
2
3 import java.util.*;
4
5 public class QueryPersonByIdOut {
6 private int personId = 0;
7 private String personName = null;
8 private Date personTime = null;
9
10 public int getPersonId() {
11 return this.personId;
12 }
13
14 public void setPersonId(int personId) {
15 this.personId = personId;
16 }
17
18 public String getPersonName() {
19 return this.personName;
20 }
21
22 public void setPersonName(String personName) {
23 this.personName = personName;
24 }
25
26 public Date getPersonTime() {
27 return this.personTime;
28 }
29
30 public void setPersonTime(Date personTime) {
31 this.personTime = personTime;
32 }
33 }
10.在com.dream.repository包下定义QueryPersonById接口。
1 package com.dream.repository;
2
3 public interface QueryPersonById {
4 QueryPersonByIdOut access(int id);
5 }
11.在com.dream.repository包下定义实现了QueryPersonById接口的QueryPersonByIdImpl类。
1 package com.dream.repository;
2
3 import javax.sql.*;
4 import org.springframework.jdbc.core.*;
5 import org.springframework.stereotype.*;
6 import org.springframework.beans.factory.annotation.*;
7 import com.dream.*;
8
9 @Repository
10 public class QueryPersonByIdImpl implements QueryPersonById {
11 private static final String STATEMENT;
12 private JdbcTemplate jdbcTemplate = null;
13
14 @Autowired
15 public void setJdbcTemplate(DataSource dataSource) {
16 this.jdbcTemplate = new JdbcTemplate(dataSource);
17 }
18
19 @Override
20 public QueryPersonByIdOut access(int id) {
21 return this.jdbcTemplate.query(STATEMENT, preparedStatement -> {
22 preparedStatement.setInt(1, id);
23 }, resultSet -> {
24 if (resultSet.next()) {
25 var out = new QueryPersonByIdOut();
26 out.setPersonId(resultSet.getInt(1));
27 out.setPersonName(resultSet.getString(2));
28 out.setPersonTime(Converter.toDate(resultSet.getString(3)));
29 return out;
30 } else {
31 return null;
32 }
33 });
34 }
35
36 static {
37 STATEMENT = ""
38 + " SELECT"
39 + " person_id, person_name, person_time"
40 + " FROM"
41 + " person"
42 + " WHERE"
43 + " person_id=?";
44 }
45 }
12.在com.dream.repository包下定义QueryPersonIdByCredential接口。
1 package com.dream.repository;
2
3 public interface QueryPersonIdByCredential {
4 int access(String phone, String password);
5 }
13.在com.dream.repository包下定义实现了QueryPersonIdByCredential接口的QueryPersonIdByCredentialImpl类。
1 package com.dream.repository;
2
3 import javax.sql.*;
4 import org.springframework.jdbc.core.*;
5 import org.springframework.stereotype.*;
6 import org.springframework.beans.factory.annotation.*;
7
8 @Repository
9 public class QueryPersonIdByCredentialImpl implements QueryPersonIdByCredential {
10 private static final String STATEMENT;
11 private JdbcTemplate jdbcTemplate = null;
12
13 @Autowired
14 public void setJdbcTemplate(DataSource dataSource) {
15 this.jdbcTemplate = new JdbcTemplate(dataSource);
16 }
17
18 @Override
19 public int access(String phone, String password) {
20 return this.jdbcTemplate.query(STATEMENT, preparedStatement -> {
21 preparedStatement.setString(1, phone);
22 preparedStatement.setString(2, password);
23 }, resultSet -> resultSet.next() ? resultSet.getInt(1) : 0);
24 }
25
26 static {
27 STATEMENT = ""
28 + " SELECT"
29 + " person_id"
30 + " FROM"
31 + " person"
32 + " WHERE"
33 + " person_phone=? AND person_password=?";
34 }
35 }
14.在com.dream.service包下定义BaseResult数据模型父类。
1 package com.dream.service;
2
3 import com.dream.*;
4
5 public class BaseResult {
6 private ErrorCode errorCode = ErrorCode.SUCCESS;
7
8 public ErrorCode getErrorCode() {
9 return this.errorCode;
10 }
11
12 public BaseResult(ErrorCode errorCode) {
13 this.errorCode = errorCode;
14 }
15 }
15.在com.dream.service包下定义ServiceLogonResult数据模型。
1 package com.dream.service;
2
3 import com.dream.*;
4
5 public class ServiceLogonResult extends BaseResult {
6 private int personId = 0;
7
8 public int getPersonId() {
9 return this.personId;
10 }
11
12 public void setPersonId(int personId) {
13 this.personId = personId;
14 }
15
16 public ServiceLogonResult(ErrorCode errorCode) {
17 super(errorCode);
18 }
19 }
16.在com.dream.service包下定义ServiceLogon接口。
1 package com.dream.service;
2
3 public interface ServiceLogon {
4 ServiceLogonResult process(String phone, String password);
5 }
17.在com.dream.service包下定义实现了ServiceLogon接口的ServiceLogonImpl类。
1 package com.dream.service;
2
3 import org.springframework.beans.factory.annotation.*;
4 import org.springframework.stereotype.*;
5 import com.dream.repository.*;
6 import com.dream.*;
7
8 @Service
9 public class ServiceLogonImpl implements ServiceLogon {
10 private QueryPersonIdByCredential queryPersonIdByCredential = null;
11
12 @Autowired
13 public void setQueryPersonIdByCredential(QueryPersonIdByCredential queryPersonIdByCredential) {
14 this.queryPersonIdByCredential = queryPersonIdByCredential;
15 }
16
17 @Override
18 public ServiceLogonResult process(String phone, String password) {
19 if (!Validator.validatePersonPhone(phone)) {
20 return new ServiceLogonResult(ErrorCode.ERROR_FATAL);
21 }
22 if (!Validator.validatePersonPassword(password)) {
23 return new ServiceLogonResult(ErrorCode.ERROR_FATAL);
24 }
25
26 var personId = queryPersonIdByCredential.access(phone, password);
27 if (personId ) {
28 return new ServiceLogonResult(ErrorCode.ERROR_CREDENTIAL);
29 }
30
31 var serviceResult = new ServiceLogonResult(ErrorCode.SUCCESS);
32 serviceResult.setPersonId(personId);
33 return serviceResult;
34 }
35 }
18.在com.dream.service包下定义ServiceRegistry接口。
1 package com.dream.service;
2
3 public interface ServiceRegistry {
4 BaseResult process(String name, String phone, String password, String confirm);
5 }
19.在com.dream.service包下定义实现了ServiceRegistry接口的ServiceRegistryImpl类。
1 package com.dream.service;
2
3 import org.springframework.beans.factory.annotation.*;
4 import org.springframework.stereotype.*;
5 import com.dream.repository.*;
6 import com.dream.*;
7
8 @Service
9 public class ServiceRegistryImpl implements ServiceRegistry {
10 private CountPersonByPhone countPersonByPhone = null;
11 private AddPerson addPerson = null;
12
13 @Autowired
14 public void setCountPersonByPhone(CountPersonByPhone countPersonByPhone) {
15 this.countPersonByPhone = countPersonByPhone;
16 }
17
18 @Autowired
19 public void setAddPerson(AddPerson addPerson) {
20 this.addPerson = addPerson;
21 }
22
23 @Override
24 public BaseResult process(String name, String phone, String password, String confirm) {
25 if(!Validator.validatePersonName(name)) {
26 return new BaseResult(ErrorCode.ERROR_FATAL);
27 }
28 if(!Validator.validatePersonPhone(phone)) {
29 return new BaseResult(ErrorCode.ERROR_FATAL);
30 }
31 if(!Validator.validatePersonPassword(password)) {
32 return new BaseResult(ErrorCode.ERROR_FATAL);
33 }
34 if(!password.equals(confirm)) {
35 return new BaseResult(ErrorCode.ERROR_FATAL);
36 }
37 if(this.countPersonByPhone.access(phone) > 0) {
38 return new BaseResult(ErrorCode.ERROR_DUPLICATE);
39 }
40
41 this.addPerson.access(name, phone, password);
42 return new BaseResult(ErrorCode.SUCCESS);
43 }
44 }
20.在com.dream.service包下定义ServicePersonInfoResult数据模型。
1 package com.dream.service;
2
3 import java.util.*;
4 import com.dream.*;
5
6 public class ServicePersonInfoResult extends BaseResult {
7 private int personId = 0;
8 private String personName = null;
9 private Date personTime = null;
10
11 public int getPersonId() {
12 return this.personId;
13 }
14
15 public void setPersonId(int personId) {
16 this.personId = personId;
17 }
18
19 public String getPersonName() {
20 return this.personName;
21 }
22
23 public void setPersonName(String personName) {
24 this.personName = personName;
25 }
26
27 public Date getPersonTime() {
28 return this.personTime;
29 }
30
31 public void setPersonTime(Date personTime) {
32 this.personTime = personTime;
33 }
34
35 public ServicePersonInfoResult(ErrorCode errorCode) {
36 super(errorCode);
37 }
38 }
21.在com.dream.service包下定义ServicePersonInfo接口。
1 package com.dream.service;
2
3 public interface ServicePersonInfo {
4 ServicePersonInfoResult process(String personId);
5 }
22.在com.dream.service包下定义实现了ServicePersonInfo接口的ServicePersonInfoImpl类。
1 package com.dream.service;
2
3 import org.springframework.beans.factory.annotation.*;
4 import org.springframework.stereotype.*;
5 import com.dream.repository.*;
6 import com.dream.*;
7
8 @Service
9 public class ServicePersonInfoImpl implements ServicePersonInfo {
10 private QueryPersonById queryPersonById = null;
11
12 @Autowired
13 public void setQueryPersonById(QueryPersonById queryPersonById) {
14 this.queryPersonById = queryPersonById;
15 }
16
17 @Override
18 public ServicePersonInfoResult process(String personId) {
19 var id = Converter.toInteger(personId);
20 if (id == null) {
21 return new ServicePersonInfoResult(ErrorCode.ERROR_FATAL);
22 }
23
24 var person = this.queryPersonById.access(id);
25 if (person == null) {
26 return new ServicePersonInfoResult(ErrorCode.ERROR_CREDENTIAL);
27 }
28
29 var personInfoResult = new ServicePersonInfoResult(ErrorCode.SUCCESS);
30 personInfoResult.setPersonId(person.getPersonId());
31 personInfoResult.setPersonName(person.getPersonName());
32 personInfoResult.setPersonTime(person.getPersonTime());
33 return personInfoResult;
34 }
35 }
23.在com.dream.controller包下定义ControlLogon类。
1 package com.dream.controller;
2
3 import org.springframework.beans.factory.annotation.*;
4 import org.springframework.web.bind.annotation.*;
5 import org.springframework.web.context.request.*;
6 import org.springframework.stereotype.*;
7 import com.dream.service.*;
8
9 @Controller
10 public class ControlLogon {
11 private ServiceLogon serviceLogon = null;
12
13 @Autowired
14 public void setServiceLogon(ServiceLogon serviceLogon) {
15 this.serviceLogon = serviceLogon;
16 }
17
18 @ResponseBody
19 @RequestMapping(value = "/logon", method = RequestMethod.POST)
20 public ServiceLogonResult visit(WebRequest request) {
21 var phone = request.getParameter("phone");;
22 var password = request.getParameter("password");
23 return this.serviceLogon.process(phone, password);
24 }
25 }
24.在com.dream.controller包下定义ControlRegistry类。
1 package com.dream.controller;
2
3 import org.springframework.beans.factory.annotation.*;
4 import org.springframework.web.bind.annotation.*;
5 import org.springframework.web.context.request.*;
6 import org.springframework.stereotype.*;
7 import com.dream.service.*;
8
9 @Controller
10 public class ControlRegistry {
11 private ServiceRegistry serviceRegistry = null;
12
13 @Autowired
14 public void setServiceRegistry(ServiceRegistry serviceRegistry) {
15 this.serviceRegistry = serviceRegistry;
16 }
17
18 @ResponseBody
19 @RequestMapping(value = "/registry", method = RequestMethod.POST)
20 public BaseResult visit(WebRequest request) {
21 var name = request.getParameter("name");
22 var phone = request.getParameter("phone");
23 var password = request.getParameter("password");
24 var confirm = request.getParameter("confirm");
25 return this.serviceRegistry.process(name, phone, password, confirm);
26 }
27 }
25.在com.dream.controller包下定义ControlPersonInfo类。
1 package com.dream.controller;
2
3 import org.springframework.beans.factory.annotation.*;
4 import org.springframework.web.bind.annotation.*;
5 import org.springframework.web.context.request.*;
6 import org.springframework.stereotype.*;
7 import com.dream.service.*;
8
9 @Controller
10 public class ControlPersonInfo {
11 private ServicePersonInfo servicePersonInfo = null;
12
13 @Autowired
14 public void setServicePersonInfo(ServicePersonInfo servicePersonInfo) {
15 this.servicePersonInfo = servicePersonInfo;
16 }
17
18 @ResponseBody
19 @RequestMapping(value = "/person_info", method = RequestMethod.POST)
20 public ServicePersonInfoResult visit(WebRequest request) {
21 var personId = request.getParameter("personId");
22 return this.servicePersonInfo.process(personId);
23 }
24 }
26.在/come-in/web/WEB-INF/目录里添加web.xml文件。
1 xml version="1.0" encoding="UTF-8"?> 2 <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation=" 5 http://xmlns.jcp.org/xml/ns/javaee 6 http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" 7 version="4.0"> 8 9 <context-param> 10 <param-name>contextConfigLocationparam-name> 11 <param-value>/WEB-INF/config/root-config.xmlparam-value> 12 context-param> 13 <listener> 14 <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class> 15 listener> 16 17 <servlet> 18 <servlet-name>dispatcherServletservlet-name> 19 <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class> 20 <init-param> 21 <param-name>contextConfigLocationparam-name> 22 <param-value>/WEB-INF/config/servlet-config.xmlparam-value> 23 init-param> 24 <load-on-startup>1load-on-startup> 25 servlet> 26 <servlet-mapping> 27 <servlet-name>dispatcherServletservlet-name> 28 <url-pattern>/url-pattern> 29 servlet-mapping> 30 web-app>
27.在/come-in/web/WEB-INF/config/目录里添加servlet-config.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-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <mvc:annotation-driven /> <mvc:default-servlet-handler /> <context:component-scan base-package="com.dream.controller" /> beans>
28.在/come-in/web/WEB-INF/config/目录里添加root-config.xml文件。
1 xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xsi:schemaLocation=" 6 http://www.springframework.org/schema/beans 7 http://www.springframework.org/schema/beans/spring-beans.xsd 8 http://www.springframework.org/schema/context 9 http://www.springframework.org/schema/context/spring-context-4.0.xsd"> 10 11 <context:component-scan base-package="com.dream.repository,com.dream.service" /> 12 <bean class="org.apache.commons.dbcp2.BasicDataSource"> 13 <property name="username" value="root" /> 14 <property name="password" value="123456" /> 15 <property name="url" value="jdbc:mysql://localhost:3306/come_in" /> 16 <property name="driverClassName" value="com.mysql.cj.jdbc.Driver" /> 17 bean> 18 19 beans>
29.在/come-in/web/目录里添加index.html文件。
1 DOCTYPE html> 2 <html> 3 <head> 4 <title>登录title> 5 <meta charset="UTF-8"> 6 <link rel="stylesheet" type="text/css" href="style/global.css"> 7 <link rel="stylesheet" type="text/css" href="style/index.css"> 8 head> 9 <body> 10 <div id="logon-box"> 11 <div class="-title-box"> 12 <h1>登陆h1> 13 div> 14 <div id="logon-body-box"> 15 <div class="-input-item"> 16 <label id="logon-phone-hint" for="logon-phone-text">手机label> 17 <input id="logon-phone-text" type="text" maxlength="48"> 18 div> 19 <div class="-input-item"> 20 <label id="logon-password-hint" for="logon-password-text">密码label> 21 <input id="logon-password-text" type="password" maxlength="48"> 22 div> 23 <div class="-button-item"> 24 <input id="logon-button" class="-button" type="button" value="登陆"> 25 div> 26 div> 27 <div id="logon-foot-box"> 28 <label for="logon-registry-button">没有账号?label> 29 <input id="logon-registry-button" type="button" value="马上注册"> 30 div> 31 div> 32 <div id="registry-box"> 33 <div class="-modal">div> 34 <div id="registry-workbench-box" class="-modal-body"> 35 <div class="-title-box"> 36 <h1>注册h1> 37 div> 38 <div id="registry-body-box"> 39 <div class="-input-item"> 40 <label id="registry-name-hint" for="registry-name-text">名字label> 41 <input id="registry-name-text" type="text" maxlength="48"> 42 div> 43 <div class="-input-item"> 44 <label id="registry-phone-hint" for="registry-phone-text">手机label> 45 <input id="registry-phone-text" type="text" maxlength="48"> 46 div> 47 <div class="-input-item"> 48 <label id="registry-password-hint" for="registry-password-text">密码label> 49 <input id="registry-password-text" type="password" maxlength="48"> 50 div> 51 <div class="-input-item"> 52 <label id="registry-confirm-hint" for="registry-confirm-text">密码确认label> 53 <input id="registry-confirm-text" type="password" maxlength="48"> 54 div> 55 <div class="-button-item"> 56 <input id="registry-ok-button" class="-button" type="button" value="注册"> 57 <input id="registry-cancel-button" class="-button" type="button" value="取消"> 58 div> 59 div> 60 div> 61 div> 62 63 <script type="text/javascript" src="script/index.js">script> 64 body> 65 html>
30.在/come-in/web/style/目录里添加global.css文件。
1 @charset "UTF-8";
2 * {
3 margin:0;
4 padding:0;
5 }
6 html {
7 width:100%;
8 height:100%;
9 background-color:white;
10 }
11 body {
12 width:100%;
13 min-height:100%;
14 background-color:white;
15 background-repeat:no-repeat;
16 background-position:center;
17 font:14px/24px "Microsoft Yahei",微软雅黑,Arial,arial,SimSun,simsun;
18 font-weight:normal;
19 color:#333333;
20 }
21 a {
22 color:#3b5999;
23 text-decoration:none;
24 outline:none;
25 }
26 a:hover {
27 color:#699857;
28 }
29 img {
30 border-width:0;
31 }
32 input {
33 outline:none;
34 }
35 input[type=text]::-ms-clear {
36 display:none;
37 }
38 input[type=button] {
39 appearance:none;
40 -moz-appearance:none;
41 -webkit-appearance:none;
42 border-radius:0;
43 }
44 textarea {
45 resize:none;
46 outline:none;
47 }
48 strong {
49 font-style:normal;
50 font-weight:bold;
51 }
52 h1,h2,h3,h4,h5,h6 {
53 font-size:100%;
54 font-weight:bold;
55 }
56 input,button,textarea,select,optgroup,option {
57 font-family:inherit;
58 font-size:inherit;
59 font-style:inherit;
60 font-weight:inherit;
61 }
62 .-button {
63 height:40px;
64 border-width:0;
65 font-size:16px;
66 font-weight:bold;
67 line-height:40px;
68 background-color:#558543;
69 color:white;
70 cursor:pointer;
71 }
72 .-button:hover {
73 background-color:#699857;
74 }
75 .-clear:after {
76 content:"\200B";
77 display:block;
78 height:0;
79 clear:both;
80 }
81 .-clear {
82 *zoom:1;
83 }
84 .-modal {
85 position:fixed;
86 top:0;
87 left:0;
88 right:0;
89 bottom:0;
90 opacity:0.3;
91 filter:alpha(opacity=30);
92 background-color:#333333;
93 z-index:90000000;
94 }
95 .-modal-body {
96 position:fixed;
97 background-color:#e9ebee;
98 z-index:91000000;
99 }
31.在/come-in/web/style/目录里添加index.css文件。
1 @charset "UTF-8";
2 body {
3 position:relative;
4 }
5 #logon-box {
6 float:left;
7 width:354px;
8 height:399px;
9 margin:60px;
10 border-bottom:9px solid #3b5999;
11 background-color:#e9ebee;
12 }
13 #logon-body-box {
14 width:auto;
15 height:258px;
16 padding:18px 18px 0px;
17 }
18 #logon-button {
19 width:100%;
20 }
21 #logon-foot-box {
22 width:auto;
23 height:20px;
24 padding:16px 18px;
25 font-size:14px;
26 line-height:20px;
27 }
28 #logon-foot-box label {
29 float:left;
30 cursor:pointer;
31 }
32 #logon-foot-box input {
33 width:auto;
34 height:20px;
35 border-width:0px;
36 font-size:14px;
37 line-height:20px;
38 background-color:transparent;
39 color:#3b5999;
40 cursor:pointer;
41 }
42 #logon-foot-box input:hover {
43 color:#699857;
44 }
45 #logon-registry-button {
46 float:left;
47 }
48 #registry-box {
49 display:none;
50 }
51 #registry-workbench-box {
52 top:142px;
53 left:50%;
54 width:354px;
55 height:380px;
56 margin-left:-177px;
57 }
58 #registry-body-box {
59 width:auto;
60 height:290px;
61 padding:18px 18px 0px;
62 }
63 #registry-ok-button {
64 float:right;
65 width:254px;
66 }
67 #registry-cancel-button {
68 float:left;
69 width:58px;
70 }
71 .-title-box {
72 width:auto;
73 height:72px;
74 padding:0px 18px;
75 font-size:36px;
76 line-height:72px;
77 background-color:#3b5999;
78 color:white;
79 }
80 .-title-box h1 {
81 font-weight:normal;
82 }
83 .-input-item {
84 position:relative;
85 width:auto;
86 height:38px;
87 margin-bottom:18px;
88 border:1px solid #888888;
89 background-color:white;
90 }
91 .-input-item label {
92 position:absolute;
93 top:0px;
94 left:0px;
95 width:auto;
96 height:38px;
97 padding:0px 9px;
98 font-size:14px;
99 line-height:38px;
100 color:#888888;
101 z-index:100;
102 }
103 .-input-item input {
104 position:absolute;
105 top:0px;
106 left:0px;
107 width:298px;
108 height:38px;
109 padding:0px 9px;
110 border-width:0px;
111 font-size:14px;
112 line-height:18px;
113 background-color:transparent;
114 color:#333333;
115 z-index:110;
116 }
117 .-button-item {
118 position:relative;
119 width:auto;
120 height:40px;
121 }
32.在/come-in/web/script/目录里添加index.js文件。
1 window.onload = function() { 2 let logonPhoneText = document.getElementById("logon-phone-text"); 3 let logonPasswordText = document.getElementById("logon-password-text"); 4 let logonButton = document.getElementById("logon-button"); 5 let logonRegistryButton = document.getElementById("logon-registry-button"); 6 let registryNameText = document.getElementById("registry-name-text"); 7 let registryPhoneText = document.getElementById("registry-phone-text"); 8 let registryPasswordText = document.getElementById("registry-password-text"); 9 let registryConfirmText = document.getElementById("registry-confirm-text"); 10 let registryOkButton = document.getElementById("registry-ok-button"); 11 let registryCancelButton = document.getElementById("registry-cancel-button"); 12 13 logonPhoneText.onfocus = onLogonPhoneTextFocus; 14 logonPhoneText.onblur = onLogonPhoneTextBlur; 15 logonPasswordText.onfocus = onLogonPasswordTextFocus; 16 logonPasswordText.onblur = onLogonPasswordTextBlur; 17 logonButton.onclick = onLogonButtonClick; 18 logonRegistryButton.onclick = onLogonRegistryButtonClick; 19 registryNameText.onfocus = onRegistryNameTextFocus; 20 registryNameText.onblur = onRegistryNameTextBlur; 21 registryPhoneText.onfocus = onRegistryPhoneTextFocus; 22 registryPhoneText.onblur = onRegistryPhoneTextBlur; 23 registryPasswordText.onfocus = onRegistryPasswordTextFocus; 24 registryPasswordText.onblur = onRegistryPasswordTextBlur; 25 registryConfirmText.onfocus = onRegistryConfirmTextFocus; 26 registryConfirmText.onblur = onRegistryConfirmTextBlur; 27 registryOkButton.onclick = onRegistryOkButtonClick; 28 registryCancelButton.onclick = onRegistryCancelButtonClick; 29 } 30 31 function onLogonPhoneTextFocus() { 32 let logonPhoneHint = document.getElementById("logon-phone-hint"); 33 logonPhoneHint.style.display = "none"; 34 } 35 36 function onLogonPhoneTextBlur() { 37 let logonPhoneText = document.getElementById("logon-phone-text"); 38 let logonPhoneHint = document.getElementById("logon-phone-hint"); 39 logonPhoneHint.style.display = (logonPhoneText.value.length === 0 ? "block" : "none"); 40 } 41 42 function onLogonPasswordTextFocus() { 43 let logonPasswordHint = document.getElementById("logon-password-hint"); 44 logonPasswordHint.style.display = "none"; 45 } 46 47 function onLogonPasswordTextBlur() { 48 let logonPasswordText = document.getElementById("logon-password-text"); 49 let logonPasswordHint = document.getElementById("logon-password-hint"); 50 logonPasswordHint.style.display = (logonPasswordText.value.length === 0 ? "block" : "none"); 51 } 52 53 function onLogonButtonClick() { 54 if(validateLogon()) { 55 let phoneText = document.getElementById("logon-phone-text"); 56 let passwordText = document.getElementById("logon-password-text"); 57 let phone = eraseSpace(phoneText.value.trim()); 58 let password = passwordText.value; 59 requestLogon(phone, password); 60 } 61 } 62 63 function onLogonRegistryButtonClick() { 64 let registryBox = document.getElementById("registry-box"); 65 registryBox.style.display = "block"; 66 } 67 68 function onRegistryNameTextFocus() { 69 let registryNameHint = document.getElementById("registry-name-hint"); 70 registryNameHint.style.display = "none"; 71 } 72 73 function onRegistryNameTextBlur() { 74 let registryNameText = document.getElementById("registry-name-text"); 75 let registryNameHint = document.getElementById("registry-name-hint"); 76 registryNameHint.style.display = (registryNameText.value.length === 0 ? "block" : "none"); 77 } 78 79 function onRegistryPhoneTextFocus() { 80 let registryPhoneHint = document.getElementById("registry-phone-hint"); 81 registryPhoneHint.style.display = "none"; 82 } 83 84 function onRegistryPhoneTextBlur() { 85 let registryPhoneText = document.getElementById("registry-phone-text"); 86 let registryPhoneHint = document.getElementById("registry-phone-hint"); 87 registryPhoneHint.style.display = (registryPhoneText.value.length === 0 ? "block" : "none"); 88 } 89 90 function onRegistryPasswordTextFocus() { 91 let registryPasswordHint = document.getElementById("registry-password-hint"); 92 registryPasswordHint.style.display = "none"; 93 } 94 95 function onRegistryPasswordTextBlur() { 96 let registryPasswordText = document.getElementById("registry-password-text"); 97 let registryPasswordHint = document.getElementById("registry-password-hint"); 98 registryPasswordHint.style.display = (registryPasswordText.value.length === 0 ? "block" : "none"); 99 } 100 101 function onRegistryConfirmTextFocus() { 102 let registryConfirmHint = document.getElementById("registry-confirm-hint"); 103 registryConfirmHint.style.display = "none"; 104 } 105 106 function onRegistryConfirmTextBlur() { 107 let registryConfirmText = document.getElementById("registry-confirm-text"); 108 let registryConfirmHint = document.getElementById("registry-confirm-hint"); 109 registryConfirmHint.style.display = (registryConfirmText.value.length === 0 ? "block" : "none"); 110 } 111 112 function onRegistryOkButtonClick() { 113 if(validateRegistry()) { 114 let nameText = document.getElementById("registry-name-text"); 115 let phoneText = document.getElementById("registry-phone-text"); 116 let passwordText = document.getElementById("registry-password-text"); 117 let confirmText = document.getElementById("registry-confirm-text"); 118 let name = nameText.value.trim(); 119 let phone = eraseSpace(phoneText.value.trim()); 120 let password = passwordText.value; 121 let confirm = confirmText.value; 122 requestRegistry(name, phone, password, confirm); 123 } 124 } 125 126 function onRegistryCancelButtonClick() { 127 let registryBox = document.getElementById("registry-box"); 128 registryBox.style.display = "none"; 129 } 130 131 function validateLogon() { 132 let phoneText = document.getElementById("logon-phone-text"); 133 let phone = eraseSpace(phoneText.value.trim()); 134 if (phone.length === 0) { 135 showMessage("请输入手机号码!", "知道了", null); 136 return false; 137 } 138 if (!isPhoneValid(phone)) { 139 showMessage("手机号码输错了!", "知道了", null); 140 return false; 141 } 142 143 let passwordText = document.getElementById("logon-password-text"); 144 let password = passwordText.value; 145 if (password.length === 0) { 146 showMessage("请输入密码!", "知道了", null); 147 return false; 148 } 149 if (password.length < 6) { 150 showMessage("密码输错了!", "知道了", null); 151 return false; 152 } 153 return true; 154 } 155 156 function validateRegistry() { 157 let nameText = document.getElementById("registry-name-text"); 158 let name = nameText.value.trim(); 159 if (name.length === 0) { 160 showMessage("名字需要1-12个字符!", "知道了", null); 161 return false; 162 } 163 if (name.length > 12) { 164 showMessage("名字不能多于12个字符!", "知道了", null); 165 return false; 166 } 167 168 let phoneText = document.getElementById("registry-phone-text"); 169 let phone = eraseSpace(phoneText.value.trim()); 170 if (phone.length === 0) { 171 showMessage("请输入您的手机号码!", "知道了", null); 172 return false; 173 } 174 if (!isPhoneValid(phone)) { 175 showMessage("请输入正确的手机号码!", "知道了", null); 176 return false; 177 } 178 179 let passwordText = document.getElementById("registry-password-text"); 180 let password = passwordText.value; 181 if (password.length === 0 || password.length < 6) { 182 showMessage("密码不能少于6个字符!", "知道了", null); 183 return false; 184 } 185 186 let confirmText = document.getElementById("registry-confirm-text"); 187 let confirm = confirmText.value; 188 if (confirm.length === 0) { 189 showMessage("请输入密码确认!", "知道了", null); 190 return false; 191 } 192 if (confirm !== password) { 193 showMessage("密码确认需与密码相同!", "知道了", null); 194 return false; 195 } 196 197 return true; 198 } 199 200 function requestLogon(phone, password) { 201 let requestData = "phone=" + encodeURIComponent(phone) 202 + "&password=" + encodeURIComponent(password); 203 let request = new XMLHttpRequest(); 204 request.onload = requestLogonHandler; 205 request.open("POST", "logon"); 206 request.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); 207 request.send(requestData); 208 } 209 210 function requestLogonHandler() { 211 if(this.status == 200 && this.responseText != null) { 212 let responseJson = JSON.parse(this.responseText); 213 if(responseJson && responseJson.errorCode === "SUCCESS") { 214 window.location.replace("welcome.html?personId=" + responseJson.personId); 215 } else if (responseJson && responseJson.errorCode === "ERROR_CREDENTIAL") { 216 showMessage("手机或密码输错了,请重新输入!", "知道了", null); 217 } else { 218 showMessage("登录失败。页面发生了严重错误,请重试!", "知道了", null); 219 } 220 } 221 } 222 223 function requestRegistry(name, phone, password, confirm) { 224 let requestData = "name=" + encodeURIComponent(name) 225 + "&phone=" + encodeURIComponent(phone) 226 + "&password=" + encodeURIComponent(password) 227 + "&confirm=" + encodeURIComponent(confirm); 228 let request = new XMLHttpRequest(); 229 request.onload = requestRegistryHandler; 230 request.open("POST", "registry"); 231 request.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); 232 request.send(requestData); 233 } 234 235 function requestRegistryHandler() { 236 if(this.status == 200 && this.responseText != null) { 237 let responseJson = JSON.parse(this.responseText); 238 if(responseJson && responseJson.errorCode === "SUCCESS") { 239 let registryBox = document.getElementById("registry-box"); 240 registryBox.style.display = "none"; 241 showMessage("注册成功!", "知道了", null); 242 } else if (responseJson && responseJson.errorCode === "ERROR_DUPLICATE") { 243 showMessage("手机号码已被注册过,请用其它号码!", "知道了", null); 244 } else { 245 showMessage("注册失败。页面发生了严重错误,请重试!", "知道了", null); 246 } 247 } 248 } 249 250 function isPhoneValid(value) { 251 return /^1[0-9]{10}$/.test(value); 252 } 253 254 function eraseSpace(value) { 255 return value.replace(/ /gi, ""); 256 } 257 258 function showMessage(msg, okButtontext, okButtonAction) { 259 let messageBox = document.createElement("div"); 260 messageBox.id = "message-box"; 261 messageBox.innerHTML = "" 262 + "" 263 + "" 264 + " " + msg + "" 265 + " " 266 + ""; 267 document.body.appendChild(messageBox); 268 269 let messageBoxOkButton = document.getElementById("message-box-ok-button"); 270 messageBoxOkButton.onmouseenter = function() { 271 messageBoxOkButton.style.background = "#699857"; 272 }; 273 messageBoxOkButton.onmouseleave = function() { 274 messageBoxOkButton.style.background = "#558543"; 275 }; 276 messageBoxOkButton.onclick = function() { 277 document.body.removeChild(messageBox); 278 if(okButtonAction) { 279 okButtonAction(); 280 } 281 }; 282 }
33.在/come-in/web/目录里添加welcome.html文件。
1 DOCTYPE html> 2 <html> 3 <head> 4 <title>欢迎title> 5 <meta charset="UTF-8"> 6 <link rel="stylesheet" type="text/css" href="style/global.css"> 7 <link rel="stylesheet" type="text/css" href="style/welcome.css"> 8 head> 9 <body> 10 <div id="person-info-box">div> 11 12 <script type="text/javascript" src="script/welcome.js">script> 13 body> 14 html>
34.在/come-in/web/style/目录里添加welcome.css文件。
1 #person-info-box p {
2 margin:12px;
3 font-size: 24px;
4 font-weight: bold;
5 }
35.在/come-in/web/script/目录里添加welcome.js文件。
1 window.onload = function() {
2 let requestData = "personId=" + encodeURIComponent(getParam("personId"));
3 let request = new XMLHttpRequest();
4 request.onload = requestPersonInfoHandler;
5 request.open("POST", "person_info");
6 request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
7 request.send(requestData);
8 }
9
10 function requestPersonInfoHandler() {
11 if(this.status == 200 && this.responseText != null) {
12 let responseJson = JSON.parse(this.responseText);
13 if(responseJson && responseJson.errorCode === "SUCCESS") {
14 let personInfoBox = document.getElementById("person-info-box");
15 personInfoBox.innerHTML = "您好," + responseJson.personName + "!";
16 } else {
17 let personInfoBox = document.getElementById("person-info-box");
18 personInfoBox.innerHTML = "页面发生了严重错误,请重新登录!";
19 }
20 }
21 }
22
23 function getParam(paramName) {
24 let query = window.location.search.substring(1);
25 let paramArray = query.split("&");
26 for (let i = 0; i < paramArray.length; i++) {
27 let paramPair = paramArray[i].split("=");
28 if(paramPair[0] === paramName) {
29 return paramPair[1];
30 }
31 }
32 return null;
33 }
完成!
当然,这个网站尚有很多缺陷。比如没有进行异常处理,导致我们的应用程序非常脆弱;比如没有进行编码处理,导致用户使用中文进行注册的话,显示的是一堆乱码。但是,所有这些缺陷并不影响我们整个网站基础功能的实现,也不影响我们希望通过这个小项目加深对Spring框架的理解的初衷。还有,随着学习的深入。大家自然而然的就知道怎么补上这些缺陷了。
Original: https://www.cnblogs.com/evanlin/p/15552739.html
Author: 林雪波
Title: 登录注册
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/571402/
转载文章受原作者版权保护。转载请注明原作者出处!