部署Deploy
https://www.cnblogs.com/yfzhou/p/9668366.html
https://blog.csdn.net/qq_36523667/article/details/78584488?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase
框架Framework
- Struts Hibernate
- Netty
- Dubbo
- Spring
| 三层架构 MVC模式MVC框架
Model View Controller 模型-视图-控制器
视图层 View、表现层
业务逻辑 服务层 Service,
与持久层 数据层 DAO
https://www.jianshu.com/p/8764c9bbc88a | | | | —- | —- | —- |
项目配置
- 邮箱配置host: “smtp.qq.com”,port: 587,
- 数据库host port username password
Java注解
@PostConstruct@PreConstructJava类称呼
| Entity类
data objectBo(business object)Po(persistant object)持久层对象Dto(data transfer object)
VO
do domain object | POJO(Plain Ordinary Java Object)即普通Java类,具有一部分getter/setter方法的那种类就可以称作POJO。
- Javabean
- ejb Enterprise Java Beans
| https://www.cnblogs.com/hunmeng/p/11298680.html
https://www.cnblogs.com/linhuaming/p/9901955.html | | —- | —- | —- |
Servlet容器Container Tomcat
- 官网https://tomcat.apache.org/
Servlet小服务程序
| 类图类型javax.servlet
javax.servlet.http
- Servlet接口
- HttpServlet抽象类 GenericServlet
- ServletRequestServletResponse接口
- HttpServletRequest接口
- HttpSession Cookie
| 浏览器过程 | | | —- | —- | —- |
Spring
- Spring事务
- 官网https://spring.io
- 环境搭建https://start.spring.io/
- Group域名的反写
- Artifact
- Dependencies选依赖
| |
- Spring用于管理对象
- Spring MVC是基于 Servlet 的一个 MVC 框架
- SpringCloud
- SpringBoot
由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。 | 参考 | | —- | —- | —- | | 核心包类型
- SpringApplication run方法
- ApplicationContext接口
模块
- SpringCore
- SpringContext
- Beans
| springboot启动
|
- org.springframework.boot
- spring-boot-starter
- org.springframework
|
注解
|
- 启动类@SpringBootApplication组合的
@Configuration
@EnableAutoConfiguration
@ComponentScan
@Filter |
- 声明
- @Component 组件,没有明确的角色
- @Service 在业务逻辑层使用(service层)
- @Repository 在数据访问层使用(dao层)
- @Controller 在展现层使用,控制器的声明
- @Bean创建
- @Scope
|
- 注入
@Autowired
@Inject:由JSR-330提供
@Resource:由JSR-250提供 |
| —- | —- | —- |
|
- @ModelAttribute用的少
| | |
IOC(InversionOfControl)控制反转
DI(DependencyInjection)依赖注入 - Field字段注入 - Setter注入 - 构造器注入 |
||
---|---|---|
SpringAOPAspectOrientedProgramming面向切面编程
切面Aspect 切点 | 代理模式 | 注解 参考 |
---|---|---|
SpringMVC
表单中有多个相同的字段,以及springmvc接收多个相同对象 | SpringMVC数据校验@NotEmpty@NotBlank@NotNull BindingResult @Valid表单验证 |
注解 - 请求Request - @RequestMapping - @RequestHeader@RequestBody@RequestParam - @PathVariable - 响应Response - @ResponseBody - @ModelAttribute |
---|---|---|
数据模型ModelModelMapModelAndView https://blog.csdn.net/u013654037/article/details/41944947 |
Cookie Session HttpSession @SessionAttributes @CookieValue |
SpringBoot
- thymeleaf
- AOP
- springboot单元测试@SpringBootTest @Test
| 运行debug模式 支持 热更新 recompare
https://www.jianshu.com/p/f658fed35786
https://blog.csdn.net/xiaojin21cen/article/details/88312873
热部署 | session
org.springframework.boot
spring-boot-devtools org.springframework.session spring-session-data-redis
- redis
org.springframework.boot spring-boot-starter-data-redis
https://blog.csdn.net/xcbeyond/article/details/81116600 | 数据库
mysql
mysql-connector-java
runtime org.mybatis.spring.boot mybatis-spring-boot-starter 2.1.0
#mysql数据库连接配置spring.datasource.url=jdbc:mysql://localhost:3306/campus_transaction?useUnicode=true&characterEncoding=utf8&serverTimezone=GMTspring.datasource.username=rootspring.datasource.password=qasdfGHjklm152 | | —- | —- | —- |
MyBatis
自动生成Mybatis-generator https://gitee.com/b-match/MyBatis_Generator 1. 打开工程文件 1. 自定义配置 1. 执行文件 1. 复制 粘贴 1. 数据库配置 1. 修改mapper文件 注解 Insert id(如果是自动生成的话去掉) gmt_created gmt_modified now() update 的 时间 |
注解 @Results @ResultMap @Param @SelectProvider @Mapper生成的mapper接口需要 |
|
---|---|---|
Java工具库
- 序列化fastjson
- Excel poi workhook sheet cel row
- lombok@Datapojo类
- kaptcha captcha
- commons-lang3
md5加密https://www.jianshu.com/p/be000cf837b2https://www.cnblogs.com/Marydon20170307/p/9116924.html
JSP
Thymeleaf模板引擎(template engine)
添加以后就无法跳转到静态页面了
https://blog.csdn.net/jintingbo/article/details/81633615
https://blog.csdn.net/zmemorys/article/details/87275032
页面控制
- @Controller
- 返回值ModelAndView
@Controller
public class Controller
@RequestMapping("/request")
public ModelAndView request() {
ModelAndView mv = new ModelAndView();
//封装要显示到视图的数据
mv.addObject("msg","hello myfirst mvc");
//视图名
mv.setViewName("hello");
return mv;
}
}
@Controller
public class Controller
@RequestMapping("/request")
public ModelAndView request() {
return new ModelAndView("redirect:login.html");;
}
}
返回值String
请求转发
@Controller
public class Controller
@RequestMapping("/request")
public String request() {
return "index";return "index.html";//好像都可以 静态页面写全
}
}
重定向
@Controller
public class Controller
@RequestMapping("/request")
public String request() {
return "redirect:/index.html"
}
}
@RestController
@RestController
public class RestController
@RequestMapping("/request")
public String request() {
return "json"
}
}
response
@Controller
public class Controller
@RequestMapping("/request")
public boolean request() {
response.sendRedirect("/yikao/login.html");
return true;
}
}
注意 : 动态页面 和静态页面方式不一样
主页默认会访问 index.html @Controller @RequestMapping(“/“) public class IndexController { @RequestMapping(“/Blog”) public String index() { return “forward:index.html”; } } |
拦截器 使用功能 拦截 不登陆 直接访问内部资源的 请求 |
请求转发重定向 |
---|---|---|
返回多媒体参考https://blog.csdn.net/u014449560/article/details/82807517 https://blog.csdn.net/sinat_25484327/article/details/94590439?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task https://www.cnblogs.com/springforall/p/12143041.html |
错误页面 参考https://blog.csdn.net/IT_faquir/article/details/79521417 |
|
用户验证
手机验证码
送10块 http://www.miaodiyun.com/ |
免费 https://www.mob.com/ |
极光 https://www.jiguang.cn/ |
---|---|---|
图片验证码
依赖
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
</dependency>
后端
import com.google.code.kaptcha.Constants;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import java.util.Properties;
@Controller
public class CaptchaControl {
生成图片
@RequestMapping(value = "/captcha")
public void getCaptcha(HttpSession session, HttpServletResponse response)
throws IOException {
// 设置 HTTP Cache 响应头 让验证码不要有本地catche
// Set to expire far in the past.
response.setDateHeader("Expires", 0);
// Set standard HTTP/1.1 no-cache headers.
response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
// Set IE extended HTTP/1.1 no-cache headers (use addHeader).
response.addHeader("Cache-Control", "post-check=0, pre-check=0");
// Set standard HTTP/1.0 no-cache header.
response.setHeader("Pragma", "no-cache");
// 设置 HTTP 内容格式
// return a jpeg
response.setContentType("image/png");
// 创建随机数
// create the text for the image.
String capText = kaptcha.createText();
// store the text in the session.
session.setAttribute(Constants.KAPTCHA_SESSION_KEY, capText);
session.setAttribute("11","111");
// 输出图片
// create the image with the text.
BufferedImage bufferedImage = kaptcha.createImage(capText);
// write the data out.
ServletOutputStream outputStream = response.getOutputStream();
ImageIO.write(bufferedImage, "png", outputStream);
try {
outputStream.flush();
} finally {
outputStream.close();
}
}
@Autowired
private DefaultKaptcha kaptcha;
// 初始化 kaptcha
@Bean
public DefaultKaptcha initKaptcha(){
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties();
//配置验证码
// properties.put(Constants.KAPTCHA_TEXTPRODUCER_CHAR_STRING, "1234567890");
// properties.put(Constants.KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, 5);
// properties.put(Constants.KAPTCHA_IMAGE_HEIGHT, "44");//不能为小数
// properties.put(Constants.KAPTCHA_IMAGE_WIDTH, "140");
// properties.put(Constants.KAPTCHA_TEXTPRODUCER_FONT_SIZE, "32");
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
}
前端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>验证码</title>
</head>
<body>
<form action="/signupmock" method="get">
<div>
<span>验证码</span>
<input class="code" type="text" placeholder="" name="code">
<img onclick="reloadCaptcha()" id="captchimage" class="image" src="/captcha">
</div>
</form>
</body>
</html>
<script>
function reloadCaptcha() {
var captchimage = document.getElementById("captchimage");
captchimage.src = "/captcha?t=" + (new Date().getTime());
}
</script>
参考
配置
https://shimo.im/sheets/USjfERxK5MQyzURV
不刷新图片
https://blog.csdn.net/ganges_zs/article/details/82355883
邮箱验证码
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
配置
spring.mail.host=smtp.qq.com
spring.mail.username=1424036574@qq.com
spring.mail.password=mnahedlqdzeegiaa
前端
后端
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import com.google.code.kaptcha.Constants;
import com.google.code.kaptcha.impl.DefaultKaptcha;
@Controller
public class EmailControl {
@Autowired
private JavaMailSender mailSender;
@Autowired
private DefaultKaptcha kaptcha;
@RequestMapping(value = "/sendmail")
@ResponseBody
public String sendmail(HttpSession session,
@RequestParam("email")String email){
//文本格式邮件
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom("1424036574@qq.com");
message.setTo(email);
message.setSubject("主题:验证码");
String code = kaptcha.createText();
session.setAttribute("EmailCode", code);
message.setText(code);
mailSender.send(message);
return "发送成功";
}
@RequestMapping(value = "/sendmail")
@ResponseBody
public String sendmail(HttpSession session,
@RequestParam("email")String email){
//html邮件
MimeMessage message = mailSender.createMimeMessage();
try {
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom("1424036574@qq.com");
helper.setTo(email);
helper.setSubject("主题:验证码");
String code = kaptcha.createText();
session.setAttribute("emailcode", code);
message.setText("<h1>" + code + "</h1>", "utf-8", "html");
mailSender.send(message);
} catch (MessagingException e) {
e.printStackTrace();
}
return "发送成功";
}
}
前端
用户登录鉴权
步骤
创建方法注解
import java.lang.annotation.*;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface NeedLogin {
}
添加自定义拦截器
import com.yikao.model.User;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class AuthHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
if(handler instanceof HandlerMethod){
HandlerMethod handlerMethod = (HandlerMethod) handler;
NeedLogin needLogin = handlerMethod.getMethodAnnotation(NeedLogin.class);
if(needLogin != null){
User user = (User) request.getSession().getAttribute("user");
if(user == null){
response.sendRedirect("/yikao/login.html");
return false;
}
}
}
return true;
}
}
注册拦截器
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
//注册拦截器
@Configuration
public class LoginWebMvcConfigurer implements WebMvcConfigurer {
@Autowired
private AuthHandlerInterceptor authHandlerInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authHandlerInterceptor).addPathPatterns("/**");
}
}
测试
@Controller
public class LoginControl {
@RequestMapping(path = "/login")
public String loginSuccess(HttpSession session,User user) {
session.setAttribute("ueser",user);
return "index.html";
}
@RequestMapping(path = "/login")
@NeedLogin
public String request() {
return "index.html";
}
@RequestMapping(path = "/logOut")
public String logOut(HttpSession session) {
session.removeAttribute("ueser",user);
return "login.html";
}
}
会话状态HttpCookie
|
-
- 属性
- 作用域 设置域名setDomain 路径
如果你是次级域名 设置顶级域名 其它次级域名 都可以访问
https://segmentfault.com/a/1190000006932934
- 有效期 路径
- 过期时间 (相对过期过期时间 是 cookie写入以后开始计算)
- 前端能否修改
- 属性默认值
有效期 默认 1969-12-31 但是浏览器关闭 就没有了
路径 是请求路径
域名 默认当前域名 |注解
@CookieValue(name = “name”,required = false) |浏览器查看
application
也可以在 network查看 某一个请求响应的 cookie | | —- | —- | —- |
HttpSession
| 概念
- session 会话 抽象概念 一种用户状态的解决方案
- 具体session的实现是 存在服务端的一个数据结构
- session借助cookie来实现 cookie 存储 sessionID 不用cookie 也可以
- 作用一样
- cookie 有很多缺点 主要是大小限制 还能被用户看到
- 存的用户信息不同
- 关系 : HashMap
- session比cookie 代码操作方便
|
- 这个id 在会话 过期之前 是不会变得 你可以软件操作 或者根据软件设置的过期时间
- 修改了 sessionID 就get不了 session里面的其他数据了
- 不同浏览器有不同的session
| 浏览器查看
- cookie存储sessionid
-
|
| —- | —- | —- |
| 属性设置默认30分钟
#spring.session.timeout=15 //过期时间 单位秒注解
@SessionAttribute(value = “msg”, required = false) | 问题如果seesionid 被盗取了了 很危险
- 普通用户 我自己登陆的
- 黑客的
- 解决 token
- 参考https://www.zhihu.com/question/19786827/answer/84540780
| |
RedisSession
作用分布式 高可用依赖 # Redis服务器地址: spring.redis.host=r-student.redis.rds.aliyuncs.com # Redis服务器连接端口 spring.redis.port=6379 # Redis服务器连接密码(默认为空) spring.redis.password=Bmatch123对象序列化 public class User implements Serializable { } |
||
---|---|---|