目录

一、开发前准备

二、设计登录页面(小程序)

三、创建 Maven 项目

四、创建数据库与数据表

五、后台代码(Java Servlet)

六、运行

七、总结 建议

一、开发前准备

 1、注册一个微信开发者账号:https://open.weixin.qq.com (略)

 2、开发工具:idea、Mysql、微信开发者工具

 3、应用技术:Java(后台)、小程序(前端)、Maven、Mysql、跨域

 4、本次案例以功能为主,页面效果能用就行(不注重页面设计)

注意:创建小程序的项目和Javaweb项目我都略过了详细的创建步骤(可能刚开始的小白会不懂怎么创建,我刚开始接触小程序的时候也是一样,创建项目都弄了好久),如果有需要的话,后面我会做一个 文章详细介绍。

二、设计登录页面(小程序)

1、login.wxml(设计登录页面的文件)

页面效果: 

 2、login.js(完成登录的逻辑代码)

  这里的代码基本上每一行我都注释了,每一行代码的意思都写的很清楚了,方便大家的阅读 

  (在我们开发编程的过程中,一定要养成写注释的习惯,这样会方便我们之后的阅读,出现 BUG了也能更快的找到问题所在)

// pages/login/login.js

Page({

/**

* 页面的初始数据

*/

/**

* 页面的初始数据

*/

data: {

account:null,

password:null,

},

/**

* 从文本框中得到输入的值

* 获取账号的方法

*/

userAccount:function(event){

// 获取文本框输出的账号

var userAccount = event.detail.value;

this.setData({

// 把获取到的账号赋值给 account 变量

account:userAccount,

})

console.log(this.data.account)

},

// 获取密码的方法

userPassword:function(event){

// 获取文本框输出的密码

var userPassword = event.detail.value;

this.setData({

// 把获取的密码赋值给 password 变量

password:userPassword,

})

console.log(this.data.password)

},

// 点击登录按钮要做的事情

loginTap:function(){

wx.request({

// 接口地址:登录的 servlet 地址

url: 'http://localhost:8080/项目名/XXX.do',

// 向后端传递的数据

data: {

// 账号

x:this.data.account,

// 密码

y:this.data.password,

},

// 以HTTP协议传HTML资料到浏览器前所送出的字串

header: {

//'content-type': 'application/json' //默认值

'Content-Type': 'application/x-www-form-urlencoded'

},

// 以什么方法传递(常用的是:POST、GET)

method: 'POST',

// 成功之后要做的操作

success(res) {

// 这里输出了登录的用户名

console.log(res.data.user_name)

console.log('----successed----')

// 判断是否存在数据,成功就跳到下一个页面

if(res){

/**

* 1、wx.navigateTo

保留当前页面,跳转到应用内的某个页面,使用wx.navigateBack可以返回到原页面。

2、wx.redirectTo

关闭当前页面,跳转到应用内的某个页面。

3、wx.switchTab

跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面

4、wx.navigateBack

关闭当前页面,返回上一页面或多级页面。可通过 [getCurrentPages()] 获取当前的页面栈,决定需要返回几层。

5、wx.reLaunch

关闭所有页面,打开到应用内的某个页面。

*/

wx.redirectTo({

// 跳到成功页面

url: '/pages/HomePage/homePage',

})

}

},

// 失败

fail(res){

// showModal:模态对话框

wx.showModal({

title:'提示',

content:'登录失败,账号或密码错误',

success(req){

if(res.confirm){

console.log("用户点击了确定",res);

} else if(res.cancel){

console.log("用户点击了取消");

}

}

})

console.log('----fail----')

}

})

},

// 点击了注册按钮

rigestTap:function(){

wx.showModal({

title:'提示',

content:'这是注册功能',

success(res){

if(res.confirm){

wx.redirectTo({

// 跳到注册页面

url: '/pages/register/reg',

})

} else{

console.log("点击了取消按钮");

}

}

})

},

/**

* 生命周期函数--监听页面加载

*/

onLoad(options) {

},

/**

* 生命周期函数--监听页面初次渲染完成

*/

onReady() {

},

/**

* 生命周期函数--监听页面显示

*/

onShow() {

},

/**

* 生命周期函数--监听页面隐藏

*/

onHide() {

},

/**

* 生命周期函数--监听页面卸载

*/

onUnload() {

},

/**

* 页面相关事件处理函数--监听用户下拉动作

*/

onPullDownRefresh() {

},

/**

* 页面上拉触底事件的处理函数

*/

onReachBottom() {

},

/**

* 用户点击右上角分享

*/

onShareAppMessage() {

}

})

