springboot中大家比较常用的是HandlerInterceptor接口,可是我不太习惯,习惯了使用servlet下的filter接口,以及jsp网页形式,所以不想改习惯。我一直觉得,编程语言这东西,各种语言以及语法都各有优劣,好坏不好乱下定义,但是最重要的,可能还是根据你的习惯来选择吧。话不多说,做一下记录吧。数据库的连接配置就不多说了,我用的mysql数据库。
大概分为七步走:
- 1.修改springboot的配置参数,包括jsp以及数据库的一些配置。
- 2.创建一个实体类,取用用户名密码。创建一个数据库,并且创建一张表格,用来存储用户名、密码。
- 3.添加一个springdata JPA来从数据库中查询匹配结果,用作用户名密码的匹配。
- 4.修改启动项中的注解,来注入servlet的使用。启动项一般都是以XXXApplication.java。
- 5.创建login.jsp登录页面,和index.jsp结果显示页面。
- 6.创建LoginController和IndexController,在此进行用户名以及密码的进行匹配,根据结果来控制页面跳转。
- 7.添加filter拦截器,匹配是否登录成功。
先看看我的目录架构
再看一样我的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 https://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.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
一、springboot的参数配置
我自行创建了一个appliacation.yml的配置文件
内容如下:
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf-8
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root
jpa:
#本地sql方言
database: mysql
show-sql: true #用来在控制台输出JPA自动生成的sql语句
hibernate:
ddl-auto: update #需要手动创建数据库,除此,数据表之类的无需手动创建。
mvc:
view:
prefix: /WEB-INF/jsp/
suffix: .jsp
二、创建一个实体类,并创建一个数据库,用来存储用户名密码
package com.example.demo.entity;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import com.alibaba.fastjson.annotation.JSONField;
@Entity//表示这是一个和数据库相关联的类
@Table(name="t_user")
public class UserEntity implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
@Id//主键
@GeneratedValue//自增长
private Long id;
@Column(name = "t_name")
private String name;
@Column(name = "t_pwd")
private String pwd;
public UserEntity()
{
}
public UserEntity(String name, int age,Date createTime,String pwd)
{
this.name = name;
this.pwd=pwd;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id=id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name=name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd=pwd;
}
}
上面就是创建了一个实体类。
然后,需要手动创建一个叫test的数据库,或者你在配置文件applicaiton.yml中自行命名的数据库名称,名称要对应上,除此,数据表之类的无需手动创建,会根据实体类自行创建。
然后在数据库中存入一些用户名密码,数据库的操作方法我就不多说了。用mysql的话可以用navicat软件进行管理。
三、添加一个SPRINGDATA JPA使用数据库
package com.example.demo.jpa;
import java.io.Serializable;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import com.example.demo.entity.UserEntity;
//数据访问接口
public interface UserJPA extends JpaRepository<UserEntity, Long>,
JpaSpecificationExecutor<UserEntity>,Serializable{
}
对,里面不需要东西,因为我们会使用到的数据库函数,都是他自带的一些函数,我们会用到findOne(),函数,就包含在JpaSpecificationExecutor中。
四、修改启动项,添加对servlet的支持
package com.example.demo;
import java.util.ArrayList;
import java.util.List;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.Bean;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
@SpringBootApplication
//添加下面这个注释,然后就可以在springboot中使用servlet了
@ServletComponentScan
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
重点在@ServletComponentScan,这个注释,很简单,就添加一个这个就行。
五、创建login.jsp和index.jsp
这一步本身很简单,不过需要注意,在springboot中默认是没有给你预留放jsp文件的地方的,这个文件目录需要自己创建,并且在applicaition.yml中标志好。我的目录在最前面那张图中已经展示了。
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>login.jsp</title>
</head>
<body>
<form method="get" action="/user/login">
用户名:<input type="text" name="name"/><br/>
密码:<input type="text" name="pwd"/>
<input type="submit" value="登录">
</form>
</body>
</html>
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>index.jsp</title>
</head>
<body>
您未通过登录界面,直接访问到该网页!
</body>
</html>
login.jsp的作用是作为登录界面用。index.jsp没啥用处。
六、创建LoginController和IndexController两个跳转的管理类
在这一部分,就是核心部分,就是进行用户名密码的匹配,并根据结果进行跳转。懒得废话,直接贴代码:
LoginController
package com.example.demo.controller;
import java.util.Optional;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.entity.UserEntity;
import com.example.demo.jpa.UserJPA;
@RestController
@RequestMapping(value = "/user")
public class LoginController {
@Autowired
private UserJPA UserJPA;
@RequestMapping(value = "/login",produces = "text/plain;charset=utf-8")//设置输出到页面的中文位utf-8,不然会出现乱码
public String login(UserEntity user,HttpServletRequest request) {
boolean flag=true;
String result= "登录成功";
//匿名内部类
/**
* 自定义查询条件
* 1.实现Specification接口(提供泛型:查询的对象类型)
* 2.实现toPredicate方法(构造查询条件)
* 3.需要借助方法参数中的两个参数(
* root:获取需要查询的对象属性
* CriteriaBuilder:构造查询条件的,内部封装了很多的查询条件(模糊匹配,精准匹配)
* )
* 案例:根据客户名称查询,查询客户名为传智播客的客户
* 查询条件
* 1.查询方式
* cb对象
* 2.比较的属性名称
* root对象
*
*/
Specification<UserEntity> spec = new Specification<UserEntity>() {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public Predicate toPredicate(Root<UserEntity> root, CriteriaQuery<?> query,
CriteriaBuilder criteriaBuilder) {
//添加限制条件,root查询的是属性名,不是表的字段名
Predicate p1=criteriaBuilder.equal(root.get("name"),user.getName());
//把Predicate应用到CriteriaQuery中去,因为还可以给CriteriaQuery添加其他的功能,比如排序、分组啥的
query.where(p1);
return query.getRestriction();
// TODO Auto-generated method stub
}
};
Optional<UserEntity> find = UserJPA.findOne(spec);
if(find==null) {
flag=false;
result="用户不存在,登录失败";
}else if(!find.get().getPwd().equals(user.getPwd())) {
flag=false;
result="用户密码不相符,登录失败";
}
//登录成功
if(flag) {
//将用户写入session
request.getSession().setAttribute("session_user", find.get());
}
return result;
}
}
IndexController
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
@RequestMapping("/user")
public class IndexController {
/**
* 初始化登录页面
* @return
*/
@RequestMapping(value = "/login_view",method = RequestMethod.GET)
public String login_view() {
return "login";
}
@RequestMapping(value = "/index",method = RequestMethod.GET)
public String index() {
return "index";
}
}
七、添加过滤器,实现过滤。
在这里,我将要servlet的过滤器filter,在springboot中不能直接创建filter过滤器,需要先创建普通的class类,然后修改成filter,当然,直接从别处复制应该也可以。
package com.example.demo.controller;
import java.util.Optional;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.entity.UserEntity;
import com.example.demo.jpa.UserJPA;
@RestController
@RequestMapping(value = "/user")
public class LoginController {
@Autowired
private UserJPA UserJPA;
@RequestMapping(value = "/login",produces = "text/plain;charset=utf-8")//设置输出到页面的中文位utf-8,不然会出现乱码
public String login(UserEntity user,HttpServletRequest request) {
boolean flag=true;
String result= "登录成功";
//匿名内部类
/**
* 自定义查询条件
* 1.实现Specification接口(提供泛型:查询的对象类型)
* 2.实现toPredicate方法(构造查询条件)
* 3.需要借助方法参数中的两个参数(
* root:获取需要查询的对象属性
* CriteriaBuilder:构造查询条件的,内部封装了很多的查询条件(模糊匹配,精准匹配)
* )
* 案例:根据客户名称查询,查询客户名为传智播客的客户
* 查询条件
* 1.查询方式
* cb对象
* 2.比较的属性名称
* root对象
*
*/
Specification<UserEntity> spec = new Specification<UserEntity>() {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public Predicate toPredicate(Root<UserEntity> root, CriteriaQuery<?> query,
CriteriaBuilder criteriaBuilder) {
//添加限制条件,root查询的是属性名,不是表的字段名
Predicate p1=criteriaBuilder.equal(root.get("name"),user.getName());
//把Predicate应用到CriteriaQuery中去,因为还可以给CriteriaQuery添加其他的功能,比如排序、分组啥的
query.where(p1);
return query.getRestriction();
// TODO Auto-generated method stub
}
};
Optional<UserEntity> find = UserJPA.findOne(spec);
if(find==null) {
flag=false;
result="用户不存在,登录失败";
}else if(!find.get().getPwd().equals(user.getPwd())) {
flag=false;
result="用户密码不相符,登录失败";
}
//登录成功
if(flag) {
//将用户写入session
request.getSession().setAttribute("session_user", find.get());
}
return result;
}
}
测试结果
在运行之后,登录http://127.0.0.1:8080/user/login_view会出现这样如下界面:
输入你之前存储好的用户名,密码。如果正确,页面会变为如下内容,注意,这时候页面未跳转,只是内容变化了。
如果这时候你把地址改成,http://127.0.0.1:8080/user/index,这时候会变成如下界面,这个是绕过了用户名密码以后的直接登录。