作业管理系统

1.系统框架

springboot+springsecurity+mybatis+websocket+thymeleaf+layui

2.功能描述

教师功能:

1.发布作业
(1)教师可以发布多种格式的作业。1纯文本作业,2.纯文件作业,3.混合式作业。

2.修改作业
(1).教师可以修改发布作业(修改发布时间)。

3.批改作业
(1)可以对成绩打分。

(2)对于不合格的作业,老师可以打回让学生从做.

4.作业统计
(1)分数段统计

(2).作业评价关键字统计

5.信箱
(1).消息

学生功能:
1.提交作业
(1).作业格式:1学生提交作业,没有按照指定格式形式提交,系统直接打回

(2).超时不可提交作业.

2.查询批改后的作业
(1).学生查看批改的作业详情。

3.信箱
(1).消息

3.项目运行效果

1.用户登录:(用户可以点击刷新验证码)
在这里插入图片描述
2.教师发布作业 :(可以为所带班级布置3种不同类别的作业)
在这里插入图片描述

3.教师修改作业(对于粗心超时未提交的学生,老师可以修改作业截止时间,从而学生继续提交作业)
在这里插入图片描述

4.教师批改作业(教师可以查看学生提交过来的作业,打分或者不合格直接打回)
在这里插入图片描述

5.作业数据统计(系统对学生的分数进行统计,评价作业进行关键字的提取)
在这里插入图片描述

6.教师查看自己的信箱中的信息
在这里插入图片描述

7.消息实时推送 (在教师发布作业的时,学生就立即收到消息)
在这里插入图片描述

8.学生查看信箱
在这里插入图片描述

9.学生提交作业
在这里插入图片描述

10.学生查看批改作业信息
在这里插入图片描述

3.项目配置:

1.工具:
IDEA

2.项目种类:
springboot-maven项目

