商业级java开发单体项目环境搭建
写在开发前,端口经常被战占,windows10用以下命令先查先杀,
netstat -aon | findstr "8080"
taskkill /F /PID <PID>
正文部份,环境再建(由于第一次笔记是随写随记,写得太乱,重新整理一下)
电脑环境:java jdk17 mysql8.0.23 idea2022 协助部份通义千问 资料来源: 幕课网java办公系例(神思者)初始依赖:Lombok,自动生对象的get set,这些方法的注解;Spring Web,基础的sprintboot web开功能,也是最核心.
SpringBootDevTool热部署插件,
MySQL Driver,这个是数据库连接的驱动,类似与jdbc;MyBatis Framework,数据库框架,mybatis; Spring Data Redis,缓存数据库;Spring Data MongoDB,文档数据库
Spring For RabbitMQ,进程间通信用的mq; Java Mail Sender,发送邮件用的工具;QuartZ Scheduler 定时器工具
整体搭建步聚,
如果果新系统,我们需要提前准备一个虚拟机,和一个windows10以上环境,然后利用IDEA的Spring Initializr可以图形化创建项目,填写好Maven项目信息,
创建SpringBoot项目,勾选若干依赖库,配置MyBatis,整合高级功能
具体步聚核 心部份:
安装liunx centos7,这儿只记录重要的,如是果是想和自己电脑共用一个ip 网络用NAT 模式,
安装好后查看自己的网卡,有网卡才能上网,

设置静态ip
进入/etc/sysconfig/network-script/目录,找到一个叫

vim ifcfg-enp0s3

最好是顺便 装了docker ,虽然暂时用不上,安装docket 之前先更新一下yum
然后是win10上安装必要软件
安装mysql window上安装的话有二步住忆一下,这一步是只安装数据库存就好要不要会多好多莫名奇妙的软件自动安装

第二就是安装时不要勾新的加密方式,否则老工具不好连,上面是新方式,勾选老方方就可以

核心就是以上二步要注意,其它的步聚不是重点,便是还是随便 记录一下,这儿选择集群方式,默认就好

选择端口

设置服务名字和是否和自动启动

navicat安装这个安装,主要是商业软件我们这儿略过,,,,
安装mongo
我们网盘有免安装版,运行成功后,可以在连接工具上新建一个用户
use admin;
db.createUser({
user: "root",
pwd: "abc123456",
roles: [{ role: "root", db: "admin" }]
});
截图如下:

然后安装开发工具,开发工具我们都 是网上购买绿版色先用,除非是工作中需要正版,这儿不方便说安装步聚。总体来讲就是先安装编辑器。
配置SpringBoot项日,配置Tomcat,配置MySQL,配置Redis,配置MongoDB , 整 合安全框架,认证框架,统一返回r类,统一异常,最后配置生成一下数据库结构
然后就能正式开发了。
新建工程,勾选完以上依赖后,其它自动有一个配置文件,我们改一下后缀名,主要是我们的课程是yml格式,其实配置文件格式对项目 没有啥 影响
# 将 application.properties 文件修改为 application.yml
#增加tomcat 配置 server: tomcat: uri-encoding: UTF-8 threads: max: 280 min-spare: 3 connection-timeout: 5000ms port: 8080 servlet: context-path: /emos-wx-api
下面增加mysql 配置,这儿要增加一下阿里druid 连接池的依赖
# 三、配置MySQL数据源
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/emos?useUnicode=true&characterEncoding=utf8
username: root
password: abc123456
initial-size: 8
max-active: 16
min-idle: 8
max-wait: 60000
test-while-idle: true
test-on-borrow: false
test-on-return: false
添加依赖为:
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.13</version> </dependency>
截图如下:

配置redis, 但是我们的环境多半没有密码,这儿如果没有密码需要改一下。这个redis 不是顶格靠边,是在

