功能:用户登陆,用户注册。登陆成功可以进去员工管理界面,可以增删改查里面的员工信息,提交后保存到后台数据库。
新建立一个module,使用快捷开发,项目名 ems ,
SpringBoot 版本号改成 2.1.13
删除一些文件,在 resources 中添加 application.yml
在 ems 包中再建立一个 controller包,里面写一个 TestController 类。
package com.baizhi.ems.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("test")
public class TestController {
@GetMapping("test")
public String test(){
System.out.println("test method invoke!!");
return "test method ok";
}
}
再点击右上方的运行。springBoot 运行起来之后,在网页输入 localhost:8080/test/test
不过因为我版本问题,在控制台中输入结果一样。
在 main 中建立一个新的 webapp 包,创建一个 index.jsp
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
springboot项目测试jsp页面hello world
然后重启去访问这个index.jsp
运行不起来,因为没有引入 jsp 的依赖
在 pom.xml 文件中加入
org.springframework.boot
spring-boot-starter-tomcat
org.apache.tomcat.embed
tomcat-embed-jasper
jar 包没有下载好,问题已经解决,
1.点击"MAVEN PROJECT",打开当前项目;
2.点击"lifecycle";
3.点击运行clear,清除上一次项目运行的数据结果;
4.点击运行"install",将项目输出组件部署到本地项目中。
在 application.yml 中添加
spring:
mvc:
view:
prefix: /
suffix: .jsp
启动了一次,发现还是访问不了 index.jsp
在
IDEA把工作目录指定为当前模块工作的目录
$MODULE_DIR$
此时springboot项目才能顺利找到 jsp 文件。
重新启动项目:
这里应该是上面的问题
为了在访问 jsp 加个项目 ems 的名字,需要在 application.yml 中添加
spring:
mvc:
view:
prefix: /
suffix: .jsp
server:
servlet:
context-path: /ems # 设置项目名称
此时除了访问 jsp 的路径变成了 localhost:8080/ems/index.jsp
甚至访问控制器也需要加 ems
重启之后继续访问,上一条是没有加 ems 的,下面加了就显示了 index.jsp 内容,虽然不完善。
访问控制器:
如果以后有微服务,就需要给应用添加名字,在 application.xml 中添加
spring:
mvc:
view:
prefix: /
suffix: .jsp
application:
name: ems #应用服务名称
server:
servlet:
context-path: /ems # 设置项目名称
以上是第一节,ems 项目环境搭建
第二节: ems 项目库表结构分析
功能:用户登陆,用户注册。登陆成功可以进去员工管理界面,可以增删改查里面的员工信息,提交后保存到后台数据库。
整个项目有两个大的模块,也就是两个大的表,一个是用户表,一个是员工表。
用户表,有用户名、真实姓名、密码、性别这四个字段。
员工表,有员工ID、姓名、工资、年龄、这四个字段。
然后新建立数据库
然后新建查询,
create table t_user(
id varchar(40) primary key,
username varchar(40),
realname varchar(40),
password varchar(60),
sex varchar(4)
);
create table t_emp(
id varchar(40) primary key,
name varchar(40),
salary double(7,2),
age int(3)
);
(注意输入要仔细,输错了两个地方)
为了保存表结构,把上面创建表的sql保存到 recourses中
此时数据库中的表也搭建成功了
下一部分是SpringBoot 与 Mybatis 的搭建
在 pom.xml 中添加依赖
值得注意的是,一般会认为先添加 mybatis 核心依赖,再引入 springboot 和 mybatis 的依赖,其实大可不必的,因为后者包含了前者。所以,在pom.xml 中添加这一个依赖就可以了。
Mybatis 是对 jdbc 的封装,所以还需要一个数据源的依赖。
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.1.0
com.alibaba
druid
1.1.19
mysql
mysql-connector-java
5.1.38
org.projectlombok
lombok
1.18.8
provided
在 application.yml 中添加
spring:
mvc:
view:
prefix: /
suffix: .jsp
datasource:
driver-class-name: com.mysql.jdbc.Driver #注册驱动
url: jdbc:mysql://localhost:3306/ems?characterEncoding=UTF-8
username: root
password: root
mybatis:
mapper-locations: classpath:com/baizhi/ems/mapper/*.xml #mapper配置文件的位置
type-aliases-package: com.baizhi.ems.entity #存放数据库中实体对象
server:
servlet:
context-path: /ems # 设置项目名称
在mybatis 一栏,建立两个路径。
然后
添加 @mapperScan,响应位置创建 dao
然后在 entity 中创建 User.java
package com.baizhi.ems.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.ToString;
import lombok.experimental.Accessors;
@Data
@ToString
@AllArgsConstructor
@Accessors(chain=true)
public class User {
private String id;
private String username;
private String realname;
private String password;
private String sex;
}
接着在 dao 中添加一个接口,UserDAO
package com.baizhi.ems.dao;
import com.baizhi.ems.entity.User;
public interface UserDAO {
//保存用户的方法
void save(User user);
}
这里应该对应
在 recourse 、mapper 中建立 UserDAOMapper.xml
insert into t_user values (#{id},#{username},#{realname},#{password},#{sex})
select id,username,realname,password,sex from t_user where username=#{username} and password=#{password}
然后就可以测试一下,
这个路径下新建一个 TestUserDAO
这里报错,但是仍然可以运行。
package com.baizhi.ems;
import com.baizhi.ems.dao.UserDAO;
import com.baizhi.ems.entity.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.UUID;
@SpringBootTest(classes = EmsApplication.class)
@RunWith(SpringRunner.class)
public class TestUserDAO {
@Autowired
private UserDAO userDAO;
@Test
public void testSave(){ userDAO.save(new User(UUID.randomUUID().toString(),"xiaochen","陈艳男","123","男")); }
}
到数据库中查看
插入成功!
第四部分验证功能的实现
在 webapp 下面床架一个 ems ,然后把
这些都复制过来。
regist.html copy一份 jsp 文件
然后把 index.jsp 的头部复制到 regist.jsp 头部
然后运行
跑起来之后,在浏览器中输入:
在 jsp 中修改,此时刷新页面不会有反应,需要重启 SpringBoot ,有没有什么办法可以快捷一点呢?
有,在 application.yml 中添加 jsp 热部署
spring:
mvc:
view:
prefix: /
suffix: .jsp
datasource:
driver-class-name: com.mysql.jdbc.Driver #注册驱动
url: jdbc:mysql://localhost:3306/ems?characterEncoding=UTF-8
username: root
password: root
mybatis:
mapper-locations: classpath:com/baizhi/ems/mapper/*.xml #mapper配置文件的位置
type-aliases-package: com.baizhi.ems.entity #存放数据库中实体对象
server:
servlet:
context-path: /ems # 设置项目名称
jsp:
init-parameters:
development: true #开启jsp页面热部署
改完之后实时刷新。
然后验证码有个类,没有必要去写,直接百度就行。
创建一个 packet ,放进验证码类
package com.baizhi.ems.utils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Random;
public class ValidateImageCodeUtils {
/**
* 验证码难度级别 Simple-数字 Medium-数字和小写字母 Hard-数字和大小写字母
*/
public enum SecurityCodeLevel {
Simple, Medium, Hard
};
/**
* 产生默认验证码,4位中等难度
*
* @return
*/
public static String getSecurityCode() {
return getSecurityCode(4, SecurityCodeLevel.Medium, false);
}
/**
* 产生长度和难度任意的验证码
*
* @param length
* @param level
* @param isCanRepeat
* @return
*/
public static String getSecurityCode(int length, SecurityCodeLevel level, boolean isCanRepeat) {
// 随机抽取len个字符
int len = length;
// 字符集合(--除去易混淆的数字0,1,字母l,o,O)
char[] codes = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
};
// 根据不同难度截取字符串
if (level == SecurityCodeLevel.Simple) {
codes = Arrays.copyOfRange(codes, 0, 10);
} else if (level == SecurityCodeLevel.Medium) {
codes = Arrays.copyOfRange(codes, 0, 36);
}
// 字符集和长度
int n = codes.length;
// 抛出运行时异常
if (len > n && isCanRepeat == false) {
throw new RuntimeException(String.format("调用SecurityCode.getSecurityCode(%1$s,%2$s,%3$s)出现异常," + "当isCanRepeat为%3$s时,传入参数%1$s不能大于%4$s", len, level, isCanRepeat, n));
}
// 存放抽取出来的字符
char[] result = new char[len];
// 判断能否出现重复字符
if (isCanRepeat) {
for (int i = 0; i < result.length; i++) {
// 索引0 and n-1
int r = (int) (Math.random() * n);
// 将result中的第i个元素设置为code[r]存放的数值
result[i] = codes[r];
}
} else {
for (int i = 0; i < result.length; i++) {
// 索引0 and n-1
int r = (int) (Math.random() * n);
// 将result中的第i个元素设置为code[r]存放的数值
result[i] = codes[r];
// 必须确保不会再次抽取到那个字符,这里用数组中最后一个字符改写code[r],并将n-1
codes[r] = codes[n - 1];
n--;
}
}
return String.valueOf(result);
}
/**
* 生成验证码图片
* @param securityCode
* @return
*/
public static BufferedImage createImage(String securityCode){
int codeLength = securityCode.length();//验证码长度
int fontSize = 18;//字体大小
int fontWidth = fontSize+1;
//图片宽高
int width = codeLength*fontWidth+6;
int height = fontSize*2+1;
//图片
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = image.createGraphics();
g.setColor(Color.WHITE);//设置背景色
g.fillRect(0, 0, width, height);//填充背景
g.setColor(Color.LIGHT_GRAY);//设置边框颜色
g.setFont(new Font("Arial", Font.BOLD, height-2));//边框字体样式
g.drawRect(0, 0, width-1, height-1);//绘制边框
//绘制噪点
Random rand = new Random();
g.setColor(Color.LIGHT_GRAY);
for (int i = 0; i < codeLength*6; i++) {
int x = rand.nextInt(width);
int y = rand.nextInt(height);
g.drawRect(x, y, 1, 1);//绘制1*1大小的矩形
}
//绘制验证码
int codeY = height-10;
g.setColor(new Color(19,148,246));
g.setFont(new Font("Georgia", Font.BOLD, fontSize));
for(int i=0;i
double deg=new Random().nextDouble()*20;
g.rotate(Math.toRadians(deg), i*16+13,codeY-7.5);
g.drawString(String.valueOf(securityCode.charAt(i)), i*16+5, codeY);
g.rotate(Math.toRadians(-deg), i*16+13,codeY-7.5);
}
g.dispose();//关闭资源
return image;
}
public static void main(String[] args) throws IOException {
String securityCode = ValidateImageCodeUtils.getSecurityCode();
System.out.println(securityCode);
BufferedImage image = ValidateImageCodeUtils.createImage(securityCode);
ImageIO.write(image,"png",new FileOutputStream("aa.png"));
}
}
在放进去之后,测试一下,发现报错:
那我暂时不管,继续跑流程
首先写一个控制类的请求,给图片路径,让他的 src 去访问这个请求。返回一个图片,就可以了。
新建立一个 UserController
在 pom.xml 中引入一个依赖
javax.servlet
servlet-api
2.5
provided
UserController
package com.baizhi.ems.controller;
import com.baizhi.ems.utils.ValidateImageCodeUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
@Controller
@RequestMapping("user")
public class UserController {
//生成验证码
@GetMapping("getImage")
public void getImage(HttpSession sesssion, HttpServletResponse response) throws IOException{
//生成验证码
String securityCode = ValidateImageCodeUtils.getSecurityCode();
// 将验证码方式 session
sesssion.setAttribute("code",securityCode);
//生成图片
BufferedImage image =ValidateImageCodeUtils.createImage(securityCode);
//输出图片
ServletOutputStream os = response.getOutputStream();
//调用工具类
ImageIO.write(image,"png",os);
}
}
再重启项目
重启之后:
接下来只需要把 图片放到 后者页面的 src 中就行了。
在 regist.jsp 中
成功啦,接下来需要做的是点击换一张!!!
复制粘贴到 image
验证码功能就成功啦!
用户注册功能
实际上是用户的保存,只需要把用户输入的参数,通过后端控制器的方法接受到,并保存到数据库中的一个过程。
在 regist.jsp 中
修改上述地方。
然后在 UserController 中增加
//开发用户注册
@PostMapping("regist")
public String regist(User user,String code,HttpSession session){
System.out.println("user = " + user);
//1.判断验证码是否通过
if(session.getAttribute("code").toString().equalsIgnoreCase(code)){//2.通过之后注册
userService.save(user);
return "redirect:/ems/login.jsp";
}else{//3.验证码不通过 直接回到注册页面
return "redirect:/ems/regist.jsp";
}
}
创建一个packet,叫 service,在里面创建一个 UserService 的接口。
package com.baizhi.ems.service;
import com.baizhi.ems.entity.User;
public interface UserService {
void save(User user);
}
用 save 方法来保存
然后在 service 中新建一个 UserServiceImpl 。
package com.baizhi.ems.service;
import com.baizhi.ems.dao.UserDAO;
import com.baizhi.ems.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.UUID;
@Service
@Transactional
public class UserServiceImpl implements UserService{
@Autowired
private UserDAO userDAO;
@Override
public void save(User user) {
user.setId(UUID.randomUUID().toString());
userDAO.save(user);
}
}
但是我的 setId 报错
Cannot resolve method 'setId' in 'User'
不管他,此时 UserServiceImpl 和 test 都标红,但是不影响。(上面的 userDAO 虽然红色,但是是正常使用的)
然后在 UserController 中添加
@Autowired
private UserService userService;
然后重启。
密码是 123
刷新数据库,居然保存到数据库中去了。!!!
报错原因是我还没有 login.jsp
在 IDEA 中。
然后把 regist.jsp 的头部复制到 login.jsp 头部。
重启项目!把数据库中的数据给清除掉。
成功跳转!!!
我的天,之前UserServiceImpl 上的两个报错,运行起来都没有任何问题!
在数据库中刷新一次,记录出来了。
下一个部分,登陆功能!
用户登陆
其实是根据用户名密码,去数据库中查询是否有符合的数据,
如果有,就放行,没有,返回登陆界面。
现在 UserController 中添加
//开发用户登录
@RequestMapping("login")
public String login(String username,String password,HttpSession session){
User user = userService.login(username, password);
//判断 user 为空 用户户名密码错误 //不为空 登录成功
if(user!=null){
session.setAttribute("user",user);
return "redirect:/emp/findAll";//查询员工的所有
}else{
return "redirect:/ems/login.jsp";
}
}
在 UserService 中添加
package com.baizhi.ems.service;
import com.baizhi.ems.entity.User;
public interface UserService {
//保存用户
void save(User user);
//登录
User login(String username,String password);
}
之后在 业务层 UserServiceImpl 中去做实现
@Override
public User login(String username, String password) {
return userDAO.findByUsernameAndPassword(username,password);
}
这里依然会报错,在 DAO 中创建这个方法。
在 mapper 中去做实现
添加
select id,username,realname,password,sex from t_user where username=#{username} and password=#{password}
然后 在 login.jsp 中修改这个
修改完之后重新启动一下。
没有我想要的效果
copy 一个 emplist.jsp 文件,然后找个 jsp 文件头部复制过去。修改样式
有个问题,这个页面刷新,需要重新登录,这就造成了表单重复提交。
前面有误,根据这个来写代码
重启之后
进入这个页面,密码 123
登录成功!!!
下一个部分:员工列表功能
在里面创建一个实体类 emp
package com.baizhi.ems.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class emp {
private String id;
private String name;
private Double salary;
private Integer age;
}
然后去开发相应的接口
然后 copy 一份。
构建一个 EmpService 接口。
再整一个实现类
在 EmpService 中创建这个方法
在 EmpServiceImpl 实现类中。
@Service
@Transactional
public class EmpServiceImpl implements EmpService{
@Autowired
private EmpDAO empDAO;
@Override
public List findAll() {
return empDAO.findAll();
}
}
然后在
在 EmpController 中
@Controller
@RequestMapping("emp")
public class EmpController {
@Autowired
private EmpService empService;
//查询所有
@GetMapping("findAll")
public String findAll(Model model){
List emps = empService.findAll();
model.addAttribute("emps",emps);
return "ems/emplist";
}
}
再去 emplist .jsp中
删除 68 - 84 ,也就是删除一行,我们这里做遍历
先去 pom.xml 添加依赖
jstl
jstl
1.2
添加 52-54 行,移动 55-71行 到52-54 之间
再修改这几个
再修改 UserController
修改之后,重启动项目
成功!!!
需要从第一步骤开始输入信息!!!
添加员工功能!
点击添加员工按钮之后,会返回到添加员工页面。
同理,添加 jsp 头部
修改这个样式,75 行
重启项目,顺利访问到下面的页面,密码都是 123456
在 EmpController 中写入保存员工的方法
save点击去,在 EmpService 中创建一个 save 方法就行。
然后在相对应的业务层中去实现 save 方法。
setId 这里不用管,右边的红色标错没有提示
下面的 save 到相应的 EmpDAO 中去
然后到 EmpDAOMapper 中去添加
insert into t_emp values (#{id},#{name},#{salary},#{age})
然后在 addEmp.jsp 中的 35 行修改成自己的路径
重启项目
成功
反复测试,并成功!!!
删除员工功能实现
点击 delete ,会把当前记录的 ID 传给后端,后端再从数据库中去找并删除。
在 EmpController 中
delete 标红的部分,去 EmpService 中创建创建就行。
然后去业务层 EmpServiceImpl 具体实现就行。
标红的部分
去 EmpDAO 中去创建就行了
接下来去 mapper 中去做对应的实现。
EmpDAOMapper
添加
delete from t_emp where id = #{id}
重启项目,然后运行,成功!!!
更新员工信息功能!
修改(更新)
点击按钮,需要先在数据库中去把这个记录给查询出来,然后在修改页面进行修改,展示,然后保存、提交。
所以修改一定是先查询,再修改。
首先点击链接,是先根据 id 去查询这个记录 ,
先去修改他的链接
在 emplist.jsp 中
然后在 EmpController 中
findById 去 EmpService 中
接下来是在 业务层中做进一步的实现
EmpServiceImpl 去重写
在 EmpDAO 中
在 EmpDAOMapper 中添加
select id,name,salary,age from t_emp where id = #{id}
整一个 updateEmp.jsp ,头部复制起来。
然后在 updateEmp.jsp 中,修改成这四部分。
重启项目
见到这个,第一部分成功!
第二部分,
直接在上图中修改完之后,直接提交给我们的控制器。再根据 id 保存到我们的数据库中的。
更新的时候,我们会把用户的 id 给传回去。所以需要给 id 做一个隐藏域。
最后在 EmpController 中开发最后一个功能
标红的地方同样的在 EmpService 中添加
然后在业务层 EmpServiceImpl 中
override 更新方法
最后 在EmpDAOMapper 中做最后的实现
update t_emp set name=#{name},salary=#{salary},age=#{age} where id = #{id}
说一下刚刚报错的地方
最后重启项目:成功!!!
整个小项目就写完啦,所有功能!