3.框架:
Layui框架(本项目的页面基本是调用X-admin写好的layui页面,下载地址:http://x.xuebingsi.com/

4.jdk:
1.8

5.数据库:
mysql5.0

6.数据库可视化工具:
navicat

4.项目详细讲解:

1.数据库设计:
总共有九张表,下面为表的相关属性。
semester表(学期表)

属性类型长度是否为主键是否为外键备注
idint2ID号1
namechar10学期名2019-2020上学年

course表(课程表)

属性类型长度是否为主键是否为外键备注
idint10流水号1
courseidchar10课程号1
namechar10课程名大学英语
scoreInt10学分3

teacher表(老师表)

属性类型长度是否为主键是否为外键备注
idint10流水号1
tcodechar10教工号001
namechar10教师名字王渊
genderchar10性别
degreechar10学历博士
titlechar10职称博士导师
introductionchar10简介本科毕业于…
photochar10照片001
UnreadinfoInt10未读总消息条数0

class表
班级表,是指开课班级表(老师与开课班级绑定)

属性类型长度是否为主键是否为外键备注
idint10班级号1
semester_idint10学期id1
course_idint10课程表id1
int10老师id1

student表(学生表)

属性类型长度是否为主键是否为外键备注
idint10流水号1
scodechar10学号201701
namechar10姓名陈联盛
genderchar10性别
photochar10照片201701
UnreadinfoInt10未读总消息0

class_student(学生课程表)
学生与开课班级绑定

属性类型长度是否为主键是否为外键备注
idint10流水号1
class_idint10开课班级1
Student_idint10学生id1

meaaage消息表
state角色0表示系统,1表示教师,2表示学生(普通消息(0),作业消息(1))

属性类型长度是否为主键是否为外键备注
idint10流水号1
SendidInt1发送者id0
ReceidInt1接收者id1
sendStateInt1发送者角色1
RecestateInt1接收者角色1
StateInt1普通消息(0),作业消息(1)0
Infochar10当state为1时,state为homework主键1

homework表(作业表)
标志是否过期(1,未过期,0表示过期)

属性类型长度是否为主键是否为外键备注
idint10流水号1
class_idint10开课班级id1
stimechar10开始时间2019-10-10
etimechar10结束时间2019-12-10
typeint10作业格式(1,纯文本,2纯文件,3,混1
Filename10文件名Null
Texttext10文本作业。。。。。。。
StateInt10标志是否过期(1,未过期,0表示过期)1

homeworkinfo 作业详情表

属性类型长度是否为主键是否为外键备注
Idint10流水号1
Homework_idint10作业id1
Student_idint10学生id1
TypeInt10否是作业格式1
filenamechar10作业文件名Null
texttext10文本答案。。。。
InfoVar10学生作业心得。。。。
piyutext10老师批语学无止境
filescoreint10文件题目得分0
textscoreint10文本提得分99
totalscoreint10总分99

2.基本的springboot的maven项目的创建.
创建初步的spingboot的项目后,注意修改两个配置文件1.pom.xml,2.application.properties

1.pom.xml

<?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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>student_work-2</groupId>
    <artifactId>alian</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>alian</name>
    <description>Demo project for Spring Boot</description>
 
    <properties>
        <java.version>1.8</java.version>
        <spring-security.version>5.1.2.RELEASE</spring-security.version>
    </properties>
    <dependencies>
        <!--springboot web启动 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- spingboot测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--安全认证-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <!--数据库驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <!--数据库连接池-->
        <!--<dependency>-->
        <!--<groupId>c3p0</groupId>-->
        <!--<artifactId>c3p0</artifactId>-->
        <!--<version>0.9.5.4</version>-->
        <!--</dependency>-->
        <!--数据库框架mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.0</version>
        </dependency>
        <!-- devtools热部署-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
        <!-- thymeleaf模板引擎-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!-- websocket消息推送-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
        <!--日志-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
        </dependency>
        <!--加密-->
        <!--json解析-->
 
        <!--保证样式版本唯一-->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>webjars-locator-core</artifactId>
            <version>0.35</version>
        </dependency>
        <!--引入wsockjs-->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>sockjs-client</artifactId>
            <version>1.1.2</version>
        </dependency>
        <!--引入websocket-->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>stomp-websocket</artifactId>
            <version>2.3.3-1</version>
        </dependency>
        <!--引入jquery-->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>jquery</artifactId>
            <version>3.3.1-1</version>
        </dependency>
        <!--引入中文工具类-->
        <dependency>
            <groupId>com.hankcs</groupId>
            <artifactId>hanlp</artifactId>
            <version>portable-1.3.2</version>
        </dependency>
 
    </dependencies>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <!--逆向工具插件引入-->
            <!-- mybatis generator 自动生成代码插件 -->
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <configuration>
                    <configurationFile>${basedir}/src/main/resources/generatorConfig.xml</configurationFile>
                    <overwrite>true</overwrite>
                    <verbose>true</verbose>
                </configuration>
            </plugin>
        </plugins>
        <resources>
            <resource>
                <directory>${project.basedir}/src/main/resources</directory>
                <filtering>true</filtering>
                <excludes>
                    <exclude>static/**</exclude>
                </excludes>
            </resource>
 
            <resource>
                <directory>${project.basedir}/src/main/resources</directory>
                <filtering>false</filtering>
                <includes>
                    <include>static/**</include>
                </includes>
            </resource>
        </resources>
    </build>
</project>

步骤请参考文章:springboot整合HanLP详解文本的关键字提取-人名识别-字体转换-分词-文本推荐:地址https://blog.csdn.net/qq_41593124/article/details/99548014。

2.application.properties

#描述数据源
spring.datasource.url=jdbc:mysql://localhost:3306/student_work?useUnicode=true&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driverClassName=com.mysql.jdbc.Driver
 
#扫描配置 mybatis整合
mybatis.type-aliases-package=alian.mapper
mybatis.mapper-locations=classpath:mapper/*Mapper.xml
 
#配置数据库连接池
#c3p0.jdbcUrl=jdbc:mysql://localhost:3306/ssm_student_work?useUnicode=true&characterEncoding=utf8&autoReconnect=true&failOverReadOnly=false
#c3p0.user=root
#c3p0.password=123456
#c3p0.driverClass=com.mysql.jdbc.Driver
#c3p0.minPoolSize=2
#c3p0.maxPoolSize=10
#c3p0.maxIdleTime=1800000
#c3p0.acquireIncrement=3
#c3p0.maxStatements=1000
#c3p0.initialPoolSize=3
#c3p0.idleConnectionTestPeriod=60
#c3p0.acquireRetryAttempts=30
#c3p0.acquireRetryDelay=1000
#c3p0.breakAfterAcquireFailure=false
#c3p0.testConnectionOnCheckout=false
#配置thymeleaf
#关闭thymeleaf缓存的功能
spring.thymeleaf.cache=false
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.check-template-location=true
spring.thymeleaf.servlet.content-type=text/html
spring.thymeleaf.encoding=UTF-8
 
#设置登录过期时间为30m
server.servlet.session.timeout=30m

3.springboot整合maybatis逆向工程生成domian,mapper 文件
1.在pom.xml配置plus插件。上面pom.xml已经修改,不用从新添加。

 <!--逆向工具插件引入-->
            <!-- mybatis generator 自动生成代码插件 -->
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <configuration>
                    <configurationFile>${basedir}/src/main/resources/generatorConfig.xml</configurationFile>
                    <overwrite>true</overwrite>
                    <verbose>true</verbose>
                </configuration>
            </plugin>

2.在 项目resources文件夹下面创建逆向工程配置文件:generatorConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
    <!-- 数据库驱动:选择你的本地硬盘上面的数据库驱动包-->
    <classPathEntry  location="D:\Java所有JAR\数据库驱动\mysql-connector-java-5.1.39.jar"/>
    <context id="DB2Tables"  targetRuntime="MyBatis3">
        <commentGenerator>
            <property name="suppressDate" value="true"/>
            <!-- 是否去除自动生成的注释 true:是 : false:-->
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>
        <!--数据库链接URL,用户名、密码 -->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://127.0.0.1/student_work" userId="root" password="123456">
        </jdbcConnection>
        <javaTypeResolver>
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>
        <!-- 生成模型的包名和位置-->
        <javaModelGenerator targetPackage="alian.domain" targetProject="src/main/java">
            <property name="enableSubPackages" value="true"/>
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>
        <!-- 生成映射文件的包名和位置-->
        <sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources">
            <property name="enableSubPackages" value="true"/>
        </sqlMapGenerator>
        <!-- 生成DAO的包名和位置-->
        <javaClientGenerator type="XMLMAPPER" targetPackage="alian.mapper" targetProject="src/main/java">
            <property name="enableSubPackages" value="true"/>
        </javaClientGenerator>
        <!-- 要生成的表 tableName是数据库中的表名或视图名 domainObjectName是实体类名-->
        <!-- 要生成的表 tableName是数据库中的表名或视图名 domainObjectName是实体类名-->
        <!--<table tableName="class"  enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>-->
        <!--<table tableName="classstudent"  enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>-->
        <!--<table tableName="course"  enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>-->
        <!--<table tableName="homework"  enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>-->
        <!--<table tableName="homeworkinfo"  enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>-->
        <!--<table tableName="meaagesinfo"  enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>-->
        <!--<table tableName="meaasge"  enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>-->
        <!--<table tableName="semester"  enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>-->
        <!--<table tableName="student"  enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>-->
        <!--<table tableName="teacher"  enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>-->
    </context>
</generatorConfiguration>

注意:三个地方需要注意:,。

1.这个路径是你本地数据库驱动的路径。
2.要生成的表 tableName是数据库中的表名或视图名 domainObjectName是实体类名

<table tableName="class"  enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>

表生成相应的domain,每张表都需要配置,上面是class表,其余的只需修改表名即可。

3.生成的mapper,domain的位置

<!-- 生成模型的包名和位置-->
        <javaModelGenerator targetPackage="alian.domain" targetProject="src/main/java">
            <property name="enableSubPackages" value="true"/>
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>
        <!-- 生成映射文件的包名和位置-->
        <sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources">
            <property name="enableSubPackages" value="true"/>
        </sqlMapGenerator>
        <!-- 生成DAO的包名和位置-->
        <javaClientGenerator type="XMLMAPPER" targetPackage="alian.mapper" targetProject="src/main/java">
            <property name="enableSubPackages" value="true"/>
        </javaClientGenerator>

生成结果如图:
在这里插入图片描述
4.springboot整合springsecurity相关配置
1.添加两个配置config类(MyUserDatalis,SpringSercurityConfig),四个拦截器配置处理器(MyAuthenticationFailHandler,MyAuthenticationSuccessHandler,UserLogoutSuccessHandler,ValidateCodeFilter)。

MyUserDatalis(配置springsecurity登录验证信息,在这一步主要对用户的登录信息进行验证)

package alian.config;
 
import alian.mapper.StudentMapper;
import alian.mapper.TeacherMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
 
@Component
public class MyUserDatalis implements UserDetailsService {
 
    @Autowired
    private StudentMapper studentMapper;
    @Autowired
    private TeacherMapper teacherMapper;
 
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        String judge1=studentMapper.findpasswordbyid(s);
        String judge2=teacherMapper.findpasswordbyid(s);
        BCryptPasswordEncoder passwordencodeing=new BCryptPasswordEncoder();
        if(judge1==null&&judge2==null)
        {
            return new User(s, "@@@", AuthorityUtils.commaSeparatedStringToAuthorityList("error"));
        }
        if(judge1!=null)
        {
            return new User(s, passwordencodeing.encode(judge1), AuthorityUtils.commaSeparatedStringToAuthorityList("student"));
        }
        if(judge2!=null)
        {
            return new User(s, passwordencodeing.encode(judge2), AuthorityUtils.commaSeparatedStringToAuthorityList("teacher"));
        }
        return null;
    }
}

SpringSercurityConfig(访问路径配置)

package alian.config;
 
import alian.filter.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
 
@EnableWebSecurity
public class SpringSercurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private MyUserDatalis myUserDatalis;
    @Autowired
    private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;
    @Autowired
    private MyAuthenticationFailHandler myAuthenticationFailHandler;
 
    @Override
    protected void configure(HttpSecurity http) throws Exception {
 
         ValidateCodeFilter validateCodeFilter=new ValidateCodeFilter();
             http.authorizeRequests()
                     .antMatchers("/teacher/**")
                     .hasAuthority ("teacher")
                    .antMatchers("/student/**")
                    .hasAnyAuthority ("student")
                    .and()
                     .addFilterBefore(validateCodeFilter,UsernamePasswordAuthenticationFilter.class)
                     .formLogin()
                    .loginPage("/login")// 登录路径
                     .loginProcessingUrl("/login/form")
                     .successHandler(myAuthenticationSuccessHandler)
                     .failureHandler(myAuthenticationFailHandler)
                    .and()
                     .logout()
                     .logoutUrl("/logout")
//                     .logoutSuccessHandler(userLogoutSuccessHandler)
                     .deleteCookies("JSESSIONID")
//                     .permitAll()
                     .and()
                    .authorizeRequests()
                    .antMatchers("/login","/login/indentycode","/test/**/").permitAll()
                    .antMatchers("/images/**","/css/**","/js/**","/font/**","/my_js/**","/webjars/**","/lib/**","/layui/**").permitAll()
                    .anyRequest()
                     .authenticated()
          .and()
                .csrf().disable();
 
        http.headers().frameOptions().disable();
        http.csrf().disable();
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(myUserDatalis).passwordEncoder(new BCryptPasswordEncoder());
    }
}

