🔖 javaapp

pull/2/head
Zhang Peng 2018-07-11 14:52:11 +08:00
parent ef9e43e817
commit 52094ec137
12 changed files with 480 additions and 5 deletions

View File

@ -52,6 +52,23 @@
<version>${tomcat.version}</version>
</dependency>
<!-- tomcat end -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.6</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>

View File

@ -1,4 +1,4 @@
package io.github.dunwu.app;
package io.github.dunwu;
import java.io.File;
import org.apache.catalina.Server;

View File

@ -0,0 +1,103 @@
package io.github.dunwu.filter;
import java.io.IOException;
import java.util.regex.Pattern;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
*/
public class CorsFilter implements Filter {
private static final Logger logger = LoggerFactory.getLogger(CorsFilter.class);
private String regex;
private String headerKey;
private String protocol = "http";
private final String ORIGIN_KEY = "Origin";
public void init(FilterConfig filterConfig) {
// 取配置参数
regex = filterConfig.getInitParameter("regex");
headerKey = filterConfig.getInitParameter("headerKey");
String protocolVal = filterConfig.getInitParameter("protocol");
if (StringUtils.isNotBlank(protocolVal)) {
if (StringUtils.equalsIgnoreCase("http", protocolVal)
|| StringUtils.equalsIgnoreCase("https", protocolVal)) {
protocol = protocolVal.toLowerCase();
} else {
logger.error("CorsFilter 配置参数 protocol 非法,仍使用默认值 http");
}
}
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
if (StringUtils.isBlank(regex) || StringUtils.isBlank(headerKey)) {
throw new ServletException("读取跨域过滤器的配置参数失败");
}
// 读取请求地址的域
String domain = httpRequest.getHeader(headerKey);
String origin = httpRequest.getHeader(ORIGIN_KEY);
if (StringUtils.isBlank(origin)) {
logger.debug("origin 为空, 跳过检查");
chain.doFilter(httpRequest, httpResponse);
return;
}
if (StringUtils.isBlank(domain)) {
logger.debug("domain 为空, 跳过检查");
chain.doFilter(httpRequest, httpResponse);
return;
}
if (origin.toLowerCase().contains(domain.toLowerCase())) {
// 判断请求方和应答方是否同为 http 或 https
// 如果相同,这里视为同源;否则,视为跨域
if (origin.startsWith(protocol)) {
logger.debug("domain={}, origin={}, 二者协议相同,且域名同源,跳过检查", domain, origin);
chain.doFilter(httpRequest, httpResponse);
return;
}
}
Pattern pattern = Pattern.compile(regex);
if (!pattern.matcher(origin).matches()) {
logger.warn("客户端域 origin={} 不在跨域白名单中", origin);
httpResponse.sendError(403, "客户端域不在跨域白名单中");
throw new ServletException("客户端域不在跨域白名单中");
}
logger.debug("对 origin={} 放开跨域限制", origin);
httpResponse.addHeader("Access-Control-Allow-Origin", origin);
httpResponse.addHeader("Access-Control-Allow-Credentials", "true");
httpResponse.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, OPTIONS, DELETE");
httpResponse.addHeader("Access-Control-Allow-Headers",
"DNT, X-CustomHeader, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since," +
" Cache-Control, Content-Type, Content-Range, Range, X-CSRF-TOKEN");
httpResponse.addHeader("Access-Control-Expose-Headers",
"DNT, X-CustomHeader, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since," +
" Cache-Control, Content-Type, Content-Range, Range");
if (httpRequest.getMethod().equals("OPTIONS")) {
httpResponse.setStatus(HttpServletResponse.SC_OK);
return;
}
chain.doFilter(httpRequest, httpResponse);
}
public void destroy() {}
}

View File

