【SSM电商项目后台开发】008-收货地址模块

一、主要功能概述

二、学习目标

主要接口:

1.添加地址:/shipping/add.do
2.删除地址:/shipping/del.do
3.登录状态更新地址:/shipping/update.do
4.选中查看具体的地址:/shipping/select.do
5.地址列表/shipping/list.do

三、数据表设计

四、DAO

package com.mmall.dao;

import com.mmall.pojo.Shipping;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface ShippingMapper {
    int deleteByPrimaryKey(Integer id);

    int insert(Shipping record);

    int insertSelective(Shipping record);

    Shipping selectByPrimaryKey(Integer id);

    int updateByPrimaryKeySelective(Shipping record);

    int updateByPrimaryKey(Shipping record);

    int deleteByShippingIdAndUserId(@Param("userId") Integer userId, @Param("shippingId") Integer shippingId);

    int updateByShipping(Shipping shipping);

    Shipping selectByShippingIdAndUserId(@Param("shippingId") Integer shippingId,
                                         @Param("userId") Integer userId);

    List<Shipping> selectShippingListByUserId(Integer userId);
}
View Code

Mapper:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.mmall.dao.ShippingMapper" >
  <resultMap id="BaseResultMap" type="com.mmall.pojo.Shipping" >
    <constructor >
      <idArg column="id" jdbcType="INTEGER" javaType="java.lang.Integer" />
      <arg column="user_id" jdbcType="INTEGER" javaType="java.lang.Integer" />
      <arg column="receiver_name" jdbcType="VARCHAR" javaType="java.lang.String" />
      <arg column="receiver_phone" jdbcType="VARCHAR" javaType="java.lang.String" />
      <arg column="receiver_mobile" jdbcType="VARCHAR" javaType="java.lang.String" />
      <arg column="receiver_province" jdbcType="VARCHAR" javaType="java.lang.String" />
      <arg column="receiver_city" jdbcType="VARCHAR" javaType="java.lang.String" />
      <arg column="receiver_district" jdbcType="VARCHAR" javaType="java.lang.String" />
      <arg column="receiver_address" jdbcType="VARCHAR" javaType="java.lang.String" />
      <arg column="receiver_zip" jdbcType="VARCHAR" javaType="java.lang.String" />
      <arg column="create_time" jdbcType="TIMESTAMP" javaType="java.util.Date" />
      <arg column="update_time" jdbcType="TIMESTAMP" javaType="java.util.Date" />
    </constructor>
  </resultMap>
  <sql id="Base_Column_List" >
    id, user_id, receiver_name, receiver_phone, receiver_mobile, receiver_province, receiver_city, 
    receiver_district, receiver_address, receiver_zip, create_time, update_time
  </sql>
  <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
    select 
    <include refid="Base_Column_List" />
    from mmall_shipping
    where id = #{id,jdbcType=INTEGER}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
    delete from mmall_shipping
    where id = #{id,jdbcType=INTEGER}
  </delete>
  <insert id="insert" parameterType="com.mmall.pojo.Shipping" useGeneratedKeys="true" keyProperty="id">
    insert into mmall_shipping (id, user_id, receiver_name, 
      receiver_phone, receiver_mobile, receiver_province, 
      receiver_city, receiver_district, receiver_address, 
      receiver_zip, create_time, update_time
      )
    values (#{id,jdbcType=INTEGER}, #{userId,jdbcType=INTEGER}, #{receiverName,jdbcType=VARCHAR}, 
      #{receiverPhone,jdbcType=VARCHAR}, #{receiverMobile,jdbcType=VARCHAR}, #{receiverProvince,jdbcType=VARCHAR}, 
      #{receiverCity,jdbcType=VARCHAR}, #{receiverDistrict,jdbcType=VARCHAR}, #{receiverAddress,jdbcType=VARCHAR}, 
      #{receiverZip,jdbcType=VARCHAR}, now(), now()
      )
  </insert>
  <insert id="insertSelective" parameterType="com.mmall.pojo.Shipping" >
    insert into mmall_shipping
    <trim prefix="(" suffix=")" suffixOverrides="," >
      <if test="id != null" >
        id,
      </if>
      <if test="userId != null" >
        user_id,
      </if>
      <if test="receiverName != null" >
        receiver_name,
      </if>
      <if test="receiverPhone != null" >
        receiver_phone,
      </if>
      <if test="receiverMobile != null" >
        receiver_mobile,
      </if>
      <if test="receiverProvince != null" >
        receiver_province,
      </if>
      <if test="receiverCity != null" >
        receiver_city,
      </if>
      <if test="receiverDistrict != null" >
        receiver_district,
      </if>
      <if test="receiverAddress != null" >
        receiver_address,
      </if>
      <if test="receiverZip != null" >
        receiver_zip,
      </if>
      <if test="createTime != null" >
        create_time,
      </if>
      <if test="updateTime != null" >
        update_time,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides="," >
      <if test="id != null" >
        #{id,jdbcType=INTEGER},
      </if>
      <if test="userId != null" >
        #{userId,jdbcType=INTEGER},
      </if>
      <if test="receiverName != null" >
        #{receiverName,jdbcType=VARCHAR},
      </if>
      <if test="receiverPhone != null" >
        #{receiverPhone,jdbcType=VARCHAR},
      </if>
      <if test="receiverMobile != null" >
        #{receiverMobile,jdbcType=VARCHAR},
      </if>
      <if test="receiverProvince != null" >
        #{receiverProvince,jdbcType=VARCHAR},
      </if>
      <if test="receiverCity != null" >
        #{receiverCity,jdbcType=VARCHAR},
      </if>
      <if test="receiverDistrict != null" >
        #{receiverDistrict,jdbcType=VARCHAR},
      </if>
      <if test="receiverAddress != null" >
        #{receiverAddress,jdbcType=VARCHAR},
      </if>
      <if test="receiverZip != null" >
        #{receiverZip,jdbcType=VARCHAR},
      </if>
      <if test="createTime != null" >
        now(),
      </if>
      <if test="updateTime != null" >
        now(),
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="com.mmall.pojo.Shipping" >
    update mmall_shipping
    <set >
      <if test="userId != null" >
        user_id = #{userId,jdbcType=INTEGER},
      </if>
      <if test="receiverName != null" >
        receiver_name = #{receiverName,jdbcType=VARCHAR},
      </if>
      <if test="receiverPhone != null" >
        receiver_phone = #{receiverPhone,jdbcType=VARCHAR},
      </if>
      <if test="receiverMobile != null" >
        receiver_mobile = #{receiverMobile,jdbcType=VARCHAR},
      </if>
      <if test="receiverProvince != null" >
        receiver_province = #{receiverProvince,jdbcType=VARCHAR},
      </if>
      <if test="receiverCity != null" >
        receiver_city = #{receiverCity,jdbcType=VARCHAR},
      </if>
      <if test="receiverDistrict != null" >
        receiver_district = #{receiverDistrict,jdbcType=VARCHAR},
      </if>
      <if test="receiverAddress != null" >
        receiver_address = #{receiverAddress,jdbcType=VARCHAR},
      </if>
      <if test="receiverZip != null" >
        receiver_zip = #{receiverZip,jdbcType=VARCHAR},
      </if>
      <if test="createTime != null" >
        create_time = #{createTime,jdbcType=TIMESTAMP},
      </if>
      <if test="updateTime != null" >
        update_time = now(),
      </if>
    </set>
    where id = #{id,jdbcType=INTEGER}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.mmall.pojo.Shipping" >
    update mmall_shipping
    set user_id = #{userId,jdbcType=INTEGER},
      receiver_name = #{receiverName,jdbcType=VARCHAR},
      receiver_phone = #{receiverPhone,jdbcType=VARCHAR},
      receiver_mobile = #{receiverMobile,jdbcType=VARCHAR},
      receiver_province = #{receiverProvince,jdbcType=VARCHAR},
      receiver_city = #{receiverCity,jdbcType=VARCHAR},
      receiver_district = #{receiverDistrict,jdbcType=VARCHAR},
      receiver_address = #{receiverAddress,jdbcType=VARCHAR},
      receiver_zip = #{receiverZip,jdbcType=VARCHAR},
      create_time = #{createTime,jdbcType=TIMESTAMP},
      update_time = now()
    where id = #{id,jdbcType=INTEGER}
  </update>
  
  <delete id="deleteByShippingIdAndUserId" parameterType="map">
    DELETE from mmall_shipping
    WHERE user_id = #{userId}
    AND id = #{shippingId}
  </delete>

  <update id="updateByShipping" parameterType="com.mmall.pojo.Shipping">
    UPDATE  mmall_shipping
    set
      receiver_name = #{receiverName,jdbcType=VARCHAR},
      receiver_phone = #{receiverPhone,jdbcType=VARCHAR},
      receiver_mobile = #{receiverMobile,jdbcType=VARCHAR},
      receiver_province = #{receiverProvince,jdbcType=VARCHAR},
      receiver_city = #{receiverCity,jdbcType=VARCHAR},
      receiver_district = #{receiverDistrict,jdbcType=VARCHAR},
      receiver_address = #{receiverAddress,jdbcType=VARCHAR},
      receiver_zip = #{receiverZip,jdbcType=VARCHAR},
      create_time = #{createTime,jdbcType=TIMESTAMP},
      update_time = now()
    where
      id = #{id, jdbcType = INTEGER}
    AND
      user_id = #{userId, jdbcType = INTEGER}
  </update>
  
  <select id="selectByShippingIdAndUserId" parameterType="map" resultMap="BaseResultMap">
    SELECT
    <include refid="Base_Column_List"/>
    FROM mmall_shipping
    WHERE id = #{shippingId} AND user_id = #{userId}
  </select>

  <select id="selectShippingListByUserId" parameterType="map" resultMap="BaseResultMap">
    SELECT
    <include refid="Base_Column_List"/>
    FROM mmall_shipping
    WHERE user_id = #{userId}
  </select>
