🍳作者:天海奈奈
💭眼过千遍不如手锤一遍:推荐一款模拟面试,斩获大厂 o f f e r ,程序员的必备刷题平台 − − 牛客网
👉🏻点击开始刷题之旅
目录
开学学校开始讲servlet 后期要求做一个登录功能,这个使用SSM先只做个简单的只带登录功能的,且项目使用了MyBatis-Plus来简化开发流程。看情况决定要不要升级功能或者换个写法。
演示中只用一个用户登录,只是为了测试功能,实际使用中是根据数据库表内数据来决定的。

1 ieda新建maven项目名字随便起
2 点击文件,项目 ,模块 ,点加号添加web模块 ,这里要注意文件路径

我们改一下第一项的路径 从web 改成src\main\webapp

下面Web资源目录也改一下

选择webapp 点击右下角创建工件系统自动创建工件,点确认

发现我们webapp有个小蓝点就算成功了。
这个时候先在java包下建一个test类构建一下项目,看一下target包出来没,如果先配置tomcat target得后期手动拉出来,很麻烦。

现在开始配tomcat 点击右上角添加配置
点击加号选择tomcat本地
点击配置,主目录放我们tomcat的文件夹,系统会自动生成其他的

完成后点右下角的小红灯泡配置工件,进去后不用动,把下面的应用程序上下文改为 “/” 就行。

点击确认。 为了验证配置是否可用进入webapp目录下,新建一个index.html
- html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Testtitle>
- head>
- <body>
- <h1> 配置完成,终于可以开始了h1>
- body>
- html>
点击gebug启动tomcat ,根据之前的端口在浏览器看看有没有我们写的网页

如果网页显示正常我们开始添加依赖和写配置文件。
pom.xml 这里只显示需要加的,每个依赖我也标上了注释
-
-
-
aliyun -
aliyun -
https://maven.aliyun.com/repository/public -
-
-
-
-
-
-
-
org.springframework -
spring-webmvc -
5.3.8 -
-
-
-
-
com.fasterxml.jackson.core -
jackson-annotations -
2.12.3 -
-
-
com.fasterxml.jackson.core -
jackson-core -
2.9.9 -
-
-
com.fasterxml.jackson.core -
jackson-databind -
2.9.9 -
-
-
-
org.springframework -
spring-jdbc -
5.3.8 -
-
-
-
-
com.baomidou -
mybatis-plus -
3.4.3.1 -
-
-
-
mysql -
mysql-connector-java -
8.0.16 -
-
-
-
com.alibaba -
druid -
1.2.6 -
-
-
-
junit -
junit -
4.12 -
test -
-
-
org.springframework -
spring-test -
5.3.8 -
-
-
-
javax.servlet -
javax.servlet-api -
3.1.0 -
provided -
-
-
-
-
ch.qos.logback -
logback-classic -
1.2.3 -
-
-
-
-
commons-codec -
commons-codec -
1.15 -
-
-
-
org.jsoup -
jsoup -
1.12.1 -
-
在resources下新建applicationContext.xml 来作为配置文件
- "1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:mvc="http://www.springframework.org/schema/mvc"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:task="http://www.springframework.org/schema/task"
- xmlns:tx="http://www.springframework.org/schema/tx"
- 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.xsd
- http://www.springframework.org/schema/task
- http://www.springframework.org/schema/task/spring-task.xsd
- http://www.springframework.org/schema/mvc
- http://www.springframework.org/schema/mvc/spring-mvc.xsd
- http://www.springframework.org/schema/tx
- http://www.springframework.org/schema/tx/spring-tx.xsd">
-
- <context:component-scan base-package="com.xatu"/>
-
- <mvc:annotation-driven>
-
- <mvc:message-converters>
- <bean class="org.springframework.http.converter.StringHttpMessageConverter">
-
- <property name="supportedMediaTypes">
- <list>
- <value>application/json;charset=utf-8value>
- list>
- property>
- bean>
- mvc:message-converters>
- mvc:annotation-driven>
-
- <mvc:default-servlet-handler/>
-
-
- <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
-
- <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
-
- <property name="url" value="jdbc:mysql://localhost:3306/cnpc_comment?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true"/>
-
- <property name="username" value="******"/>
-
- <property name="password" value="******"/>
-
- <property name="initialSize" value="5"/>
-
- <property name="maxActive" value="20"/>
-
- bean>
-
-
-
-
-
- <bean id="sessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
- <property name="dataSource" ref="dataSource"/>
-
- <property name="mapperLocations" value="classpath:mappers/*.xml"/>
-
- <property name="configLocation" value="classpath:mybatis-config.xml"/>
-
-
-
- <property name="plugins">
- <array>
- <bean class="com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor">
- <property name="interceptors">
- <list>
- <bean class="com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor"/>
- list>
- property>
- bean>
- array>
- property>
-
- bean>
-
- <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
- <property name="basePackage" value="com.xatu.mapper"/>
- bean>
-
-
-
- <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
- <property name="dataSource" ref="dataSource"/>
- bean>
-
- <tx:annotation-driven transaction-manager="transactionManager"/>
-
-
- beans>
mybatis.config
- "1.0" encoding="UTF-8" ?>
- configuration
- PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-config.dtd">
- <configuration>
-
- <settings>
- <setting name="mapUnderscoreToCamelCase" value="true"/>
- settings>
-
-
-
-
- configuration>
logback.xml
- "1.0" encoding="UTF-8"?>
- <configuration>
- <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
-
- <encoder>
- <pattern>%d{HH:mm:ss} %-5level [%thread] %logger{30} - %msg%npattern>
-
- <charset>GBKcharset>
- encoder>
- appender>
-
- <root level="debug">
-
- <appender-ref ref="console"/>
- root>
-
- configuration>
mappers包下的manager.xml 他要跟自己的mapper包进行绑定 由于用的mybatis-plus所以不用自己写语句
- "1.0" encoding="UTF-8"?>
- mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.xatu.mapper.">
-
-
基本配置就完成了
2 表设计 表名叫manager (实体类要绑定的注意)

