SpringMvc(五) – 支付宝沙箱和关键字过滤,md5加密,SSM项目重要知识点

SpringMvc(五) - 支付宝沙箱和关键字过滤,md5加密,SSM项目重要知识点

1、支付宝沙箱

1.1 jar包 alipay-sdk

<!-- alipay-sdk -->
<dependency>
    <groupId>com.alipay.sdk</groupId>
    <artifactId>alipay-sdk-java</artifactId>
    <version>4.10.90.ALL</version>
</dependency>

1.2 信息配置类

1.2.1 配置信息

public class AlipayConfig {
	// 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
	public static String app_id = "";

	// 商户应用私钥,您的PKCS8格式RSA2私钥
	public static String merchant_private_key = "";
	// 对应APPID下的支付宝公钥。
	public static String alipay_public_key = "";
    
	// 服务器异步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
	public static String notify_url = "http://localhost:8080(/项目名,没有的不需要)/Alipay/notify_url.do";

	// 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
	public static String return_url = "http://localhost:8080(/项目名,没有的不需要)/Alipay/alipay_return.do";

	// 签名方式
	public static String sign_type = "RSA2";

	// 字符编码格式
	public static String charset = "UTF-8";

	// 支付宝网关
	public static String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";
}

1.2.2配置信息来源

登录自己已经入驻的支付宝账号:https://open.alipay.com/develop/sandbox/app

1.2.2.1 APPID

1.2.2.2 公钥,私钥

1.3 支付控制层

/**
 * 支付宝支付
 */
@Controller
@RequestMapping("/Alipay")
public class AlipayController {

    /**
     * 生成订单直接跳转支付宝付款
     */
    @RequestMapping("/to_alipay.do")
    public void toAlipay(HttpServletResponse response, HttpServletRequest request) throws Exception{

        AlipayClient alipayClient = new DefaultAlipayClient(
                AlipayConfig.gatewayUrl, AlipayConfig.app_id,
                AlipayConfig.merchant_private_key, "json", AlipayConfig.charset,
                AlipayConfig.alipay_public_key, AlipayConfig.sign_type);

        // 取购买人名称
        String in_name = request.getParameter("in_name");
        // 取手机号
        String in_phone = request.getParameter("in_phone");
        // 创建唯一订单号
        int random = (int) (Math.random() * 10000);
        String dateStr = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());

        // 订单号拼接规则:手机号后四位+当前时间后四位+随机数四位数
        String out_trade_no = in_phone.substring(7) + dateStr.substring(10)
                + random;
        // 拼接订单名称
        String subject = in_name + "的订单";

        // 取付款金额
        String total_amount = request.getParameter("in_money");

        // 设置请求参数
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl(AlipayConfig.return_url);//支付成功响应后跳转地址
        alipayRequest.setNotifyUrl(AlipayConfig.notify_url);//异步请求地址

