Day01
软件开发流程(面试题)
三种软件环境
项目中用到的技术
功能架构
数据库表的设计
yml配置
server:
port: 8080
spring:
application:
# 应用的名称 可选择配置
name: reggie_take_out
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/reggie?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: root
mybatis-plus:
configuration:
# address_book ----->AddressBook
#在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
id-type: ASSIGN_ID
设置静态资源映射
@Slf4j
@Configuration
public class WebMVCConfig extends WebMvcConfigurationSupport {
/**
* 设置静态资源映射
* @param registry
*/
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
log.info("开始进行静态资源映射...");
registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");
}
登录接口
@RequestBody
主要用于接收前端传递给后端的json字符串(请求体中的数据)HttpServletRequest
作用:如果登录成功,将员工对应的id存到session一份,这样想获取一份登录用户的信息就可以随时获取出来
@RestController
@Slf4j
@RequestMapping("/employee")
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
/**
* 登录功能
*
* @param request
* @param employee
* @return
* @RequestBody 主要用于接收前端传递给后端的json字符串(请求体中的数据)
* HttpServletRequest 作用:如果登录成功,将员工对应的id存到session一份,这样想获取一份登录用户的信息就可以随时获取出来
*/
@PostMapping("/login")
// wrapper.eq("实体类::查询字段", "条件值"); //相当于where条件
public R<Employee> login(HttpServletRequest request, @RequestBody Employee employee) {
//1 将页面提交的密码进行md5加密
String password = employee.getPassword();
password = DigestUtils.md5DigestAsHex(password.getBytes());
//2 根据页面提交的用户名username查询数据库
QueryWrapper<Employee> wrapper = new QueryWrapper<>();
wrapper.eq("username", employee.getUsername());
Employee emp = employeeService.getOne(wrapper);
//3 如果没有查询到则返回登陆失败信息
if (emp == null) {
return R.error("登陆失败");
}
//4 密码比对 如果不一致返回登陆失败结果
if (!emp.getPassword().equals(password)) {
return R.error("登陆失败");
}
//5 查看员工状态 如果说已禁用状态 返回禁用结果
if (emp.getStatus() == 0) {
return R.error("账号已经禁用");
}
//6 登陆成功 将员工id存入Session并返回登陆成功结果
request.getSession().setAttribute("employee", emp.getId());
return R.success(emp);
}
完善登录功能
问题分析:
- 之前的登录功能,我们不登录,直接访问 http://localhost/backend/index.html 也可以正常访问,这显然是不合理的
- 我们希望看到的效果是,只有登录成功才能看到页面,未登录状态则跳转到登录页面
- 那么具体改如何实现呢?使用过滤器或拦截器,在过滤器或拦截器中判断用户是否登录,然后在选择是否跳转到对应页面。
1 测试Filter拦截路径
/**
* 检查用户是否完成登陆的过滤器
*/
@Slf4j
@WebFilter(filterName = "loginCheckFilter", urlPatterns = "/*")
public class LoginCheckFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
log.info("拦截到请求:{}", request.getRequestURI());
filterChain.doFilter(request, response);
}
2 并在启动类上加上 @servletComponentScan
@SpringBootApplication
@ServletComponentScan
public class ReggieApplication {
public static void main(String[] args) {
SpringApplication.run(ReggieApplication.class, args);
}
}
上面我们已经能成功拦截到路径了,那现在我们来开发逻辑,主要分为以下几个步骤
/**
* 检查用户是否完成登陆的过滤器
*/
@Slf4j
@WebFilter(filterName = "loginCheckFilter", urlPatterns = "/*")
public class LoginCheckFilter implements Filter {
/**
* 路径匹配器
* 判断本次请求是否需要处理
* 使用Spring概念模型: PathMatcher
*/
public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
//1 获取本次请求的URI
String requestURI = request.getRequestURI();
//定义不需要的路径请求
String[] urls = new String[]{"/employee/login", "/employee/logout", "/backend/**", "/front/**"};
//2 判断本次请求是否需要处理
boolean check = check(urls, requestURI);
//3 如果不需要处理 则直接放行
if (check) {
log.info("本次请求:{},不需要处理",requestURI);
filterChain.doFilter(request, response);
return;
}
//4 判断用户登录状态,如果已经登录,则直接放行 当初存的 session是employee 所以拿到他来判断
if (request.getSession().getAttribute("employee") != null) {
filterChain.doFilter(request, response);
return;
}
//5 如果未登录返回未登录结果 通过输出流 向客户端页面响应数据
//未登录状态为什么要返回一个error呢?而且msg为NOTLOGIN
response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
return;
}
/**
* 路径匹配, (check)检查本次请求是否需要放行
* @param requestURI
* @param urls
* @return
*/
public boolean check(String[] urls, String requestURI) {
for (String url : urls) {
boolean match = PATH_MATCHER.match(url, requestURI);
if (match) {
//匹配
return true;
}
}
//不匹配
return false;
}
}
测试登录
当我们直接访问 http://localhost/backend/index.html 时,日志输出如下
: 用户未登录
: 用户id为:null
随后将自动跳转至登录页面
: 拦截到请求:/employee/login
: 本次请求:/employee/login,不需要处理
成功登录后
: 拦截到请求:/employee/page
: 用户已登录,id为1
那么至此,登录