</mapper>
View Code

五、Service

package com.mmall.service;

import com.github.pagehelper.PageInfo;
import com.mmall.common.ServerResponse;
import com.mmall.pojo.Shipping;

/**
 * @author GenshenWang.nomico
 * @date 2018/4/18.
 */
public interface IShippingService {
    ServerResponse addShipping(Integer userId, Shipping shipping);

    ServerResponse<String> delShipping(Integer userId, Integer shippingId);

    ServerResponse<String> updateShipping(Integer userId, Shipping shipping);

    ServerResponse<Shipping> selectShipping(Integer userId, Integer shippingId);

    ServerResponse<PageInfo> listShipping(Integer userId, Integer pageNum, Integer pageSize);

}
View Code

Impl:

package com.mmall.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Maps;
import com.mmall.common.ResponseCode;
import com.mmall.common.ServerResponse;
import com.mmall.dao.ShippingMapper;
import com.mmall.pojo.Shipping;
import com.mmall.service.IShippingService;
import com.sun.xml.internal.ws.developer.Serialization;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

/**
 * @author GenshenWang.nomico
 * @date 2018/4/18.
 */
@Service("iShippingService")
public class ShippingServiceImpl implements IShippingService {


    @Autowired
    private ShippingMapper shippingMapper;


    @Override
    public ServerResponse addShipping(Integer userId, Shipping shipping){
        if (userId == null){
            return ServerResponse.createByErrorCodeMsg(ResponseCode.ILLEGAL_ARGUMENT.getCode(), "参数错误");
        }

        shipping.setUserId(userId);
        int rowCount = shippingMapper.insert(shipping);

        if (rowCount > 0){
            Map result = Maps.newHashMap();
            //在mappers文件中生成主键id,会通过setId()方法自动填充,然后就可以获取到该id
            result.put("shippingId", shipping.getId());
            return ServerResponse.createBySuccess("新建地址成功", result);
        }
        return ServerResponse.createByErrorMsg("新建地址失败");
    }