        /*FAST_INSTANT_TRADE_PAY 二维码瞬时支付
         * out_trade_no 订单号 total_amount 订单金额  subject 订单名称
         */
        alipayRequest.setBizContent("{"out_trade_no":"" + out_trade_no
                + ""," + ""total_amount":"" + total_amount + "","
                + ""subject":"" + subject + ""," + ""body":""
                + ""+ ""," + ""product_code":"FAST_INSTANT_TRADE_PAY"}");
        String result = "请求无响应";
        // 请求
        try {
            //通过阿里客户端,发送支付页面请求
            result = alipayClient.pageExecute(alipayRequest).getBody();
            response.setContentType("text/html;charset=UTF-8");
            response.setCharacterEncoding("UTF-8");
            response.getWriter().println(result);
            response.getWriter().flush();
        } catch (AlipayApiException e) {
            e.printStackTrace();
        } finally {
            response.getWriter().close();
        }
    }


    /**
     * 支付成功后处理业务
     */
    @RequestMapping("/alipay_return.do")
    public String alipayReturn(HttpServletRequest request, Map<String, Object> map) throws Exception{

        // 响应信息
        String msg = "";

        // 请在这里编写您的程序(以下代码仅作参考)
        if (verifyAlipayReturn(request)) {//验签成功后执行的自定义业务代码
            // 商户订单号
            String out_trade_no = new String(request.getParameter(
                    "out_trade_no").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);

            // 支付宝交易号
            String trade_no = new String(request.getParameter("trade_no")
                    .getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);

            // 付款金额
            String total_amount = new String(request.getParameter(
                    "total_amount").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
            msg = "支付宝交易号:" + trade_no + "<br/>商户订单号"
                    + out_trade_no + "<br/>付款金额:" + total_amount;

        } else {
            msg = "验签/支付失败";
        }

        map.put("msg", msg);

        return "forward:/success.jsp"; //支付完成后,跳转的页面
    }

    /**
     * 支付宝异步通知
     * @param request
     * @param response
     * @throws Exception
     */
    @RequestMapping("/notify_url.do")
    public void alipayNotify(HttpServletRequest request,HttpServletResponse response)
                                                throws Exception {
        // ——请在这里编写您的程序(以下代码仅作参考)——

        /*
         * 实际验证过程建议商户务必添加以下校验: 1、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
         * 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
         * 3、校验通知中的seller_id(或者seller_email)
         * 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email)
         * 4、验证app_id是否为该商户本身。
         */
        if (verifyAlipayReturn(request)) {// 验证成功
            // 商户订单号
            String out_trade_no = new String(request.getParameter(
                    "out_trade_no").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
            System.out.println(out_trade_no);
            // 支付宝交易号
            String trade_no = new String(request.getParameter("trade_no")
                    .getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
            System.out.println(trade_no);

            // 交易状态
            String trade_status = new String(request.getParameter(
                    "trade_status").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);

            if (trade_status.equals("TRADE_FINISHED")) {
                // 判断该笔订单是否在商户网站中已经做过处理
                // 如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
                // 如果有做过处理,不执行商户的业务程序
                // 注意:
                // 退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知
            } else if (trade_status.equals("TRADE_SUCCESS")) {
                // 判断该笔订单是否在商户网站中已经做过处理
                // 如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
                // 如果有做过处理,不执行商户的业务程序
                // 注意:
                // 付款完成后,支付宝系统发送该交易状态通知
            }

        } else {// 验证失败
            response.setContentType("text/html;charset=UTF-8");
            response.setCharacterEncoding("UTF-8");
            response.getWriter().println("验签/支付失败!");
            response.getWriter().flush();
            response.getWriter().close();

            // 调试用,写文本函数记录程序运行情况是否正常
            // String sWord = AlipaySignature.getSignCheckContentV1(params);
            // AlipayConfig.logResult(sWord);
        }
    }

    /**
     * @author zhukang
     * @date 2021-04-23
     * @return
     * @description 验证支付宝的反馈信息
     */
    private boolean verifyAlipayReturn(HttpServletRequest request) throws UnsupportedEncodingException {
        // 获取支付宝回调反馈的信息
        Map<String, String> params = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter
                .hasNext();) {
            String name = iter.next();
            String[] values = requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            // 乱码解决,这段代码在出现乱码时使用
            valueStr = new String(valueStr.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
            params.put(name, valueStr);
        }

        boolean signVerified = false;
        try {// 调用SDK验证签名
            signVerified = AlipaySignature.rsaCheckV1(params,
                    AlipayConfig.alipay_public_key, AlipayConfig.charset,
                    AlipayConfig.sign_type);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }

        return signVerified;
    }

}

1.4 测试访问

直接访问 Alipay/to_alipay.do 这个请求即可(参数根据实际操作进行添加);

2、关键字过滤

2.1 关键字文件 sensitivewords.txt

小笨蛋
...(根据实际需求添加关键字)

2.2 关键字工具类

2.2.1 关键字初始化


/**
 * Created On : 2022/7/26.
 * <p>
 * Author : zhukang
 * <p>
 * Description: 敏感词初始化类
 */
public class SensitiveWordInit {
    // 敏感词集合
    public static Map sensitiveWordMap;

    // 初始化敏感词
    public Map initSensitiveWord(){
        System.out.println("------- 系统启动,从文件中读取敏感字,存入sensitiveWordMap -------");

        try {
            // 读取敏感词文件,将敏感词加入HashMap
            addSensitiveWordToHashMap(readSensitiveWordFile());

        } catch (Exception e){
            e.printStackTrace();
        }
        return sensitiveWordMap;
    }

    /**
     * @author : zhukang
     * @date   : 2022/7/26
     * @param  : [java.util.Set<java.lang.String>]
     * @return : java.util.Map
     * @description : 将HashSet中的敏感词,存入HashMap中
     */
    private void addSensitiveWordToHashMap(Set<String> wordSet) {
        // 初始化敏感词容器,减少扩容操作
        sensitiveWordMap = new HashMap(wordSet.size());
        for (String word : wordSet) {
            Map nowMap = sensitiveWordMap;
            for (int i = 0; i < word.length(); i++) {
                // 转换成char型
                char keyChar = word.charAt(i);
                // 获取
                Object tempMap = nowMap.get(keyChar);
                // 如果存在该key,直接赋值
                if (tempMap != null) {
                    // 一个一个放进Map中
                    nowMap = (Map) tempMap;
                }
                // 不存在则,则构建一个map,同时将isEnd设置为0,因为他不是最后一个
                else {
                    // 设置标志位,不是最后一个
                    Map<String, String> newMap = new HashMap<String, String>();
                    // 没有这个key,就把(isEnd,0) 放在Map中
                    newMap.put("isEnd", "0");
                    // 添加到集合
                    nowMap.put(keyChar, newMap);
                    //指向当前map,继续遍历
                    nowMap = newMap;
                }
                // 最后一个
                if (i == word.length() - 1) {
                    nowMap.put("isEnd", "1");
                }
            }
        }
    }

    /**
     * @author : zhukang
     * @date   : 2022/7/26
     * @param  : []
     * @return : java.util.Set<java.lang.String>
     * @description : 读取敏感词库文件,存入HashMap中
     */
    private Set<String> readSensitiveWordFile() {
        // 敏感词集合
        Set<String> wordSet = null;
        //敏感词库
        try
                (
                // 获取输入流,读取resources目录下的static目录中的敏感词文件(一个敏感词一行)
                InputStream inputStream = new ClassPathResource("sensitivewords.txt").getInputStream();

                // 读取文件输入流
                InputStreamReader read = new InputStreamReader(inputStream, "UTF-8");

                // 高效读取
                BufferedReader br = new BufferedReader(read);
        )
        {
            // 创建set集合,存储读取的敏感字
            wordSet = new HashSet<>();


            //手动 添加词语
//            wordSet.add("笨蛋");
//            wordSet.add("傻瓜");

            // 读取文件,将文件内容放入到set中
            String txt = null;
            while ((txt = br.readLine()) != null) {
                wordSet.add(txt);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 返回敏感字集合
        return wordSet;
    }
}

2.2.2 关键字过滤类

/**
 * Created On : 2022/7/26.
 * <p>
 * Author : zhukang
 * <p>
 * Description: 敏感字过滤工具类
 */
@Component
public class SensitiveWordFilterUtil {
    // 最小匹配规则
    public static final int MIN_MATCH_TYPE = 1;

    // 最大匹配规则
    public static final int MAX_MATCH_TYPE = 2;

    // 敏感词集合
    public static Map sensitiveWordMap;

    // 应用启动后,创建实例对象,自动执行此方法
    @PostConstruct
    public void init() {
        // 从数据库查询敏感词,转换为set集合 将敏感词库加入到HashMap中,确定有穷自动机DFA
        sensitiveWordMap = new com.kgc.weddingshop.utils.SensitiveWordInit().initSensitiveWord();

        System.out.println("------ " + sensitiveWordMap + "------");
    }

    /**
     * @param : [java.lang.String]
     * @return : boolean true 包含;false 不包含
     * @author : zhukang
     * @date : 2022/7/26
     * @description : 是否包含敏感词(默认按最小匹配规则来,只要有敏感词就ok),最小匹配规则
     */
    public boolean isContainSensitiveWordMin(String txt) {
        return isContainSensitiveWord(txt, MIN_MATCH_TYPE);
    }

    /**
     * @param : [java.lang.String, int]
     * @return : boolean
     * @author : zhukang
     * @date : 2022/7/26
     * @description : 是否包含敏感词(默认按指定匹配规则来,只要有敏感词就ok)
     * 如果敏感词库为:
     * * 傻叉
     * * 傻叉人
     * * 大傻叉
     * * 初始化之后为:{傻={叉={人={isEnd=1}, isEnd=1}, isEnd=0}, 大={傻={叉={isEnd=1}, isEnd=0}, isEnd=0}}
     * * 1、按最小规则匹配,  匹配 傻叉 的时候,匹配到叉,就为最后一个了 直接break。如果输入的敏感词是傻叉人,命中的只是傻叉,而不是傻叉人
     * * 2、按最大规则匹配,  匹配 傻叉 的时候,匹配到叉,已经为最后一个,但是按照最大规则,会继续匹配人,命中的是傻叉人
     * * 3、如果关键词是傻叉猫,两种匹配规则都会匹配到傻叉,会命中,如果输入的是傻叉人猫,按最小规则匹配是傻叉,按最大规则匹配傻叉人,只是匹配敏感词不同
     */
    public boolean isContainSensitiveWord(String txt, int matchType) {
        if (txt == null || "".equals(txt)) {
            return false;
        }
        for (int i = 0; i < txt.length(); i++) {
            int matchFlag = this.checkSensitiveWords(txt, i, matchType);
            if (matchFlag > 0) {
                return true;
            }
        }
        return false;
    }

    /**
     * @param : 待判断文本 起始位置 匹配类型: 1 最小匹配原则;2 最大匹配原则
     * @return : int 大于0表示包含敏感词且表示敏感词匹配长度,否则不包含
     * @author : zhukang
     * @date : 2022/7/26
     * @description : 校验是否包含敏感词
     */
    private static int checkSensitiveWords(String txt, int beginIndex, int matchType) {
        // 敏感词结束标识位:用于敏感词只有1位的情况
        boolean flag = false;

        // 匹配标识数默认为0
        int matchFlag = 0;
        // 从内存中,获取敏感词库
        Map nowMap = sensitiveWordMap;
        for (int i = beginIndex; i < txt.length(); i++) {
            // 获取第一个字符
            char word = txt.charAt(i);

            // 获取指定key,判断当前字符是不是一个敏感词的开头
            nowMap = (Map) nowMap.get(word);

            // 不存在,直接返回
            if (nowMap == null) {
                break;
            }

            // 根据排列组合的匹配,如果出现在敏感词库中,即找到相应key,匹配标识+1
            matchFlag++;

            // 如果已经匹配到词库中完整的敏感词, 改匹配结束标识,并根据匹配规则判断,是否继续
            if ("1".equals(nowMap.get("isEnd"))) {
                // 结束标志位为true,已经命中到了一个完整敏感词
                flag = true;

                // 最小规则,直接返回, 最大规则还需继续查找
                if (matchType == MIN_MATCH_TYPE) {
                    break;
                }
            }
        }

        // 长度必须大于等于1,为词,敏感词只有1个字的情况
        if (matchFlag < 2 || !flag) {
            matchFlag = 0;
        }

        return matchFlag;
    }


    /**
     * @param : txt 待判断文本
     * @return : 匹配类型: 1 最小匹配原则;2 最大匹配原则
     * @author : zhukang
     * @date : 2022/7/26
     * @description :  获取匹配的敏感词
     */
    public Set<String> getSensitiveWords(String txt, Integer matchType) {
        Set<String> sensitiveWords = new HashSet<>();

        for (int i = 0; i < txt.length(); i++) {
            Integer length = checkSensitiveWords(txt, i, matchType);
            if (length > 0) {
                sensitiveWords.add(txt.substring(i, i + length));
                // 循环i会+1,所以需-1
                i = i + length - 1;
            }
        }
        return sensitiveWords;
    }

    /**
     * @param : txt,文本 matchType 匹配类型: 1 最小匹配原则;2 最大匹配原则
     * @return : 替换字符
     * @author : zhukang
     * @date : 2022/7/26
     * @description :  替换敏感词
     */
    public String replaceSensitiveWords(String txt, Integer matchType, String replaceStr) {
        if (txt == null || "".equals(txt)) {
            return txt;
        }
        // 获取所有敏感词
        Set<String> sensitiveWords = getSensitiveWords(txt, matchType);
        Iterator<String> iterator = sensitiveWords.iterator();
        String replaceString = "";
        while (iterator.hasNext()) {
            String sWord = iterator.next();
            replaceString = getReplaceString(replaceStr, sWord.length());
            txt = txt.replaceAll(sWord, replaceString);
        }
        return txt;
    }

    /**
     * @param : replaceStr 替换字符
     * @return : 敏感字长度
     * @author : zhukang
     * @date : 2022/7/26
     * @description :  替换为指定字符,没有指定替换字符,默认*
     */
    private static String getReplaceString(String replaceStr, Integer length) {
        // 指定替换字符为*
        if (replaceStr == null) {
            replaceStr = "*";
        }
        // 可变字符串对象
        StringBuffer replaceString = new StringBuffer();
        // 循环遍历,替换内容
        for (int i = 0; i < length; i++) {
            replaceString.append(replaceStr);
        }
        return replaceString.toString();
    }

}

2.3 关键字过滤 控制层

/**
 * Created On : 2022/7/26.
 * <p>
 * Author : zhukang
 * <p>
 * Description: 敏感词测试入口
 */
@Controller
public class SensitiveWordController {

    @Autowired
    private SensitiveWordFilterUtil sensitiveWordFilterUtil;

    /**
     * @author : zhukang
     * @date   : 2022/5/17
     * @param  : [java.lang.String]
     * @return : com.kgc.sbt.util.RequestResult<java.lang.String>
     * @description : 测试搜索中的敏感词,并指定规则
     */
    @RequestMapping(value = "/testSensitiveWord", produces = {"application/json;charset=utf-8"})
    @ResponseBody
    public String testSensitiveWord(@RequestParam String searchKey, @RequestParam int matchType){

        // 校验搜索关键字中,是否包含敏感词,如果包含,提示错误
        if(sensitiveWordFilterUtil.isContainSensitiveWord(searchKey, matchType)){
            System.out.println(String.format("------ 命中敏感词,搜索关键字:%s ------", searchKey));
            System.out.println(String.format("------ 命中敏感字为:%s ------", sensitiveWordFilterUtil.getSensitiveWords(searchKey, matchType)));
            return "搜索失败,命中敏感词!";
        }
        return "搜索成功!";
    }

}

3、SSM项目 知识点

3.1 SpringMvc 重定向后,中文乱码

3.1.1 RedirectAttributes attributes

将参数,放入RedirectAttributes 中,在重定向的时候,会自动拼接参数,并且不会乱码;

@RequestMapping("/test")
public String delAllViewHistory(//attributes 请求,自动拼接参数
    RedirectAttributes attributes){
    
    attributes.addAttribute("test","测试");
    return "redirect:/viewHistory/viewViewHistoryList";

}

3.2 location.href 会暴露参数问题

解决方法:创建一个form表单,进行post方法提交;

//创建一个 form 表单,并提交
var form = $("<form>");
    
form.attr("style","display:none");
form.attr("target","");
form.attr("method","post");
    
//请求地址
form.attr("action","${pageContext.request.contextPath}/user/modUserInfo");

//请求参数
var input1 = $("<input>");
var input2 = $("<input>");
input1.attr("type","hidden");
input1.attr("name","uid");
input1.attr("value","${sessionScope.loginUser.uid}");
input2.attr("type","hidden");
input2.attr("name","password");
input2.attr("value",$password.val());

//在body标签中追加form 表单
$("body").append(form);
form.append(input1);
form.append(input2);

//表单体提交
form.submit();

//移除表达
form.remove();

3.3 mysql 查询日期操作 ,今天,本周,本月,本季度,今年

-- 今天
select to_days(now()) -- 738788 天

-- 本周
select yearweek(now(),1) -- 202239 周, 第二个参数,是因为,中国人喜欢将周一当作一周的第一天

-- 本月
select date_format(now(),"%Y%m") --  202209 月 

-- 本季度
select quarter(now()) -- 3 季度 quarter

-- 今年
select year(now()) -- 2022 年 year

-- 日期格式化
select DATE_FORMAT(now(),"%Y-%m-%d")

3.4 头像点击上传

3.4.1 jsp

3.4.1.1 头像修改表单
<%--     头像修改 form    start   --%>
<form action="${pageContext.request.contextPath}/user/headImg" method="post" enctype="multipart/form-data"  id="userHeadImgForm">
    <input type="file" name="userHeaderImg" id="userHeaderPic" style="display: none"/>
</form>
<%--     头像修改 form    end   --%>
3.4.1.2 头像展示
<%--     头像 展示  start   --%>
<h3>
    <a style="margin-left: 130px">
        <img style=" width: 50px;height: 50px"
             id="userHeaderImg"
             src="${pageContext.request.contextPath}/${sessionScope.loginUser.uhead}"/>
    </a>
</h3>
<%--     头像 展示  end   --%>
3.4.1.3 点击头像触发 图片选择input 头像选择
//============  头像更换 start ================
$(function (){

    // 点击头像图片,触发文件预点击
    $("#userHeaderImg").click(function (){
        $("#userHeaderPic").click();
    });

    // 当文件域内容改变,实现头像预览
    $("#userHeaderPic").change(function () {

        // 获取上传文件对象
        var file = $(this)[0].files[0];

        // 判断类型
        var imageType = /^image//;
        if (file === undefined || !imageType.test(file.type)) {
            alert("请选择图片!");
            return;
        }
        // 判断大小
        if (file.size > 512000) {
            alert("图片大小不能超过500K!");
            return;
        }

        // 读取文件URL,预览文件
        var reader = new FileReader();
        // 读取文件
        reader.readAsDataURL(file);
        // 阅读文件完成后触发的事件
        reader.onload = function () {
            // 读取的URL结果:this.result
            $("#userHeaderImg").attr("src", this.result);
            // alert("图片上传");
            $("#userHeadImgForm").submit();
        };

        // TODO 还可以不预览,直接异步ajax发送请求到后台,上传文件,然后返回页面显示头像,并将图片的路径防止页面隐藏域,提交表单记录头像的地址
    });
//============  头像更换 end ================

3.4.2 控制层

1.获取头像文件流,并保存图片;

2.将图片地址保存到用户的头像中;

3.刷新session中的用户信息;

@RequestMapping("/headImg")
public String headImg(HttpSession session,
                      @RequestParam("userHeaderImg") MultipartFile multipartFile,
                      Map<String, String> map) throws IOException {
    // 获取上传的头像文件名称
    String targetFileName = multipartFile.getOriginalFilename();
    System.out.println("------ 上传文件名:" + targetFileName + " ------");

    // 重新定义新的文件名,要保留上传文件的类型
    targetFileName = UUID.randomUUID().toString().substring(0, 8) + targetFileName.substring(targetFileName.indexOf("."));

    System.out.println("------ 新的文件名:" + targetFileName + " ------");

    // 上传文件,要保存服务器上的真实路径中,idea项目发布,默认不会放到目标tomcat中,放在本地项目的target目录中
    String realFilePath = session.getServletContext().getRealPath("img/about");

    System.out.println("------ 服务器真实路径:" + realFilePath + " ------");

    // 目标文件目录可能不存在,不能人为干预,必须程序主动处理
    File targetFilePath = new File(realFilePath);
    if(!targetFilePath.exists()){
        // 目标不存在,主动创建
        if(targetFilePath.mkdirs()){
            System.out.println("------ 上传目录创建成功 ------");
        }
    }

    // 创建目标文件对象
    File targetFile = new File(targetFilePath + "/" + targetFileName);

    // 文件上传到服务器,只需要一步,组件自动支持功能
    multipartFile.transferTo(targetFile);

    // 数据库存入头像信息
    targetFileName = "img/about/"+targetFileName;

    //获取当前登录用户对象
    User loginUser =  (User)session.getAttribute(CommConstant.SYS_SESSION_LOGINUSER);

    //换头像
    loginUser.setUhead(targetFileName);

    //重置 session 中的 用户对象
    session.setAttribute(CommConstant.SYS_SESSION_LOGINUSER,loginUser);

    // 调用 修改用户信息 方法,修改用户信息
    User userForm = new User();
    userForm.setUid(loginUser.getUid());
    userForm.setUhead(loginUser.getUhead());
    userService.modUserInfo(userForm);

    //放入修改成功提示信息,可以不提示(操作过后感觉,不返回效果好些,看时机需求)
    map.put("modUserInfoMsg","用户头像修改成功!");

    return "/personCenter";
}
hmoban主题是根据ripro二开的主题,极致后台体验,无插件,集成会员系统
自学咖网 » SpringMvc(五) – 支付宝沙箱和关键字过滤,md5加密,SSM项目重要知识点