MyAuthenticationFailHandler(失败登录过滤器)

package alian.filter;
 
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
 
@Component
public class MyAuthenticationFailHandler implements AuthenticationFailureHandler {
    @Autowired
    private ObjectMapper objectMapper;
 
    @Override
    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
        Map<String, Object> map = new HashMap<>();
        map.put("code","0");
        map.put("msg","用户名或者密码错误");
        httpServletResponse.setContentType("application/json;charset=UTF-8");
        httpServletResponse.getWriter().write(objectMapper.writeValueAsString(map));
    }
}

MyAuthenticationSuccessHandler(成功登录过滤器)

package alian.filter;
 
import alian.domain.Student;
import alian.domain.Teacher;
import alian.mapper.StudentMapper;
import alian.mapper.TeacherMapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import netscape.security.Principal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.support.SimpleTriggerContext;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Authenticator;
import java.util.*;
 
@Component
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
 
    @Autowired
    private ObjectMapper objectMapper;
 
    @Autowired StudentMapper studentMapper;
 
    @Autowired TeacherMapper teacherMapper;
 
    @Override
    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
        Map<String, Object> map = new HashMap<>();
        Collection<? extends GrantedAuthority> authorities= authentication.getAuthorities();
        Iterator <SimpleGrantedAuthority>  temp= (Iterator<SimpleGrantedAuthority>) authorities.iterator();
        String role=null;
        while(temp.hasNext())
        {
            SimpleGrantedAuthority a=temp.next();
            role=a.toString();
            map.put("msg",role);
        }
        map.put("code","0");
        String name=authentication.getName();
        if(role.equals("student"))
        {
            Student student=studentMapper.findinfoByname(name);
            httpServletRequest.getSession().setAttribute("user", student);
        }
        else{
            Teacher teacher=teacherMapper.findinfoByname(name);
            httpServletRequest.getSession().setAttribute("user", teacher);
        }
        httpServletResponse.setContentType("application/json;charset=UTF-8");
        httpServletResponse.getWriter().write(objectMapper.writeValueAsString(map));
    }
}

UserLogoutSuccessHandler(用户退出过滤器)

package alian.filter;
 
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
 
/**
 * 用户登出处理类
 */
 
@Component("UserLogoutSuccessHandler")
 
public class UserLogoutSuccessHandler implements LogoutSuccessHandler{
 
    @Override
    public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
 
        httpServletResponse.setContentType("application/json;charset=utf-8");
        PrintWriter out = httpServletResponse.getWriter();
        out.flush();
        out.close();
 
 
 
//        HttpServletRequest request = (HttpServletRequest) req;
//        HttpServletResponse response = (HttpServletResponse) res;
//        // 1 匹配到/logout请求
//        if (requiresLogout(request, response)) {
//            Authentication auth = SecurityContextHolder.getContext().getAuthentication();
//            // 2 清空Cookie、remember-me、session和SecurityContext
//            this.handler.logout(request, response, auth);
//            // 3 重定向到注册界面
//            logoutSuccessHandler.onLogoutSuccess(request, response, auth);
//
//            return;
//        }
 
 
    }
}

ValidateCodeFilter(验证码过滤器)

package alian.filter;
 
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
import org.springframework.web.filter.OncePerRequestFilter;
import org.thymeleaf.util.StringUtils;
 
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
 