    @Override
    public ServerResponse<String> delShipping(Integer userId, Integer shippingId){
        if (userId == null){
            return ServerResponse.createByErrorCodeMsg(ResponseCode.ILLEGAL_ARGUMENT.getCode(), "参数错误");
        }

        int rowCount = shippingMapper.deleteByShippingIdAndUserId(userId, shippingId);
        if (rowCount > 0){
            return ServerResponse.createBySuccess("删除地址成功");
        }
        return ServerResponse.createByErrorMsg("删除地址失败");
    }

    @Override
    public ServerResponse<String> updateShipping(Integer userId, Shipping shipping){
        if (userId == null){
            return ServerResponse.createByErrorCodeMsg(ResponseCode.ILLEGAL_ARGUMENT.getCode(), "参数错误");
        }
        //防止横向越权:A用户登录后,调用此接口后就可以修改B用户收获地址信息。
        // 所以需要指定当前用户,即当前用户只能修改当前用户信息
        shipping.setUserId(userId);
        int rowCount = shippingMapper.updateByShipping(shipping);
        if (rowCount > 0){
            return ServerResponse.createBySuccess("更改地址成功");
        }
        return ServerResponse.createByErrorMsg("更改地址失败");
    }

    @Override
    public ServerResponse<Shipping> selectShipping(Integer userId, Integer shippingId){
        if (userId == null || shippingId == null){
            return ServerResponse.createByErrorCodeMsg(ResponseCode.ILLEGAL_ARGUMENT.getCode(), "参数错误");
        }
        Shipping shipping = shippingMapper.selectByShippingIdAndUserId(shippingId, userId);
        if (shipping == null){
            return ServerResponse.createByErrorMsg("无法查询到该地址");
        }
        return ServerResponse.createBySuccess(shipping);
    }