# 配置Redis数据源
redis:
database: 0
host: localhost
port: 6379
password: abc123456
jedis:
pool:
max-active: 1000
max-wait: -1ms
max-idle: 16
min-idle: 8
mongo 配置
# mongo配置
data:
mongodb:
host: localhost
port: 27017
database: emos
authentication-database: admin
username: admin
password: abc123456
配置mybaits 利用idea 自带的连个工具生成表
自带的sql 管理工具生成数据库的mapper
配置好sql 环境后在我们的开发工具的数据库存表右健点击表格会有如下菜单。

在自动生成前需要提前建好文件,相应的文件目录。

然后就可以在面板配置生成路径,然后生成文件

生成的dao 文件需要加上@Mapper注解:自动生成的增删除方式功能不灵活,可以全删了,但是如果全删在实现层的相关代码也要删,
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface SysConfigDao {
//以下自动生成的方法可以删了,但是删了要顺便删了具体的实现方法。
int deleteByPrimaryKey(Integer id);
int insert(SysConfig record);
int insertSelective(SysConfig record);
SysConfig selectByPrimaryKey(Integer id);
int updateByPrimaryKeySelective(SysConfig record);
int updateByPrimaryKey(SysConfig record);
}
详细流程解释如下:

最后还要优化配置日志显示和mybatis 的输出sql 和pojo 路径,和mapper 路径, 由于dao文件有加注解
所以不需要在这儿配置