public class ValidateCodeFilter extends OncePerRequestFilter {
 
 
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
 
 
        /*
         *
         * 拦截表单登录url 进行验证码的提前验证
         *
         * */
        if(StringUtils.equals("/login/form", request.getRequestURI())&& StringUtils.equalsIgnoreCase("post", request.getMethod()))
        {
                String validatecode=request.getParameter("validatecode");
                String code= (String) request.getSession().getAttribute("code");
                Map<String, Object> map = new HashMap<>();
                map.put("code","0");
               ObjectMapper objectMapper=new ObjectMapper();
 
                if(StringUtils.isEmpty(validatecode))
                {
                    map.put("msg","验证码不能为空");
                    response.setContentType("application/json;charset=UTF-8");
                    response.getWriter().write(objectMapper.writeValueAsString(map));
                    return;
                }
                if(StringUtils.isEmpty(validatecode))
                {
                    map.put("msg","验证码已过期");
                    response.setContentType("application/json;charset=UTF-8");
                    response.getWriter().write(objectMapper.writeValueAsString(map));
                    return;
                }
 
                if(code.toUpperCase().equals(validatecode.toUpperCase()))
                {
                    filterChain.doFilter(request, response);
                }
                else{
                    map.put("msg","验证码输入不正确");
                    response.setContentType("application/json;charset=UTF-8");
                    response.getWriter().write(objectMapper.writeValueAsString(map));
                    return;
                }
        }
        else {
            filterChain.doFilter(request, response);
        }
    }
}

springsecurity引入的好处:实现单点登录,对密码的加密处理,对资源的分权限访问。

5.springboot整合websocket (实现消息推送)
1.引入websocket相关的jar包(上面pom.xml文件引入即可),这里用到了webjar资源管理,可以引入库中的js和css样式。

 <!--保证样式版本唯一-->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>webjars-locator-core</artifactId>
            <version>0.35</version>
        </dependency>
        <!--引入wsockjs-->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>sockjs-client</artifactId>
            <version>1.1.2</version>
        </dependency>
        <!--引入websocket-->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>stomp-websocket</artifactId>
            <version>2.3.3-1</version>
        </dependency>
        <!--引入jquery-->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>jquery</artifactId>
            <version>3.3.1-1</version>
        </dependency>

2.添加java配置类:(WebSocketSecurityConfig)

package alian.config;
 
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.messaging.MessageSecurityMetadataSourceRegistry;
import org.springframework.security.config.annotation.web.socket.AbstractSecurityWebSocketMessageBrokerConfigurer;
 
//@Configuration
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
 
    @Override
    protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
        messages.nullDestMatcher().authenticated()  //任何没有目的地的消息(即消息类型为MESSAGE或SUBSCRIBE以外的任何消息)将要求用户进行身份验证
                .simpSubscribeDestMatchers("/user/queue/errors").permitAll() //任何人都可以订阅/ user / queue / error
                .simpDestMatchers("/app/**").hasRole("USER")  //任何目的地以“/ app /”开头的消息都要求用户具有角色ROLE_USER
                .anyMessage().denyAll(); //拒绝任何其他消息。这是一个好主意,以确保您不会错过任何消息。
    }
    // @formatter:on
 
    @Override
    protected boolean sameOriginDisabled() {
        return true;
    }
}

参考文章,springboot整合springsecurity+websocket+thymeleaf https://blog.csdn.net/qq_41593124/article/details/99309260

3.添加js配置类:mywebscoket.js文件

var stompClient = null;// 创建全局变量
var receviemessages=null;
var isMessageing=false;
function receiveMessage() {
    if (isMessageing)
    {
        return receviemessages;
    }
}
function connect(distinctPath,sendPath) {// 连接方法(连接成功后会自动接收服务器传来的消息)
    var socket = new SockJS(distinctPath);
    stompClient = Stomp.over(socket);
    console.log("连接服务器成功");
    stompClient.connect({}, function(frame) {
        // setConnected(true);
        stompClient.subscribe(sendPath, function(greeting) {
            // isMessageing=true;
            // receviemessages=JSON.parse(greeting.body);
            // console.log("接收服务器传来的信息");
            // // console.log(JSON.parse(greeting.body));
            // console.log(greeting)
            // console.log(greeting.body)
            var info=greeting.body;
                layui.use(['layer','jquery'],function () {
                    var $=layui.$;
                    /*
                    *
                    * 将消息插入固定下拉列表位置
                    *
                    * */
                    var node = $('<dd><a href="javascript:void(0);" οnclick="alert(\'' + info + '\')">' + info + '</a></dd>');
                    $('#messageBox').append(node);
 
                // <a href="javascript:void(0);" οnclick="alert('1:1班:王渊老师:发布:60作业')">1:1班:王渊老师:发布:60作业</a>
                });
        });
    });
}
// 断开连接方法
function disconnect() {
    if (stompClient !== null) {
        stompClient.disconnect();
        console.log("关闭服务器连接成功");
    }
}
// 发送消息 meaaages智能为json数据
function sendMessage(receviePath,messages) {
    stompClient.send(receviePath, {}, messages
    );
}
function teacherconnect(id)
{
    connect("/chat","/topic/teacherinfo/"+id+"/");
}
function studentconnect(id)
{
    connect("/chat","/topic/studentinfo/"+id+"/");
}
 

4.调用的html页面(这里分两种权限连接,地址都是一样的,通过与服务器建立连接,达到即时通讯的目的)

<script>
        window.onload=function () {
            /*
            *
            * 进行用户角色的判断
            *
            * */
            // 注意:导航 依赖 element 模块,否则无法进行功能性操作
            layui.use('element', function(){
                var element = layui.element;
            });
            var state='[[${session.user.photo}]]'; // --获取session中的值
            var id='[[${session.user.id}]]';
            if (state.length>3)// 学生连接
            {
                studentconnect(id);
            }
            else {// 教师连接
                teacherconnect(id);
            }
        }
    </script>

5.Controller服务器端消息发送(这里用学生向老师发送info举例,SimpMessagingTemplate可以点对点发送消息,前台通过字符串的拼接可以实现向不同用户发送消息)

  @Autowired
    SimpMessagingTemplate simpMessagingTemplate;
    public void sendMessagesToTeacher(int teacherid,int student,int sendstate,int receivestate,int state,String info) throws Exception {
 
             simpMessagingTemplate.convertAndSend("/topic/teacherinfo/"+teacherid+"/",info);// 向老师发送消息
 
    }

5.项目整体结构图

在这里插入图片描述

6.Controller源码解析

LoginController用于管理用户的登录

package alian.controller;
 
import alian.utils.VerifyCodeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
 
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
 
/*
 * 登录控制器
 *
 */