    @Override
    public ServerResponse<PageInfo> listShipping(Integer userId, Integer pageNum, Integer pageSize){
        if (userId == null){
            return ServerResponse.createByErrorCodeMsg(ResponseCode.NEED_LOGIN.getCode(), ResponseCode.NEED_LOGIN.getDesc());
        }
        PageHelper.startPage(pageNum, pageSize);
        List<Shipping> shippingList = shippingMapper.selectShippingListByUserId(userId);
        PageInfo pageInfo = new PageInfo(shippingList);
        return ServerResponse.createBySuccess(pageInfo);
    }


}
View Code

六、Controller

package com.mmall.controller.portal;

import com.mmall.common.Const;
import com.mmall.common.ResponseCode;
import com.mmall.common.ServerResponse;
import com.mmall.pojo.Shipping;
import com.mmall.pojo.User;
import com.mmall.service.IShippingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpSession;

/**
 * @author GenshenWang.nomico
 * @date 2018/4/18.
 */
@Controller
@RequestMapping(value = "/shipping")
public class ShippingController {

    @Autowired
    private IShippingService iShippingService;

    /**
     *添加地址
     * @param session
     * @param shipping
     * @return
     */
    @RequestMapping(value = "/add.do", method = RequestMethod.POST)
    @ResponseBody
    public ServerResponse addShipping(HttpSession session, Shipping shipping){
        User user = (User) session.getAttribute(Const.CURRENT_USER);
        if (user == null){
            return ServerResponse.createByErrorCodeMsg(ResponseCode.NEED_LOGIN.getCode(), ResponseCode.NEED_LOGIN.getDesc());
        }
        return iShippingService.addShipping(user.getId(), shipping);
    }