3 实体类
- @TableName("manager")
- public class Manager {
- @TableId(type = IdType.AUTO)
- private Long managerId;
- private String username;
- private String password;
- private Integer salt;
-
- @Override
- public String toString() {
- return "Manager{" +
- "userId=" + managerId +
- ", username='" + username + '\'' +
- ", password='" + password + '\'' +
- ", salt=" + salt +
- '}';
- }
-
- public Long getUserId() {
- return managerId;
- }
-
- public void setUserId(Long userId) {
- this.managerId = userId;
- }
-
- 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 Integer getSalt() {
- return salt;
- }
-
- public void setSalt(Integer salt) {
- this.salt = salt;
- }
- }
4 mapper
- public interface ManagerMapper extends BaseMapper
{ - }
5 service
- public interface ManagerService {
- public Manager checkLogin1(String username, String password);
- }
Impl 实现类
先使用mapper查看是否用这个用户名的用户再调用用户表的信息来判断密码是否正确,我们这里假设没有重名用户。
- @Service
- //默认方法不开启事务
- @Transactional(propagation = Propagation.NOT_SUPPORTED,readOnly = true)
- public class ManagerServiceImpl implements ManagerService {
-
- @Resource
- private ManagerMapper managerMapper;
-
- @Transactional(rollbackFor = Exception.class)
- @Override
- public Manager checkLogin1(String username, String password) {
- QueryWrapper
wrapper = new QueryWrapper(); - wrapper.eq("username", username);
- Manager manager = managerMapper.selectOne(wrapper);
- if (manager == null) {
- throw new MemberException("用户不存在");
- }
- String md5 = MD5Utils.md5Digest(password, manager.getSalt());
- if (!md5.equals(manager.getPassword())) {
- throw new MemberException("您输入的密码有误");
- }
- return manager;
- }
- }
异常
- public class MemberException extends RuntimeException{
- public MemberException(String message){
- super(message);
- }
- }
6 controller
调用service的chedkLogin1方法来检验登录 为了安全,在成功登录后我们将密码 和盐值 设为null
- @RestController
- @RequestMapping("/api/manager")
- public class ManagerController {
- @Resource
- private ManagerService managerService;
- @PostMapping("/check_login1")
- public ResponseUtils checkLogin1(String username , String password){
- ResponseUtils resp ;
- resp = new ResponseUtils();
-
- try {
- Manager manager = managerService.checkLogin1(username, password);
- manager.setPassword(null);
- manager.setSalt(null);
- resp = new ResponseUtils().put("manager" , manager);
- }catch (Exception e){
- e.printStackTrace();
- resp = new ResponseUtils(e.getClass().getSimpleName(), e.getMessage());
- }
- return resp;
- }
- }
7 工具类
MD5
用来使用hash算法使密码变复杂
- public class MD5Utils {
- public static String md5Digest(String source ,Integer salt){
- char[] ca = source.toCharArray();
- for(int i = 0 ; i < ca.length ;i++){
- ca[i] = (char) (ca[i] + salt);
- }
- String target = new String(ca);
- String md5 = DigestUtils.md5Hex(target);
- return md5;
- }
- }
统一返回对象
- public class ResponseUtils {
- private String code;//服务处处理编码
- private String message;//服务器返回消息
- private Map data = new LinkedHashMap<>();//服务器返回的数据
-
- //成功
- public ResponseUtils(){
- this.code = "0";
- this.message = "success";
- }
- //失败,传入编码和消息
- public ResponseUtils(String code , String message){
- this.code = code;
- this.message = message;
- }
- //给data进行赋值
- public ResponseUtils put(String key , Object value){
- this.data.put(key, value);
- return this;
- }
-
- public String getCode() {
- return code;
- }
-
- public void setCode(String code) {
- this.code = code;
- }
-
- public String getMessage() {
- return message;
- }
-
- public void setMessage(String message) {
- this.message = message;
- }
-
- public Map getData() {
- return data;
- }
-
- public void setData(Map data) {
- this.data = data;
- }
- }
整体

