日志:
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>