    /**
     * 删除地址
     * @param session
     * @param shippingId
     * @return
     */
    @RequestMapping(value = "/del.do", method = RequestMethod.POST)
    @ResponseBody
    public ServerResponse delShipping(HttpSession session, Integer shippingId){
        User user = (User) session.getAttribute(Const.CURRENT_USER);
        if (user == null){
            return ServerResponse.createByErrorCodeMsg(ResponseCode.NEED_LOGIN.getCode(), ResponseCode.NEED_LOGIN.getDesc());
        }
        return iShippingService.delShipping(user.getId(), shippingId);
    }

    /**
     * 登录状态更新地址
     * @param session
     * @param shipping
     * @return
     */
    @RequestMapping(value = "/update.do", method = RequestMethod.POST)
    @ResponseBody
    public ServerResponse updateShipping(HttpSession session, Shipping shipping){
        User user = (User) session.getAttribute(Const.CURRENT_USER);
        if (user == null){
            return ServerResponse.createByErrorCodeMsg(ResponseCode.NEED_LOGIN.getCode(), ResponseCode.NEED_LOGIN.getDesc());
        }
        return iShippingService.updateShipping(user.getId(), shipping);
    }


    /**
     * 选中查看具体的地址
     * @param session
     * @param shippingId
     * @return
     */
    @RequestMapping(value = "/select.do", method = RequestMethod.POST)
    @ResponseBody
    public ServerResponse selectShipping(HttpSession session, Integer shippingId){
        User user = (User) session.getAttribute(Const.CURRENT_USER);
        if (user == null){
            return ServerResponse.createByErrorCodeMsg(ResponseCode.NEED_LOGIN.getCode(), ResponseCode.NEED_LOGIN.getDesc());
        }
        return iShippingService.selectShipping(user.getId(), shippingId);
    }

    /**
     * 地址列表
     * @param session
     * @param pageNum
     * @param pageSize
     * @return
     */
    @RequestMapping(value = "/list.do", method = RequestMethod.POST)
    @ResponseBody
    public ServerResponse listShipping(HttpSession session,
                                       @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
                                       @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize){
        User user = (User) session.getAttribute(Const.CURRENT_USER);
        if (user == null){
            return ServerResponse.createByErrorCodeMsg(ResponseCode.NEED_LOGIN.getCode(), ResponseCode.NEED_LOGIN.getDesc());
        }
        return iShippingService.listShipping(user.getId(), pageNum, pageSize);

    }


}
View Code

七、POJO

package com.mmall.pojo;

import java.util.Date;

public class Shipping {
    private Integer id;

    private Integer userId;

    private String receiverName;

    private String receiverPhone;

    private String receiverMobile;

    private String receiverProvince;

    private String receiverCity;

    private String receiverDistrict;

    private String receiverAddress;

    private String receiverZip;

    private Date createTime;

    private Date updateTime;

    public Shipping(Integer id, Integer userId, String receiverName, String receiverPhone, String receiverMobile, String receiverProvince, String receiverCity, String receiverDistrict, String receiverAddress, String receiverZip, Date createTime, Date updateTime) {
        this.id = id;
        this.userId = userId;
        this.receiverName = receiverName;
        this.receiverPhone = receiverPhone;
        this.receiverMobile = receiverMobile;
        this.receiverProvince = receiverProvince;
        this.receiverCity = receiverCity;
        this.receiverDistrict = receiverDistrict;
        this.receiverAddress = receiverAddress;
        this.receiverZip = receiverZip;
        this.createTime = createTime;
        this.updateTime = updateTime;
    }

