学习过程中注意点的总结

Updated on with 0 views and 0 comments

注意点

@author:HB、ocean

@time:2021-7-12

单例模式

懒汉模式

恶汉模式

核心代码

mybatis 涉及到的模式

构造者模式

例如SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、XMLStatementBuilder、CacheBuilder;

工厂模式

例如SqlSessionFactory、ObjectFactory、MapperProxyFactory;

单例模式

例如ErrorContext和LogFactory;

代理模式

Mybatis实现的核心,比如MapperProxy、ConnectionLogger,用的jdk的动态代理;还有executor.loader包使用了cglib或者javassist达到延迟加载的效果;

组合模式

例如SqlNode和各个子类ChooseSqlNode等;

模板方法模式

例如BaseExecutor和SimpleExecutor,还有BaseTypeHandler和所有的子类例如IntegerTypeHandler;

适配器模式

例如Log的Mybatis接口和它对jdbc、log4j等各种日志框架的适配实现;

装饰者模式,例如Cache包中的cache.decorators子包中等各个装饰者的实现;

迭代器模式

例如迭代器模式PropertyTokenizer;

Spring 框架涉及到的设计模式

单例模式 scope属性/注解

工厂模式 BeanFactory

代理模式 aop 动态代理

模板模式 jdbcTemplate

springmvc 框架中涉及的模式

适配器模式:接口、抽象类、实现类

ctrl+alt+b:查看接口的实现类;
ctrl+h:查看类或接口的继承关系;

jdbcUrl

///代表不写地址和端口,默认也是localhost:3306

yum解决方案

在使用yum安装软件包时提示标题所示的错误信息,原因估计是yum查找软件包依赖时使用的是过时的缓存,清空更新之后,再次安装软件,问题消失,

具体指令如下:

yum clean all
yum update

spring的重点

事务和AOP

默认使用jdk动态代理(基于接口)

aop典型的应用场景

  1. 分页插件采用 aop 思想

    如:mybatis 分页插件 pageHelper(采用 aop 思想)

  2. 日志管理采用 aop 思想

    如:log4j 日志打印信息 (aop 前通知的思想)

  3. 拦截器采用 aop 思想、实现

    如:spring-mvc Interceptor

  4. 权限验证采用 aop 思想

    如:Spring Security 权限验证框架 用户的操作权限

  5. 事务管理采用 aop 思想

从一开始的单页面到分层架构到现在的分布式+微服务

JBLJAVAToWEB Java项目转换web

alt+shift+insert 快速编辑多行

前端页面改的 不用重启 刷新就行

SpringMVC 拦截器 涉及 的 问题、坑!

