ダークホースプログラマー Java プロジェクトの実戦「レジス・テイクアウェイ」メモ 2 日目: ビデオ P15-P25
このコースは、現在人気のテイクアウト食品注文ビジネスに基づいており、ビジネスは現実的で実践的かつ広範囲です。Spring Boot や mybatis plus などの一般的な技術フレームワークに基づいて開発されており、学生は実際のプロジェクト開発プロセス、要件分析プロセス、コード実装プロセスを体験できます。このコースを完了すると、需要分析能力、コーディング能力、バグ デバッグ能力を鍛え、開発経験を増やすことができます。
- リンク: https://www.bilibili.com/video/BV13a411q753
20230319 Day2: ビデオ P15-25
- 充実したログイン機能
- 新入社員
- 従業員情報ページングクエリ
- 従業員アカウントの有効化/無効化
- 従業員情報を編集する
ログイン機能を改善します。
問題分析:
バックグラウンド システムの従業員ログイン機能の開発は完了しましたが、まだ問題があります。ユーザーがログインしていなくても、システムのホームページに直接アクセスでき、通常どおりアクセスできます。 。
この設計には無理があります。私たちが確認したい効果は、ログインに成功した場合にのみシステム内のページにアクセスでき、ログインがない場合はログイン ページにジャンプすることです。
では、それはどのように実現されるべきなのでしょうか?
答えは、フィルターまたはインターセプターを使用してユーザーがログインしたかどうかを判断し、ログインしていない場合はログイン ページにジャンプすることです。
実装手順:
1. カスタム フィルター LoginCheckFilter を作成します。
2. アノテーション @ServletComponentScan をスタートアップ クラスに追加します
。 3. フィルターの処理ロジックを改善します。
フィルター パッケージを作成し、フィルター内に LoginCheckFilter フィルター クラスを作成し、@WebFilter アノテーションを追加し、フィルター名 filterName = "LoginCheckFilter" を設定し、インターセプト パス urlPatterns = "/*" (すべてインターセプト)、Filter インターフェイスを継承し、doFilter メソッドを実装します。
package com.raggie.filter;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 检查用户是否完成登录
*/
@WebFilter(filterName = "LoginCheckFilter",urlPatterns = "/*")
@Slf4j
public class LoginCheckFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
}
}
servletRequest、servletResponseを強制転送によりHttpServletRequest、HttpServletResponseに変換し、インターセプト情報をログ出力し、解放命令を追加
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
log.info("拦截到请求:{}",request);
filterChain.doFilter(request,response);
@ServletComponentScan アノテーションをスタートアップ クラスに追加します (スキャン フィルター用)
package com.raggie;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@Slf4j
@SpringBootApplication
@ServletComponentScan
public class ReggieApplication {
public static void main(String[] args) {
SpringApplication.run(ReggieApplication.class, args);
log.info("Spring项目启动成功...");
}
}
プログラムを実行すると、コンソールは傍受が成功したことを示す情報を返します。
[nio-8080-exec-1] com.raggie.filter.LoginCheckFilter : インターセプトされたリクエスト: org.apache.catalina.connector.RequestFacade@286ca83e
[nio-8080-exec-2] com.raggie.filter.LoginCheckFilter : インターセプトされましたリクエスト: org.apache.catalina.connector.RequestFacade@286ca83e
フィルターの具体的な処理ロジックは次のとおりです。
1. このリクエストの URI を取得します。
String requestURI = request.getRequestURI();
2. このリクエストを処理する必要があるかどうかを判断します。
処理する必要のないアクセス パスを格納する URL 配列を定義します。
String[] urls = new String[]{
"/employee/login",
"/employee/logout",
"backend/**",
"front/**"
};
パスマッチャーを定義する
public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
新しいブール メソッド チェックを作成し、定義された URL 配列と requestURI 値を渡します。
public boolean check(String[] urls,String requestURI){
for(String url:urls){
boolean match = PATH_MATCHER.match(url, requestURI);
if(match==true)
return true;
}
return false;
}
3. 処理が必要ない場合は、直接解放します。
boolean check = check(urls,requestURI);
if(check){
filterChain.doFilter(request,response);
}
4. ログイン状態を判断し、すでにログインしている場合は直接解除されます
if(request.getSession().getAttribute("employee")!=null){
filterChain.doFilter(request,response);
return;
}
5. ログインしていない場合は、ログインしていないという結果を返し、出力ストリームを通じてデータを含むページに応答します。
response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
LoginCheckFilter の完全なコード:
package com.raggie.filter;
import com.alibaba.fastjson.JSON;
import com.raggie.common.R;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.util.AntPathMatcher;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 检查用户是否完成登录
*/
@WebFilter(filterName = "LoginCheckFilter",urlPatterns = "/*")
@Slf4j
public class LoginCheckFilter implements Filter {
//路径匹配器,支持通配符
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/**"
};
log.info("拦截到请求:{}",request);
//2.判断本次请求是否需要处理
boolean check = check(urls,requestURI);
if(check){
// 3.如果不需要处理,则直接放行
filterChain.doFilter(request,response);
return;
}
//4.判断登录状态,如果已登录,则直接放行
if(request.getSession().getAttribute("employee")!=null){
filterChain.doFilter(request,response);
return;
}
//5.如果未登录则返回未登录结果,通过输出流的方式,向页面响应数据
response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
}
/**
* 进行路径匹配,检查本次请求是否需要放行
* @param urls
* @param requestURI
* @return
*/
public boolean check(String[] urls,String requestURI){
for(String url:urls){
boolean match = PATH_MATCHER.match(url, requestURI);
if(match==true)
return true;
}
return false;
}
}
新入社員機能:
- 需要分析
- データ・モデル
- コード開発
- 機能テスト
コードを開発する前に、プログラム全体の実行プロセスを整理する必要があります。
1. ページは ajax リクエストを送信し、新入社員ページに入力されたデータを )json 形式でサーバーに送信します。 2.
サーバー コントローラーはページによって送信されたデータを受信し、サービスを呼び出してデータを保存します
。 3. サービスMapperを呼び出してデータベースを操作し、データを保存します
戻り値がRのメソッドsaveを作成し、受け取ったjsonデータを@アノテーション型に変換する
@PostMapping
public R<String> save(@RequestBody Employee employee){
return null;
}
従業員の初期パスワードを md5 暗号化結果の 123456 に設定します。
employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));
従業員の更新および作成時刻をシステム時刻に設定する
employee.setCreateTime(LocalDateTime.now());
employee.setUpdateTime(LocalDateTime.now());
従業員の作成と更新をセッションに保存された従業員として設定します (HttpServletRequest リクエストをパラメータに追加する必要があります)
Long empID = (Long) request.getSession().getAttribute("employee");
employee.setCreateUser(empID);
employee.setUpdateUser(empID);
employeeServiceのsaveメソッドを呼び出し、R.successを返します。
employeeService.save(employee);
return R.success("新增员工成功!");
完全な保存コードは次のとおりです。
@PostMapping
public R<String> save(HttpServletRequest request,@RequestBody Employee employee){
//设置初始密码为123456,进行md5加密处理
employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));
employee.setCreateTime(LocalDateTime.now());
employee.setUpdateTime(LocalDateTime.now());
Long empID = (Long) request.getSession().getAttribute("employee");
employee.setCreateUser(empID);
employee.setUpdateUser(empID);
employeeService.save(employee);
log.info("新增员工,员工信息:{}",employee.toString());
return R.success("新增员工成功!");
}
グローバル例外ハンドラーを作成します。
共通パッケージ内に新しい GlobalExceptionHandler クラスを作成して、グローバル例外情報を取得します
package com.raggie.common;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.sql.SQLIntegrityConstraintViolationException;
@ControllerAdvice(annotations = {
RestControllerAdvice.class, Controller.class})
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {
/**
* 异常处理方法
* @return
*/
@ExceptionHandler(SQLIntegrityConstraintViolationException.class)
public R<String> exceptionHandler(SQLIntegrityConstraintViolationException ex){
log.error(ex.getMessage());
return R.error("操作失败!");
}
}
例外ハンドラで判断し、エラーメッセージに重複エントリが含まれている場合は、xxx がすでに存在しますを返します
@ExceptionHandler(SQLIntegrityConstraintViolationException.class)
public R<String> exceptionHandler(SQLIntegrityConstraintViolationException ex){
log.error(ex.getMessage());
if(ex.getMessage().contains("Duplicate entry")){
String[] split = ex.getMessage().split(" ");
String msg=split[2]+"已存在!";
return R.error(msg);
}
return R.error("未知错误!");
}
従業員情報ページング クエリ:
需要分析:
システム内の従業員数が多い場合、すべての従業員を1ページに表示するとごちゃごちゃして見にくくなるため、一般的なシステムでは一覧データをページ単位で表示します
。やり方。
コード開発
コードを開発する前に、プログラム全体の実行プロセスを整理する必要があります。
1. ページは ajax リクエストを送信し、ページング クエリ パラメーター (page、pageSize、name) をサーバーに送信します。
2. サーバー コントローラーはページによって送信されたデータを受信し、サービスを呼び出してデータをクエリします
。 3. サービスはマッパーはデータベースを操作し、ページング データをクエリします。
4. コントローラーは、クエリされたページング データをページに応答します。
5. ページはページング データを受信し、ElementUl の Table: コンポーネントを通じてページ上に表示します。
構成パッケージに新しい MyBatisPlusConfig を作成して、MyBatisPlus ページング プラグインを構成します。
package com.raggie.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mybatisPlusInterceptor;
}
}
EmployeeController で新しい Page メソッドを作成します。ジェネリック型は、mybatis が提供するエンティティ クラス Page です。フロントエンド リクエストを分析することにより、page/pageSize/name の 3 つのパラメーターを渡し、 @GetMapping("/page を追加する必要があります) ") 注釈
@GetMapping("/page")
public R<Page> page(int page,int pageSize,String name){
return null;
}
}
ページネーションコンストラクターを構築する
Page pageinfo=new Page(page,pageSize);
条件付きコンストラクターを構築する
LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper();
フィルターを追加
queryWrapper.like(StringUtils.isNotEmpty(name),Employee::getName,name);
並べ替え基準を追加する
queryWrapper.orderByDesc(Employee::getUpdateTime);
クエリを実行して結果を返す
employeeService.page(pageinfo,queryWrapper);
return R.success(pageinfo);
ページ メソッドの完全なコードは次のとおりです。
@GetMapping("/page")
public R<Page> page(int page,int pageSize,String name){
log.info("接收到查询请求,page={},pagesize={},name={}",page,pageSize,name);
//构造分页构造器
Page pageinfo=new Page(page,pageSize);
//构造条件构造器
LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper();
//添加过滤条件
queryWrapper.like(StringUtils.isNotEmpty(name),Employee::getName,name);
//添加排序条件
queryWrapper.orderByDesc(Employee::getUpdateTime);
//执行查询
employeeService.page(pageinfo,queryWrapper);
return R.success(pageinfo);
}
従業員アカウントを有効/無効にするには:
要件分析
従業員管理リスト ページでは、従業員アカウントを有効または無効にすることができます。アカウントが無効になっている従業員はシステムにログインできませんが、アカウントが有効になっている従業員は通常どおりログインできます。
なお、他の一般ユーザーの有効・無効を設定できるのは管理者(adminユーザー)のみであるため、一般ユーザーがシステムにログインした後は有効・無効ボタンは表示されません。
EmployeeController に新しい更新メソッドを作成し、@PutMapping アノテーションを追加して
従業員の UpdateTime と UpdateUser を設定します。
Long empID = (Long) request.getSession().getAttribute("employee");
employee.setUpdateUser(empID);
employee.setUpdateTime(LocalDateTime.now());
従業員情報を更新し、成功を返すには、employeeService の updateById メソッドを呼び出します。
update メソッドの完全なコードは次のとおりです。
@PutMapping
public R<String> update(HttpServletRequest request,@RequestBody Employee employee){
log.info(employee.toString());
Long empID = (Long) request.getSession().getAttribute("employee");
employee.setUpdateUser(empID);
employee.setUpdateTime(LocalDateTime.now());
employeeService.updateById(employee);
log.info("员工信息修改为:{}",employee.toString());
return R.success("员工信息修改成功!");
}
従業員情報を編集するには:
需要分析:
従業員管理一覧ページの編集ボタンをクリックして編集ページにジャンプし、編集ページ上の従業員情報をエコーして修正し、最後に保存ボタンをクリックして編集操作は完了
です
コードを開発する前に、対応するプログラムの操作プロセスと実行プロセスを整理する必要があります。
1. 編集ボタンをクリックすると、ページは add.html にジャンプし、URL にパラメータ [従業員 ID] が含まれます。
2. add.html ページの URL にあるパラメータ [従業員 ID] を取得します
。 3. ajax を送信します。 request サーバーにリクエストすると同時に、従業員 ID パラメータを送信します
4. サーバーはリクエストを受け取り、従業員 ID に従って従業員情報をクエリし、JSON 形式でページに従業員情報を応答します
。ページはサーバーから応答された jso データを受け取り、VUE データバインディングを通じて従業員情報を返します 表示
6. 保存ボタンをクリックし、ajax リクエストを送信し、ページ上の従業員情報を json 形式でサーバーに送信します
。サーバーは従業員情報を受信して処理し、完了後にページに応答します。8.
ページはサーバーから応答情報を受信し、それに応じて処理します。
EmployeeController で新しい getById メソッドを作成し、@PathVariable Long id 変数を渡し、@GetMapping("/{id}") アノテーションを追加します。
@GetMapping("/{id}")
public R<Employee> getById(@PathVariable Long id){
return null;
}
employeeServiceのgetByIdメソッドを呼び出し、従業員情報を問い合わせて空かどうかを判断し、R.successを呼び出してフロントエンドに情報を返す
@GetMapping("/{id}")
public R<Employee> getById(@PathVariable Long id){
log.info("根据id查询员工信息...");
Employee employee = employeeService.getById(id);
if(employee!=null){
log.info("查询到员工信息为:{}",employee.toString());
return R.success(employee);
}
log.info("未查询到员工信息!");
return R.error("未查询到对应员工信息!");
}