@Controller
@RequestMapping(path = "/login")
public class LoginController {
    @GetMapping()
    public String login()
    {
        return "login";
    }
    @RequestMapping(value ="indentycode")
    public void indentycode(HttpServletRequest request, HttpServletResponse response) throws IOException {
        VerifyCodeUtil.setHeight(37);
        VerifyCodeUtil.setWidth(83);
        VerifyCodeUtil.setSize(10);
        VerifyCodeUtil.setDsize(10);
        String indentycode=VerifyCodeUtil.generateVerifyCode();
        request.getSession().setAttribute("code", indentycode);
        BufferedImage image = VerifyCodeUtil.getBufferedImage(indentycode);
        ImageIO.write(image, "jpg", response.getOutputStream());
    }
    /*测试*/
 
    @Autowired
    SimpMessagingTemplate simpMessagingTemplate;
    @MessageMapping("/hello")
    public @ResponseBody void greeting(String name)throws Exception{
        simpMessagingTemplate.convertAndSend("/topic/greetings",name);
    }
    @RequestMapping("/text")
    public String test()
    {
        return "text";
    }
 
 
}

StudentController(配置学生相关操作)

package alian.controller;
 
import alian.domain.Homework;
import alian.domain.Meaasge;
import alian.domain.Student;
import alian.domain.UserInfo;
import alian.service.StudentService;
import org.apache.commons.compress.utils.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
 
@Controller
@RequestMapping("/student")
public class StudentController {
 
    @GetMapping()
    public String Student()
    {
        return "index";
    }
 
    @Autowired
    private StudentService studentService;
 
    /*
    *
    * 查询用户收到的信息
    *
    * */
    @RequestMapping("/findallStudentMessages")
    public @ResponseBody Map findallStudentMessages(HttpServletRequest request)
    {
        Student user= (Student) request.getSession().getAttribute("user");
        List<Meaasge> messages= studentService.findallStudentMessages(user.getId());
        Map map=new LinkedHashMap();
        map.put("code", 0);
        map.put("msg", "查询成功");
        map.put("count", 20);
        map.put("data", messages);
        return map;
    }
 
    /*
    *
    * 查询学生所在班级发布作业
    *
    * */
    @RequestMapping("/findallStudentHomeworks")
    public @ResponseBody Map findallStudentHomeworks(HttpServletRequest request)
    {
        Student user= (Student) request.getSession().getAttribute("user");
        List<Homework> messages= studentService.findallStudentHomeworks(user.getId());
        Map map=new LinkedHashMap();
        map.put("code", 0);
        map.put("msg", "查询成功");
        map.put("count", 20);
        map.put("data", messages);
        return map;
    }
 
    @RequestMapping("/readinfo")
    public @ResponseBody Map readinfo(int messageid,HttpServletRequest request)
    {
        Student user= (Student) request.getSession().getAttribute("user");
        Map map=new HashMap();
        if(studentService.readMeeages(messageid))
        {
            studentService.readinfo(user.getId());
            map.put("msg", "读取成功");
        }
        else {
            map.put("msg", "请不要重复点击读取");
        }
        return map;
    }
 
    @RequestMapping("/readmanyinfo")
    public @ResponseBody Map readmanyinfo(@RequestParam(value = "messageid[]",required = true) int messageid[], HttpServletRequest request)
    {
        Student user= (Student) request.getSession().getAttribute("user");
        Map map=new HashMap();
        String ids="";
        for(int i=0;i<messageid.length;i++)
        {
            if(i==0){
                ids=""+messageid[i];
            }
            else
                ids=ids+","+messageid[i];
        }
        UserInfo userInfo = new UserInfo();
        userInfo.setId(user.getId());
        userInfo.setNums(messageid.length);
        if(studentService.receivemanyinfo(userInfo))
        {
            if(studentService.readmanyinfo(ids))
            {
                map.put("msg", "读取成功");
            }
        }
        else{
            map.put("msg", "读取成功");
        }
        return map;
    }
    /*
    *
    * 学生下载走也
    *
    * */
    @RequestMapping("/downHomework")
    public  void downHomework(String filename, HttpServletResponse response)
    {
        File a=new File("D:/"+filename);
        FileInputStream read=null;
        OutputStream outputStream=null;
        try {
            read=new FileInputStream(a);
            outputStream=response.getOutputStream();
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/x-download");
            response.addHeader("Content-Disposition", "attachment;filename=test.txt");
            IOUtils.copy(read, outputStream);
            outputStream.flush();
        }catch (IOException e) {
            e.printStackTrace();
        }
    }
}

TeacherController(配置教师相关操作)


package alian.controller;
 
import alian.config.WebSocketServer;
import alian.domain.*;
import alian.service.StudentService;
import alian.service.TeacherService;
import alian.utils.SaveFileUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
 
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.security.PublicKey;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
 
@Controller
@RequestMapping("/teacher")
public class TeacherController {
    @GetMapping()
    public  String teacher()
    {
        return "index";
    }
 