一、拦截器的用法

  1. 编写拦截器类 继承HandlerInterceptorAdapter类并重写需要的方法 或实现HandlerInterceptor接口并实现所有方法。

  2. 在spring-mvc.xml(也就是springmvc的配置文件)中添加拦截器,代码如下

    <!-- 拦截器 -->
    <mvc:interceptors>   
        <mvc:interceptor>
            <!-- 拦截所有的请求,这个必须写在前面,也就是写在【不拦截】的上面 -->
            <mvc:mapping path="/**"/>
            <!-- 下面是配置不拦截的请求 -->
            <mvc:exclude-mapping path="/login.html" />
            <bean class="com.mm.interceptor.AuthorityInterceptor"/>   
        </mvc:interceptor> 
    </mvc:interceptors>
    
    • 需要注意的是,其中bean就是指定前面实现的拦截器类,
    • /**的意思是所有文件夹及里面的子文件夹
    • /*是所有文件夹,不含子文件夹
    • /是web项目的根目录

    除此之外还可以通过DefaultAnnotationHandlerMapping注册自定义拦截器

    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
            <property name="interceptors">
                <list>
                    <bean class="com.mm.interceptor.MyInterceptor1"></bean>
                    <bean class="com.mm.interceptor.MyInterceptor2"></bean>
                </list>
               </property>
    </bean>
    

    这种方式注册的时候需要注意,如果配置文件中有<mvc:annotation-driven />那么它默认已经注册了DefaultAnnotationHandlerMapping,AnnotationMethodHandlerAdapter 。我们在配置的这个自定义的就不起作用了,需要把它去掉。所以对待<mvc:annotation-driven />这种简化方法注册的时候,应该是在掌握的足够熟练的前提下使用比较好。

二、不拦截jsp页面的问题

拦截器只拦截@Controller注解的类和方法,对于jsp没有拦截(就因为这个耽误了四个小时,一直以为是拦截器配置出错,其实只是访问jsp页面的时候不拦截而已)

另外需要注意的是,拦截器是会拦截静态资源的 比如html js css image这类,虽然都是页面 但是html属于静态资源,jsp不属于

解决方案有两种:

1、将所有的jsp文件放入到WEB-INF文件夹下,这样用户是直接不能访问WEB-INF文件下的jsp文件的。spring mvc的理念也是通过controller里的@RequestMapping来请求相关jsp页面,而非用户直接访问jsp页面。

  1. 也就是说,jsp页面的访问需要通过controller来进行一次请求,因为会拦截对controller的请求,所以也就相当于拦截了jsp页面。
  2. 如果要做登陆拦截,只需要把登陆页面不拦截,其余页面拦截进行是否登陆的验证即可。

2、还有一种解决方案:jsp如果不放在WEB-INF文件下,spring mvc是无法拦截的,这种情况下需要用最原始的servlet的Filter接口。

原理:通过Request获取请求的uri进行分析过滤。

三、防止SpringMVC拦截器拦截js等静态资源文件

SpringMVC提供mvc:resources来设置静态资源,但是增加该设置如果采用通配符的方式增加拦截器的话仍然会被拦截器拦截,可采用如下方案进行解决:

方案一、拦截器中增加针对静态资源不进行过滤(涉及spring-mvc.xml)

<mvc:resources location="/" mapping="/**/*.js"/>  
<mvc:resources location="/" mapping="/**/*.css"/>  
<mvc:resources location="/assets/" mapping="/assets/**/*"/>  
<mvc:resources location="/images/" mapping="/images/*" cache-period="360000"/>

<mvc:interceptors>
     <mvc:interceptor>
         <mvc:mapping path="/**/*"/>
         <mvc:exclude-mapping path="/**/fonts/*"/>
         <mvc:exclude-mapping path="/**/*.css"/>
         <mvc:exclude-mapping path="/**/*.js"/>
         <mvc:exclude-mapping path="/**/*.png"/>
         <mvc:exclude-mapping path="/**/*.gif"/>
         <mvc:exclude-mapping path="/**/*.jpg"/>
         <mvc:exclude-mapping path="/**/*.jpeg"/>
         <mvc:exclude-mapping path="/**/*login*"/>
         <mvc:exclude-mapping path="/**/*Login*"/>
         <bean class="com.luwei.console.mg.interceptor.VisitInterceptor"></bean>
     </mvc:interceptor>
</mvc:interceptors>

方案二、使用默认的静态资源处理Servlet处理静态资源(涉及spring-mvc.xml, web.xml)

在spring-mvc.xml中启用默认Servlet

<mvc:default-servlet-handler/>

在web.xml中增加对静态资源的处理

