demo项目开发笔录(开发技巧)

这里记录一些小技巧和注意事项:

一、

注册时给密码加密,md5方式,并加“盐”,以确保不会被数据库人员识别密码,也不会被md5库被破解密码。

加密如下:

/**
	 * Md5加密
	 */
	public static String md5(String str,String salt){
		return new Md5Hash(str,salt).toString();
	}

第一个参数就是原密码,salt是干扰参数,计算结果是一串md5密码,此密码不可被反向逆推,所以能保证安全。

在保存时对原密码进行md5计算得到新密码然后保存即可。

使用如下:

/**
	 * 用户登录
	 */
	@RequestMapping("/login")
	public String login(Users user, HttpServletRequest request){
		Subject subject= SecurityUtils.getSubject();
		UsernamePasswordToken token=new UsernamePasswordToken(user.getUsername(), CryptographyUtil.md5(user.getPassword(),"gcc"));
		try{
			subject.login(token);
			return "redirect:/index.html";
		}catch(Exception e){
			e.printStackTrace();
			request.setAttribute("user", user);
			request.setAttribute("errorMsg", "用户名或密码错误!");
			return "redirect:/frontLogin.html";
		}
	}

在用shiro时将表单密码进行相同方式的md5计算得到对应密码,然后正常使用shiro即可。

二、

在使用mybatis时返回方式由resultMap和resultType两种,笔者原先使用前者,后来习惯使用后者,原因是可以少写点代码,但使用resultType方式返回的数据库字段如果和实体属性名字不相同时,那么得到的数据无法填充到对应字段,这样就出现了一个有趣的bug例如:

<select id="getUser" parameterType="String" resultType="Users">
		select *
		 from t_users a where username=#{username}
</select>

查询指定用户名的所有信息,数据库字段如下:


实体字段如下:


然后sql查询后所得实体,除了picUrl字段没有数据,其他都正常,日志也不会报错。

这种情况修改sql(加别名)如下即可:

	<sql id="UsersColumns">
		a.id AS "id",
		a.username AS "username",
		a.nickname AS "nickname",
		a.password AS "password",
		a.company AS "company",
		a.job AS "job",
		a.city AS "city",
		a.profile AS "profile",
		a.pic_url AS "picUrl"
	</sql>

	<select id="getUser" parameterType="String" resultType="Users">
		select
			<include refid="UsersColumns"/>
		 from t_users a where username=#{username}
	</select>

三、

在开发中,大部分人喜欢使用new Date()来获取时间,使用方便,同时能获取其他信息,比如:小时,分钟等。但只是为了获取毫秒数,就可以直接使用System.currentTimeMillis()来获取,来取代new Date().getTime(),特别是在多次这样调用时,效率上会高一点。

下面是源码:

/**
     * Allocates a <code>Date</code> object and initializes it so that
     * it represents the time at which it was allocated, measured to the
     * nearest millisecond.
     *
     * @see     java.lang.System#currentTimeMillis()
     */
    public Date() {
        this(System.currentTimeMillis());
    }
/**
     * Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
     * represented by this <tt>Date</tt> object.
     *
     * @return  the number of milliseconds since January 1, 1970, 00:00:00 GMT
     *          represented by this date.
     */
    public long getTime() {
        return getTimeImpl();
    }

    private final long getTimeImpl() {
        if (cdate != null && !cdate.isNormalized()) {
            normalize();
        }
        return fastTime;
    }

四、$.post和$.ajax

笔者原先使用$.ajax,近来觉得$.post书写更顺畅,后者的格式如下:

jQuery.post( url, [data], [callback], [type] ) :使用POST方式来进行异步请求

具体例子如下:

$.post("${pageContext.request.contextPath}/saveArticle.html",
                    {	'title':title,
                        'typeId':typeId,
                        'content':content
                    },
                    function(result){
                        if(result.flag){
                            alert("发布成功");
                        }
                    },"json");

使用的感觉像是给一个方法传递四个参数,熟悉参数类型即可,而$.ajax简单的实际案例如下:

$.ajax({ 
  type:'get', 
  url:'http://www.www.daimajiayuan.com/rss', 
  beforeSend:function(XMLHttpRequest){ 
    //ShowLoading(); 
  }, 
  success:function(data,textStatus){ 
    $('.ajax.ajaxResult').html(''); 
    $('item',data).each(function(i,domEle){ 
      $('.ajax.ajaxResult').append('<li>'+$(domEle).children('title').text()+'</li>'); 
    }); 
  }, 
  complete:function(XMLHttpRequest,textStatus){ 
    //HideLoading(); 
  }, 
  error:function(){ 
    //请求出错处理 
  } 
}); 

使用上更加繁琐,而且理解上也有不顺畅的感觉,所以如果您使用的是较为简单的异步响应可以尝试书写更流畅的$.post方式。

注:

$.post的data数据的别名如果和后台接收的对象的属性同名,则会自动赋值给对象实体。

