补springMVC后续

springMVC环境:基于spring环境;spring-web,spring-webMVC,commons-BeanUtils,commons-Collections

​ jackson组件3个jar.

简单了解spring与springMVC父子容器的概念:

initServletBean()方法中:
this.webApplicationContext = this.initWebApplicationContext();

//spring父容器对象
WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
//去全局的ServletContext对象中获取对象
Object attr = ServletContext.getAttribute("WebApplication.ROOT");

//springmvc子容器对象:XmlWebApplicationContext
WebApplicationContext wac = this.createWebApplicationContext(rootContext);
//子容器持有了父容器
wac.setParent(rootContext);
//子容器持有了全局的ServletContext对象
wac.setServletContext(this.getServletContext());
//加载springmvc.xml,进行包扫描,创建容器对象。
wac.refresh();

前端控制器:在tomcat启东时,初始化springmvc子容器(N个bean对象),并持有了spring父容器。

写业务处理器(控制层):对于一个实体类的所有操作,都放在一个处理器类中。

处理器映射器:RequestMappingHandlerMapping

处理器适配器:RequestMappingHandlerAdapter

视图解析器:IntelResourceViewResolver

jackson消息转换器:MappingJackson2HttpMessageConverter

#springMVC

1.转发与重定向:

同步开发中,处理器方法之间的转发与重定向。

在返回的String以forward:或redirect:开头.

2.resturl:

同步开发中不能使用,前后端分离的项目中使用最多

rest是对url的写法,描述性状态转移,url中不含动词

urlRequestMethoddataresturlRequestMethod
/user/addpost请求体:{k:v,k,v}/userPOST添加
/user/selectById?uid=1GET/user/1GET查询
/user/updateByIdPOST请求体:{k:v,k:v}/userPUT修改
/user/deleteById?uid=1GET/user/1DELETE删除

注意点:

put和delete请求:如果请求体中的数据是key=value&key=value格式的话,收不到数据。可以通过配置FormContentFilter过滤器来接收数据。

3.异常处理:

把服务器端处理器方法内部产生的各种信息进行处理。

  • 在web.xml中对不同的错误码进行错误页面配置。
<error-page>
        <error-code>404</error-code>
        <location>/404.html</location>
    </error-page>
    <error-page>
        <error-code>500</error-code>
        <location>/500.html</location>
    </error-page>

缺点:提示信息无法动态定义。只能够返回页面,在前端分离的情况下,不能使用。

  • 局部异常处理:只对一个处理器类中的异常生效。
@ExceptionHandler(Exception.class)
    public ResponseEntity doException(Exception e){
        String message = e.getMessage();
        Map<String,String> datas = new HashMap<>();
        datas.put("msg",message);
        datas.put("date",System.currentTimeMillis()+"");
        return ResponseEntity.ok(datas);
    }

缺点:范围太小,只对一个类有效

  • 全局异常处理:对所有处理器类中的异常生效。
public class MyExceptionHandler implements HandlerExceptionResolver {

    //适合于同步开发,当出现异常,转到一个自定义的异常页。
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        HandlerMethod hm = (HandlerMethod)o;
        Method method = hm.getMethod();
        String clzName = method.getDeclaringClass().getName();
        String methodName = method.getName();
        ModelAndView mv = new ModelAndView();
        mv.setViewName("error");
        mv.addObject("msg",e.getMessage());
        mv.addObject("date",System.currentTimeMillis()+"");

        return mv;
    }

缺点:只能够同步开发中使用。异步开发中不支持。

  • 全局统一异常处理:项目中使用,在局部异常处理的基础上结合着@ControllerAdvice注解一起使用

前端程序员调用后端接口,后端需要把执行结果返回前端(数字状态码,中文文字信息,数据)。

状态码枚举类;StatusBean;ResponseBean;自定义异常;定义全局的异常处理类;

4.静态资源处理:重要

同步开发,半分离异步开发。(前端资源和后端代码在一个项目中)

在web目录下的前端资源无法直接访问。

为什么jsp能访问,也是因为tomcat,tomcat中有默认的serlvet:default,jsp,当访问XXX.jsp进入JspServlet中处理。当我们访问XXX.html,XXX.css等非jsp后缀的时候,进入DispatcherServlet,前端控制器解析url,找处理器对象,找不到,则404.

  • 解决方法1:在web.xml中配置defaultServlet
<servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.html</url-pattern>
        <url-pattern>*.css</url-pattern>
        <url-pattern>*.jpg</url-pattern>
        <url-pattern>*.png</url-pattern>
        <url-pattern>*.js</url-pattern>
    </servlet-mapping>
  • 解决方式2:springMVC中有标签自动配置defaultServlet,建议使用这种。
<!--所有的静态资源都走DefaultServlet, default-servlet-name="default"-->
<mvc:default-servlet-handler></mvc:default-servlet-handler>
  • 解决方式3:springMVC中通过静态资源映射器,对静态资源进行处理。
<mvc:resources mapping="/static/**" location="/static/"></mvc:resources>
<mvc:resources mapping="/page/**" location="/page/"></mvc:resources>

5.文件上传:

springMVC的文件上传仍然基于apache common-fileupload。

  • 添加fileupload;io两个文件上传的jar包;
  • 在springmvc.xml中配置文件上传解析对象。
 <!--文件上传解析器-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="UTF-8"></property><!--上传中文文件名-->
        <property name="maxUploadSize" value="50000000"></property><!--上传文件最大大小-->
        <property name="maxInMemorySize" value="10000000"></property><!--临时文件的存储域-->
        <property name="uploadTempDir" value="/upload/tmp"></property><!--临时文件存储目录-->
    </bean>
  • 写文件上传处理器

前端提交url:

@RequestParam只能用在key=value数据格式,只能用在简单类型上。

@RequestBody只能 用在{k:v}数据格式,只能用在自定义对象类型上,map上。

@PathValiable只能用来获取url内的变量。

前端提交的url传输数据提交方式后端获取数据
/url?k=v&k1=v1数据在url上?后get可以直接加形参,@RequetParam
/url/v数据在url内get|delete后端使用@PathValiable来获取uri中的变量
/url数据在请求体,而且是json格式,无乱码post|put|delete后端使用@RequestBody来获取数据
/url数据在请求体,而且是k=v&k=vpost|put|delete可以直接加形参,@RequetParam

项目中使用全局统一异常处理:

自定义状态码枚举,自定义异常(持有了一个枚举对象)

定义一个全局统一的异常处理类,使用@ControllerAdvice注解。对所有RequestMapping做增强处理。

定义响应体。

静态资源处理:前端未分离

mvc:default-servlet-handler静态资源由DefaultServlet处理。不在走DispathcerServlet

文件上传下载:

添加两个jar包:commons-fileupload,commons-io

配置文件解析器:CommonsMultipartResolver,该bean对象的id必须是multipartResolver

在文件上传处理器中,表单参数类型写成MultipartFile对象即可。

6.拦截器:interceptor

​ 类似于过滤器filter,拦截器是框架中的概念。

登陆拦截器是个项目中都会使用。权限拦截器

  • 编写拦截器类
public class LoginInterceptor implements HandlerInterceptor {

    //前拦截
    @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session = request.getSession();
        Object login_user = session.getAttribute("LOGIN_USER");
        if (login_user != null) {
            return true;
        }
        throw new MvcException(StatusEnum.NO_LOGIN);
    }
}
  • 配置拦截器
 <mvc:interceptors>
        <mvc:interceptor>
            <!--拦截路径-->
            <mvc:mapping path="/**"/>
            <!--忽略路径-->
            <mvc:exclude-mapping path="/u/login"></mvc:exclude-mapping>
            <!--拦截器类-->
            <bean class="com.javasm.common.interceptor.LoginInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

7.跨域处理:

发起的请求与当前页面所在服务, 协议,ip,端口三者只要有一个不同,违反了浏览器的同源策略,造成跨域问题。

需要在服务器端配置响应头,告诉浏览器服务端允许这个客户端的请求:

响应头需要配置如下信息:

​ 允许的域:http://127.0.0.1:8848

​ 允许的请求头:

​ 允许的请求方法:GET/POST/PUT/DELETE/OPTIONS预检.

​ 是否允许请求携带cookie信息:

​ 可以暴露给客户端的响应头:

跨域产生的问题:

问题1:请求不能正常响应。因为浏览器的同源保护(springmvc.xml中配置全局跨域)

​ 解决方法:配置springMVC全局跨域设置mvc:cors

问题2:httpSession保存用户会话信息:每次请求服务器都会创建新的HttpSession对象,无法做到多次请求之间共享session中数据。

​ 解决方法:前端axios请求配置withCredentials=true,表示请求时携带cookie

​ 服务端跨越配置中允许接收客户端cookie,allow-credentials=“true”

​ 如果使用chrome发现配置后仍然不行,开发中暂时先chrome://flags/,把samesite禁用了。

​ 仍然存在的问题:

​ tomcat分布式部署的时候,多服务器之间的session共享问题(通过spring-session,结合redis使用)。

​ chrome浏览器的samesite同站点默认配置lax,不保存第三方的cookie问题。

​ 解决方法2:JWT组件,token工具包

注意点:

在跨域的情况下,浏览器对POST,PUT,DELETE三种请求,会先向服务器发送预检请求,(检查服务端是否支持客户端的本次请求).

8.aop事务切面

定义出事务管理器对象。

定义事务切面,切入点表达式使用注解方式。

总结:

拦截器在项目中登录拦截,权限拦截。

​ 从HandlerInterceptor接口派生,重写preHandle前拦截。(在拦截方法中一定把OPTIONS请求放行,避免预检请求被拦着,造成跨域设置失败)

​ 配置拦截器

跨域:

​ 服务端:springMVC全局跨域配置或者配置跨域过滤器:

​ <mvc:mapping path="/**" allowed-origins=“http://127.0.0.1:8848” allowed-methods="" allowed-headers="" allow-credentials=“true”/>

登录用户的状态信息维护:

​ 服务器端HttpSession保存用户登录信息:

​ 客户端:axios配置携带cookie:axios.defaults.withCredentials = true;

​ 服务端:allow-credentials=“true”

​ 如果chrome浏览器不保存第三方的cookie,禁止chrome的samesite=lax。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值