<servlet-mapping>  
     <servlet-name>default</servlet-name>  
     <url-pattern>*.js</url-pattern>  
     <url-pattern>*.css</url-pattern>  
     <url-pattern>/assets/*"</url-pattern>  
     <url-pattern>/images/*</url-pattern>  
</servlet-mapping> 

方案三、修改Spring的全局拦截设置为*.do的拦截(涉及web.xml)

<servlet>
     <servlet-name>SpringMVC</servlet-name>
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
     <init-param>
         <param-name>contextConfigLocation</param-name>
         <param-value>classpath:spring-mvc.xml</param-value>
     </init-param>
     <load-on-startup>1</load-on-startup>
     <async-supported>true</async-supported>
</servlet>

<servlet-mapping>
     <servlet-name>SpringMVC</servlet-name>
     <url-pattern>*.action</url-pattern>
</servlet-mapping>

这样设置,Spring就会只针对以'.do'结尾的请求进行处理,不再维护静态资源

针对这三种方案的优劣分析:

  第一种方案配置比较臃肿,多个拦截器时增加文件行数,不推荐使用;

  第二种方案使用默认的Servlet进行资源文件的访问,Spring拦截所有请求,然后再将资源文件交由默认的Sevlet进行处理,性能上少有损耗;

  第三种方案Spring只是处理以'.action'结尾的访问,性能上更加高效,但是再访问路径上必须都以'.action'结尾,URL不太文雅;

综上所述,推荐使用第二和第三种方案


在SpringMVC3.0之后推荐使用:

<mvc:resources location="/WEB-INF/html/" mapping="/**/*.html"/>
<mvc:resources location="/WEB-INF/html/" mapping="/**/*.ico"/>
<mvc:resources location="/WEB-INF/html/" mapping="/**/*.js"/>
<mvc:resources location="/WEB-INF/html/" mapping="/**/*.css"/>
<mvc:resources location="/WEB-INF/html/" mapping="/**/*.png"/>
<mvc:resources location="/WEB-INF/html/" mapping="/**/*.gif"/>
<mvc:resources location="/WEB-INF/html/" mapping="/**/*.jpg"/>
<mvc:resources location="/WEB-INF/html/" mapping="/**/*.ttf"/>
<mvc:resources location="/WEB-INF/html/" mapping="/**/*.woff"/>
<mvc:resources location="/WEB-INF/html/" mapping="/**/*.woff2"/>

本文内容参照地方过多,这里不一一列举了。