三、创建 Maven 项目

  为什么要选择使用 Maven 呢? 因为我们开发需要使用很多的 jar 包,每需要一个就需要去下载一个,还要在项目配置中添加进去,操作非常繁琐,所以我们使用 Maven 来对我们的项目依赖我们需要的 jar 包,只需要到网上复制到 pom.xml 文件中就可以使用该 jar 包的 API 方法。

1、首先我们要创建一个Maven项目,这里我选择的是 Java ,但是我们需要的是web项目,后面我在项目结构中创建 web 项目

2、把我们的项目创建为 web 项目 

步骤:点击我们软件的设置按钮  ----- Project Structure

 

3、配置pom.xml文件

      下载依赖的网址:Maven Repository: Search/Browse/Explore (mvnrepository.com)

注意:一定要记得把我们的打包方式设置为 war 包,因为我们这次的项目为 web项目

  1、junit依赖:

        用途:

                1、进行单元测试,测试一个方法或者类是否能够正常运行

                       略.......

2、servlet依赖:

        用途:

                1、允许程序员注册一个类,在 Tomcat 收到的某个特定的 HTTP 请求的时候,执行这个类中的一些代码                 2、帮助程序员解析 HTTP 请求,把 HTTP 请求从一个字符串解析成一个 HttpRequest 对象                 3、帮助程序员构造 HTTP 响应,程序员只要给指定的 HttpResponse 对象填写一些属性字段,Servlet 就会自动的按照 HTTP 协议的方式构造出一个 HTTP 响应字符串,并通过 Socket 编写返回给客户端

3、MySQL依赖:

        用途:

                1、MySQL依赖是用于Java程序中连接和操作MySQL数据库的工具包

4、lombok依赖:

        用途:为我们的实体类省去重复的代码

                1、@Data 不需要写getter setter 

                2、@NoArgsConstructor 无参构造方法

            3、@AllArgsConstructor 有参数构造

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">

4.0.0

org.example

untitled1

1.0-SNAPSHOT

war

11

11

UTF-8

javax.servlet

javax.servlet-api

4.0.1

provided

junit

junit

4.13.2

test

mysql

mysql-connector-java

8.0.33

org.projectlombok

lombok

1.18.26

provided

四、创建数据库与数据表

-- 创建数据库

create database psm;

-- 使用数据库

use pms;

-- 创建数据表:userInfo

-- if not exists userInfo:判断userInfo表是否存在,不存在则创建

create table if not exists userInfo(

UserId int primary key auto_increment, -- 用户ID

userName varchar(20) , -- 账号

userPwd varchar(32), -- 密码(我们要使用MD5加密,加密后密码长度为32位)

picture varchar(200) -- 头像

);

select * from userInfo;

五、后台代码(Java Servlet)

1、创建用户实体类

      是不是觉得我们的实体类少了很多代码,没错,这就是 Lombok 帮我们省去了

package entity;

import lombok.AllArgsConstructor;

import lombok.Data;

import lombok.NoArgsConstructor;

/**

* @Date 2023-04-25

* @Author qiu

*/

@Data // 生成get\set

@NoArgsConstructor // 无参构造方法

@AllArgsConstructor // 有参构造方法

public class UserInfo {

/**

* 账号

*/

String userName;

/**

* 密码

*/

String userPwd;

/**

* 头像

*/

String picture;

}

 

2、SqlRunner执行器(增、删、改、查操作的封装)

        对JDBC 进行封装,封装后我们就不再需要写那7个恶心的步骤了,省去了大量的重复代码。

package runner;

import java.lang.reflect.Field;

import java.sql.*;

import java.util.ArrayList;

import java.util.List;

