Web development learning 13 talk about java reflection

I really like a book called "Out of the Software Workshop". There is a sentence in it that makes me more profound, "The person who walks the tightrope between architects, customers and programmers", an excellent programmer will look left and right when he crosses a one-way line. What's more, an architect must be very cautious. So how can we be cautious? In my opinion, the architect's caution is actually a sentence: don't let the programmer write code that should not have been written by him. This sentence seems to be a bit abstract, but it is actually easy to understand. It is to let the programmer's code as much as possible. It is not only efficient to develop, but also it is very convenient to review the code and troubleshoot bugs, so how can programmers write less code? Today I want to use java reflection to give a few examples, through reflection encapsulation to make coding easier, of course, this is certainly not the only way.

1. Excel file export
This package is what I thought of when I was working for two years. At that time, I was really forced to do nothing. More than a dozen modules needed to add the excel export function. When I made it, I was really moved by myself. The importance of packaging. First create an annotation class

/**
 *
 * @author sdh 2012-7-26
 */
@Target(value={java.lang.annotation.ElementType.METHOD,java.lang.annotation.ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Export{

	/**
	 * @return header name
	 */
	String header() default " ";

	/**
	 * @return sort
	 */
	int sort();
	
	/**
	 * set column width
	 * @return
	 */
	int columnWidth() default 100;
	
	/**
	 * state transition
	 * @return
	 */
	String stateStr() default "";
	
}

The header marks the name of the column header, the sort mark is the number of columns, columnWidth marks the column width, and stateStr is the state transition, which is used when the database is of int type and is converted into Chinese, and then add annotation configuration as required in the entity class field to be exported.
public class Coupon implements IBasicBean {

	private static final long serialVersionUID = -8233437005461628357L;
	private Long id;
	@Export(header="Business Type",sort=0,stateStr="1:Print,2:DM,3:Video")
	private Integer businessType;
	@Export(header="Product number",sort=1)
	private Integer productId;
	@Export(header="Coupon number",sort=2)
	private String couponNum;
	@Export(header="Coupon name",sort=3)
	private String couponName;
	@Export(header="Coupon price",sort=4)
	private Float couponPrice;
}

See the package class cast code
public class ExcelExportUtils<T> {

	public ExcelExportUtils() {

	}

It is a common method to use generic classes to cooperate with reflection. It is only necessary to pass the operation type when calling, and it can be reflected in the encapsulation class. The caller passes the operation type and the data set of the operation type, and the encapsulation class obtains the field information through reflection After the annotation, go to the data set to get the value of the field to complete the export logic. The length relationship will not be described in detail here.

2. The base class of hibernate I saw
this method in Kaitao's "Learn Springmvc with Me", I feel It is also useful. Define the basic query statement corresponding to each database access class in the base class, so that subsequent development does not need to be repeated. Look at the code.

public class HibernateDaoImpl<T extends BaseEntity> extends HibernateDaoSupport
		implements HibernateDao<T>{

	protected final String COUNT_HQL = "select count(id) ";

	protected final String LIST_HQL;
	
	protected final String TABLE_NAME;

	/**
	 * Data entity type
	 */
	protected Class<T> entityClass;

	/**
	 * default constructor
	 */
	@SuppressWarnings("unchecked")
	public HibernateDaoImpl() {
		Type superClassType = getClass().getGenericSuperclass();

		if (superClassType instanceof ParameterizedType) {
			Type[] paramTypes = ((ParameterizedType) superClassType)
					.getActualTypeArguments();
			this.entityClass = (Class<T>) paramTypes[0];
		}
		TABLE_NAME = this.entityClass.getSimpleName();
		LIST_HQL = "from " + this.entityClass.getSimpleName() + " where 1=1";
	}


Through getClass().getGenericSuperclass() reflection, the generic type passed by the subclass is obtained in the construction of the parent class.

3.springmvc global parameter verification If the
parameter is empty, the program may crash, so it is necessary to force the verification in the program, but the text parameter If the length of the check is a bit cumbersome, so I encapsulated a global parameter length check through reflection, which can be inserted in the interceptor

//Verify request parameters (according to custom validation annotations)
    public boolean paramsValidate(BaseControler handler,HttpServletRequest request) throws Exception{
    	
    	//Get all methods of the current controll
    	Method[] m = handler.getClass().getDeclaredMethods();
    	//traverse
    	for (int i = 0; i < m.length; i++) {
    		//Get the RequestMapping annotation
    		RequestMapping an = m[i].getAnnotation(RequestMapping.class);
    		//if the annotation is not empty
    		if(an != null){
    			// Compare the value of the annotation with the url of the current request
    			String[] vs = an.value();
    			if(vs != null && vs.length > 0){
    				if(request.getRequestURI().endsWith(vs[0])){
    					//Consistently get the parameter list of the current method
    					@SuppressWarnings("rawtypes")
						Class[] c =  m[i].getParameterTypes();
    					for (int j = 0; j < c.length; j++) {
    						//If the current parameter is a subclass of basebean, it is regarded as a carrier
							if(c[j].getSuperclass() != null && c[j].getSuperclass().equals(BaseBean.class)){
								
								Map<String, String[]> map = request.getParameterMap();
								
								for(String key : map.keySet()){
									//Only verify the parameters of type string
									Field f = c[j].getDeclaredField(key);

									//Get the validation annotation of the current field
									MyValidation valid = f.getAnnotation(MyValidation.class);
									String v1 = StringUtil.array2String(map.get(key));
									if(StringUtil.isEmpty(v1)){
										return true;
									}
									
									if(valid != null){
										// Verify the parameters according to the configuration
										int maxLen = valid.maxLen();
										if(v1.length() > maxLen){
											throw new Exception(f.getName() + " not accord with maxlenth");
										}
										
										String pattern = valid.pattern();
										if(!StringUtil.isEmpty(pattern)){
											Pattern p = Pattern.compile(pattern);
											Matches matches = p.matches (v1);
											if(!matcher.matches()){
												throw new Exception(f.getName() + " not accord with pattern");
											}
										}
									}else{
										//Control according to the default length
										if(v1.length() > IConstans.PARAM_MAX_LEN){
											throw new Exception(f.getName() + " not accord with maxlenth");
										}
									}
									
									
								
								}
							}
						}
    				}
    			}
    		}
		}
    	return true;
    }

The key point of this encapsulation is that the operation class in the interceptor is not passed and cannot be reflected, but the interceptor has the currently accessed controller class and access address, so my idea is to reflect the @ corresponding to the controller class through the accessed address link The method of the RequestMapping annotation, and then get the parameter of the type baseEntity

subclass in the parameter list of the method, which is the operation class, and then obtain the fields and annotation verification through the operation class
. Now, mainly in the interceptor to use annotation reflection to locate the user's current operation and record it to the log
@Override
	protected String doIntercept(ActionInvocation invocation) throws Exception {
		String result = null;
		try {
			// first execute the action method
			result = invocation.invoke();
			
			String enterMethod = invocation.getProxy().getMethod();
			//Get the WebOperateAnno annotation on the action method
			WebOperateAnno webOperateAnno = invocation.getAction().getClass().getMethod(enterMethod, new Class[0]).getAnnotation(WebOperateAnno.class);
			
			Object returnData = invocation.getAction();
			
			writeLog(webOperateAnno,returnData);
		} catch (Exception e) {
			sysLogger.error("Operation logging failed",e);
		}
		
		
		return result;
	}


这种例子在程序中还有很多,目的就是做好封装减少程序员的编码量,如果以后面试的时候碰到面试官问你用java反射做了什么,或许你可以借鉴这些例子

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326818498&siteId=291194637