2-4 统一异常类,我们先在根目录下建一个exception包 在下面新建一个异常类,类名叫 EmsoExcepion, 这个类继随运行异常,
目的抛出后系统自己外理
package com.example.emos.wx.exception;
import lombok.Data;
@Data
public class EmosException extends RuntimeException {
private String msg;
private int code = 500;
public EmosException(String msg) {
super(msg);
this.msg = msg;
}
public EmosException(String msg, Throwable e) {
super(msg, e);
this.msg = msg;
}
}
统一返回类
虽然SpringMVC的Controller可以自动把对象转换成JSON返回给客户端,但是我们需要制定一个统-的标准,保证所有Controller返回的数据格式一致。最简便的办法就是定义封装类,来统一封装返回给客户端的数据。
修改 pom.xml 文件,添加依赖库。Apache的 httpcomponents 库里面的 Httpstatus 类封装了很多状态码,所以我们在Web返回对象中封装状态吗,可以用到这些状态码,
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpcore</artifactId> <version>4.4.13</version> </dependency>
先创建 com.example.emos.wx.common.util 包,然后创建 R 类
package com.example.emos.wx.common.util; import org.apache.http.HttpStatus; import java.util.HashMap; import java.util.Map; public class R extends HashMap<String, Object> { public R() { put("code", HttpStatus.SC_OK); put("msg", "success"); } public static R error() { return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, "未知异常,请联系管理员"); } public static R error(String msg) { return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, msg); } public static R error(int code, String msg) { R r = new R(); r.put("code", code); r.put("msg", msg); return r; } public static R ok(String msg) { R r = new R(); r.put("msg", msg); return r; } public static R ok(Map<String, Object> map) { R r = new R(); r.putAll(map); return r; } public static R ok() { return new R(); } @Override public R put(String key, Object value) { super.put(key, value); return this; } }
第三部份 利用Swagger搭建REST API
第一步需要先导入依赖:
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency>
swagger 配置如下,在根目录定义一个config 存放配置文件, 名字为SwaggerConfig 内容如下:
配置分二部份,一部是标准功能,一部份是支持Tonker
package com.example.emos.wx.config; import io.swagger.annotations.ApiOperation; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.ApiKey; import springfox.documentation.service.AuthorizationScope; import springfox.documentation.service.SecurityReference; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spi.service.contexts.SecurityContext; import springfox.documentation.spring.web.plugins.ApiSelectorBuilder; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; import java.util.ArrayList; import java.util.List; @Configuration @EnableSwagger2 public class package com.example.emos.wx.config; import io.swagger.annotations.ApiOperation; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.ApiKey; import springfox.documentation.service.AuthorizationScope; import springfox.documentation.service.SecurityReference; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spi.service.contexts.SecurityContext; import springfox.documentation.spring.web.plugins.ApiSelectorBuilder; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; import java.util.ArrayList; import java.util.List; @Configuration @EnableSwagger2 public class SwaggerConfig { @Bean public Docket createRestApi() { Docket docket = new Docket(DocumentationType.SWAGGER_2); ApiInfoBuilder builder = new ApiInfoBuilder(); builder.title("EMOS在线办公系统"); ApiInfo info = builder.build(); docket.apiInfo(info); ApiSelectorBuilder selectorBuilder = docket.select(); selectorBuilder.paths(PathSelectors.any()); selectorBuilder.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)); docket = selectorBuilder.build(); ApiKey apiKey = new ApiKey("token", "token", "header"); List<ApiKey> apiKeyList = new ArrayList<>(); apiKeyList.add(apiKey); docket.securitySchemes(apiKeyList); AuthorizationScope scope = new AuthorizationScope("global", "accessEverything"); AuthorizationScope[] scopes = {scope}; SecurityReference reference = new SecurityReference("token", scopes); List refList = new ArrayList(); refList.add(reference); SecurityContext context = SecurityContext.builder().securityReferences(refList).build(); List cxtList = new ArrayList(); cxtList.add(context); docket.securityContexts(cxtList); return docket; } } { @Bean public Docket createRestApi() { Docket docket = new Docket(DocumentationType.SWAGGER_2); ApiInfoBuilder builder = new ApiInfoBuilder(); builder.title("EMOS在线办公系统"); ApiInfo info = builder.build(); docket.apiInfo(info); ApiSelectorBuilder selectorBuilder = docket.select(); selectorBuilder.paths(PathSelectors.any()); selectorBuilder.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)); docket = selectorBuilder.build(); ApiKey apiKey = new ApiKey("token", "token", "header"); List<ApiKey> apiKeyList = new ArrayList<>(); apiKeyList.add(apiKey); docket.securitySchemes(apiKeyList); AuthorizationScope scope = new AuthorizationScope("global", "accessEverything"); AuthorizationScope[] scopes = {scope}; SecurityReference reference = new SecurityReference("token", scopes); List refList = new ArrayList(); refList.add(reference); SecurityContext context = SecurityContext.builder().securityReferences(refList).build(); List cxtList = new ArrayList(); cxtList.add(context); docket.securityContexts(cxtList); return docket; } }
编写测试例:
@RestController
@RequestMapping("/test")
@Api("测试web接口")
public class TestController {
@GetMapping("/sayHello")
@ApiOperation("最简单的测试方法")
public R sayHello() {
return R.ok().put("message", "HelloWorld");
}
}
浏览器运行:
测试Web接口,打开浏览器,访问 http://127.0.0.1:8080/emos-wx-api/swagger-ui.html
第四部份给请求参数加参数验证。
第一步是无添加依赖,第二步,首行得让请求的参数是一个类,有get set 方法,并在属性中增加验证,
然后在控制器传入这个类,
详细步聚如下:
在项目的pom.xml文件中添加spring-boot-starter-validation依赖,以便使用Validation库。然后让Maven加载这个依赖库。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
第二步:编写验证类
@ApiModel
@Data
public class TestSayHelloForm {
@NotBlank
@Pattern(regexp = "^[\\u4e00-\\u9fa5]{2,15}$")
@ApiModelProperty("姓名")
private String name;
}
第三步,在控制器中使用这个类
@RestController
@RequestMapping("/test")
@Api("测试web接口")
public class TestController {
@PostMapping("/sayHello")
@ApiOperation("最简单的测试方法")
public R sayHello(@Valid @RequestBody TestSayHelloForm form) {
return R.ok().put("message", "Hello," + form.getName());
}
}
抵御即跨站脚本:(XsS)攻击
XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java、 VBScript、ActiveX、 Flash 或者甚至是普通的HTML。攻击成功后,攻击者可能得到包括但不限于更高的权限(如执行一些操作)私密网页内容、会话和cookie等各种内容。
例如用户在发帖或者注册的时候,在文本框中输入<script>alert('xss')</script>这段代码如果不经过转义处理,而直接保存到数据库。将来视图层渲染HTML的时候,把这段代码输出到页面上,那么<script>标签的内容就会被执行。
通常情况下,我们登陆到某个网站。如果网站使用Httpsession保存登陆凭证,那
会以的形式保存在浏览器上。如果黑客在这个网页发帖的时候,填写SessionIdCookie代码是用来获取Cookie 内容的,并且把CookieJavascript内容通过Ajax发送给黑客自己的电脑。于是只要有人在这个网站上浏览黑客发的帖子,那么视图层渲染HTML页面,就会执行注于是你的就可以入的XSS脚本,:Cookie信息就泄露了。黑客在自己的电脑上构建出Cookie冒充已经登陆的用户。
即便很多网站使用了JWT,登陆凭证Token分牌)是存储在浏览器上面的。所以用XSS脚本可以轻松的从Storage中提取出Token黑客依然可以轻松的冒充已经登陆的用户。
所以避免XSS攻击最有效的办法就是对用户输入的数据进行转义,然后存储到数据库里面。等到视图层渲染HTML页面的时候。转义后的文字是不会被当做JavaScript执行的,这就可以抵御XSS攻击。
二、导入依赖库
因为 Hutool 工具包带有XSS转义的工具类,所以我们要导入 Hutool ,然后利用 Servlet 规范提供的请求包装类,定义数据转义功能,
<dependency> <groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.4.0</version>
</dependency>
三、定义请求包装类,优邪的设计模式
,它其实是个接口。如果我们想要重新定义请我们平时写Web项目遇到的 HttpservletRequest求类,扩展这个接口是最不应该的。因为 HttpservletRequest 接口中抽象方法太多了,我们逐一实现起来太耗费时间。所以我们应该挑选一个简单一点的自定义请求类的方式。那就是继承 HttpservletRequestWrapper 父类
JavaEE只是一个标准,具体的实现由各家应用服务器厂商来完成。比如说 Tomcat 在实现 Servlet 规范的时候,就自定义了 HttpServletRequest 接口的实现类。同时JavaEE规范还定义了 HttpServletRequestwrapper ,这个类是请求类的包装类,用上了装饰器模式。不得不说这里用到的设计模式真的非常棒,无论各家应用服务器厂商怎么去实现 HttpservletRequest 接口,用户想要自定义请求,只需要继承 HttpServletRequestwrapper ,对应覆盖某个方法即可,然后把请求传入请求包装类,装饰器模式就会替代请求对象中对应的某个方法。用户的代码和服务器厂商的代码完全解耦,我们不用关心 HttpServletRequest 接口是怎么实现的,借助于包装类我们可以随意修改请求中的方法。
主要思路是写二个过虑器,然后主类增加扫码,主类方法如下:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@SpringBootApplication
@ServletComponentScan
public class EmosWxApiApplication {
public static void main(String[] args) {
SpringApplication.run(EmosWxApiApplication.class, args);
}
}
过虑器代码一个是封装的wrpper。一人是真正用的过虑器
封装的wrapper 过虑器最后就是用请求过虑的过虑器
package com.example.emos.wx.config.xss; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import java.io.IOException; @WebFilter(urlPatterns = "/*") public class XssFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request= (HttpServletRequest) servletRequest; XssHttpServletRequestWrapper wrapper=new XssHttpServletRequestWrapper(request); filterChain.doFilter(wrapper,servletResponse); } @Override public void destroy() { } }
文件结构如下:


浙公网安备 33010602011771号