/**

* SqlRunner 执行器 - 执行 增、删、改、查操作

* *

* * 更新操作:insert、update、delete

* * 查询操作:select

* @Date 2023-04-25

* @Author qiu

*/

public class SqlRunner {

private Connection connection;

public SqlRunner(Connection connection) {

this.connection = connection;

}

/**

* 通用更新操作:执行 增、删、改的 SQL 语句

*

* insert into staffs(name,age,phone,sta_pos)

* values (?,?,?,?) ;

*

* @param sql

* @param params 不定长参数,本质上是一个数组

* @return

*/

public int executeUpdate(String sql, Object... params) {

// 第一:获取连接对象

if (connection == null) {

throw new RuntimeException("连接对象为null");

}

// 第二:预编译SQL语句

PreparedStatement ps = null;

try {

ps = connection.prepareStatement(sql);

// 第三:填充参数

setParameter(ps, params);

// 第四:执行SQL语句

// 第五:返回结果

return ps.executeUpdate();

} catch (SQLException e) {

throw new RuntimeException(e);

} finally {

// 第六:关闭相关的对象

close(ps);

close(connection);

}

}

/**

* 填充 SQL 语句中的占位符数据

*

* @param ps

* @param params

* @throws SQLException

*/

private static void setParameter(PreparedStatement ps, Object[] params) throws SQLException {

for (int i = 0; i < params.length; i++) {

ps.setObject(i + 1, params[i]);

}

}

/**

* 返回实体对象的属性名称

*

* @param clazz 实体对象的 Class 对象

* @param columnLabel select 后面的名称

* @param

* @return

*/

private String getFieldName(Class clazz, String columnLabel) {

// 1.获取实体对象所有的字段对象

Field[] fields = clazz.getDeclaredFields();

// 2.循环遍历字段数组

for (Field field : fields) {

// 3.判断字段是否存在 Column 注解

boolean isExist = field.isAnnotationPresent(Column.class);

// 4.如果存在,则获取注解的内容

if (isExist) {

String columnName = field.getAnnotation(Column.class).value();

// 5.判断注解的内容是否与 select 后面的字段名称一样

if (columnName.equals(columnLabel)) {

// 6.如果一样,则返回字段名称 - staPos

return field.getName();

}

}

}

// 7.如果不一样,则返回 select 后面的字段名称

return columnLabel;

}

/**

* 通用查询操作 - 返回的List集合

*

* @param clazz 实体对象的Class对象

* @param sql 要执行查询语句

* @param params 查询语句点位符数据

* @param T为具体的实体类型对象

* @return 返回的List集合

*/

public List executeQuery(Class clazz, String sql, Object... params) {

List list = new ArrayList<>();

// 第一:获取连接对象

if (connection == null) {

throw new RuntimeException("连接对象为null");

}

PreparedStatement ps = null;

ResultSet rs = null;

try {

// 第二:预编译SQL语句

ps = connection.prepareStatement(sql);

// 第三:填充参数

setParameter(ps, params);

// 第四:执行SQL语句 - ResultSet

rs = ps.executeQuery();

// 第五:获取结果集元数据对象

ResultSetMetaData metaData = rs.getMetaData();

// 第六:获取查询字段的数量

int count = metaData.getColumnCount();

// 第七:对结果集进行处理 - 遍历结果集,读取结果集中的数据,封装到List集合

while (rs.next()) {

// 1.实例化实体对象 - 思考:实体对象是谁呢? - 在这里,谁都可以,我们要做一个通用的查询 - 通过 clazz 这个参数来确定要操作的具体实体对象的Class对象

T entity = clazz.getConstructor().newInstance();

// 2.读取结果集各列的数据 - 思考:有几列数据?是不确定的 - 解决? - ResultSetMetaData

// Object xxx = rs.getObject("yyy") ;

for (int i = 1; i <= count; i++) {

// 2.1)获取查询字段名称 - 必须和实体对象的属性名称保持一致 - sta_pos、add_time

String name = getFieldName(clazz, metaData.getColumnLabel(i));

// 2.2)根据名称获取实体对象的字段对象

Field declaredField = clazz.getDeclaredField(name);

// 2.3)设置字段访问权限

declaredField.setAccessible(true);

// 2.4)获取结果集中的数据

Object obj = rs.getObject(i);

// 2.5)封装数据到实体对象中 - 思考:获取数据后,给对象的哪个属性初始化呢? - 反射

declaredField.set(entity, obj);

}

// 3.把实体对象添加到 List 集合中

list.add(entity);

}

} catch (SQLException e) {

throw new RuntimeException(e);

} catch (Exception e) {

throw new RuntimeException(e);

} finally {

// 第八:关闭对象

close(rs);

close(ps);

close(connection);

}

return list;

}

/**

* 查询数据,返回数据表的一行数据

*

* @param clazz

* @param sql

* @param params

* @param

* @return

*/

public T query4Entity(Class clazz, String sql, Object... params) {

T entity = null;

// 第一:获取连接对象

if (connection == null) {

throw new RuntimeException("连接对象为null");

}

PreparedStatement ps = null;

ResultSet rs = null;

try {

// 第二:预编译SQL语句

ps = connection.prepareStatement(sql);

// 第三:填充参数

setParameter(ps, params);

// 第四:执行SQL语句 - ResultSet

rs = ps.executeQuery();

// 第五:获取结果集元数据对象

ResultSetMetaData metaData = rs.getMetaData();

// 第六:获取查询字段的数量

int count = metaData.getColumnCount();

// 第七:对结果集进行处理 - 遍历结果集,读取结果集中的数据,封装到List集合

if (rs.next()) {

// 1.实例化实体对象 - 思考:实体对象是谁呢? - 在这里,谁都可以,我们要做一个通用的查询 - 通过 clazz 这个参数来确定要操作的具体实体对象的Class对象

entity = clazz.getConstructor().newInstance();

// 2.读取结果集各列的数据 - 思考:有几列数据?是不确定的 - 解决? - ResultSetMetaData

// Object xxx = rs.getObject("yyy") ;

for (int i = 1; i <= count; i++) {

// 2.1)获取查询字段名称 - 必须和实体对象的属性名称保持一致 - sta_pos、add_time

String name = getFieldName(clazz, metaData.getColumnLabel(i));

// 2.2)根据名称获取实体对象的字段对象

Field declaredField = clazz.getDeclaredField(name);

// 2.3)设置字段访问权限

declaredField.setAccessible(true);

// 2.4)获取结果集中的数据

Object obj = rs.getObject(i);

// 2.5)封装数据到实体对象中 - 思考:获取数据后,给对象的哪个属性初始化呢? - 反射

declaredField.set(entity, obj);

}

}

} catch (SQLException e) {

throw new RuntimeException(e);

} catch (Exception e) {

throw new RuntimeException(e);

} finally {

// 第八:关闭对象

close(rs);

close(ps);

close(connection);

}

return entity;

}

/**

* 关闭结果集对象

*

* @param rs

*/

private void close(ResultSet rs) {

if (rs != null) {

try {

rs.close();

} catch (SQLException e) {

throw new RuntimeException(e);

}

}

}

/**

* 关闭语句对象

*

* @param stmt

*/

private void close(Statement stmt) {

if (stmt != null) {

try {

stmt.close();

} catch (SQLException e) {

throw new RuntimeException(e);

}

}

}

/**

* 关闭结果集对象

*

* @param conn

*/

private void close(Connection conn) {

if (conn != null) {

try {

conn.close();

} catch (SQLException e) {

throw new RuntimeException(e);

}

}

}

}