8 前端页面
我们是有vue 并且使用element-plus组件库来简化和美化我们的页面

这里我选择的是创建静态文件包,里面放着常用文工具,需要的时候直接把包放在webapp下载页面编写时进行调用。没有的话请选择替他方法,方法很多。
login.html
- html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>登录title>
-
- <link rel="stylesheet" type="text/css" href="assets/element-plus/index.css">
-
- <script src="/assets/vue/vue.global.js">script>
- <script src="/assets/element-plus/index.full.js">script>
- <script src="/assets/axios/axios.js">script>
- <style>
- .login-box {
- border: 1px solid #DCDFE6;
- width: 350px;
- margin: 180px auto;
- padding: 35px 35px 15px 35px;
- border-radius: 5px;
- -webkit-border-radius: 5px;
- -moz-border-radius: 5px;
- box-shadow: 0 0 25px #909399;
- }
- .login-title{
- text-align: center;
- margin: 0 auto 40px auto;
- color: #303133;
- }
- style>
- head>
- <body>
- <div id="app">
- <el-form ref="loginForm" label-width="80px" :rules="rules" :model="form" class="login-box">
- <h2 class="login-title">登录h2>
- <el-form-item label="账号" prop="username">
- <el-input type="text" placeholder="请输入账号" v-model="form.username">el-input>
- el-form-item>
- <el-form-item label="密码" prop="password">
- <el-input type="password" placeholder="请输入密码" v-model="form.password">el-input>
- el-form-item>
- <el-form-item>
- <el-button type="primary" v-on:click="onSubmit('loginForm')" style="width:200px">登录el-button>
- el-form-item>
- <el-form-item>
- <el-button type="primary" v-on:click="returnBack" style="width:200px">退出el-button>
- el-form-item>
- el-form>
- div>
- <script>
- const Main = {
- data() {
- return {
- form: {
- username: ''
- ,password: ''
- }
- ,rules:{
- username: [
- {required: true,message : '账号不能为空' , trigger:'blur'}
- ],
- password:[
- {required: true,message : '密码不能为空' , trigger:'blur'}
- ]
- }
- }
- }
- ,methods : {
- onSubmit(formName){
- const objApp = this;
- const form = this.$refs[formName];
-
- form.validate((valid) => {
- if(valid){
- console.info("表单校验成功,准备提交数据");
- const form = this.form;
- const $message = this.$message;
- const params = new URLSearchParams();
- params.append("username", form.username);
- params.append("password", form.password);
- axios.post("/api/manager/check_login1", params)
- .then(function (response) {
- console.info(response);
- const json = response.data;
- if(json.code=="0"){
- window.location.href = "/index1.html";
- }else{
- $message.error({message:json.message, offset: 100});
- }
- });
- }
- })
- }
- ,returnBack : function (){
- window.location.href = "/index.html";
- }
- }
- };
- //初始化Vue,绑定Main中的数据,利用ElementPlus对#app容器进行重新渲染
- const app = Vue.createApp(Main);
- app.use(ElementPlus);
- app.mount("#app");
- script>
- body>
- html>
至于另外两个页面,只是使用a标签添加链接 因为只是登录功能没有下一步所以建立两个网页来判断跳转与登录是否成功
总结
这算是完成了基础的登录功能,虽然我们并没有涉及到使用到session去保存用户信息以及去进行权限的判定,但是这个项目算是已经为后续的工作完成了基础的搭建后面只要在库中新建表或者在manager表上进行扩充,改写实体类并进行设计就可以添加更多的功能,这个前端登录页面也可以作为一个通用化的页面,只需要改变里面的的api接口就能做到重复使用。