微信小程序 + Java + Mysql(登录 Demo)

目录

一、开发前准备

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

三、创建 Maven 项目

四、创建数据库与数据表

五、后台代码(Java Servlet)

六、运行

七、总结 建议


一、开发前准备

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

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

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

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

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

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

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

<!--pages/login/login.wxml-->
<view>
  <view class="login-title" >
    <label>登陆</label>
  </view>

  <view>
    <view class="weui-form__control-area">
      <view class="weui-cells__group weui-cells__group_form">
        <view class="weui-cells weui-cells_form">
          <view class="weui-cell">
            <view class="weui-cell__hd">
              <label class="weui-label">账号</label>
            </view>
            <view class="weui-cell__bd">
              <input class="weui-input"  placeholder="请输入账号" bindinput="userAccount"/>
            </view>
          </view>

          <view class="weui-cell">
            <view class="weui-cell__hd">
              <label class="weui-label">密码</label>
            </view>
            <view class="weui-cell__bd">
              <input class="weui-input" password="true" placeholder="请输入密码" bindinput="userPassword" />
            </view>
          </view>
        </view>
      </view>
    </view>

    <view class="login-button">
      <button type="primary" bindtap="loginTap"> 登陆 </button>
      <button type="default" bindtap="rigestTap"> 注册 </button>
    </view>

  </view>

</view>

页面效果: 

 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 有参数构造

<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <!-- GAV坐标:可以自己定义 -->
    <groupId>org.example</groupId>
    <artifactId>untitled1</artifactId>
    <version>1.0-SNAPSHOT</version>
    <!-- 打包方式有 jar 和 war,默认是 jar 包,我们现在是 web 项目 所以要打成  war -->
    <packaging>war</packaging>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <!-- 依赖:servlet -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <!-- 依赖:Mysql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
        </dependency>

     

        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.26</version>
            <scope>provided</scope>
        </dependency>




    </dependencies>




</project>

四、创建数据库与数据表

-- 创建数据库
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 执行器 - 执行 增、删、改、查操作
 *  * <p>
 *  * 更新操作:insert、update、delete
 *  * 查询操作:select
 * @Date 2023-04-25
 * @Author qiu
 */
public class SqlRunner {

    private Connection connection;

    public SqlRunner(Connection connection) {
        this.connection = connection;
    }

    /**
     * 通用更新操作:执行 增、删、改的 SQL 语句
     * <p>
     * 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 <T>
     * @return
     */
    private <T> String getFieldName(Class<T> 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>    T为具体的实体类型对象
     * @return 返回的List集合
     */
    public <T> List<T> executeQuery(Class<T> clazz, String sql, Object... params) {
        List<T> 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 <T>
     * @return
     */
    public <T> T query4Entity(Class<T> 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都可用

 <filter>
        <filter-name>CharEncodingFilter</filter-name>
        <filter-class>filter.CharEncodingFilter</filter-class>
        <init-param>
            <description>编码设置</description>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

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

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

六、运行

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

 

2、运行页面 404?

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

 

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

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

 2、登录成功后跳转页面

3、后台提示

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

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

七、总结 建议

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

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

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

 

  • 9
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值