3、接口类(定义登录和注册的方法)

package dao;

import entity.UserInfo;

/**

* @Date 2023-04-25

* @Author qiu

*/

public interface UserDao {

/**

* 登录的方法

*/

UserInfo login(String account,String password);

/**

* 注册账号的方法

*

*/

int insert(String account,String pwd,String prictrue);

}

4、接口实现类(实现接口后,完成接口中的方法的功能)

package dao.daoImpl;

import dao.UserDao;

import entity.UserInfo;

import runner.SqlRunner;

import utils.DbUtil;

/**

* @Date 2023-04-25

* @Author qiu

*/

public class UserDaoImpl implements UserDao {

// 实例化 SQL Runner 对象 - 提供了增、删、改、查

SqlRunner sqlRunner = new SqlRunner(DbUtil.getConnection());

/**

* 实现登录的方法

* @param account 账号

* @param password 密码

* @return

*/

@Override

public UserInfo login(String account, String password) {

String sql = "select userName,userPwd from userInfo where userName = ? and userPwd = ?";

return sqlRunner.query4Entity(UserInfo.class,sql,account,password);

}

/**

* 用户注册的方法

* @param account

* @param pwd

* @return

*/

@Override

public int insert(String account, String pwd,String prictrue) {

String sql = "insert into userInfo(userName,userPwd,picture) values(?,?,?)";

return sqlRunner.executeUpdate(sql,account,pwd,prictrue);

}

}