    @Autowired
    private TeacherService teacherService;
 
 
    @Autowired
    private StudentService studentService;
    /*
     *
     * 查询教师所带的班级接口
     *
     * */
    @RequestMapping(value ="class")
    public @ResponseBody
    Map classbyteacher_id(HttpServletRequest request)
    {
        Teacher user= (Teacher) request.getSession().getAttribute("user");
 
        List<Integer> lists = teacherService.coursebycourse_id(user.getId());
        Map map=new LinkedHashMap();
        map.put("lists", lists);
        return map;
    }
    /**
     *
     * 作业的发布
     *
     */
    @RequestMapping(value = "publishHomework")
    public @ResponseBody Map publishHomework(String classid, int type ,String time, String text,MultipartFile file, HttpServletRequest request)
    {
        Map map=new LinkedHashMap();
        map.put("code", 0);
        /*
         *
         * 将文件按照班级号+发布时间名命名
         * 存入upload文件夹
         *
         * 班级号 时间戳 文件名
         *
         * */
        String stime=time.substring(0,19);
        String etime=time.substring(22, 41);
        Homework homework=new Homework();
        homework.setClassId(Integer.parseInt(classid));
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:MM:SS");
        Date date1=null,date2=null;
        Teacher user= (Teacher) request.getSession().getAttribute("user");
 
        try {
            date1 = format.parse(stime);
            date2=format.parse(etime);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        List<Integer> students=teacherService.findStudentsbyClassId(Integer.parseInt( classid));
        homework.setStime(date1);
        homework.setEtime(date2);
        homework.setState(1);
        homework.setType(type);
        homework.setText(text);
        /*消息类型
        *
        * 消息类型:几班:xxlao老师:发布:xx作业
        * */
        String info=null;
        if(type==0)
        {
            /*解析text*/
            homework.setText(text);
            int homeworkid=teacherService.uploadHomework(homework);
            info=1+":"+classid+"班:"+user.getName()+"老师:"+"发布:"+homeworkid+"作业";
                map.put("msg","作业发布成功");
                /*
                *
                * 作业成功发布的同时向学生推送
                *
                * */
                /*
                *
                *
                * 发送者 接受者 发送者类型 接受者类型 消息类型
                * (state角色0表示系统,1表示教师,2表示学生)(普通消息(0),作业消息(1))
                *
                *
                * */
                try {
                    sendMessagesToStudents(user.getId(),students,1,2,1,info);
                } catch (Exception e) {
                    e.printStackTrace();
                }
        }
        else
        {
            if(type==1) text=null;
            homework.setText(text);
            // 文件后缀名
            String lastfilename=file.getOriginalFilename();
            lastfilename =lastfilename.substring(lastfilename.lastIndexOf('.'), lastfilename.length());
            /*文件名*/
            String filename=classid+new Date().getTime()+lastfilename ;
            filename=filename.replace(":", "");
            homework.setFilename(filename);
 
            int homeworkid=teacherService.uploadHomework(homework);
            info=classid+"班:"+user.getName()+"老师:"+"发布:"+homeworkid+"作业";
                String path="D:\\upload";
                if(SaveFileUtil.savefile(path,filename,file))
                {
                    map.put("msg", "作业发布成功");
                    try {
                        //老师id先写死
                        sendMessagesToStudents(1,students,1,2,1,info);
 
                        } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                else  map.put("msg", "作业发布失败,文件上传失败");
 
            }
        return map;
    }
    /*跟新消息队列*/
    /*
     *
     *
     * 发送者 接受者 发送者类型 接受者类型 消息类型
     * (state角色0表示系统,1表示教师,2表示学生)(普通消息(0),作业消息(1))
     *
     *
     * */
    public void  updateMessages(int teacherid,Integer studentsid,int sendstate,int receivestate,int state,String info)
    {
    Meaasge message=new Meaasge();
    message.setSendid(teacherid);
    message.setReceid(studentsid);
    message.setSendstate(sendstate);
    message.setRecestate(receivestate);
    message.setState(state);
    message.setInfo(info);
    teacherService.insertMessage(message);
    }
    /*
    *
    * 向学生列表发送信息
    * 同时跟新消息队列
    *
    * */
    @Autowired
    SimpMessagingTemplate simpMessagingTemplate;
    public void sendMessagesToStudents(int teacherid,List<Integer> students,int sendstate,int receivestate,int state,String info) throws Exception {
        for(Integer student: students)
        {
            simpMessagingTemplate.convertAndSend("/topic/studentinfo/"+student+"/",info);// 向学生发送消息
            updateMessages(teacherid,student,sendstate,receivestate,state,info);//跟新消息队列
            studentService.receiveInfo(student);// 学生更新未读消息
        }
    }
 
    /*教师查询发布的作业*/
 
    @RequestMapping("/findallHomeworksbyteacherid")
    public @ResponseBody Map findallHomeworksbyteacherid(HttpServletRequest request)
    {
        Teacher user= (Teacher) request.getSession().getAttribute("user");
        List<Homework> messages= teacherService.findallHomeworksbyteacherid(user.getId());
        Map map=new LinkedHashMap();
        map.put("code", 0);
        map.put("msg", "查询成功");
        map.put("count", messages.size());
        map.put("data", messages);
        return map;
    }
 
    @RequestMapping("/checkhomeworkwork")
    public @ResponseBody Map checkhomeworkwork(HttpServletRequest request)
    {
        Teacher user= (Teacher) request.getSession().getAttribute("user");
        List<Homeworkinfo> messages= teacherService.checkhomeworkwork(user.getId());
        Map map=new LinkedHashMap();
        map.put("code", 0);
        map.put("msg", "查询成功");
        map.put("count", messages.size());
        map.put("data", messages);
        return map;
    }
 
    /*
    *
    * 修改作业
    *
    *
    * */
    @RequestMapping(value = "changePublishHomework")
    public @ResponseBody Map changePublishHomework(String id ,String time, String text,MultipartFile file, HttpServletRequest request)
    {
        Map map=new LinkedHashMap();
        map.put("code", 0);
        /*
         *
         * 将文件按照班级号+发布时间名命名
         * 存入upload文件夹
         *
         * 班级号 时间戳 文件名
         *
         * */
        Homework homework=new Homework();
        homework.setId(Integer.parseInt(id));
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:MM:SS");
        Date date1=null;
        Teacher user= (Teacher) request.getSession().getAttribute("user");
        try {
            date1 = format.parse(time);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        homework.setEtime(date1);
        List<Integer> students=teacherService.findStudentsbyHomeworkid(Integer.parseInt(id));
        String lastfilename=file.getOriginalFilename();
        lastfilename =lastfilename.substring(lastfilename.lastIndexOf('.'), lastfilename.length());
        /*文件名*/
        String filename=id+new Date().getTime()+lastfilename ;
        filename=filename.replace(":", "");
        homework.setFilename(filename);
        /*消息类型
         *
         * 消息类型:几班:xxlao老师:发布:xx作业
         * */
        String info=null;
        /*解析text*/
        homework.setText(text);
        boolean homeworkid=teacherService.changePublishHomework(homework);
        info=0+":"+id+"班:"+user.getName()+"老师:"+"修改:"+id+"作业";
        map.put("msg","作业发布成功");
        String path="D:\\upload";
        if(SaveFileUtil.savefile(path,filename,file))
        {
            map.put("msg", "作业修改成功");
            try {
                //老师id先写死
                sendMessagesToStudents(1,students,1,2,1,info);
 
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        else  map.put("msg", "作业修改失败,文件上传失败");
        return map;
    }
}

7.Html源码解析 :

login.html

<!doctype html>
<html  class="x-admin-sm" xmlns:th="http://www.thymeleaf.org">
<head>
	<meta charset="UTF-8">
	<title>作业管理系统登录</title>
	<meta name="renderer" content="webkit|ie-comp|ie-stand">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width,user-scalable=yes, minimum-scale=0.4, initial-scale=0.8,target-densitydpi=low-dpi" />
    <meta http-equiv="Cache-Control" content="no-siteapp" />
    <link rel="stylesheet" href="./css/font.css">
    <link rel="stylesheet" href="./css/xadmin.css">
    <link rel="stylesheet" href="./lib/layui/css/layui.css">
    <script type="text/javascript" src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
    <script src="./lib/layui/layui.js" charset="utf-8"></script>
    <!--[if lt IE 9]>
      <script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script>
      <script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
 
    <style type="text/css">
        body{color:#FFF;background:#E2E2E2 url(/images/bg.jpg) repeat-y center 0; text-align:center}
        #box{
            margin-top: 15%;
            margin-left: 35%;
            width:420PX;
            height:420PX;
            background-color:#E3D8D9;
            background: rgba(224,204,204,0.3);
        }
    </style>
</head>
<div id="box">
    <form class="layui-form"  style="opacity:1;" id="form">
        <br/><br/><br/><br/><br/><br/>
        <div class="layui-form-item">
            <label class="layui-form-label"><i class="layui-icon layui-icon-username" style="font-size: 15px;color:black;">用户名</i>  </label>
            <div class="layui-input-block">
                <input type="text" name="username" required   placeholder="请输入标题" autocomplete="off" class="layui-input">
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label"><i class="layui-icon layui-icon-password" style="font-size: 15px;color:black;">密码</i></label>
            <div class="layui-input-inline">
                <input type="password" name="password" required  placeholder="请输入密码" autocomplete="off" class="layui-input">
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label"><i class="layui-icon layui-icon-vercode" style="font-size: 15px;color:black;">验证码</i></label>
            <div class="layui-input-inline">
                <input type="text" name="validatecode" required  placeholder="请输入密码" autocomplete="off" class="layui-input">
            </div>
            <img id="suiji" src="/login/indentycode" alt="验证码" />
        </div>
        <div class="layui-form-item">
            <div class="layui-input-block">
                <button class="layui-btn"  lay-submit lay-filter="formDemo" >登录</button>
                <button type="reset" class="layui-btn layui-btn-primary">注册</button>
            </div>
        </div>
    </form>
    <!--调入自定义登录脚本-->
    <script th:src="@{/my_js/login.js}" type="text/javascript"></script>
</div>
</body>
</html>

关于其中x-admin.js和x-admin.css的下载,是调用layui集成好的开源框架,地址:http://x.xuebingsi.com/

直接免费下载。

index.html主页

<!doctype html>
<html class="x-admin-sm" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>作业管理主页</title>
        <meta name="renderer" content="webkit|ie-comp|ie-stand">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <!--<meta name="viewport" content="width=device-width,user-scalable=yes, minimum-scale=0.4, initial-scale=0.8,target-densitydpi=low-dpi" />-->
        <meta http-equiv="Cache-Control" content="no-siteapp" />
        <link rel="stylesheet" href="/css/font.css" th:href="@{/css/font.css}">
        <link rel="stylesheet" href="/css/xadmin.css" th:href="@{/css/xadmin.css}">
        <link rel="stylesheet" href="/lib/layui/css/layui.css" th:href="@{/lib/layui/css/layui.css}">
        <!-- <link rel="stylesheet" href="./css/theme5.css"> -->
 
        <!--IE8/9支持媒体查询,从而兼容栅格 -->
        <!--[if lt IE 9]>
          <script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script>
          <script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
        <![endif]-->
        <script>
            // 是否开启刷新记忆tab功能
            // var is_remember = false;
        </script>
    </head>
    <body class="index">
        <!-- 顶部开始 -->
        <div class="container">
            <div class="logo">
                <a href="./index.html">作业管理系统</a></div>
            <div class="left_open">
                <a><i title="展开左侧栏" class="layui-icon">&#xe668;</i> </a>
 
            </div>
            <ul class="layui-nav left fast-add" lay-filter="">
                <li class="layui-nav-item">
                    <a href="javascript:;">+新增</a>
                    <dl class="layui-nav-child">
                        <!-- 二级菜单 -->
                        <dd>
                            <a onclick="xadmin.open('最大化','http://www.baidu.com','','',true)">
                                <i class="layui-icon">&#xe65b;</i>弹出最大化</a></dd>
                        <dd>
                            <a onclick="xadmin.open('弹出自动宽高','http://www.baidu.com')">
                                <i class="layui-icon">&#xe65a;</i>弹出自动宽高</a></dd>
                        <dd>
                            <a onclick="xadmin.open('弹出指定宽高','http://www.baidu.com',500,300)">
                                <i class="layui-icon">&#xe602;</i>弹出指定宽高</a></dd>
                        <dd>
                            <a onclick="xadmin.add_tab('在tab打开','member-list.html')">
                                <i class="layui-icon">&#xe642;</i>在tab打开</a></dd>
                        <dd>
                            <a onclick="xadmin.add_tab('在tab打开刷新','member-del.html',true)">
                                <i class="layui-icon">&#xe638;</i>在tab打开刷新</a></dd>
                    </dl>
                </li>
            </ul>
            <ul class="layui-nav right" lay-filter="">
                <li class="layui-nav-item">
                    <a href="javascript:;" id="judge"><i class="layui-icon"  style="font-size:20px;">&#xe611;</i>消息</a>
                    <dl class="layui-nav-child" id="messageBox">
                        <!--&lt;!&ndash; 二级菜单 &ndash;&gt;-->
                        <!--<dd>-->
                            <!--<a onclick="xadmin.open('个人信息','http://www.baidu.com')">个人信息</a></dd>-->
                        <!--<dd>-->
                            <!--<a onclick="xadmin.open('切换帐号','http://www.baidu.com')">切换帐号</a></dd>-->
                        <!--<dd>-->
                            <!--<a href="./login.html">退出</a></dd>-->
                    </dl>
                </li>
                <li class="layui-nav-item">
                    <a href="javascript:;" th:text="${session.user.name}"></a>
                    <dl class="layui-nav-child">
                        <!-- 二级菜单 -->
                        <dd>
                            <a onclick="xadmin.open('个人信息','http://www.baidu.com')">个人信息</a></dd>
                        <dd>
                            <a onclick="xadmin.open('切换帐号','http://www.baidu.com')">切换帐号</a></dd>
                        <dd>
                            <a href="./login.html">退出</a></dd>
                    </dl>
                </li>
                <li class="layui-nav-item to-index">
                    <a href="javascript:void(0);">回到主页</a></li>
            </ul>
        </div>
        <!-- 顶部结束 -->
        <!-- 中部开始 -->
        <!-- 左侧菜单开始 -->
        <div class="left-nav">
            <div id="side-nav">
                <ul id="nav">
                    <li>
                        <a href="javascript:;">
                            <i class="layui-icon left-nav-li" lay-tips="作业管理">&#xe705;</i>
                            <cite>作业管理</cite>
                            &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;
                            <i class="layui-icon ">&#xe603;</i></a>
                        <ul class="sub-menu">
                            <li>
                                <a onclick="xadmin.add_tab('发布作业','publishomework')">
                                    <i class="layui-icon">&#xe602;</i>
                                    <cite>发布作业</cite></a>
                            </li>
                            <li>
                                <a onclick="xadmin.add_tab('修改作业','edithomeworkwork')">
                                    <i class="layui-icon">&#xe602;</i>
                                    <cite>修改作业</cite></a>
                            </li>
                            <li>
                                <a onclick="xadmin.add_tab('批改作业','checkhomeworkwork',true)">
                                    <i class="layui-icon">&#xe602;</i>
                                    <cite>批改作业</cite></a>
                            </li>
                            <li>
                                <a onclick="xadmin.add_tab('测试','test',true)">
                                    <i class="layui-icon">&#xe602;</i>
                                    <cite>测试</cite></a>
                            </li>
                        </ul>
                    </li>
                    <li>
                        <a href="javascript:;">
                            <i class="layui-icon left-nav-li" lay-tips="教师通知管理模块">&#xe609;</i>
                            <cite>教师通知管理模块</cite>
                            &nbsp;&nbsp; &nbsp;&nbsp;
                            <i class="layui-icon ">&#xe603;</i></a>
                            <ul class="sub-menu">
                            <li>
                                <a onclick="xadmin.add_tab('发布通知','order-list.html')">
                                    <i class="layui-icon">&#xe602;</i>
                                    <cite>发布通知</cite></a>
                            </li>
                            <li>
                                <a onclick="xadmin.add_tab('查看通知','order-list1.html')">
                                    <i class="layui-icon">&#xe602;</i>
                                    <cite>查看通知</cite></a>
                            </li>
                        </ul>
                    </li>
                    <li>
                        <a href="javascript:;">
                            <i class="layui-icon left-nav-li" lay-tips="学生通知管理模块">&#xe613;</i>
                            <cite>学生通知管理模块</cite>
                            &nbsp;&nbsp; &nbsp;&nbsp;
                            <i class="layui-icon ">&#xe603;</i></a>
                        <ul class="sub-menu">
                            <li>
                                <a onclick="xadmin.add_tab('查看消息','studentReceiveMessages')">
                                    <i class="layui-icon">&#xe602;</i>
                                    <cite>查看消息</cite></a>
                            </li>
                            <li>
                                <a onclick="xadmin.add_tab('查看作业','StudentReceiveHomeworks')">
                                    <i class="layui-icon">&#xe602;</i>
                                    <cite>查看作业</cite></a>
                            </li>
                        </ul>
                    </li>
 
                </ul>
            </div>
        </div>
        <!-- <div class="x-slide_left"></div> -->
        <!-- 左侧菜单结束 -->
        <!-- 右侧主体开始 -->
        <div class="page-content">
            <div class="layui-tab tab" lay-filter="xbs_tab" lay-allowclose="false">
                <ul class="layui-tab-title">
                    <li class="home">
                        <i class="layui-icon">&#xe68e;</i>我的桌面</li></ul>
                <div class="layui-unselect layui-form-select layui-form-selected" id="tab_right">
                    <dl>
                        <dd data-type="this">关闭当前</dd>
                        <dd data-type="other">关闭其它</dd>
                        <dd data-type="all">关闭全部</dd></dl>
                </div>
                <div class="layui-tab-content">
                    <div class="layui-tab-item layui-show">
                        <iframe src='/welcome' frameborder="0" scrolling="yes" class="x-iframe"></iframe>
                        <!--<iframe th:src='@{/welcome.html}' frameborder="0" scrolling="yes" class="x-iframe"></iframe>-->
                    </div>
                </div>
                <div id="tab_show"></div>
            </div>
        </div>
        <div class="page-content-bg"></div>
        <style id="theme_style"></style>
    <script src="/my_js/mywebscoket.js"></script>
    <script src="/lib/layui/layui.js" charset="utf-8" th:src="@{/lib/layui/layui.js}"></script>
    <script type="text/javascript" src="/js/xadmin.js" th:src="@{/js/xadmin.js}"></script>
    <!--<script th:src="@{/webjars/jquery/jquery.min.js}"  type="text/javascript"></script>-->
    <script th:src="@{/webjars/sockjs-client/sockjs.min.js}"  type="text/javascript"></script>
    <!--<script th:src="@{/webjars/jquery/jquery.min.js}"  type="text/javascript"></script>-->
    <script th:src="@{/webjars/stomp-websocket/stomp.min.js}"  type="text/javascript"></script>
    <script>
        window.onload=function () {
            /*
            *
            * 进行用户角色的判断
            *
            * */
            // 注意:导航 依赖 element 模块,否则无法进行功能性操作
            layui.use('element', function(){
                var element = layui.element;
            });
            var state='[[${session.user.photo}]]'; // --获取session中的值
            var id='[[${session.user.id}]]';
            if (state.length>3)// 学生连接
            {
                studentconnect(id);
            }
            else {// 教师连接
                teacherconnect(id);
            }
        }
 
        /*
          *
          *
          * 自定义定时器 为存在消息的图标添加样式
          *
          *
          * */
        layui.use(['layer','jquery'],function(){
            var $ = layui.$;
            function check(){
                if ($("#messageBox").children().length>0)
                {
                    // 有新消息
                    var info='<i class="layui-icon"  style="font-size:25px;color:red;">&#xe611;</i><font style="color:red;">'+$("#messageBox").children().length+'</font>新消息';
                    $("#judge").html(info);
                }
                else{
                    // 无新消息
                    var info='<i class="layui-icon"  style="font-size:20px;">&#xe611;</i>消息';
                    $("#judge").html(info);
                    // console.log("replypoint无消息");
                }
            }
            window.setInterval(check, 1000);
 
        });
    </script>
    </body>
</html>

其他页面基本相似

8.项目总结与展望

对这个项目的总结:熟悉了springboot的基本项目该怎样去做,对Layui进一步了解(本来是准备用vue做的,还不太熟悉,所以采用了Layui),对websocket消息推送进一步了解,对springsecurity的配置能有了宏观的掌握。

展望:希望自己这个小白能在编程之路上越走越远。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值