5.28 学习记录

286 阅读4分钟

安恒实习记录

公司项目学习

HandlerMethodArgumentResolver的使用

当我们需要在controller频繁的从session中获取数据,比如从session中获取user对象,之前常用的做法是从Request中取,这样会使得在代码中出现大量重复的代码,显得很臃肿。 因此选用其他的方法

  • HandlerMethodArgumentResolver自定义解析器 实现请求数据绑定方法入参,只需要在参数中使用自定义的注解即可。
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyUser {
}
@RequestMapping("/index")
public String index(@MyUser User user,ModelMap modelMap) {
    Logger.inf(user.getUsername() + "------");
    return "login";
}

原理

首先,我们需要知道一点的就是SpringMVC的工作流程,SpringMVC的DispatchServlet会根据请求来找到对应的HandlerMapping,最终Spring会选择用RequestMappingHandlerMapping,然后根据RequestMappingHandlerMapping来获取HandlerMethod,然后来找支持的HandlerMethodArgumentResolver来处理对应controller的方法的入参.

项目中的实现

继承HandlerMehtodArgumentResolver,重写supportParameter和resolveArument方法。 其中supportParameter的入参是MethodParameter类型的类,下面来聊聊这个类。 首先它是spring核心中的一个类,并不是通过反射实现的,包含了方法对象、参数类型、方法名等属性。具体构造方法和私有方法的介绍请参考:www.cnblogs.com/guangshan/p… 在项目中用到的是它的getParameterType方法和isAssignableFrom()方法,入参是我们要入参的对象类,如Account.class。还调用了hasParameterAnnotation()方法,从字面可以理解,作用是判断是否有指定注解,入参是注解类,如InjectAccount.class,两者返回的类型都是boolean,即只有当两者都为true时,源对象和注解与我们需要的相同,返回true,可以执行resolveArgument方法。 resolveArgument方法比较简单,即从request中取出指定的对象头并返回。

X平台中JSON的序列化与反序列化

简介

X平台是公司的一个数据平台,通过http进行远程访问,因此设计到数据的序列化与反序列化。 涉及的方法只要有getXpfToken()这个比较简单,获得token进行一个身份验证。getJsonString()从X平台获得数据,postJson()发送数据给X平台。使用alibaba的fastjson处理json。

实现分析

  • getXpfToken() X平台的url、用户名、密码已经在配置中设置好,创建一个JSONObject对象,将属性配置设置进去,利用Http远程访问获得token。
  • postJson() 入参的是String url,Map<String, Object> urlparams,Object类对象。如果参数不为空,则要先调用方法组装带参数的url。创建一个HttpPost对象,入参为带参数的url。使用addHeader方法添加头信息,"Content-type"。如果Object类对象不为空,则将Object序列化:
String body = JSON.toJSONString(object);

然后利用StringEntity的构造方法,将body入参,创建StringEntity对象(一种消息体形式,具体概念见https://blog.csdn.net/songmaolin_csdn/article/details/52776920)。设置进post对象,然后作为参数传入doexcute()方法。

doexcute()

核心就是通过传入的request和handler使用apache.http.client包中的execute()方法,远程访问X平台得到数据并返回。首先创建一个信任所有SSL证书的客户端对象,然后执行execute(),返回得到结果。

拓展学习

AQS框架的原理和实现

见读书报告

每日一题

题目

全排列II 给定一个可包含重复数字的序列,返回所有不重复的全排列。

示例:

输入: [1,1,2] 输出: [ [1,1,2], [1,2,1], [2,1,1] ]

思路

本质还是使用回溯法进行全排列,区别是有重复的数字。使用一个大小与输入数组相同的数组来记录数字被使用的状态。1表示已使用,0表示未使用,在每次递归结束后对状态进行还原。在进行遍历时如果当前数字的状态是已使用或(下标大于0且当前下标对应值与前一位的值相同,前一位的状态是未使用) 则continue,这一步的目的是去重。

代码

class Solution {
    public List<List<Integer>> permuteUnique(int[] nums) {
   if(nums.length == 0) return new ArrayList<>();
        Arrays.sort(nums);
        List<List<Integer>> lists = new ArrayList<>();
        int[] visited = new int[nums.length];
         util( visited,nums, lists, new ArrayList<>());
        return lists;

    }

    public static void util(int[] visited, int[] nums, List<List<Integer>> lists, List<Integer>  list ) {
         if (list.size() == nums.length) {
                 lists.add(new ArrayList<>(list));
             return;
         }
           for (int i = 0; i < nums.length; i ++) {
               if(visited[i] == 1 || (i > 0 && visited[i - 1] == 0 && nums[i] == nums[i - 1])) continue;
               visited[i] = 1;
               list.add(nums[i]);
               util(visited, nums, lists, list);
               list.remove(list.size() -1);
               visited[i] = 0;
           }
    }
}