5、连接数据库的工具类(DbUtil) 

package utils;

import java.sql.*;

/**

* 连接数据库 & 释放相关对象

*

*

*

* @Date 2023-03-29

* @Author qiu

*/

public class DbUtil {

/**

* 连接驱动程序

*/

private static final String DRIVER = "com.mysql.cj.jdbc.Driver";

/**

* 连接URL

*/

private static final String URL = "jdbc:mysql://localhost:3306/pms?useUnicode=true;characterEncoding=utf8;serverTimezone=Asia/Shanghai";

/**

* 帐号

*/

private static final String USER = "账号";

/**

* 密码

*/

private static final String PASS = "密码";

static {

/*

* 加载驱动程序

*/

try {

Class.forName(DRIVER);

} catch (ClassNotFoundException e) {

System.out.println("加载驱动程序失败...");

e.printStackTrace();

}

}

/**

* 获取连接对象 -- Java程序 与 数据库之间的桥梁

*

* @return

*/

public static Connection getConnection() {

Connection conn = null;

try {

conn = DriverManager.getConnection(URL, USER, PASS);

} catch (SQLException e) {

System.out.println("获取连接对象失败...");

e.printStackTrace();

}

return conn;

}

/**

* 关闭相关的 JDBC 对象

*

* DriverManager:驱动管理对象,获取连接对象

*

* DriverManager.getConnection(URL, USER, PASS);

*

* ResultSet:结果集对象 用于接收查询数据时,返回的结果

*

* Statement:语句对象 用于执行SQL语句(PreparedStatement、CallableStatement)

* 增、删、改:executeUpdate() 查询:executeQuery()

*

*

* Connection:连接对象 建立JAVA程序与数据库之间的桥梁

*

* @param rst

* @param stmt 父类对象可以接收子类对象 - 多态

* @param conn

*/

public static void close(ResultSet rst, Statement stmt, Connection conn) {

if (rst != null) {

try {

rst.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

if (stmt != null) {

try {

stmt.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

if (conn != null) {

try {

conn.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

}

// executeUpdate()、executeQuery() - 略

public static void main(String[] args) {

System.out.println(DbUtil.getConnection());

}

}

6、登录的Servlet

package servlet;

import dao.daoImpl.UserDaoImpl;

import entity.UserInfo;

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

import java.io.PrintWriter;

/**

*

* 用户登录的 servlet

*

* @Date 2023-04-25

* @Author qiu

*/

@WebServlet("/login.do")

public class LoginServlet extends HttpServlet {

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

// 获取小程序端传递过来的数据并打印输出

String account = req.getParameter("x");

String password = req.getParameter("y");

// 判断 账号和密码不为空

if (account != null && password != null) {

// 实例化 UserDaoImp

UserDaoImpl userDao = new UserDaoImpl();

// 调用登录的方法进行登录

UserInfo login = userDao.login(account, password);

System.out.println("登陆成功");

PrintWriter writer = resp.getWriter();

writer.write("你好");

} else {

System.out.println("账号密码为空");

}

}

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

this.doGet(req, resp);

}

}

7、跨域过滤器

package filter;

import javax.servlet.*;

import javax.servlet.annotation.WebFilter;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

/**

* @Date 2023-04-26

* @Author qiu

*/

@WebFilter("/servlet/*")

public class CorsFilter implements Filter {

@Override

public void init(FilterConfig filterConfig) throws ServletException {

System.out.println("跨域访问--初始化");

}

@Override

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

// 向下转换类型

HttpServletRequest req = (HttpServletRequest) servletRequest;

HttpServletResponse resp = (HttpServletResponse) servletResponse;

// 解决跨域问题

// 允许所有的域名

String origin = req.getHeader("origin");

resp.setHeader("Access-Control-Allow-Origin", origin);

// 允许发送cookies

resp.setHeader("Access-Control-Allow-Credentials", "true");

// 允许请求所有的方法

resp.setHeader("Access-Control-Allow-Methods", "*");

// 预检请求的最大超时(有效)时间为3600秒

resp.setHeader("Access-Control-Max-Age", "3600");

// 定义可以返回的头部信息字段

resp.setHeader("Access-Control-Allow-Headers", "Authorization,Origin,X-Requested-With,Content-Type,Accept,"

+ "content-Type,origin,x-requested-with,content-type,accept,authorization,token,id,X-Custom-Header,X-Cookie,Connection,User-Agent,Cookie,*");

resp.setHeader("Access-Control-Request-Headers", "Authorization,Origin, X-Requested-With,content-Type,Accept");

// 可以暴露给外部所有头部信息字段

resp.setHeader("Access-Control-Expose-Headers", "*");

// 过滤器放行

filterChain.doFilter(req, resp);

}

@Override

public void destroy() {

System.out.println("跨域访问--销毁");

}

}

8、防止页面乱码的过滤器

package filter;

import java.io.IOException;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

public class CharEncodingFilter implements javax.servlet.Filter {

// 定一个变量存编码

private String encoding;

@Override

public void init(FilterConfig filterConfig) throws ServletException {

// filterConfig:读取过滤器的一些配置信息

String encoding = filterConfig.getInitParameter("encoding");

this.encoding = encoding;

System.out.println("中文处理....初始化" + encoding);

}

@Override

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

throws IOException, ServletException {

// 父接口转为子接口

HttpServletRequest req = (HttpServletRequest) request;

HttpServletResponse resp = (HttpServletResponse) response;

// 设置请求

req.setCharacterEncoding(encoding);

// 设置响应对象的编码

resp.setCharacterEncoding(encoding);

//resp.setContentType("text/html;charset=" + encoding);

// 放行

chain.doFilter(req, resp);

}

@Override

public void destroy() {

System.out.println("中文编码销毁....");

}

}

        还需要配置xml,星号表示全部servlet都可用

CharEncodingFilter

filter.CharEncodingFilter

编码设置

encoding

UTF-8

CharEncodingFilter

/*

好啦,到这里我们的登录功能的所有准备和代码都已经完成了,那么怎么执行我们的服务器(TomCat)呢?怎么去登录呢?

其实,和我们之前写 web 项目一样,只不过现在我们是用微信小程序来设计页面,后台代码还是我们熟悉的JavaServlet。我们只需要运行我们的猫就可以了

六、运行

1、直接点击运行,开启服务器

 

2、运行页面 404?

 运行之后是不是发现页面报错啦,没关系,这是因为我们没有在web项目中写我们的页面,我们的页面在小程序中设计了,如果不行看到这个错误的话,可以在项目中随便写一个页面就ok啦!

 

3、运行小程序的登录页面

1、输入账号密码进行登录

 2、登录成功后跳转页面

3、后台提示

好啦,到这里我们的小程序+ Java 的登录 DEMO已经完成了。

这次没有使用到MD5加密和文件上传的工具类,我打算在下一章的注册功能中再实现代码给到大家。

七、总结 建议

1、我是在学校学习Java后台开发的学生,只是这段时间老师讲的内容不是很多,就自己开始学习一点课外的知识来充实自己的知识库。

2、大家在学习的时候呢,不要盲目的学习,要有目标性去学,才会从中获取到自己想要的。不要学这个学一下,学那个又学一下,这样只会让自己什么都学不到,我就试过这样了,看这个新鲜就学这个,看哪个新鲜又学哪个,到最后什么都没有学会。就会觉得自己什么都学不好,所以大家在学习过程中一定要专注一门课程,等你学会了,再去学别的。

3、本次是自己第一次发布博客,没有经验,全靠自己的感觉去写,如果有写的不好的,请各位大佬指出,我会及时更正!

 

参考文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: