1228springmvc
老师说这是没事找事,可能这个json有问题
指定FASTJSON
这个代码看着好亲切啊
这个xml中央转发器 用的这个参数是这里复制过来的
昨天学得结构
URI 就是端口后面的那部分
不要去扣字眼了,这个应该就是对应的那个类,这个是对应的那个方法
(根据uri映射方式)我用的是requestMappingHandleMapping 就调用何时的adapter来执行,要看
把一个url绑定到一个类上面去了
原来找适配器就是这玩意,我他吗。。。
handler就是自己编写的方法
String消息转换器,就是那个把string转换成Integer Double之类的那个东西
1.resturl(重要)
NB嗷,URL都没有了,请开始你的表演
uri路径变量 听着名字NB## uri路径变量 听着名字NB
整挺好
如何区分
NB嗷,还能这么用
这种只适合需要传的参数比较少的,比如豆瓣这个
正常的
豆瓣的
post请求中如果去掉了 json注解,就是接收k=v的参数
过滤器 不要单写/ 这个是置顶范围的 要写 /*
配置文件里面指定的是这个类下面的这个初始化参数
过滤器的那个逻辑
实际开发中,这个东西不用指定,因为:url tomcat已经变成utf-8了,post请求中的json已经有工具帮你转了,post k=value 不用这个
在springMvc里面所有的同步开发,想转视图,必须通过视图转发器来转
restUrl是一种有别于之前的url写法,要求url中不能有动词,查询参数可以是uri的一部分.
RESTUrl又称为描述性状态转移。restUrl的路径变量不能含有/符号
传统url | 参数 | 请求方式 | restUrl | 参数 |
---|---|---|---|---|
/user/queryById | ?id=1 | GET|GET | /user/1 | 参数是uri的一部分 |
/user/insert | 请求体的json格式 | POST|POST | /user | 请求体的json格式 |
/user/deleteById | ?id=1 | GET|DELETE | /user/1 | 参数是uri的一部分 |
/user/queryList | ?uname=fyt | GET|GET | /user | ?k=v |
/user/update | 请求体的json | POST|PUT | /user | 请求体的json格式 |
查询:get。添加:post。更新:put。删除:delete
后端使用@GetMapping,@PostMapping,@PutMapping,@DeleteMapping分别做映射。
2.乱码处理(不重要)
GET请求:k=v格式参数追加url后,无乱码,因为tomcat7以上版本对uri按照UTF-8编码解析。
POST请求:json格式参数放在请求体,无乱码,因为springmvc内部依赖jackson组件,内部使用UTF-8编码进行json字符串与对象的转换。
put请求:json格式参数放在请求体,无乱码,因为springmvc内部依赖jackson组件,内部使用UTF-8编码进行json字符串与对象的转换。
总结:json格式数据无乱码;get请求的k=v无乱码;请求体中参数如果是k=v格式的有乱码,tomcat对请求体中是不支持中文ISO-8859-1
如果要支持ik=v中文数据:
<!--编码过滤器-->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3.处理器方法转发与重定向(不重要)
只用在同步开发中。
之前处理器方法返回视图名,把前面追加forward:或者redirect:来进行处理器方法的转发与重定向。
4.静态资源处理(不重要)
在服务端应用中,保存有静态文件:js,html,css,img,文件,在前端如何访问这些文件。
在tomcat下的web.xml中默认有两个Servlrt:DefaultServlet映射路径/.JspServlet映射路径*.jsp。
JspServlet:用户访问xXX.jsp进入此servlet处理;
DefaultServlet:用户访问服务器静态资源,进入此servlet处理。
如果使用springmvc框架,把DispatchServlet映射路径设置为/,就会覆盖掉DefaultServlet
jsp能访问:通过jspServlet处理了请求。
静态资源不能访问:因为DefaultServlet被覆盖了,访问静态资源也进入了DispatcherSevlet。
方法1:重新配置DefualtServlet的Uri映射路径
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.html</url-pattern>
<url-pattern>*.css</url-pattern>
<url-pattern>*.js</url-pattern>
<url-pattern>*.jpg</url-pattern>
<url-pattern>*.png</url-pattern>
<url-pattern>*.docx</url-pattern>
<url-pattern>*.xlsx</url-pattern>
</servlet-mapping>
方法2:springmvc内部配置DefaultServlet来处理静态资源(建议使用)
<!--仍然是所有请求都进入DispatcherSerlvet,对有后缀的uri,通过default处理。default-servlet-name:默认名称default-->
<mvc:default-servlet-handler default-servlet-name="default"></mvc:default-servlet-handler>
方法3:
<!--所有以/static开头的uri,不再查处理器方法,直接通过ResourceHttpRequestHandler静态资源处理器对象来处理-->
<!--/static/css/main.css /static/css/main.css -->
<mvc:resources mapping="/static/**" location="/static/"></mvc:resources>
<mvc:resources mapping="/pages/**" location="/pages/"></mvc:resources>
<mvc:resources mapping="/upload/**" location="/upload/"></mvc:resources>
5.异常处理(重要)
把服务器的异常信息,捕获到异常,当出现对应的异常时候,返回客户端对应的错误码,错误提示信息。而不要返回给异常堆栈信息。
这种设计也太精巧了吧
如果你不知道这东西是啥,打个断点就知道了
handleMethod 里面存的可能是 String bean name
里面存了好多东西啊
存的不是字符串啊,存的是一个对象啊,尼玛的
垃圾到家的代码,像是我能干出来的事
@Document 这个注解什么意思
用来生成文档的
那么@Documented的作用是什么?
如果一个注解@B,被@Documented标注,那么被@B修饰的类,生成文档时,会显示@B。如果@B没有被@Documented标准,最终生成的文档中就不会显示@B。
这也太贴心了吧
异常处理 28:18
等学了日志组件之后,把这些信息记录下来,定期去服务器上面拿下来,分析并修改
局部异常处理:只对某一个处理器类中异常生效。
缺点:作用范围太小,只对一个类有效。
优点:能够对不同的异常做不同的返回处理。
@ExceptionHandler(ArithmeticException.class)
public AxiosResult doArithmeticException(){
return AxiosResult.error(E.BY_ZERO);
}
@ExceptionHandler(NullPointerException.class)
public AxiosResult doNullpointerException(){
return AxiosResult.error(E.ERROR);
}
@ExceptionHandler(Exception.class)
public AxiosResult doException(){
return AxiosResult.error(E.ERROR);
}
全局异常处理:能够对所有处理器类中异常生效。
优点:能够对所有处理器类的方法都有效。
缺点:无法对不同的异常进行不同的处理。
全局统一异常处理(重要)
@RestControllerAdvice来定义全局异常通知,对所有处理类中全部生效;
@ExceptionHandler来对不同的异常进行不同的处理。
自定义异常对象,改对象中有错误码和提示信息的枚举对象。当处理器方法内一些不正常的操作时可以直接抛出自定义异常。
6.文件上传下载(重要)
文件上传配置文件
我好烦这种啊,写一个变量就代表我要接收这种参数,这种不是我掌控的感觉好难受啊。但是内部实现也很简单。
就是拿到我的方法签名,然后判断参数,做判断,好烦啊
这几个字段是与用户下载需要用的
表单名 必须叫myfile
springmvc中文件上传使用的是commons-fileupload组件,springmvc对此组件使用代码又进行了封装。
- 添加commons-fileupload;commons-io包;
- 在springmvc.xml配置文件中配置文件解析器对象(改对象中封装了commons-fileupload代码)
<!--id必须是multipartResolver-->
<!--文件解析器对象,如果请求头Content-type为multipart/form-data的请求,
则进行该解析器对象对request进行处理,
调用commons-fileupload组件进行文件处理,把文件表单封装称为MutipartFile对象,-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8"></property><!--对中文文件名支持-->
<property name="maxInMemorySize" value="10000000"></property><!--临时文件限制域:10M-->
<property name="uploadTempDir" value="/upload/tmp"></property><!--临时文件存储位置 afa234234234.tmp-->
<property name="maxUploadSize" value="100000000"></property><!--文件上传的最大大小-->
</bean>
- 编写文件上传下载接口
@PostMapping("upload")
public AxiosResult doupload(MultipartFile myfile, HttpServletRequest req) throws IOException {
//这里进行文件上传操作。
InputStream in = myfile.getInputStream();//文件数据流,大文件用文件流处理
byte[] bytes = myfile.getBytes();//文件内容,小文件直接获取。
String originalFilename = myfile.getOriginalFilename();//文件名
long size = myfile.getSize();//文件大小
String realPath = req.getServletContext().getRealPath("/");//得到项目的部署根路径D://work
String savePath="/upload/"+originalFilename;// /upload/aaa.txt
String path =realPath+savePath;
IOUtils.write(bytes,new FileOutputStream(path));
Map<String,String> map =new HashMap<>();
map.put("path",savePath);
map.put("size",size+"");
map.put("fileName",originalFilename);
return AxiosResult.suc(map);
}
//如果上传的是图片,浏览直接预览图片,如果上传的是docx,xlsx,MP4文件,则需要提供下载功能。
//文件下载 /download?path=/upload/1227springmvc.md&fileName=1227springmvc.md
@GetMapping("download")
public ResponseEntity download(String path, String fileName, HttpServletRequest req) throws Exception {
String realPath = req.getServletContext().getRealPath("/");//得到项目的部署根路径D://work
String rootPath = realPath+path;
File f = new File(rootPath);
long length = f.length();
byte[] bytes = new byte[(int)length];
FileInputStream in = new FileInputStream(rootPath);
IOUtils.read(in,bytes);
//怎么把字节数组中的数据返回前端。并让前端弹出下载框
//指定响应头,来让前端浏览器弹出下载框
//文件内容作为响应体;resp.setHeader("Content-Disposition", "attachment; filename="+fileName);
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition","attachment; filename="+URLEncoder.encode(fileName,"UTF-8"));
return new ResponseEntity(bytes,headers,HttpStatus.OK);
}
7.拦截器(重要)
interceptor拦截器,是springmvc框架中的一个概念,类似于servlet中的Filter过滤器作用。
他这个拦截器使用true 和 false 来控制的啊
这个处理也太精巧了吧,等会要练一下这个
1.定义出拦截器对象,从HandlerInterceptor接口派生;
2.注册拦截器对象进入容器
3.配置拦截器的拦截范围与忽略范围。
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/user/login"></mvc:exclude-mapping>
<bean class="com.javasm.commons.interceptors.LoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
切记:请求进来,先执行filter,再进入DispathcerSevlet,根据uri找到处理器方法,以及该方法对应的拦截器栈集;顺序执行拦截器,所有拦截器返回true,才执行处理器方法;一旦任意一个拦截器返回false,则请求返回。
8.跨域处理(重要)
在实际项目中,springMvc是一定要配跨域请求的
这个鬼跨域拦截器为什么 是最后一个执行的???谁设计的??
哦,有这个设计,如果是域前请求的话,返回ture,就是这个过滤器直接放行
笑了,每一个拦截器只要用的session判断,就是需要cookie那个,它的前面都要做这个配置,所以这个东西是谁设计的
过滤器和拦截器
过滤器 是 servlet那个
拦截器是用于aop的,在对用方法前执行的东西,说是用反射实现的
mapping是映射的意思
volatile 关键字的作用
1 保证内存可见性
可见性是指线程之间的可见性,一个线程修改的状态对另一个线程是可见的。也就是一个线程修改的结果,另一个线程马上就能看到。
实现原理
当对非volatile变量进行读写的时候,每个线程先从主内存拷贝变量到CPU缓存中,如果计算机有多个CPU,每个线程可能在不同的CPU上被处理,这意味着每个线程可以拷贝到不同的CPU cache中。
volatile变量不会被缓存在寄存器或者对其他处理器不可见的地方,保证了每次读写变量都从主内存中读,跳过CPU cache这一步。当一个线程修改了这个变量的值,新值对于其他线程是立即得知的。
2 禁止指令重排
指令重排序是JVM为了优化指令、提高程序运行效率,在不影响单线程程序执行结果的前提下,尽可能地提高并行度。指令重排序包括编译器重排序和运行时重排序。
latile变量禁止指令重排序。针对volatile修饰的变量,在读写
这个我之后肯定会不懂,但是我现在知道,我不知道怎么表达出来
就是这是个执行对象代理方法的机器
我往里面放了我的过滤器,他去执行过滤器的方法
其实执行的是这个
这个命令没见过啊
操作指令前后会插入内存屏障,指令重排序时不能把后面的指令重排序到内存屏
当前端代码分离出去,以一个独立项目存在,独立部署。
在前端服务器下发起向后端服务器的请求,由于ip或端口的不同,违反了浏览器的同源策略。产生了跨域。
浏览器对跨域请求是如何处理?
简单请求:请求方式:get或post;不能有自定义请求头;content-type请求头只能是application/x-www-form-urlencoded、multipart/form-data、text/plain;
复杂请求:axios发起的post,put,delete都属于复杂请求。因为axios请求的请求头content-type是applicaiotn/json
。
对于复杂请求,浏览器在发起真正的请求之前,会先发起一个options预检请求。预检请求不带参数。
预检请求,检查什么?检查当前请求uri,服务器端是否允许跨域请求。
什么叫做服务器端是否允许跨域呢?预检请求到服务器,服务器返回的响应头中包含跨域响应头(客户端源,客户端提交方式,客户端请求头,跨域缓存),这些跨域响应头返回客户端,客户端根据跨域响应头判断真正的请求是不是符合响应头的要求。
springmvc中对跨域请求支持有两种方式:
基于拦截器跨域配置:
<mvc:cors>
<mvc:mapping path="/**" allowed-origins="http://localhost:8081" allowed-headers="*" allowed-methods="*" allow-credentials="true" max-age="1800"/>
</mvc:cors>
在自定义拦截器中对预检请求进行放行
//预检请求放行。不做session校验。
String method = request.getMethod();//获取提交方式
if("options".equals(method)){
return true;
}
基于CrosFilter过滤器跨域配置:(建议使用)
<!--真正的跨域过滤器-->
<bean id="corsFilter" class="org.springframework.web.filter.CorsFilter">
<constructor-arg name="configSource">
<bean class="org.springframework.web.cors.UrlBasedCorsConfigurationSource">
<property name="corsConfigurations">
<map>
<entry key="/**">
<bean class="org.springframework.web.cors.CorsConfiguration">
<property name="allowCredentials" value="true"/>
<property name="allowedMethods">
<list>
<value>GET</value>
<value>POST</value>
<value>PUT</value>
<value>DELETE</value>
<value>OPTIONS</value>
</list>
</property>
<property name="allowedHeaders" value="*"/>
<property name="allowedOrigins" value="http://localhost:8088"/>
</bean>
</entry>
</map>
</property>
</bean>
</constructor-arg>
</bean>
在web.xml配置过滤器代理对象
<!--过滤器代理对象-->
<filter>
<filter-name>delegatingFilterProxy</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetBeanName</param-name>
<param-value>corsFilter</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>delegatingFilterProxy</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
控制层:controller,handler
实体层:entity,domain
dao:dao,mapper