/和/*的区别

在配置web.xml中SpringMVC拦截器时url-pattern后面配/不能是/*

其中/和/*的区别:
< url-pattern > / </ url-pattern >   不会匹配到*.jsp,即:*.jsp不会进入spring的 DispatcherServlet类 。
< url-pattern > /* </ url-pattern > 会匹配*.jsp,会出现返回jsp视图时再次进入spring的DispatcherServlet 类,导致找不到对应的controller所以报404错。

总之,关于web.xml的url映射的小知识:
< url-pattern>/</url-pattern>  会匹配到/login这样的路径型url,不会匹配到模式为*.jsp这样的后缀型url
< url-pattern>/*</url-pattern> 会匹配所有url:路径型的和后缀型的url(包括/login,*.jsp,*.js和*.html等)

jsp 的本质是 servlet (编译称为servlet 然后执行),servlet 优先级 默认是最高的(底层实现) 所以 jsp 一般设置为 / 不进行拦截

UUID

Java UUID 统一唯一识别码 的生成 UUID.randomUUID().toString().replaceAll("-", "")

下载文件中文乱码

//下载的时候,响应头即下载文件名可能出现中文乱码
// 处理方式一
byte[] bytes = name.getBytes("UTF-8");
String nName = new String(bytes,"iso8859-1");
// 处理方式二
String nName = URLEncoder.encode(name,"UTF-8");
//实现下载 -- 原生方案:一个头、两个流
//头:响应头
response.setHeader("content-disposition","attachment;filename="+nName);//设置下载时文件名称
                                                                        
String path = "C:\\Users\\Administrator\\Desktop\\upload";              
File file = new File(path,name);                                        
//流 -- 本地读取流   远程写出流                                                    
InputStream is = new FileInputStream(file);                             
                                                                        
OutputStream os = response.getOutputStream();                           
                                                                        
//边读边写                                                                  
                                                                        
byte[]bs = new byte[1024];                                              
int len = -1;                                                           
                                                                        
while((len = is.read(bs)) != -1){                                       
    os.write(bs,0,len);                                                 
}                                                                       
                                                                        
os.close();                                                             
is.close();                                                             

String的endWith判断后缀

// 获取到当前请求url 
String uri = request.getRequestURI();
// 判断是否是addCart 如:xxx/yyy/zzz/addCart
uri.endsWith("addCart");

Spring 整合 Junit

在使用 spring-test 的过程中,有两个 runner 可以选择,分别是 SpringRunner 和 SpringJUnit4ClassRunner。
如果是在 4.3 之前,只能选择 SpringJUnit4ClassRunner,如果是 4.3 之后,建议选择 SpringRunner。
SpringRunner 对 junit 的版本有要求,需要 4.12 及以上。

Spring 和 SpringMVC 分别扫描

Spring 容器和 SpringMVC 容器,父子容器,Spring 是父,SpringMVC 是子;SpringMVC 可以调用父容器对象,反之不可以。

为了安全,进行分别扫描 MVC扫描Controller 不扫描Service,Spring不扫描Controller

image-20210720105507966

image-20210720105616712

MVC 注解驱动

<mvc:annotation-driven 注解驱动 默认帮你导入三大模块、处理器映射器、处理器适配器、视图解析器,并且帮你使用了jackson 对象 转换 json 格式

idea 新项目导入环境

删除.idea、.impl和target文件,这样环境为自己的。

项目的根路径

${pageContext.request.contextPath}

命令的简称习惯

执行:eXcute,目录:Directory

追问

执行是E开头的啊!

追答

英文中excute开头的音(ex...)与X字母的音相近,老外都喜欢这样,类似的圣诞节(Christmas)也曾被简化为Xmas

JS注意大小引号嵌套的关系

表单的序列化jQuery ajax - serialize() 方法

Tomcat启动出错

缓存问题 清除 work目录下 catalina 重启即好

Redis启动

先开启服务端 在开启客户端

./redis-server redis.conf ./redis-cli

Mysql驱动

高版本需要 com.mysq.cj.jdbc.Driver

释放防火墙

直接关闭防火墙

systemctl stop firewalld.service

开启防火墙mysql3306端口的外部访问

firewall-cmd --zone=public --add-port=3306/tcp --permanent

重启防火墙

 firewall-cmd --reload

SpringBoot 整合 Dubbo 启动不了服务提供者

dubbo 的 springboot starter 必须卸载 web 依赖 下面 否则 会报错SLF4J 异常

getResource().getPath()返回的路径空格变成了 +

最近我们有一个 web 程序,为了取到配置文件的路径,采用了 this.getClass().getResource(“/”).getPath()
的方法来取得存放 class 的物理路径。本来测试的时候没问题,一发布崩溃掉了。究其原因是发布环境的 Tomcat 的安装目录带有空格,而 getPath 的返回值把空格给转换成了 “+”。经过一番调查,原来是这是 Java 的一个历史悠久的 bug:

Bug ID: 4466485 getClass( ).getResource( ).getFile( ) returns file name with +

此 bug 于 2001年6月被提出来,2002年11月最终关闭。没有修复的原因是这样做会导致兼容性问题。官方给出的解决方法是采用URI类再把它解码出来。

方法(1),使用repaceAll("+",' ')替换后,只能解决空格问题。但是路径中包含%和中文就不行了。
方法(2),使用URLDecoder.decode(str,"UTF-8")解码,但是只能解决一部分,若路径中含有+,也是不能解决的,原因是URL并不是完全用 URLEncoder.encode(str,"UTF-8")编码的,+号被解码后,却变成了空格。
方法(3),可以解决所有的问题,用TestURL().class.getResource("").toURI().getPath(),但是需要处理URISyntaxException异常,比较麻烦点。

XML 写 SQL 解析出错

xml 格式

第一种方法:
用转义字符把">"和"<"替换掉,就没有问题了。

附:XML转义字符

<     	<   	小于号   
>     	>   	大于号   
&     	&   	和   
'     	’   	单引号   
"     	"   	双引号   

第二种方法:
因为这个是xml格式的,所以不允许出现类似">"这样的字符

<![CDATA[ ]]>符号进行说明,将此类符号不进行解析 

<![CDATA[ 这里写你的sql ]]>  

Controller 实体类传参接收为 null

实体类起的名字过于简单 第二个为大写字母导致的 因为 RequestBody JSON 解析对象 会去寻找 get方法 但是由于连续的大写字母会导致出错 不遵循驼峰命名规范 和 lombok 有关

@JsonProperty(value = "IdentityCard") (原因: 因为实体类参数和 传入的参数不一致,驼峰命名,具体详细原因不详。增加上这个注解映射后,及可获取实体类中的参数值)

JSTL c if 没有 else

使用如下替代

<c:choose>
   <c:when test="">    如果
   </c:when>   
   <c:otherwise>  否则
   </c:otherwise>  
</c:choose>

标题:学习过程中注意点的总结
作者:HB2Ocean
地址:http://future-hb.top:8080/articles/2021/08/29/1630240673304.html