    public Shipping() {
        super();
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getReceiverName() {
        return receiverName;
    }

    public void setReceiverName(String receiverName) {
        this.receiverName = receiverName == null ? null : receiverName.trim();
    }

    public String getReceiverPhone() {
        return receiverPhone;
    }

    public void setReceiverPhone(String receiverPhone) {
        this.receiverPhone = receiverPhone == null ? null : receiverPhone.trim();
    }

    public String getReceiverMobile() {
        return receiverMobile;
    }

    public void setReceiverMobile(String receiverMobile) {
        this.receiverMobile = receiverMobile == null ? null : receiverMobile.trim();
    }

    public String getReceiverProvince() {
        return receiverProvince;
    }

    public void setReceiverProvince(String receiverProvince) {
        this.receiverProvince = receiverProvince == null ? null : receiverProvince.trim();
    }

    public String getReceiverCity() {
        return receiverCity;
    }

    public void setReceiverCity(String receiverCity) {
        this.receiverCity = receiverCity == null ? null : receiverCity.trim();
    }

    public String getReceiverDistrict() {
        return receiverDistrict;
    }

    public void setReceiverDistrict(String receiverDistrict) {
        this.receiverDistrict = receiverDistrict == null ? null : receiverDistrict.trim();
    }

    public String getReceiverAddress() {
        return receiverAddress;
    }

    public void setReceiverAddress(String receiverAddress) {
        this.receiverAddress = receiverAddress == null ? null : receiverAddress.trim();
    }

    public String getReceiverZip() {
        return receiverZip;
    }

    public void setReceiverZip(String receiverZip) {
        this.receiverZip = receiverZip == null ? null : receiverZip.trim();
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public Date getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
}
View Code

八、补充

1、Mybatis自动生成主键值:

使用useGeneratedKeys和keyProperty可以生成主键id的值。如果不使用,后台返回的是Null值,但是数据库中id依然是有值并且自增的。

  <insert id="insert" parameterType="com.mmall.pojo.Shipping" useGeneratedKeys="true" keyProperty="id">
    insert into mmall_shipping (id, user_id, receiver_name, 
      receiver_phone, receiver_mobile, receiver_province, 
      receiver_city, receiver_district, receiver_address, 
      receiver_zip, create_time, update_time
      )
    values (#{id,jdbcType=INTEGER}, #{userId,jdbcType=INTEGER}, #{receiverName,jdbcType=VARCHAR}, 
      #{receiverPhone,jdbcType=VARCHAR}, #{receiverMobile,jdbcType=VARCHAR}, #{receiverProvince,jdbcType=VARCHAR}, 
      #{receiverCity,jdbcType=VARCHAR}, #{receiverDistrict,jdbcType=VARCHAR}, #{receiverAddress,jdbcType=VARCHAR}, 
      #{receiverZip,jdbcType=VARCHAR}, now(), now()
      )
  </insert>

后台使用:  在mappers文件中生成主键id,会通过setId()方法自动填充,然后就可以获取到该id的值

    @Override
    public ServerResponse addShipping(Integer userId, Shipping shipping){
        if (userId == null){
            return ServerResponse.createByErrorCodeMsg(ResponseCode.ILLEGAL_ARGUMENT.getCode(), "参数错误");
        }

        shipping.setUserId(userId);
        int rowCount = shippingMapper.insert(shipping);

        if (rowCount > 0){
            Map result = Maps.newHashMap();
            //在mappers文件中生成主键id,会通过setId()方法自动填充,然后就可以获取到该id
            result.put("shippingId", shipping.getId());
            return ServerResponse.createBySuccess("新建地址成功", result);
        }
        return ServerResponse.createByErrorMsg("新建地址失败");
    }

2、防止横向越权:

后台必须传userId参数,然后可以指定userId。

@Override
    public ServerResponse<String> updateShipping(Integer userId, Shipping shipping){
        if (userId == null){
            return ServerResponse.createByErrorCodeMsg(ResponseCode.ILLEGAL_ARGUMENT.getCode(), "参数错误");
        }
        //防止横向越权:A用户登录后,调用此接口后就可以修改B用户收获地址信息。
        // 所以需要指定当前用户,即当前用户只能修改当前用户信息
        shipping.setUserId(userId);
        int rowCount = shippingMapper.updateByShipping(shipping);
        if (rowCount > 0){
            return ServerResponse.createBySuccess("更改地址成功");
        }
        return ServerResponse.createByErrorMsg("更改地址失败");
    }
原文地址:https://www.cnblogs.com/noaman/p/8874754.html