@ -0,0 +1,12 @@
package io.github.dunwu.util;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
public class IOObjectMapper extends ObjectMapper {
public IOObjectMapper() {
this.setSerializationInclusion(Include.NON_EMPTY);
this.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
}

View File

@ -0,0 +1,108 @@
package io.github.dunwu.web.controller;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.github.dunwu.web.dto.BaseResponseDTO;
import io.github.dunwu.web.dto.MenuDTO;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
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.ResponseBody;
/**
* API
* @author zhangpeng0913
* @date 2017/8/23.
*/
@Controller
@RequestMapping(value = "/api")
public class ApiController {
@ResponseBody
@RequestMapping(value = "/menu", method = RequestMethod.GET)
public BaseResponseDTO getAll(HttpServletRequest request) throws JsonProcessingException {
String data = request.getParameter("data");
BaseResponseDTO baseResponseDTO = new BaseResponseDTO();
baseResponseDTO.setData(getAll());
ObjectMapper om = new ObjectMapper();
System.out.println("ResponseDTO: " + om.writeValueAsString(baseResponseDTO));
return baseResponseDTO;
}
@ResponseBody
@RequestMapping(value = "/login")
public BaseResponseDTO login(@RequestBody Map<String, String> map) throws IOException {
String username = map.get("username");
String password = map.get("password");
BaseResponseDTO<Map<String, String>> baseResponseDTO = new BaseResponseDTO();
if (StringUtils.equals(username, "admin") && StringUtils.equals(password, "123456")) {
Map<String, String> result = new HashMap<String, String>();
result.put("name", "admin");
result.put("role", "ADMIN");
result.put("uid", "1");
baseResponseDTO.setData(result);
System.out.println(baseResponseDTO.toString());
return baseResponseDTO;
} else {
baseResponseDTO.setCode(BaseResponseDTO.DEFAULT_RESPONSE_RESULT.SYSTEM_ERROR.value());
baseResponseDTO.getMessages().add(BaseResponseDTO.DEFAULT_RESPONSE_RESULT.SYSTEM_ERROR.desc());
return baseResponseDTO;
}
}
@ResponseBody
@RequestMapping(value = "/logout", method = RequestMethod.GET)
public BaseResponseDTO logout(HttpServletRequest request) {
BaseResponseDTO baseResponseDTO = new BaseResponseDTO();
return baseResponseDTO;
}
@ResponseBody
@RequestMapping(value = "/my", method = RequestMethod.GET)
public BaseResponseDTO my(HttpServletRequest request) {
Map<String, String> map = new HashMap<String, String>();
map.put("name", "admin");
map.put("role", "ADMIN");
map.put("uid", "1");
BaseResponseDTO baseResponseDTO = new BaseResponseDTO();
baseResponseDTO.setData(map);
return baseResponseDTO;
}
private static Set<MenuDTO> getAll() {
MenuDTO item0 = new MenuDTO("0", "首页", "home", "Item", "/pages/home");
MenuDTO subMenu1 = new MenuDTO("1", "业务", "bars", "SubMenu", null);
MenuDTO item11 = new MenuDTO("11", "Mailbox", "mail", "Item", "/pages/mailbox");
MenuDTO item12 = new MenuDTO("12", "用户列表", "user", "Item", "/pages/user");
subMenu1.addChild(item11);
subMenu1.addChild(item12);
MenuDTO subMenu2 = new MenuDTO("2", "Others", "coffee", "SubMenu", null);
MenuDTO itemGroup1 = new MenuDTO("21", "Group1", "windows-o", "ItemGroup", null);
MenuDTO item22 = new MenuDTO("22", "Group1-1", null, "Item", null);
MenuDTO divider = new MenuDTO("23", "Divider1", null, "Divider", null);
MenuDTO itemGroup2 = new MenuDTO("24", "Group2", "apple-o", "ItemGroup", null);
MenuDTO item25 = new MenuDTO("25", "Group2-1", null, "Item", null);
itemGroup1.addChild(item22);
itemGroup2.addChild(item25);
subMenu2.addChild(itemGroup1);
subMenu2.addChild(divider);
subMenu2.addChild(itemGroup2);
Set<MenuDTO> menus = new TreeSet<MenuDTO>();
menus.add(item0);
menus.add(subMenu1);
menus.add(subMenu2);
return menus;
}
}

View File

@ -1,4 +1,4 @@
package io.github.dunwu.app.controller;
package io.github.dunwu.web.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

View File

@ -1,7 +1,7 @@
/**
* The Apache License 2.0 Copyright (c) 2016 Zhang Peng
*/
package io.github.dunwu.app.controller;
package io.github.dunwu.web.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

View File

@ -0,0 +1,87 @@
package io.github.dunwu.web.dto;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class BaseResponseDTO<T> {
private Integer code = DEFAULT_RESPONSE_RESULT.SUCCESS.value();
private final List<String> messages = new ArrayList<>();
private T data;
public BaseResponseDTO() {}
public BaseResponseDTO(T dto) {
this.data = dto;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public void addError(String error) {
this.messages.add(error);
}
public void addErrors(String[] errors) {
this.addErrors(Arrays.asList(errors));
}
public void addErrors(List<String> errorList) {
this.messages.addAll(errorList);
}
public void removeError(String error) {
this.messages.remove(error);
}
public List<String> getMessages() {
return messages;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public enum DEFAULT_RESPONSE_RESULT {
SUCCESS(0, "[]"), // 成功
AUTHEN_FAIL(-1, "认证失败"), // 认证失败
AUTHOR_FAIL(-2, "权限不足"), // 授权不足
PARAM_CHECK_FAIL(-3, ""), // 参数校验失败,错误信息交由业务逻辑处理
RESOURCE_NOT_EXIST(-4, "请求资源不存在"), // 请求资源不存在
SYSTEM_ERROR(-5, "系统错误"),
DATA_MALFORMAT(-6, "请求参数数据格式不正确"),
REQMETHOD_ERROR(-7, "请求方法不正确"),
TYPE_MISMATCH(-8, "请求参数类型不匹配"),
MISS_REQUEST_PARAM(-9, "请求参数缺失");
private final Integer value;
private final String desc;
DEFAULT_RESPONSE_RESULT(int value, String desc) {
this.value = value;
this.desc = desc;
}
public int value() {
return value;
}
public String desc() {
return desc;
}
}
}

View File

@ -0,0 +1,122 @@
package io.github.dunwu.web.dto;
import java.util.Arrays;
import java.util.Set;
import java.util.TreeSet;
import org.apache.commons.lang3.builder.CompareToBuilder;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
public class MenuDTO implements Cloneable, Comparable<MenuDTO> {
private String key;
private String title;
private String icon;
private String type;
private String url;
private final Set<MenuDTO> children = new TreeSet<MenuDTO>();
public MenuDTO() {}
public MenuDTO(String key, String title, String icon, String type, String url) {
this.key = key;
this.title = title;
this.icon = icon;
this.type = type;
this.url = url;
}
public MenuDTO clone() throws CloneNotSupportedException {
super.clone();
MenuDTO menuDTO = new MenuDTO();
menuDTO.setType(type);
menuDTO.setKey(key);
menuDTO.setTitle(title);
menuDTO.setIcon(icon);
menuDTO.setUrl(url);
menuDTO.setUrl(url);
return menuDTO;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public Set<MenuDTO> getChildren() {
return children;
}
public void addChild(MenuDTO child) {
this.children.add(child);
}
public void addChildren(Set<MenuDTO> children) {
this.children.addAll(children);
}
public void addChildren(MenuDTO[] children) {
this.children.addAll(Arrays.asList(children));
}
@Override
public boolean equals(Object obj) {
boolean equals = false;
if (obj instanceof MenuDTO) {
MenuDTO menuDTO = (MenuDTO) obj;
equals = (new EqualsBuilder().append(url, menuDTO.getUrl())).isEquals();
}
return equals;
}
@Override
public int hashCode() {
return new HashCodeBuilder(17, 37).append(url).toHashCode();
}
@Override
public int compareTo(MenuDTO otherMenuDTO) {
return new CompareToBuilder().append(key, otherMenuDTO.getKey()).append(url, otherMenuDTO.getUrl())
.toComparison();
}
}

View File

@ -12,11 +12,19 @@
<!-- 启动注解服务 -->
<mvc:annotation-driven/>
<context:component-scan base-package="io.github.dunwu.app"/>
<context:component-scan base-package="io.github.dunwu.web"/>
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/views/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<bean id="jacksonObjectMapper" name="jacksonObjectMapper"
class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="indentOutput" value="true" />
<property name="objectMapper">
<bean class="io.github.dunwu.util.IOObjectMapper" />
</property>
</bean>
</beans>

View File

@ -1,2 +1,2 @@
Manifest-Version: 1.0
Main-Class: io.github.dunwu.app.Main
Main-Class: io.github.dunwu.Main

View File

@ -39,6 +39,24 @@
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>io.github.dunwu.filter.CorsFilter</filter-class>
<init-param>
<param-name>headerKey</param-name>
<param-value>Host</param-value>
</init-param>
<init-param>
<param-name>regex</param-name>
<!--<param-value>((http://)|(https://))?(\w*\.)*(demo*.com|demo*)(\S)*</param-value>-->
<param-value>((http://)|(https://))?(\w*\.)*(\S)*</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- FILTER END -->
<welcome-file-list>