如果使用同步请使用$.ajax;  $post默认异步,改同步需要做如下处理:

  $.ajaxSettings.async = false;  
  $.post("/saveArticle.html", data, function(result) {  
     // 请求处理  
  },"json"); 
  $.ajaxSettings.async = true; 

五、mybatis传参为多种不同类型时怎么处理

给接口方法取别名,使用如下:

List<Article> getList(@Param("username") String username, @Param("pageStart") int pageStart, @Param("pageSize") int pageSize);
<select id="getList" resultMap="ArticleResult">
	SELECT *
	from t_article a
	WHERE a.username=#{username} ORDER BY a.postTime DESC LIMIT #{pageStart},#{pageSize}
</select>

六,json使用

    @ResponseBody
    @RequestMapping(value = { "/autoKpiData" })
    public String autoKpiData(Master master, HttpServletRequest request) {
        try {
            String planId = request.getParameter("planId");
            String flag=kpiDataService.autoKpiData(master,planId);
            String json = JsonMapper.toJsonString(master);
            Master master = (Master) JsonMapper.fromJsonString(json,Master.class);
            return flag;
        } catch (Exception e) {
            return e.getMessage();
        }
    }

    1,使用@ResponseBody,返回的数据不是html标签的页面,而是其他某种格式的数据(如json、xml等),可以简化原始的写法,如PrintWriter的处理,如下:

                JSONObject result = new JSONObject();
                result.put("flag", true);
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out=response.getWriter();
		out.println(result.toString());
		out.flush();
		out.close();

   

 2,通过JsonMapper.toJsonString()将实体类型转换成json类型,可以通过ajax的回调对象result,对象.属性名来取值。

在页面取到规则的(对应属性名字)json值时也可以通过JsonMapper.fromJsonString来将json数据填充到实体属性里。

mavne引入如下:

        <!-- jackson json -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.module</groupId>
            <artifactId>jackson-module-jaxb-annotations</artifactId>
            <version>${jackson.version}</version>
        </dependency>

对ObjectMapper简单封装的类如下:

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
 * 简单封装Jackson,实现JSON String<->Java Object的Mapper.
 * 封装不同的输出风格, 使用不同的builder函数创建实例.
 */
public class JsonMapper extends ObjectMapper {
	private static final long serialVersionUID = 1L;
	private static Logger logger = LoggerFactory.getLogger(JsonMapper.class);
	private static JsonMapper mapper;
	public JsonMapper() {
		this(Include.NON_EMPTY);
	}

