Servlet,当由浏览器直接调用servlet时,出现的The specified HTTP method is not allowed for the requested resource.

本文解释了当浏览器直接访问Servlet时,默认使用Get方法。若未重写doGet方法,将导致父类GenericServlet处理Http请求失败的问题。文章提供了解决方案:通过重写doGet方法来确保正确处理Http请求。

HttpServlet 是继承父类GenericServlet,当直接由浏览器转入Servlet时,默认的是Get方法,若未重写父类的doGet类,当你访问时,则子类自然交给父类,但父类不认识Http协议,自然会报出该错误。

解决方案:重写父类。

package com.taixin.dvbc2; import com.google.gson.Gson; import javax.servlet.*; import javax.servlet.http.*; import java.io.*; import java.net.*; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; public class LoadProgramServlet extends HttpServlet { private static final String MCAST_IP = "236.78.78.1"; private static final int PORT = 59000; private static final int MTU = 7 * 188; private static final Gson GSON = new Gson(); private static final Map<Integer, Integer> progToPmtPid = new HashMap<Integer, Integer>(); private static final Map<Integer, String> programNames = new HashMap<Integer, String>(); private static final Map<Integer, Integer> pidToProgram = new HashMap<Integer, Integer>(); private static final Map<Integer, Long> pidBytesCounter = new HashMap<Integer, Long>(); private static final long REPORT_INTERVAL_NS = 3000000000L; // 3秒 private static long lastReportNs = System.nanoTime(); private static final Map<Integer, SectionAssembler> assemblers = new HashMap<Integer, SectionAssembler>(); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { // 获取参数 final String ip = request.getParameter("ip"); final String portStr = request.getParameter("port"); if (ip == null || portStr == null) { response.setStatus(400); response.getWriter().write("{\"error\":\"缺少参数 ip 或 port\"}"); return; } final int port = Integer.parseInt(portStr); // SSE 响应头 response.setContentType("text/event-stream;charset=UTF-8"); response.setCharacterEncoding("UTF-8"); response.setHeader("Cache-Control", "no-cache"); response.setHeader("Connection", "keep-alive"); final PrintWriter writer = response.getWriter(); new Thread(new Runnable() { @Override public void run() { try { processInputChannelSSE(ip, port, writer); } catch (Exception e) { e.printStackTrace(); } } }).start(); } private void processInputChannelSSE(String ip, int port, PrintWriter writer) throws Exception { MulticastSocket sock = new MulticastSocket(port); InetAddress group = InetAddress.getByName(ip); sock.joinGroup(group); byte[] buf = new byte[MTU]; DatagramPacket pkt = new DatagramPacket(buf, buf.length); lastReportNs = System.nanoTime(); while (true) { // 一直接收数据 sock.receive(pkt); int len = pkt.getLength(); int off = 0; while (off + 188 <= len) { parseTsPacket(buf, off); off += 188; } long now = System.nanoTime(); if (now - lastReportNs > REPORT_INTERVAL_NS) { String jsonResponse = buildProgramReportJson(); if (jsonResponse != null) { writer.write("data: " + jsonResponse + "\n\n"); writer.flush(); } lastReportNs = now; } } } private String buildProgramReportJson() { Map<Integer, Long> programBytes = new HashMap<Integer, Long>(); for (Map.Entry<Integer, Long> e : pidBytesCounter.entrySet()) { int pid = e.getKey(); long bytes = e.getValue(); Integer prog = pidToProgram.get(pid); if (prog != null) { Long oldVal = programBytes.containsKey(prog) ? programBytes.get(prog) : 0L; programBytes.put(prog, oldVal + bytes); } } pidBytesCounter.clear(); if (programBytes.isEmpty()) return null; List<Map<String, Object>> programsData = new ArrayList<Map<String, Object>>(); for (Map.Entry<Integer, Long> e : programBytes.entrySet()) { int program = e.getKey(); long bytes = e.getValue(); double bits = bytes * 8.0; double mbps = bits / 3.0 / 1000000.0; // 3秒间隔 String name = programNames.containsKey(program) ? programNames.get(program) : "(未知节目)"; Map<String, Object> programData = new HashMap<String, Object>(); programData.put("name", name); programData.put("no", program); programData.put("rate", String.format("%.3f Mbit/s", mbps)); programsData.add(programData); } return GSON.toJson(programsData); } // --- 这里保留你原来的 parseTsPacket / parsePAT / parseSDT / parsePMT / SectionAssembler 等方法 --- // (我不再重复全部代码,只保留修改重点) private static void parseTsPacket(byte[] buf, int off) { if ((buf[off] & 0xFF) != 0x47) return; // sync int tei = (buf[off + 1] & 0x80) >>> 7; int pusi = (buf[off + 1] & 0x40) >>> 6; int pid = ((buf[off + 1] & 0x1F) << 8) | (buf[off + 2] & 0xFF); int afc = (buf[off + 3] & 0x30) >>> 4; if (tei == 1) return; // 计数 if (pid != 0x1FFF) { Long old = pidBytesCounter.get(pid); pidBytesCounter.put(pid, (old == null ? 0L : old) + 188L); } int i = off + 4; if (afc == 2) return; if (afc == 3) { int afl = buf[i] & 0xFF; i += 1 + afl; } if (i >= off + 188) return; if (pid == 0x0000 || pid == 0x0011 || containsValue(progToPmtPid, pid)) { SectionAssembler sa = assemblers.get(pid); if (sa == null) { sa = new SectionAssembler(); assemblers.put(pid, sa); } sa.push(buf, i, off + 188 - i, pusi == 1, (buf[off + 3] & 0x0F)); while (sa.hasSection()) { byte[] sec = sa.pollSection(); parseSection(pid, sec); } } } private static boolean containsValue(Map<Integer, Integer> map, int val) { for (Integer v : map.values()) { if (v != null && v == val) return true; } return false; } private static void parseSection(int pid, byte[] sec) { if (sec.length < 3) return; int tableId = sec[0] & 0xFF; int sectionLength = ((sec[1] & 0x0F) << 8) | (sec[2] & 0xFF); if (sectionLength + 3 != sec.length) return; if (pid == 0x0000 && tableId == 0x00) { parsePAT(sec); } else if (pid == 0x0011 && (tableId == 0x42 || tableId == 0x46)) { parseSDT(sec); } else if (tableId == 0x02) { parsePMT(sec); } } private static void parsePAT(byte[] sec) { int pos = 8; int end = sec.length - 4; while (pos + 4 <= end) { int programNumber = ((sec[pos] & 0xFF) << 8) | (sec[pos + 1] & 0xFF); int pmtPid = ((sec[pos + 2] & 0x1F) << 8) | (sec[pos + 3] & 0xFF); pos += 4; if (programNumber == 0) continue; progToPmtPid.put(programNumber, pmtPid); pidToProgram.put(pmtPid, programNumber); } } private static void parsePMT(byte[] sec) { int programNumber = ((sec[3] & 0xFF) << 8) | (sec[4] & 0xFF); programNames.put(programNumber, "Program " + programNumber); } private static void parseSDT(byte[] sec) { int pos = 11; int end = sec.length - 4; while (pos + 5 <= end) { int serviceId = ((sec[pos] & 0xFF) << 8) | (sec[pos + 1] & 0xFF); int descriptorsLoopLen = ((sec[pos + 3] & 0x0F) << 8) | (sec[pos + 4] & 0xFF); int descPos = pos + 5; int descEnd = descPos + descriptorsLoopLen; String name = null; while (descPos + 2 <= descEnd && descEnd <= end) { int tag = sec[descPos] & 0xFF; int len = sec[descPos + 1] & 0xFF; if (descPos + 2 + len > descEnd) break; if (tag == 0x48 && len >= 3) { int serviceProviderNameLen = sec[descPos + 3] & 0xFF; int nameLenPos = descPos + 4 + serviceProviderNameLen; if (nameLenPos + 1 <= descPos + 2 + len) { int serviceNameLen = sec[nameLenPos] & 0xFF; int nameStart = nameLenPos + 1; int nameEnd = Math.min(nameStart + serviceNameLen, descPos + 2 + len); byte[] nameBytes = Arrays.copyOfRange(sec, nameStart, nameEnd); name = decodeDvbString(nameBytes); } } descPos += 2 + len; } if (name != null && !name.isEmpty()) { programNames.put(serviceId, name); } pos = descEnd; } } static String decodeDvbString(byte[] bs) { if (bs == null || bs.length == 0) return ""; int offset = 0; String charset = "GB18030"; int first = bs[0] & 0xFF; if (first == 0x10 && bs.length >= 3) { charset = "UTF-16BE"; offset = 1; } else if (first == 0x15 || first == 0x14) { charset = "GB2312"; offset = 1; } else if (first == 0x1F) { charset = "UTF-8"; offset = 1; } else if (first < 0x20) { offset = 1; } try { return new String(bs, offset, bs.length - offset, charset).trim(); } catch (Exception e) { return ""; } } static class SectionAssembler { private final ByteArrayOutputStream cur = new ByteArrayOutputStream(); private Integer expectedLen = null; private final Queue<byte[]> ready = new LinkedList<byte[]>(); void push(byte[] src, int off, int len, boolean payloadStart, int continuityCounter) { int i = off; if (payloadStart) { int pointer = src[i] & 0xFF; i += 1 + pointer; startNew(); } while (i < off + len) { if (expectedLen == null) { if (off + len - i < 3) { write(src, i, off + len - i); return; } int sl = ((src[i + 1] & 0x0F) << 8) | (src[i + 2] & 0xFF); expectedLen = sl + 3; } int remaining = expectedLen - cur.size(); int copy = Math.min(remaining, off + len - i); write(src, i, copy); i += copy; if (cur.size() == expectedLen) { ready.add(cur.toByteArray()); startNew(); } } } boolean hasSection() { return !ready.isEmpty(); } byte[] pollSection() { return ready.poll(); } private void startNew() { cur.reset(); expectedLen = null; } private void write(byte[] src, int off, int len) { cur.write(src, off, len); } } } document.getElementById('btnParse').addEventListener('click', () => { const selectedGroup = groups.find(g => g.selected); if (!selectedGroup) { alert("请先选择一个输入通道"); return; } const { ip, port, name, id } = selectedGroup; const es = new EventSource(`/loadProgramServlet?ip=${ip}&port=${port}&name=${name}&id=${id}`); es.onmessage = function (event) { try { const data = JSON.parse(event.data); console.log('收到节目列表:', data); selectedGroup.programs = data; renderTree(); } catch (e) { console.error("解析 SSE 数据失败", e); } }; es.onerror = function (err) { console.error("SSE 连接出错", err); }; }); 报错 AdminServlet:1101 加载节目数据失败 405 <html><head><title>Apache Tomcat/6.0.29 - Error report</title><style><!--H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}HR {color : #525D76;}--></style> </head><body><h1>HTTP Status 405 - HTTP method POST is not supported by this URL</h1><HR size="1" noshade="noshade"><p><b>type</b> Status report</p><p><b>message</b> <u>HTTP method POST is not supported by this URL</u></p><p><b>description</b> <u>The specified HTTP method is not allowed for the requested resource (HTTP method POST is not supported by this URL).</u></p><HR size="1" noshade="noshade"><h3>Apache Tomcat/6.0.29</h3></body></htm
最新发布
09-06
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值