日志:
Log4j2
配置文件:
- Log4j2 采用的是.xml、.json或者.jsn
- Log4j2.xml放置在resource目录下。
- 也可以修改为 log4j 的配置文件.properties (这个需要到web.xml里面配置监听)
spring
- 一个分层的JavaSE/EEfull(一站式)轻量级开源框架
- 特征
- 轻量:从大小与开销两方面而言Spring都是轻量的,非侵入式
- 控制反转:通过一种称作控制反转(Ioc)的技术促进了低耦合
- 面向切面:允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事物(transaction)管理)进行内聚性的开发
- 容器:包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器。
spring mvc
- 与struts2的区别
- spring mvc和spring是无缝的
- struts2是类级别的拦截,spring mvc是方法级别的拦截
- spring mvc 的入口是servlet,而struts2是filter
- spring mvc 开发效率和性能高于struts2
- 进行更简洁的web层的开发;
- 天生与spring框架即成(如Ioc容器、Aop等);
- 提供强大的约定大于配置的契约式编程支持;
- 能简单的进行web层的单元测试;
- 支持灵活的url到页面控制器的映射;
mybatis-plus
- 一款mybatis的增强crud工具包,简化增删改查操作。启动加载xml配置时注入表单sql操作,为简化开发工作、提高生产率而生。mybatis-plus启动注入非拦截实现、性能更优。
- 与mybatis相比的优势
- 增强了mybatis通用单表操作的能力,只需要继承通用的service或者dao就能拥有单表增删改查的能力
- mybatis-plus启动注入非拦截实现、性能更优
- 多种ID选择,类型ID_WORKER,UUID全局唯一、支持实现分库
- 完全继承原生,易理解、扩展使用,支持自定义表、字段、ID动态注解
shiro
一个强大一用的Java安全框架,提供了认证、授权、加密和会话管理等功能,可为任何应用提供安全保障-从命令行应用、移动应用到大型网络及企业应用。
druid监控
- 替换dbcp和c3p0。Druid提供了一个高效、功能强大、可扩展性好的数据库连接池。
- 可以监控数据库访问性能,Druid内置提供了一个功能强大的statFilter插件,能够详细统计sql的执行性能,这对于线上分析数据库访问性能有帮助。
- 数据库密码加密。直接把数据库密码写在配置文件中,这是不好的行为,容易导致安全问题。DruidDruiver和DruidDataSource都支持PasswordCallback。
- sql执行日志,Druid提供了不同的LogFilter,能够支持Common-Logging、Log4j和JdkLog,你可以按需求选择相应的LogFilter,监控你应用的数据库访问情况。
- 扩展JDBC,如果你要对JDBC层有编程的需求,可以通过Druid提供的Filter机制,很方便编写JDBC层的扩展插件。
使用redis缓存
pom.xml中将redis放开,将ehcahe注掉! spring-config.xml中把ehcache注掉,把redis放开!
项目常用注解
spring 与 spring mvc
- @Controller 用于标注控制层组件
- @Service 服务组件,用于标注业务层组件
- @Component 泛指组件,当组件不好归类的时候,我们可以使用这个组件进行标注
- @GetMapping method为get请求的@RequestMapping简写
- @PostMapping method为post请求的@RequestMapping简写
- @RequestMapping
- 处理请求地址映射的注解,可用于类或方法上
- 用于类上,表示类中的所有相应请求的方法都是以改地址作为父路径
- @Autowired
- 对类成员变量、方法及构造函数进行标注,完成自动装配的工作
- 通过@Autowired的使用来消除set、get方法
- 默认是按照byType进行注入的
- @ResponseBody
- 表示该方法的返回结果直接写入HTTP response body中
- 一般在异步获取数据时使用,在使用@RequestMapping后,返回值通常解析为跳转路径,加上@responsebody后返回结果不会被解析为跳转路径,而是直接写入http response body中。比如异步获取json数据,加上@responsebody后,会直接返回json数据。
- @Scheduled spring定时任务注解,使用cron表达式
- @InitBinder 绑定请求参数到指定的属性编辑器,解决类型的转换问题
spring aop
- @Pointcut 声明切入点表达式,一般在该方法中不再添加其他代码
- @Around 环绕通知,围绕着方法执行
- @Aspect 配置在类上,把这个类声明为一个切面,需要把该类放入到IOC容器中,再声明为一个切面
- @Order 指定切面的优先级,当有多个切面时,数值越小优先级越高
mybatic plus
- @TableName 表名注解
- @TableField 字段注解
- @TableId 主键注解
其它
- @CsrfToken 完成检测登录时是否带有token,防止跨站请求伪造攻击
- @SuppressWarnings 对被批注的代码元素内部的某些警告保持静默
- @JsonProperty
- @JsonProperty 此注解用于属性上,作用是把该属性的名称序列化为另外一个名称,如把trueName属性序列化为name,@JsonProperty(name)。
- 拓展
- @JsonIgnore 此注解用于属性上,作用是进行JSON操作时忽略该属性。
- @JsonFormat 此注解用于属性上,作用是把Data类型直接转化为想要的格式,如:@JsonFormat(pattern = “yyyy-MM-dd HH-mm-ss”)。
Validation模版引擎
注解
// Bean Validation 中内置的 constraint
@Null 被注释的元素必须为 null
@NotNull 被注释的元素必须不为 null
@AssertTrue 被注释的元素必须为 true
@AssertFalse 被注释的元素必须为 false
@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max=, min=) 被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past 被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个将来的日期
@Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式
// Hibernate Validator 附加的 constraint
@NotBlank(message =) 验证字符串非null,且长度必须大于0
@Email 被注释的元素必须是电子邮箱地址
@Length(min=,max=) 被注释的字符串的大小必须在指定的范围内
@NotEmpty 被注释的字符串的必须非空
@Range(min=,max=,message=) 被注释的元素必须在合适的范围内
生成原理
/**
* 生成代码
*/
public void execute() {
logger.debug("==========================准备生成文件...==========================");
// 初始化配置
initConfig();
// 创建输出文件路径
mkdirs(config.getPathInfo());
// 获取上下文
Map<String, VelocityContext> ctxData = analyzeData(config);
// 循环生成文件
for (Map.Entry<String, VelocityContext> ctx : ctxData.entrySet()) {
batchOutput(ctx.getKey(), ctx.getValue());
}
// 打开输出目录
if (config.getGlobalConfig().isOpen()) {
try {
String osName = System.getProperty("os.name");
if (osName != null) {
if (osName.contains("Mac")) {
Runtime.getRuntime().exec("open " + config.getGlobalConfig().getOutputDir());
} else if (osName.contains("Windows")) {
Runtime.getRuntime().exec("cmd /c start " + config.getGlobalConfig().getOutputDir());
} else {
logger.debug("文件输出目录:" + config.getGlobalConfig().getOutputDir());
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
logger.debug("==========================文件生成完成!!!==========================");
}
- 从mpg.execute()执行开始,根据执行方法一步步走
- 初始化配置
- 方法:AbstractGenerator.initConfig()
- 涉及初始化数据源DataSourceConfig,数据表StrategyConfig,包配置PackageConfig,模版TemplateConfig配置,全局信息GlobalConfig等属性。
- 就是说你执行前的一些属性设置初始化,方便接下来的取值。
- 创建输出的文件夹
- 方法:mkdirs(config.getPathInfo());
- 就是创建你的java文件,jsp文件最终要输出的目录
- 获取上下文
- 方法:analyzeData(ConfigBuilder config)
- 根据全局配置取出controller,service等包名,超类的类名等变量
- 循环表信息,为每个表设定controller类名,service类名、自定义属性等信息,为渲染vm模版数据准备
- 合成上下文模版
- 根据表信息生成java文件和jsp文件
- 将模版转化成为文件,使用velocity模版引擎合成数据与模版生成新的文件
- 打开输出目录
异常处理
spring异常处理
- 实现方法 需要实现HandlerExceptionResolver这个接口类,并重写resolveException方法,在resolveExcepiton方法中处理自己的异常逻辑。
- 全局处理器
- /scan/ExceptionResolver.java
- 继承HandlerEexceptionResolver并添加注解@Component交给spring处理
- resolveExcetion方法里面需要做的事情
- 使用log4j2记录异常,把异常信息记录到日志里面,方便查看日志找出问题
- 判断方法是否是异步请求
- 异步请求应该返回json数据并弹窗提示,同步请求返回到错误页面
Java web项目自带
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/views/error/404.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/WEB-INF/views/error/500.jsp</location>
</error-page>
web项目的简单异常指引,一般来说有了异常处理之后可以不配这这个。
System.out.println()是指输出信息到控制台,不会记录到日志文件里面
在生成环境中,一般每天会生成一个日志文件,记录系统的运行信息
shiro权限控制
常用功能
帮助系统完成认证、授权、加密、会话管理、与web集成、缓存等。
- Authentication:身份认证/登陆,验证永华是不是拥有相应的身份;
- Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限;
- Session Manager:会话管理,即用户登陆后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通javaSE环境的,也可以是如web环境的;
- Caching:缓存,比如用户登陆后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率;
- Remember Me:记住我,这个是非常常见的功能,即一次登陆后,下次再来的话不用登陆了。
名词
- Subject:主体,代表了当前“用户”
- SecurityManager:安全管理器;即所有与安全有关的操作都会与SecurityManager交互;且它管理着所有Subject
- Realm:域,Shiro从Realm获取安全数据(如用户、角色、权限)
- SessionManager:管理主体与应用之间交互的数据
- CacheManager:缓存控制器,来管理如用户、角色、权限等的缓存
- Authrizer:授权器,或者访问控制器,用来决定主体是否有权限进行相应的操作
- Authenticator:认证器,负责主体认证
shiro使用
从配置文件spring-shiro.xml看起,通过这个配置文件集成spring与shiro
<!-- Shiro Filter -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 安全管理器 -->
<property name="securityManager" ref="securityManager"/>
<!-- 默认的登陆访问url -->
<property name="loginUrl" value="/login"/>
<!-- 登陆成功后跳转的url -->
<property name="successUrl" value="/index"/>
<!-- 没有权限跳转的url -->
<property name="unauthorizedUrl" value="/unauth"/>
<property name="filterChainDefinitions">
<value>
<!--
anon 不需要认证
authc 需要认证
user 验证通过或RememberMe登录的都可以
-->
/captcha.jpg = anon
/commons/** = anon
/static/** = anon
/webhooks = anon
/login = anon
/** = user
</value>
</property>
</bean>
过滤器(Shiro Filter) :是整个配置文件的入口,用于拦截需要安全控制的请求进行处理;属性主要包括url、登陆成功url、没权限url、不需要验证的url和安全管理器等
安全管理器(securityManager)
- realm
- 自定义ShiroDbRealm
- 重写doGetAuthenticationInfo()方法:主要验证登陆密码是否正确,已经获取用户的权限和角色,交给shiro
- 认证步骤:
- 用户提交用户名和密码
- shiro封装令牌(token,包含username和password信息)
- realm 通过用户名将密码查询返回
- shiro 自动去比较查询出密码和用户输入密码是否一致
- 进行登陆控制
- matcher — RetryLimitCredentialsMatcher — 密码错误5次锁定
- 自定义ShiroDbRealm
- cacheManager:集成spring-cache作为shiro的缓存,项目中redis和ehcache用其中一个
- rememberMeManager:记住登陆状态管理器
- SessionManager — 会话管理器 — 主要配置登陆超时的session管理
注意:
Shiro不会去维护用户、维护权限;这些需要我们自己去设计/提供;然后通过相应的接口注入给shiro即可。
缓存机制
简介
缓存是介于应用程序和物理数据源之间,其作用是为了降低应用程序对物理数据源访问的频次,从而提高了应用的运行性能。
spring-cache
- 它本质上不是一个具体的混存实现方案,而是一个对缓存使用的抽象
- 通过在既有代码中添加少量它定义的各种annotation,即能够达到缓存方法的返回对象的效果
- 特点:
- 能够使用SpEL(Spring Expression Language)来定义缓存的key 和 各种 condition
- 支持和主流的专业缓存,例如:EHCache、redis集成
注解形式:
@Cacheable(value = "hour", key = "#id")
public User selectById(Serializable id) {
return userMapper.selectById(id);
}
/impl/TestService.java
@Cacheable 缓存方法返回的值
编码形式:
@Autowired private CacheManager cacheManager;
@Scheduled(cron = "0 5/20 * * * ?")
public void cronTest() {
// 测试手动存储cache
Cache cache = cacheManager.getCache("hour");
Integer xx = cache.get("x", new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return 111111;
}
});
// 测试redis
// redisTemplate.boundListOps("xxxx").leftPush("xxxx");
// 测试注解
testService.selectById(1L);
testService.selectById(1L);
testService.selectById(1L);
logger.debug(xx);
logger.debug(new Date());
}
/task/TestTask.java
Cache cache = cacheManager.getCache(“hour”);
redis 和 ehcache 区别
ehcache:
- 配置文件chcache.xml,配置缓存时间
- 流行的纯Java开源缓存框架,配置简单、结构清晰、功能强大
- 直接在jvm虚拟机中缓存,速度快,效率高
- 但是缓存共享麻烦,集群分布式应用不方便
redis:
- 通过socket访问到缓存服务
- 效率比ecache低,比数据库要快很多
- 处理集群和分布式缓存方便,有成熟的方案
spring-cache集成缓存
切换两种缓存:只需要注释其中一个即可
<import resource="classpath:spring/spring-ehcache.xml"/>
<!--
<import resource="classpath:spring/spring-redis.xml"/>
-->
使用建议
如果是单个应用或者缓存访问要求很高的应用,用ehcache。
如果是大型系统,存在缓存共享、分布式部署、缓存内容很大的,建议用redis。
Druid数据源监控
一个JDBC组件,包括3部分
- DruidDriver代理Driver,能够提供基于Filter - Chain模式的插件体系
- DruidDataSource 高效可管理的数据库连接池。
- SQLParser
可以做什么
- 可以监控数据库访问性能,Druid内置提供了一个功能强大的StatFilter插件,能够详细统计SQL的执行性能,这对线上分析数据库访问性能有帮助
- 替换DBCP和C3P0.Druid提供了一个高效、波恩那个强大、可扩展性好的数据库连接池。
- SQL执行日志,Druid提供了不同的LogFilter,能够支持Common-Logging、Log4j和jdkLog,你可以按需求选择相应的LogFilter,监控你的应用数据库访问情况。
- 扩展JDBC,如果你要对JDBC层有编程需求,可以通过Druid提供的Filter-Chain机制,很方便编写JDBC扩展插件。
简单使用
spring-mabatis.xml 中使用Druid连接池作为数据源
<!-- base dataSource -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="url" value="${db.master.url}" />
<property name="username" value="${db.master.user}" />
<property name="password" value="${db.master.password}" />
<!-- 配置监控统计拦截的filters -->
<property name="filters" value="mergeStat,wall,log4j2" />
<property name="initialSize" value="5" />
<property name="maxActive" value="100" />
<property name="minIdle" value="10" />
<property name="maxWait" value="60000" />
<property name="validationQuery" value="SELECT 'x'" />
<property name="testOnBorrow" value="true" />
<property name="testOnReturn" value="true" />
<property name="testWhileIdle" value="true" />
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<property name="minEvictableIdleTimeMillis" value="300000" />
<property name="removeAbandoned" value="true" />
<property name="removeAbandonedTimeout" value="1800" />
<property name="logAbandoned" value="true" />
</bean>
在web.xml中配置Druid过滤器
<filter>
<filter-name>DruidWebStatFilter</filter-name>
<filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class>
<init-param>
<param-name>exclusions</param-name>
<param-value>/static/*,*.ico,/druid/*</param-value>
</init-param>
<init-param>
<param-name>sessionStatEnable</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>DruidWebStatFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- druid监控 -->
<servlet>
<servlet-name>DruidStatView</servlet-name>
<servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
<init-param>
<param-name>loginUsername</param-name>
<param-value>druid</param-value>
</init-param>
<init-param>
<param-name>loginPassword</param-name>
<param-value>druid</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>DruidStatView</servlet-name>
<url-pattern>/druid/*</url-pattern>
</servlet-mapping>