ディレクトリ
ユーザーログイン
前回の記事では、我々はそのログインを達成するために引き続き、ユーザー登録と認証を実施し、成功したログイン情報は、ページ上に表示されるようにした後。
次に、我々はコードを書きます。
サービスを実現
でcom.liferunner.service.IUserService
追加ユーザーログインインターフェイスのメソッド:
public interface IUserService {
...
/**
* 用户登录
* @param userRequestDTO 请求dto
* @return 登录用户信息
* @throws Exception
*/
Users userLogin(UserRequestDTO userRequestDTO) throws Exception;
}
その後、内com.liferunner.service.impl.UserServiceImpl
実装クラスの実装:
@Service
@Slf4j
public class UserServiceImpl implements IUserService {
...
@Override
public Users userLogin(UserRequestDTO userRequestDTO) throws Exception {
log.info("======用户登录请求:{}", userRequestDTO);
Example example = new Example(Users.class);
val condition = example.createCriteria();
condition.andEqualTo("username", userRequestDTO.getUsername());
condition.andEqualTo("password", MD5GeneratorTools.getMD5Str(userRequestDTO.getPassword()));
val user = this.usersMapper.selectOneByExample(example);
log.info("======用户登录处理结果:{}", user);
return user;
}
}
エラーヒント:
ここで少しだ坑点
、我々が使用、注意を払わなければならないselectOneByExample()
プロセスが着信パラメータがあることに留意しなければならないとき、クエリをtk.mybatis.mapper.entity.Example
インスタンスではなく、tk.mybatis.mapper.entity.Example.Criteria
次のようにそれ以外の場合は、動的に生成されたSQLクエリのエラー情報を報告されています
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'distinct' in 'class tk.mybatis.mapper.entity.Example$Criteria'
at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:92)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:440)
at com.sun.proxy.$Proxy106.selectOne(Unknown Source)
at org.mybatis.spring.SqlSessionTemplate.selectOne(SqlSessionTemplate.java:159)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:87)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:93)
at com.sun.proxy.$Proxy109.selectOneByExample(Unknown Source)
at com.liferunner.service.impl.UserServiceImpl.userLogin(UserServiceImpl.java:80)
...
新しいコードを書くとき、それは1行書かれたクエリ変数に特に脆弱である、直接オープンして次の行には、より多くの人々は、よりシンプルエラーは起動できません。
実現コントローラー
@RestController
@RequestMapping(value = "/users")
@Slf4j
@Api(tags = "用户管理")
public class UserController {
...
@ApiOperation(value = "用户登录", notes = "用户登录接口")
@PostMapping("/login")
public JsonResponse userLogin(@RequestBody UserRequestDTO userRequestDTO,
HttpServletRequest request,
HttpServletResponse response) {
try {
if (StringUtils.isBlank(userRequestDTO.getUsername()))
return JsonResponse.errorMsg("用户名不能为空");
if (StringUtils.isBlank(userRequestDTO.getPassword()) ||
userRequestDTO.getPassword().length() < 8) {
return JsonResponse.errorMsg("密码为空或长度小于8位");
}
val user = this.userService.userLogin(userRequestDTO);
UserResponseDTO userResponseDTO = new UserResponseDTO();
BeanUtils.copyProperties(user, userResponseDTO);
log.info("BeanUtils copy object {}", userResponseDTO);
if (null != userResponseDTO) {
// 设置前端存储的cookie信息
CookieTools.setCookie(request, response, "user",
JSON.toJSONString(userResponseDTO), true);
return JsonResponse.ok(userResponseDTO);
}
} catch (Exception e) {
e.printStackTrace();
log.error("用户登录失败,{},exception = {}", userRequestDTO, e.getMessage());
}
return JsonResponse.errorMsg("用户登录失败");
}
}
上記のコードでは、基本的なキャリブレーションの問題は、我々はいくつかの新しい機能情報に焦点を当て、にはなりません。
com.liferunner.dto.UserResponseDTO
私たちは、新しいリターン・オブジェクトのためのデータパッケージの前面にそれを表示する必要があります、我々はデータベースから照会Users
POJOなど、すべてのユーザーデータを、含まれているpassword
、mobile
と一部のユーザーように、プライベートなデータであっても、前にそれを表示するように想定されていませんそれを表示することも脱感作、および暗号化を通過する必要があります。このように、一般的な方法は、新しいオブジェクトが唯一のデータフィールドのフロントエンドは、それを必要と含まれている必要がありますされ、返されるパッケージ化することです。
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ApiModel(value = "用户信息返回DTO", description = "用户登录成功后需要的返回对象")
public class UserResponseDTO {
/**
* 主键id
*/
private String id;
/**
* 用户名
*/
private String username;
/**
* 昵称 昵称
*/
private String nickname;
/**
* 头像
*/
private String face;
/**
* 性别 1:男 0:女 2:保密
*/
private Integer sex;
}
ここでは、使用することを示唆しているCtrl+C
私たちのcom.liferunner.pojo.Users
オブジェクトを、その後、我々はそれを必要としないフィールドを削除し、なぜ建议
良いが行うので、それを、それがあります。
org.springframework.beans.BeanUtils.copyProperties(user, userResponseDTO);
あなたが見ることができるように、ここでの直接の使用であるSpring BeanUtils
コピーツールクラスの値は、それが割り当てへ1によって各フィールド1をループに私たちを低減し(SetValue)
、作業の。(また、怠惰な小さなトリックは、ああ、これは権利ではありません- )CookieTools.setCookie();
私達は私達のユーザーがログインした後、データはローカルのブラウザに保存され、通常の状況下では、前に述べたCookie
ように、私のログインとして、baidu.com
:
この時点では、左側の画像でマウスCookies => www.baidu.com
の右はclear
、再び私たちの現在のインターフェイスをリフレッシュ効果を次のように:
ログイン状態が終了状態になっていますから、私たちは見ることができ、およびCookies
コンテンツは、ログイン情報を暗号化して、ブラウザのクッキーに保存された後、Baiduは私達のユーザーであることがどの番組もはるかに少ないです。
我々は、などJingdongは、淘宝網を、見ることができるとも言えるたら、開口部の冒頭で、このようにして達成私たちのシステムは実現するために、デモの生産に基づいており、我々は主流の実装を行うに基づいています。もちろん、一部の学生たちは、フロントエンドを達成するためにそうすることを、フロントエンドにデータを渡す必要があること、言うだろう!!!もちろん、あなたは正しいが、私たちは一つの実施を持って、私たちは個人的に傷つけてはならないため、右?
ここでは、ユーティリティクラスを必要とする、私たちのことができますgithubのポータルダウンロードコードへ。ディレクトリcom.liferunner.utils.CookieTools
。com.alibaba.fastjson.JSON.toJSONString(userResponseDTO)
我々は、オブジェクトのリターンをしたいが、そのためcookie
我々がいることを配置する必要がありString
、ここで我々はアリババのJSONツールを導入し、mscx-shop-common/pom.xml
それを追加することによって異なります。<dependencies> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.56</version> </dependency> </dependencies>
ユーザーがログアウト
我々のユーザーのログイン情報をブラウザのクッキーに保存されますので、我々は、ユーザのログアウト操作に基づいて、関連するユーザーのキャッシュを削除する必要があるので、エンドユーザーの後、我々は、ユーザーがシステムからログアウトする必要があります。
@ApiOperation(value = "用户登出",notes = "用户登出",httpMethod = "POST")
@PostMapping("/logout")
public JsonResponse userLogout(@RequestParam String uid,
HttpServletRequest request,HttpServletResponse response){
// clear front's user cookies
CookieTools.deleteCookie(request,response,"user");
// return operational result
return JsonResponse.ok();
}
開発や小規模福祉のデバッグ
Javaのログの追跡
一般電気事業シナリオは、要求の応答時間は、ボタンのすべてのクリックが待つべき場合は、サイトで商品を購入、またはシステムがそれを感じるカトン場合など、非常に厳しい要件を、持っている、あなたがすることを躊躇しないだろう右上隅を選択し小红叉
、それを取り除きます。したがって、我々のシステムの開発では、多くの場合、私たちも、テストストレステストに、私たちの要求の応答時間を監視する必要があります。しかし、そのような要求を達成するためにあらゆる方法が明らかに不合理であり、我々は一般的な方法を達成するために持っている、そしてそれは通過であるので、開発者が不快できるようになってもその私たちがやらせAOP
アスペクト指向達成するために、。基本的な使用上のセクションでは、我々はを参照することができAOPポータル、次に、私たちは、コーディングを開始します。
するためによるspringboot
機能トリロジーを実現:
SETP 1.依存追加
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2.スタートアップコンフィギュレーション(ちょうどこのステップを無視しない)ステップ
注釈付きSETP 3.
当社ではmscx-shop-api
、プロジェクトを作成しcom.liferunner.api.aspect
たパッケージを、次に作成するcom.liferunner.api.aspect.CommonLogAspect
次のコードを:
package com.liferunner.api.aspect;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* CommonLogAspect for : AOP切面实现日志确认
*
* @author <a href="mailto:[email protected]">Isaac.Zhang | 若初</a>
* @since 2019/11/11
*/
@Component
@Aspect
@Slf4j
public class CommonLogAspect {
@Around("execution(* com.liferunner.api.controller..*.*(..))")
public void recordLogTime(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
log.info("----------- {}.{} process log time started.---------------",
proceedingJoinPoint.getTarget().getClass(),
proceedingJoinPoint.getSignature().getName());
val startTime = System.currentTimeMillis();
proceedingJoinPoint.proceed();
val afterTime = System.currentTimeMillis();
if (afterTime - startTime > 1000) {
log.warn("cost : {}", afterTime - startTime);
} else {
log.info("cost : {}", afterTime - startTime);
}
log.info("----------- {}.{} process log time ended.---------------",
proceedingJoinPoint.getSourceLocation().getClass(),
proceedingJoinPoint.getSignature().getName());
}
}
- あなたはどのような種類のを監視する方法私たちに代わってログの最初の行
proceedingJoinPoint.proceed();
表現の実行- 要求は1000ミリ秒をチェックすると、私たちは、使用
log.warn(...)
ログの警告を
ステップ4.デモ
- クエリを消費するユーザー
- かかる登録ユーザー
チャートから、我々は明確にするたびに、我々は時間のかかるを要求することを確認することができ、そしてすべての方法を最適化するために標的とすることができます!!!
SQLログの追跡
我々の開発の過程では、多くの場合のデータベースに対して実行CRUD
我々が使用しているため、しかし、操作mybatis
に動的ではなく、手動で書くよりも、単純なSQLクエリを生成するためにこのような私たちがしているように、UserServiceImpl.java
ユーザーのクエリおよびユーザ登録コードを実装tk.mybatis.mapper.entity.Example
良くthis.usersMapper.insertSelective(user);
public Users findUserByUserName(String username) {
// 构建查询条件
Example example = new Example(Users.class);
val condition = example.createCriteria()
.andEqualTo("username", username);
return this.usersMapper.selectOneByExample(example);
}
@Transactional(propagation = Propagation.REQUIRED)
@Override
public Users createUser(UserRequestDTO userRequestDTO) throws Exception {
log.info("======begin create user : {}=======", userRequestDTO);
val user = Users.builder()
.id(sid.next()) //生成分布式id
.username(userRequestDTO.getUsername())
.password(MD5GeneratorTools.getMD5Str(userRequestDTO.getPassword()))
.birthday(DateUtils.parseDate("1970-01-01", "yyyy-MM-dd"))
.nickname(userRequestDTO.getUsername())
.face(this.FACE_IMG)
.sex(SexEnum.secret.type)
.createdTime(new Date())
.updatedTime(new Date())
.build();
this.usersMapper.insertSelective(user);
log.info("======end create user : {}=======", userRequestDTO);
return user;
}
問題を抱えてたら、私たちはしばしば、エラーが発生した場所で終わりに私たちは、この時間を知らないSQL
私たちが知らない問題が、それでは、私たちのために道を設定してみましょうが看
SQLの小さな実装に:
1.設定ロギング設定(図)
2.変更MyBatisの設定(log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
)
3. SELECT
デモ
4. INSERT
デモンストレーション効果
コンソールからは二回、図JDBC操作で見ることができますが、最初の時間は、実際に私達のユーザー名ですチェック。第二はINSERT
本物のインサートです。
以上の結果を示すことによって、私たちは考えることができ、このログは非常に必要である私たちの日々の開発で問題を解決するための針。しかし、我々はそれを覚えておく必要があり、製造時に、ログは、そうでない場合は、一度に大量のデータの後に、システムのパフォーマンスが重傷の原因となります、閉じる必要があります!!!
ソースのダウンロード
セクションの下のお知らせ
我々は電気の供給業者のコア部分を開発していきます次のセクション - 製品とディスプレイ広告を、任意の開発コンポーネントの過程で使用するためには、私は兄弟後半パニックのいずれかによって、特別なプレゼンテーションになります!
GOGOGO!