	public JsonMapper(Include include) {
		// 设置输出时包含属性的风格
		if (include != null) {
			this.setSerializationInclusion(include);
		}
		// 允许单引号、允许不带引号的字段名称
		this.enableSimple();
		// 设置输入时忽略在JSON字符串中存在但Java对象实际没有的属性
		this.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        // 空值处理为空串
		this.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>(){
			@Override
			public void serialize(Object value, JsonGenerator jgen,
					SerializerProvider provider) throws IOException,
					JsonProcessingException {
				jgen.writeString("");
			}
        });
		// 进行HTML解码。
		this.registerModule(new SimpleModule().addSerializer(String.class, new JsonSerializer<String>(){
			@Override
			public void serialize(String value, JsonGenerator jgen,
					SerializerProvider provider) throws IOException,
					JsonProcessingException {
				jgen.writeString(StringEscapeUtils.unescapeHtml4(value));
			}
        }));
		// 设置时区
		this.setTimeZone(TimeZone.getDefault());//getTimeZone("GMT+8:00")
	}

	/**
	 * 创建只输出非Null且非Empty(如List.isEmpty)的属性到Json字符串的Mapper,建议在外部接口中使用.
	 */
	public static JsonMapper getInstance() {
		if (mapper == null){
			mapper = new JsonMapper().enableSimple();
		}
		return mapper;
	}

	/**
	 * 创建只输出初始值被改变的属性到Json字符串的Mapper, 最节约的存储方式,建议在内部接口中使用。
	 */
	public static JsonMapper nonDefaultMapper() {
		if (mapper == null){
			mapper = new JsonMapper(Include.NON_DEFAULT);
		}
		return mapper;
	}
	
	/**
	 * Object可以是POJO,也可以是Collection或数组。
	 * 如果对象为Null, 返回"null".
	 * 如果集合为空集合, 返回"[]".
	 */
	public String toJson(Object object) {
		try {
			return this.writeValueAsString(object);
		} catch (IOException e) {
			logger.warn("write to json string error:" + object, e);
			return null;
		}
	}

	/**
	 * 反序列化POJO或简单Collection如List<String>.
	 * 
	 * 如果JSON字符串为Null或"null"字符串, 返回Null.
	 * 如果JSON字符串为"[]", 返回空集合.
	 * 
	 * 如需反序列化复杂Collection如List<MyBean>, 请使用fromJson(String,JavaType)
	 * @see #fromJson(String, JavaType)
	 */
	public <T> T fromJson(String jsonString, Class<T> clazz) {
		if (StringUtils.isEmpty(jsonString)) {
			return null;
		}
		try {
			return this.readValue(jsonString, clazz);
		} catch (IOException e) {
			logger.warn("parse json string error:" + jsonString, e);
			return null;
		}
	}

	/**
	 * 反序列化复杂Collection如List<Bean>, 先使用函數createCollectionType构造类型,然后调用本函数.
	 * @see #createCollectionType(Class, Class...)
	 */
	@SuppressWarnings("unchecked")
	public <T> T fromJson(String jsonString, JavaType javaType) {
		if (StringUtils.isEmpty(jsonString)) {
			return null;
		}
		try {
			return (T) this.readValue(jsonString, javaType);
		} catch (IOException e) {
			logger.warn("parse json string error:" + jsonString, e);
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 構造泛型的Collection Type如:
	 * ArrayList<MyBean>, 则调用constructCollectionType(ArrayList.class,MyBean.class)
	 * HashMap<String,MyBean>, 则调用(HashMap.class,String.class, MyBean.class)
	 */
	public JavaType createCollectionType(Class<?> collectionClass, Class<?>... elementClasses) {
		return this.getTypeFactory().constructParametricType(collectionClass, elementClasses);
	}

	/**
	 * 當JSON裡只含有Bean的部分屬性時,更新一個已存在Bean,只覆蓋該部分的屬性.
	 */
	@SuppressWarnings("unchecked")
	public <T> T update(String jsonString, T object) {
		try {
			return (T) this.readerForUpdating(object).readValue(jsonString);
		} catch (JsonProcessingException e) {
			logger.warn("update json string:" + jsonString + " to object:" + object + " error.", e);
		} catch (IOException e) {
			logger.warn("update json string:" + jsonString + " to object:" + object + " error.", e);
		}
		return null;
	}

	/**
	 * 輸出JSONP格式數據.
	 */
	public String toJsonP(String functionName, Object object) {
		return toJson(new JSONPObject(functionName, object));
	}

	/**
	 * 設定是否使用Enum的toString函數來讀寫Enum,
	 * 為False時時使用Enum的name()函數來讀寫Enum, 默認為False.
	 * 注意本函數一定要在Mapper創建後, 所有的讀寫動作之前調用.
	 */
	public JsonMapper enableEnumUseToString() {
		this.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
		this.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
		return this;
	}

	/**
	 * 支持使用Jaxb的Annotation,使得POJO上的annotation不用与Jackson耦合。
	 * 默认会先查找jaxb的annotation,如果找不到再找jackson的。
	 */
	public JsonMapper enableJaxbAnnotation() {
		JaxbAnnotationModule module = new JaxbAnnotationModule();
		this.registerModule(module);
		return this;
	}

	/**
	 * 允许单引号
	 * 允许不带引号的字段名称
	 */
	public JsonMapper enableSimple() {
		this.configure(Feature.ALLOW_SINGLE_QUOTES, true);
		this.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
		return this;
	}
	
	/**
	 * 取出Mapper做进一步的设置或使用其他序列化API.
	 */
	public ObjectMapper getMapper() {
		return this;
	}

	/**
	 * 对象转换为JSON字符串
	 * @param object
	 * @return
	 */
	public static String toJsonString(Object object){
		return JsonMapper.getInstance().toJson(object);
	}
	
	/**
	 * JSON字符串转换为对象
	 * @param jsonString
	 * @param clazz
	 * @return
	 */
	public static Object fromJsonString(String jsonString, Class<?> clazz){
		return JsonMapper.getInstance().fromJson(jsonString, clazz);
	}
	
	/**
	 * 测试
	 */
	public static void main(String[] args) {
		List<Map<String, Object>> list = Lists.newArrayList();
		Map<String, Object> map = Maps.newHashMap();
		map.put("id", 1);
		map.put("pId", -1);
		map.put("name", "根节点");
		list.add(map);
		map = Maps.newHashMap();
		map.put("id", 2);
		map.put("pId", 1);
		map.put("name", "你好");
		map.put("open", true);
		list.add(map);
		String json = JsonMapper.getInstance().toJson(list);
		System.out.println(json);
	}	
}

    3,data传值方式如下时:

$.post(
	"${ctx}/pa/in/kpiData/autoKpiData",
	{
	     'id':masterId,
         'planId':planId,
         'groupId':groupId
	},
	function (result) {
	   if("Success"==result){
                $("#btnSubmit").click();
                  window.setTimeout(function () { $.jBox.tip('操作成功!', 'success'); }, 500)
		}else{
                  window.setTimeout(function () { $.jBox.tip('操作失败,请确认是否已有考核计划在运行!', 'error'); }, 1000)
		}
           },
	"json"
)

spring也可以将属性名对应的数据填充到实体内:

public String autoKpiData(Master master, HttpServletResponse response,HttpServletRequest request){...}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值