zoukankan      html  css  js  c++  java
  • Java基于ssm框架的restful应用开发

    Java基于ssm框架的restful应用开发

    好几年都没写过java的应用了,这里记录下使用java ssm框架、jwt如何进行rest应用开发,文中会涉及到全局异常拦截处理、jwt校验、token拦截器等内容。

    1、jwt工具类

    直接贴代码了,主要包括jwt的sign、verify、decode三个方法,具体实现如下:

    package com.isoft.util;
    
    import java.util.Date;
    
    import com.auth0.jwt.JWT;
    import com.auth0.jwt.JWTVerifier;
    import com.auth0.jwt.algorithms.Algorithm;
    import com.auth0.jwt.interfaces.DecodedJWT;
    
    public class JwtUtil {
    
    	private static final String SECRET = "xxxxx";
    	private static final String USERID = "userId";
    	private static final String ISSUER = "xxxx.com";
    
    	// 过期时间7天
    	private static final long EXPIRE_TIME = 7 * 24 * 60 * 60 * 1000;
    
    	// jwt sign
    	public static String sign(Integer userId) {
    		try {
    			Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
    			Algorithm algorithmHS = Algorithm.HMAC256(SECRET);
    			return JWT.create().withClaim(USERID, userId).withExpiresAt(date).withIssuer(ISSUER).sign(algorithmHS);
    		} catch (Exception e) {
    			return null;
    		}
    	}
    
    	// jwt verify
    	public static boolean verify(String token, Integer userId) {
    		try {
    			Algorithm algorithmHS = Algorithm.HMAC256(SECRET);
    			JWTVerifier verifier = JWT.require(algorithmHS).withClaim(USERID, userId).withIssuer(ISSUER).build();
    			verifier.verify(token);
    			return true;
    		} catch (Exception e) {
    			System.out.println(e);
    			return false;
    		}
    	}
    
    	// 返回token中的用户名
    	public static Integer getUserId(String token) {
    		try {
    			DecodedJWT jwt = JWT.decode(token);
    			return jwt.getClaim(USERID).asInt();
    		} catch (Exception e) {
    			return null;
    		}
    	}
    }
    
    

    2、全局异常处理类

    ssm中进行rest全局异常拦截处理主要用到RestControllerAdvice型注解类,直接贴代码:

    package com.isoft.exception;
    
    import org.springframework.http.HttpStatus;
    import org.springframework.http.converter.HttpMessageNotReadableException;
    import org.springframework.web.HttpRequestMethodNotSupportedException;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseStatus;
    import org.springframework.web.bind.annotation.RestControllerAdvice;
    
    import com.isoft.po.Response;
    
    @RestControllerAdvice
    public class ExceptionAdvice {
    
    	/**
    	 * 400 - Bad Request
    	 */
    	@ResponseStatus(HttpStatus.BAD_REQUEST)
    	@ExceptionHandler(HttpMessageNotReadableException.class)
    	public Response handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
    		return new Response().failure("could not read json");
    	}
    
    	/**
    	 * 405 - Method Not Allowed
    	 * 
    	 * @param e
    	 * @return
    	 */
    	@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    	@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    	public Response handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
    		return new Response().failure("request method not supported");
    	}
    
    	/**
    	 * 500 - Internal Server Error
    	 * 
    	 * @param e
    	 * @return
    	 */
    	@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    	@ExceptionHandler(Exception.class)
    	public Response handleException(Exception e) {
    		System.err.println(e);
    		return new Response().failure(e.getMessage());
    	}
    	
    }
    
    

    这里主要拦截了405、400、500的n行yi'chang异常情况,可根据具体情况拓展。

    3、自定义Response返回类

    我们自定义的Response返回类格式如下:

    {
        "meta": {
            "success": true,
            "message": "ok"
        },
        data: Array or Object
    }
    

    代码如下:

    package com.isoft.po;
    
    public class Response {
    
    	private static final String OK = "ok";
    	private static final String ERROR = "error";
    
    	private Meta meta;
    	private Object data;
    
    	public Response success() {
    		this.meta = new Meta(true, OK);
    		return this;
    	}
    
    	public Response success(Object data) {
    		this.meta = new Meta(true, OK);
    		this.data = data;
    		return this;
    	}
    	
    	public Response success(Object data, String msg){
    		this.meta = new Meta(true, msg);
    		this.data = data;
    		return this;
    	}
    	
    	public Response failure() {
    		this.meta = new Meta(false, ERROR);
    		return this;
    	}
    
    	public Response failure(String message) {
    		this.meta = new Meta(false, message);
    		return this;
    	}
    
    	public Meta getMeta() {
    		return meta;
    	}
    
    	public Object getData() {
    		return data;
    	}
    
    	public class Meta {
    
    		private boolean success;
    		private String message;
    
    		public Meta(boolean success) {
    			this.success = success;
    		}
    
    		public Meta(boolean success, String message) {
    			this.success = success;
    			this.message = message;
    		}
    
    		public boolean isSuccess() {
    			return success;
    		}
    
    		public String getMessage() {
    			return message;
    		}
    	}
    }
    
    

    4、jwt的token拦截器Interceptor

    spring mvc的Interceptor实现类一般是继承HandlerInterceptor接口并重写preHandle、postHandle、afterCompletion的方法来实现的,这里我们直接进行token的verify返回即可,具体代码如下:

    package com.isoft.interceptor;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.http.HttpStatus;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    import com.isoft.util.JwtUtil;
    import com.isoft.util.StringUtil;
    
    /**
     * jwt token拦截
     * @author sd
     *
     */
    public class TokenInterceptor implements HandlerInterceptor{
    
    	@Override
    	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
    			throws Exception {
    		// TODO Auto-generated method stub
    		
    	}
    
    	@Override
    	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
    			throws Exception {
    		// TODO Auto-generated method stub
    		
    	}
    
    	@Override
    	public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) throws Exception {
    		String token = req.getHeader("Authorization");
    		if (StringUtil.isEmpty(token)) {
    			return false;
    		}
    		token = token.replace("Bearer ", "");
    		boolean isPass = JwtUtil.verify(token, JwtUtil.getUserId(token));
    		if (isPass) {
    			return true;
    		}
    		res.setStatus(401);
    		return false;
    	}
    	
    }
    
    

    写完这些还不行,需要将拦截器注册到spring-mvc的config中:

    <!-- mvc拦截器 -->
    <mvc:interceptors>
    	<mvc:interceptor>
    		<mvc:mapping path="/**"/>
    		<mvc:exclude-mapping path="/users/login"/>
    		<bean class="com.isoft.interceptor.TokenInterceptor"></bean>
    	</mvc:interceptor>
    </mvc:interceptors>
    

    这里使用mvc:exclude-mapping可以直接排除某个接口的拦截,比较方便。

    5、mysql插入中文乱码解决

    使用ssm框架mybatis进行数据插入时,发现插入中文进去后数据有乱码情况,除了设置数据库编码之外还解决不了问题的话,不妨看下mybatis的链接编码设置,如果是db.properties的话,使用如下设置:

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://ip:port/dbname?useUnicode=true&characterEncoding=utf-8
    jdbc.username=username
    jdbc.password=password
    

    6、一个简单的rest controller实例

    package com.isoft.web.controller;
    
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import javax.annotation.Resource;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.http.HttpStatus;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestBody;
    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.ResponseStatus;
    import org.springframework.web.bind.annotation.RestController;
    
    import com.isoft.po.PageBean;
    import com.isoft.po.Response;
    import com.isoft.po.User;
    import com.isoft.service.UserService;
    import com.isoft.util.JwtUtil;
    import com.isoft.util.StringUtil;
    
    /**
     * 用户控制器类
     */
    
    @RequestMapping("/users")
    @RestController
    public class UserController {
    
    	@Resource
    	private UserService userService;
    
    	/**
    	 * 用户注册
    	 * 
    	 * @param user
    	 * @param res
    	 * @return
    	 * @throws Exception
    	 */
    	@RequestMapping(value = "/", method = RequestMethod.POST)
    	@ResponseStatus(value = HttpStatus.CREATED)
    	public Response save(@RequestBody User user, HttpServletResponse res) throws Exception {
    		userService.add(user);
    		return new Response().success(user);
    	}
    
    	/**
    	 * 用户登录
    	 * 
    	 * @param user
    	 * @param res
    	 * @return
    	 * @throws Exception
    	 */
    	@RequestMapping(value = "login", method = RequestMethod.POST)
    	@ResponseStatus(value = HttpStatus.OK)
    	public Response login(@RequestBody User user, HttpServletResponse res) throws Exception {
    		System.out.println(user);
    		User u = userService.login(user);
    		if (u != null) {
    			String token = JwtUtil.sign(u.getId());
    			u.setToken(token);
    			u.setHashedPassword("");
    			return new Response().success(u, "login success");
    		}
    		return new Response().failure("username or password wrong");
    	}
    
    	/**
    	 * 用户查询带分页
    	 * 
    	 * @param user
    	 * @param res
    	 * @return
    	 * @throws Exception
    	 */
    	@RequestMapping(value = "/", method = RequestMethod.GET)
    	@ResponseStatus(value = HttpStatus.OK)
    	public Response list(@RequestParam(value = "page", required = false, defaultValue = "1") String page,
    			@RequestParam(value = "rows", required = false, defaultValue = "10") String rows, User s_user, HttpServletResponse res)
    			throws Exception {
    		System.out.println(s_user);
    		PageBean pageBean = new PageBean(Integer.parseInt(page), Integer.parseInt(rows));
    		Map<String, Object> map = new HashMap<String, Object>();
    		map.put("userName", StringUtil.formatLike(s_user.getUserName()));
    		map.put("email", s_user.getemail());
    		map.put("start", pageBean.getStart());
    		map.put("size", pageBean.getPageSize());
    		List<User> userList = userService.find(map);
    		return new Response().success(userList);
    	}
    	
    	/**
    	 * 用户更新
    	 * 
    	 * @param user
    	 * @param res
    	 * @return
    	 * @throws Exception
    	 */
    	@RequestMapping(value = "/{id}", method = RequestMethod.PUT)
    	@ResponseStatus(value = HttpStatus.OK)
    	public Response update(@PathVariable Integer id, @RequestBody User user, HttpServletResponse res) throws Exception {
    		user.setId(id);
    		System.out.println(user);
    		Integer count = userService.update(user);
    		if (count != 0) {
    			return new Response().success();
    		}
    		return new Response().failure();
    	}
    	
    	/**
    	 * 用户删除,支持批量
    	 * @param id
    	 * @param user
    	 * @param res
    	 * @return
    	 * @throws Exception
    	 */
    	@RequestMapping(value = "/{ids}", method = RequestMethod.DELETE)
    	@ResponseStatus(value = HttpStatus.OK)
    	public Response delete(@PathVariable String ids, HttpServletResponse res) throws Exception {
    		String[] idsStrings = ids.split(",");
    		for (String id : idsStrings) {
    			userService.delete(Integer.parseInt(id));
    		}
    		return new Response().success();
    	}
    	
    	/**
    	 * 用户详情
    	 * @param id
    	 * @param user
    	 * @param res
    	 * @return
    	 * @throws Exception
    	 */
    	@RequestMapping(value = "/{id}", method = RequestMethod.GET)
    	@ResponseStatus(value = HttpStatus.OK)
    	public Response getUser(@PathVariable Integer id, HttpServletResponse res) throws Exception {
    		Map<String, Object> map = new HashMap<String, Object>();
    		map.put("id", id);
    		List<User> users = userService.find(map);
    		return new Response().success(users);
    	}
    }
    
    
  • 相关阅读:
    b站评论爬取
    推算身份证的生日位
    mac安装mysql
    H3C V7版本的系统默认权限
    H3C IRF2的三种配置情况
    一张图看懂高通QC1.0-QC4.0快充进化之路!QC2.0跟QC3.0充电区别
    云服务器 ECS Linux 软件源自动更新工具
    透明代理、匿名代理、混淆代理、高匿代理有什么区别?
    ping正常但是ssh到linux服务器很卡的解决方法
    Python GUI编程(Tkinter) windows界面开发
  • 原文地址:https://www.cnblogs.com/vipzhou/p/9053736.html
Copyright © 2011-2022 走看看